Jak pobrać sterowanie zdalnym pojazdem w aplikacji konsolowej?

0

Cześć

Potrzebuje pętli , która będzie działała ciągle, ale po wciśnięciu klawisza wykona jakąś procedure.
W skrócie zabieram się za zbudowanie pojazdu zdalnie sterowanewgo.

Mam jednak problem z biblioteka keyboard.
Nie zwraca żadnej wartości.

Instalowana z poziomu root na Linux i z roota uruchamiania.

Nie działa nawet najprostszy skrypt.

import keyboard
while True:
    if keyboard.is_pressed("a"):
        print("You pressed 'a'.")
        break

Ktoś wie co jest nie tak. Używam python3.
Dzieki

0
  1. Formatuj kod — instrukcję obsługi Markdowna masz zalinkowaną w prawym dolnym rogu pola edycji, możesz też zajrzeć w swój post, żeby zobaczyć, jak tego dokonałem.
  2. Instrukcja obsługi biblioteki wprost odradza takie pętle: https://github.com/boppreh/keyboard#waiting-for-a-key-press-one-time Spróbuj napisać kod zgodnie z ich zaleceniami i daj znać, czy pomogło. Jak nie, to będziemy kombinować dalej.
0

Zainteresuj się GUI dla Pytonga o nazwie Kivy. Będziesz mógł sobie sprawić apkę na Android/iphone.

Pozdrawiam
Radek Glebicki

0
Robertforum napisał(a):

Cześć

Potrzebuje pętli , która będzie działała ciągle, ale po wciśnięciu klawisza wykona jakąś procedure.
W skrócie zabieram się za zbudowanie pojazdu zdalnie sterowanewgo.

Mam jednak problem z biblioteka keyboard.
Nie zwraca żadnej wartości.

Instalowana z poziomu root na Linux i z roota uruchamiania.

Nazywając rzeczy po imieniu, chcesz po prostu zrobić aplikację do sterowania zdalnym pojazdem z interfejsem konsolowym. Pytanie czy to jest dobre wyjście do Twojego problemu?

0

Dzięki za szybkie odpowiedzi.

@Althorion - zmieniłem kod za Twoja sugestią, ale niestety nadal nie działa. Nie wiem, czy coś jest nie ze środowiskiem? Tak jak mowilem uruchamiam i instalowałem na root (biblioteka keyboard tego wymaga). Po uruchomieniu nic sie nie dzieje. Po wciśnięciu a rownież. kiedy odinstaluję bibliotekę obaj jest prawidłowy, czyli mam błąd ze jest nie znana.

import keyboard

while True:
    keyboard.wait('a')
    print('a was pressed! Waiting on it again...')

@Radek dzięki za info, nie chce na tą chwilę GUI, wyjaśnię to niżej.
@Riddle Generalnie to chce sterować pinami GPIO w rasperrypi : (pojazd rc, kosiarka zdalnie sterowana w dalej kolejnosci sterowania z pada ps3 lub ps4 itd.) .Czy ide dobra droga, nie wiem dopiero zaczynam grzebać w python3, poległem na pierwszej bibliotece...
Oczywiście bardzo chętnie usłyszę o ewentualnie lepszych rozwiązaniach. Na tą chwile chciałem prostą petlę.... a dalej zobaczę :P.

Samo sterowanie można zrobić dość łatwo przez www, za pomocą php, ale to na dluższą strone chyba ślepa droga.

U Was działa ten prosty skrypt ? sprawdzałem na dwóch serwerach i nie działa. dziwne.

Jeszcze raz dzięki.

0

A chcesz ten program uruchamiać z komputera lokalnie?

To moim zdaniem najlepszy byłby jakiś program z graficznym interfejsem, w kilka linijek zrobisz to z tkinterem który jest wbudowany w Python. Nie musiałbyś instalować nic nowego i byłoby to bardzo mało kodu.

Podeślę Ci zaraz przykład jak będę na komputerze.

0
Riddle napisał(a):

A chcesz ten program uruchamiać z komputera lokalnie?

To moim zdaniem najlepszy byłby jakiś program z graficznym interfejsem, w kilka linijek zrobisz to z tkinterem który jest wbudowany w Python. Nie musiałbyś instalować nic nowego i byłoby to bardzo mało kodu.

Podeślę Ci zaraz przykład jak będę na komputerze.

uruchamiam przez putty - ssh z laptopa a serwer debianowy będzie jeździł na kółkach po podwórku :P.
Widizalem gotowsce oparte na python, gdzie parujesz pada od PS3 lub 4 po bluetooth z raspberry, no i sterujesz z pada. Ale po kolei, sam do tego dojdę, torche praktyki mam. Nie kumam dlaczego nie dziala ten prosty skrypt.

0
Robertforum napisał(a):
Riddle napisał(a):

A chcesz ten program uruchamiać z komputera lokalnie?

To moim zdaniem najlepszy byłby jakiś program z graficznym interfejsem, w kilka linijek zrobisz to z tkinterem który jest wbudowany w Python. Nie musiałbyś instalować nic nowego i byłoby to bardzo mało kodu.

Podeślę Ci zaraz przykład jak będę na komputerze.

uruchamiam przez putty - ssh z laptopa a serwer debianowy będzie jeździł na kółkach po podwórku :P.
Widizalem gotowsce oparte na python, gdzie parujesz pada od PS3 lub 4 po bluetooth z raspberry, no i sterujesz z pada. Ale po kolei, sam do tego dojdę, torche praktyki mam. Nie kumam dlaczego nie dziala ten prosty skrypt.

Chcesz się łączyć interfejsem konsolowym przez ssh do samochodzika?

Nie działa bo while leci w nieskończoność i blokuje.

Zamiast keyboard.is_pressed() zrób if input() == "a":.

0
Riddle napisał(a):
Robertforum napisał(a):
Riddle napisał(a):

A chcesz ten program uruchamiać z komputera lokalnie?

To moim zdaniem najlepszy byłby jakiś program z graficznym interfejsem, w kilka linijek zrobisz to z tkinterem który jest wbudowany w Python. Nie musiałbyś instalować nic nowego i byłoby to bardzo mało kodu.

Podeślę Ci zaraz przykład jak będę na komputerze.

uruchamiam przez putty - ssh z laptopa a serwer debianowy będzie jeździł na kółkach po podwórku :P.
Widizalem gotowsce oparte na python, gdzie parujesz pada od PS3 lub 4 po bluetooth z raspberry, no i sterujesz z pada. Ale po kolei, sam do tego dojdę, torche praktyki mam. Nie kumam dlaczego nie dziala ten prosty skrypt.

Chcesz się łączyć interfejsem konsolowym przez ssh do samochodzika?

Nie działa bo while leci w nieskończoność i blokuje.

Zamiast keyboard.is_pressed() zrób if input() == "a":.

Tak, chce się tak łączyć.
Tak, to dziala, z tym ze czeka na wciśniecie Enter po wprowadzeniu znaku wiec petla sie zatrzymuje.
Może da sie to zasymulować (wciśniecie Enter) właśnie za pomocą tej biblioteki, ktora chyba jednak nie działa ?:P

taki kod turbo kod

import keyboard
keyboard.write("Hello")

zwraca:

python3 b.py
Traceback (most recent call last):
  File "/root/b.py", line 2, in <module>
    keyboard.write("Hello")
  File "/usr/local/lib/python3.9/dist-packages/keyboard/__init__.py", line 854, in write
    scan_code, modifiers = next(iter(entries))
StopIteration

Pewnie to coś banalnego :(

0
Robertforum napisał(a):

uruchamiam przez putty - ssh z laptopa

A, to to rozwiązuje ten problem. Przeczytaj dokumentację swojej biblioteki: https://github.com/boppreh/keyboard

SSH connections forward only the text typed, not keyboard events. Therefore if you connect to a server or Raspberry PI that is running keyboard via SSH, the server will not detect your key events.

(oraz czemu „U mnie działa”™)

0
Robertforum napisał(a):

Tak, chce się tak łączyć.
Tak, to dziala, z tym ze czeka na wciśniecie Enter po wprowadzeniu znaku wiec petla sie zatrzymuje.
Może da sie to zasymulować (wciśniecie Enter) właśnie za pomocą tej biblioteki, ktora chyba jednak nie działa ?:P

Okej, czyli potrzebujesz wczytać po prostu znak z wejścia standardowego (std in), bez czekania na Enter?

No dlatego właśnie powiedziałem że interfejs konsolowy do tego celu jest średni, bo w pythonie z tego co wiem nie ma wbudowanego sposobu na to.

Są sposoby takie hacki, ale one są platform-specific, co znaczy że jak to napiszesz i zadziała na windowsie, to nie zadziała na linuxie, i odwrotnie. Dlatego interfejs konsolowy do takich rzeczy jak interaktywne sterowanie czymś w real time, i to jeszcze bez Enter, tylko po prostu tak że klikasz, to raczej nie jest dobre wyjście do Twojego celu.

Jak wpiszesz w google "python read from stdin interactive without newline", to Ci wyjdą same rozwiązania które działają tylko na jednej platformie, np to: https://gist.github.com/ashelly/e24de5e9cdd268f9d16a

Jeśli ja miałbym robić coś takiego, to chyba napisałbym to jak klient/server po UDP albo TCP. W ogóle skąd pomysł że sterowanie tego przez CLI po SSH i putty to dobry pomysł?

0

Macie rację, bezpośrednio na virtualce działa a po ssh nie.

Riddle napisał(a):

W ogóle skąd pomysł że sterowanie tego przez CLI po SSH i putty to dobry pomysł?

Do tej pory pisałem trochę aplikacji www i nie spotkałem się z takim problemem. Zaczynam, błąd wynika z niedoświadczenia. Myślałem że do tak prostych rzeczy wystarczy.

Pomyśle nad zaproponowanymi rozwiązaniami i na pewno się podzielę

Dzięki za poświęcony czas.

0
Robertforum napisał(a):

Macie rację, bezpośrednio na virtualce działa a po ssh nie.

Riddle napisał(a):

W ogóle skąd pomysł że sterowanie tego przez CLI po SSH i putty to dobry pomysł?

Do tej pory pisałem trochę aplikacji www i nie spotkałem się z takim problemem. Zaczynam, błąd wynika z niedoświadczenia. Myślałem że do tak prostych rzeczy wystarczy.

Pomyśle nad zaproponowanymi rozwiązaniami i na pewno się podzielę

Dzięki za poświęcony czas.

No mój strzał żeby sterować takim autkiem to raczej tylko klient/server po TCP, ewentualnie jak nie ma dużych opóźnień to można by po HTTP.

Tutaj spróbuj: https://www.digitalocean.com/community/tutorials/python-socket-programming-server-client

0

Ten kod działa na windowsie, tylko trzeba wywalić "break" bo inaczej przestaje działać po jednym naciśnięciu
Z tego co widzę moduł "keyboard" na linuksie wymaga roota bo podpina się bezpośrednio do /dev/input/input...
Jeśli podpinasz się po ssh to naciśnięcia klawiszy chyba nie są odczytywane jako zwykły input, tu trzeba by było się spiąć z sesją ssh
Widzę że jest moduł który sobie z tym radzi - sshkeyboard https://sshkeyboard.readthedocs.io/en/latest/index.html

Wbrew pozorom łatwiej może ci być od razu działać z padem niż z klawiaturą. Wykrywanie klawiszy wysłanych po ssh będzie kiepsko działało i z losowym opóźnieniem, sygnał musi przelecieć do routera i z powrotem z różnymi przeszkodami po drodze - twój samochodzik będzie za wolno reagował i wjeżdżał w ściany.

Tu masz moduł do pada ps4 - https://pypi.org/project/pyPS4Controller/

No i mam nadzieję że to wiesz i to tylko prototyp ale nie rób tego na nieskończonej pętli tylko na eventach, nieskończona pętla będzie grzała urządzenie i drainowała baterie

0

ok. thx.
Drenowanie cpu a co za tym idzie baterii,nie przejmowa bym się, testowałem zuzywa 0,5 W w szczycie. co nie oznacza że trzeba tak robić, skoro można lepiej.
a może "simply clewer" i prosta klawiatura pod bluetooth (być może wifi) i dongel wpięty bezpośrednio w raspberry ?
Biblioteka sshkeyboard działa, ale mało płynnie.

Dzięki wielkie za pomoc.

0

Cześć

Idąc wątkiem client-server popełniłem poniższy kod, który działa poprawnie (jak na 2 dzień mojego programowania w python, będę wklejał kolejne wersje). Wklejam kod może komuś się przyda. Przesyła klawisze WASD na serwer. Client działa na Windows, oczywiście na Linux też. Doszedłem jednak do miejsca, gdzie wciśnięcie dwóch klawiszy na raz np. WA, powoduje że wczytuje się jeden klawisz, raz jeden , raz drugi, działa to losowo. Chyba jest to ograniczenie sprzętowe klawiatury, bo testując pod notatnikiem, albo openwriter, działa to podobnie, czyli jeden klawisz, nie ma multifuction.

Mam dwa pytania:

  1. Czy rzeczywiście jest to fizyczne ograniczenie klawiatury na laptopie ?
  2. Zakładając że znajdę klawiature która wczytuja na raz min dwa znaki a może i wecej, to stawiam że moj kod nie będzie potrafił obsłużyć dwóch klawiszy na raz, czy nalezy wtedy iść w programowanie asynchroniczne, czy tez inne rozwiązania ?

Dzięki.

Client


import socket
import time
import keyboard 


msgFromClient       = "witaj serwerze"

bytesToSend         = str.encode(msgFromClient) 

serverAddressPort   = ("192.168.31.200", 20001)

bufferSize          = 1024

 

# Create a UDP socket at client side

UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)

 
while True:
    if keyboard.read_key() == "w" :
    #    global msgFromClient
        costam = "w"
        print("przod")
        msgFromClient       = "przod"
        bytesToSend         = str.encode(msgFromClient)

    elif keyboard.read_key() == "s" :
    #    global msgFromClient
        costam = "s"
        print("tyl")
        msgFromClient       = "tyl"
        bytesToSend         = str.encode(msgFromClient)
    
    elif keyboard.read_key() == "a" :
    #    global msgFromClient
        costam = "a"
        print("lewo")
        msgFromClient       = "lewo"
        bytesToSend         = str.encode(msgFromClient)
     
    elif keyboard.read_key() == "d" :
    #    global msgFromClient
        costam = "d"
        print("prawo")
        msgFromClient       = "prawo"
        bytesToSend         = str.encode(msgFromClient)
    else:
        print('nie obslugiwany klawisz konczne')
        time.sleep(0.01)
    bytesToSend         = str.encode(msgFromClient)

    UDPClientSocket.sendto(bytesToSend, serverAddressPort)

 

    msgFromServer = UDPClientSocket.recvfrom(bufferSize)
    msg = "Message from Server {}".format(msgFromServer[0])

#    print(msg)

    time.sleep(0.01) 
	
	

serwer

import socket


localIP     = "192.168.31.200"

localPort   = 20001

bufferSize  = 1024

licznik = 0

msgFromServer       = ""

bytesToSend         = str.encode(msgFromServer)



# Create a datagram socket

UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)



# Bind to address and ip

UDPServerSocket.bind((localIP, localPort))



print("UDP server up and listening")



# Listen for incoming datagrams

while(True):

    bytesAddressPair = UDPServerSocket.recvfrom(bufferSize)

    message = bytesAddressPair[0]

    address = bytesAddressPair[1]

    clientMsg = "Message from Client:{}".format(message)
    clientIP  = "Client IP Address:{}".format(address)

    print(clientMsg)
    print(clientIP)


    licznik += 1
    print (licznik)
    # Sending a reply to client

    UDPServerSocket.sendto(bytesToSend, address)

0
Robertforum napisał(a):

Cześć

Idąc wątkiem client-server popełniłem poniższy kod, który działa poprawnie (jak na 2 dzień mojego programowania w python, będę wklejał kolejne wersje). Wklejam kod może komuś się przyda. Przesyła klawisze WASD na serwer. Client działa na Windows, oczywiście na Linux też. Doszedłem jednak do miejsca, gdzie wciśnięcie dwóch klawiszy na raz np. WA, powoduje że wczytuje się jeden klawisz, raz jeden , raz drugi, działa to losowo. Chyba jest to ograniczenie sprzętowe klawiatury, bo testując pod notatnikiem, albo openwriter, działa to podobnie, czyli jeden klawisz, nie ma multifuction.

Mam dwa pytania:

  1. Czy rzeczywiście jest to fizyczne ograniczenie klawiatury na laptopie ?
  2. Zakładając że znajdę klawiature która wczytuja na raz min dwa znaki a może i wecej, to stawiam że moj kod nie będzie potrafił obsłużyć dwóch klawiszy na raz, czy nalezy wtedy iść w programowanie asynchroniczne, czy tez inne rozwiązania ?

Spróbuj zamienić if keyboard.read_key() == "w" na keyboard.is_pressed('w'). I zabierz else.

0
Riddle napisał(a):

Spróbuj zamienić if keyboard.read_key() == "w" na keyboard.is_pressed('w'). I zabierz else.

Niestety niewiele to zmienia, no i petla wykonuję się cały czas na client.

0
Robertforum napisał(a):
Riddle napisał(a):

Spróbuj zamienić if keyboard.read_key() == "w" na keyboard.is_pressed('w'). I zabierz else.

Niestety niewiele to zmienia, no i petla wykonuję się cały czas na client.

Otwórz dokumentację tej biblioteki, i spróbuj znaleźć informacje jak zrobić to co chcesz.

Dla przykładu (https://pypi.org/project/keyboard/):

import keyboard

keyboard.press_and_release('shift+s, space')

keyboard.write('The quick brown fox jumps over the lazy dog.')

keyboard.add_hotkey('ctrl+shift+a', print, args=('triggered', 'hotkey'))

# Press PAGE UP then PAGE DOWN to type "foobar".
keyboard.add_hotkey('page up, page down', lambda: keyboard.write('foobar'))

# Blocks until you press esc.
keyboard.wait('esc')

# Record events until 'esc' is pressed.
recorded = keyboard.record(until='esc')
# Then replay back at three times the speed.
keyboard.play(recorded, speed_factor=3)

# Type @@ then press space to replace with abbreviation.
keyboard.add_abbreviation('@@', '[email protected]')

# Block forever, like `while True`.
keyboard.wait()
0

Nie wiem co mam wybrać, chyba ogranicza mnie klawiatura fizycznie, to co pisałem wyżej nie można użyć dwóch klawiszy w jednym czasie.

0
Robertforum napisał(a):

Nie wiem co mam wybrać, chyba ogranicza mnie klawiatura fizycznie, to co pisałem wyżej nie można użyć dwóch klawiszy w jednym czasie.

Żadna klawiatura Cię nie ogranicza. Możesz normalnie grać na niej w gry. Twój program który napisałeś Cię ogranicza.

0

ok. Jest argument.

0
Robertforum napisał(a):

ok. Jest argument.

Zobacz mój post z wyżej, zwłaszcza linijki:

import keyboard
keyboard.add_hotkey('ctrl+shift+a', print, args=('triggered', 'hotkey'))

# Blocks until you press esc.
keyboard.wait('esc')
0

Zgodnie z sugestią popełniłem to co niżej, działa na dwóch klawiszach na raz, czyli naprawiona klawiatura :) Czyli mam to co chciałem, ale...... Nie potrafię przesłać zmiennej poza fukcje :), próbowałem zmiennych globalnych tak jak w poprzedniej wersji kodu, generalnie chyba nic poza keyboard.wait się nie wykonuje. Potrzebna jeszcze jedna pętla ?

dla 'wd' - umieściłem tworzenie socketu, i oczywście dane "lecą" na serwer, ale powinno być to oddzielnie , gdzieś na dole kodu, ale nie moze przesłać tej zmiennej. Prośba o podpowiedź

Dziekuje za pomoc, dzięki Waszym podpowiedzą nie marnuję się całych dni na szukanie rozwiązania.

def hotkey_pressed_wd():
    wd = 'pressed wd'
    print(wd)
    msgFromClient = "wd"
    bytesToSend = str.encode(msgFromClient)
    print(bytesToSend)
    UDPClientSocket.sendto(bytesToSend, serverAddressPort)
def hotkey_pressed_sa():
    sa = 'pressed sa'
    print(sa)
def hotkey_pressed_sd():
    sd = 'pressed sd'
    print(sd)
def hotkey_pressed_w():
    w = 'pressed w'
    print(w)
def hotkey_pressed_a():
    a = 'pressed a'
    print(a)
def hotkey_pressed_s():
    s = 'pressed s'
    print(s)
def hotkey_pressed_d():
    d = 'pressed d'
    print(d)

# register the hotkey using the keyboard library
keyboard.add_hotkey('a + w', hotkey_pressed_wa)
keyboard.add_hotkey('d + w', hotkey_pressed_wd)
keyboard.add_hotkey('d + s', hotkey_pressed_sd)
keyboard.add_hotkey('a + s', hotkey_pressed_sa)
keyboard.add_hotkey('w', hotkey_pressed_w)
keyboard.add_hotkey('a', hotkey_pressed_a)
keyboard.add_hotkey('s', hotkey_pressed_s)
keyboard.add_hotkey('d', hotkey_pressed_d)

# wait for keyboard events
keyboard.wait()

print(bytesToSend)
1
Robertforum napisał(a):

Nie potrafię przesłać zmiennej poza fukcje :), próbowałem zmiennych globalnych tak jak w poprzedniej wersji kodu, generalnie chyba nic poza keyboard.wait się nie wykonuje. Potrzebna jeszcze jedna pętla ?

Na pewno nie.

Co do tego jak do tego podejść, odpowiedź to jest jeszcze raz: Po prostu przeczytaj dokumentacje. Biblioteka której używasz ma dokumentację tutaj: https://github.com/boppreh/keyboard#api Zajęło mi dosłownie 5 sekund żeby znaleźć opis tego jak działa keyboard.add_hotkey(), i ten opis jest tutaj: https://github.com/boppreh/keyboard#keyboardadd_hotkeyhotkey-callback-args-suppressfalse-timeout1-trigger_on_releasefalse

Żeby przerobić Twój kod, powinieneś zrobić coś takiego:

def start():
  def send(keys: list[str]) -> None:
      send_udp("pressed " + ",".join(keys))

  keyboard.add_hotkey('a + w', send, args=['a', 'w'])
  keyboard.add_hotkey('a + s', send, args=['a', 's'])
  keyboard.add_hotkey('d + w', send, args=['d', 'w'])
  keyboard.add_hotkey('d + s', send, args=['d', 's'])
  keyboard.add_hotkey('w', send, args=['w'])
  keyboard.add_hotkey('s', send, args=['s'])
  keyboard.add_hotkey('a', send, args=['a'])
  keyboard.add_hotkey('d', send, args=['d'])
  keyboard.wait("esc")

def send_udp(message: str, address_port) -> None:
  print("Sending...:" + message)
  UDPClientSocket.sendto(str.encode(msgFromClient), serverAddressPort)

if __name__ == '__main__':
 print("Started listening for keys...")
 start()
 print("Stopped listening for keys.")
Robertforum napisał(a):

Nie potrafię przesłać zmiennej poza fukcje :),

Tego się nie da zrobić, bo keyboard.add_hotkey() wystawia Ci callback, więc jedyne co możesz zrobić to wywołać odpowiednią funkcję wtedy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1