Webapp per il controllo da tastiera wasd
In questo tutorial vedremo come controllare un robot attraverso i tasti wasd per farlo muovere nelle 4 direzioni. In particolare vedremo:
-
come sviluppare una webapp in grado di controllare il robot attraverso la tastiera
-
come sviluppare lo sketch in ROS per sottoscriversi al topic della webapp
La webapp
Come prima cosa andiamo a sviluppare l'applicazione web che ci permetterà di controllare il robot tramite la tastiera. Da qui scaricate (premendo sul pulsante clone or download) la cartella ed estraetela in un luogo facilmente raggiungibile.
Aprite la cartella keyboardteleop_files e aprite il file all'interno della cartella (la "struttura" in javascript della nostra webapp) con l'applicazione blocco note. A questo punto cercate le righe dove sono indicate le direzioni (nella forma //command
) e aggiungete sotto ognuno di essi la stringa console.log("direzione")
, sostituendo la parola "direzione" in base a dove si dirigerà il robot.
Queste aggiunte serviranno a verificare l'effettiva funzionalità della nostra webapp. Il lavoro non è però ancora completo: è necessario far sì che la nostra app sia in grado di dialogare con il nostro robot. Aprite il file html keyboardteleop con il blocco note e cercate la stringa start_ros('192.168.0.112', 'silverbot', '192.168.0.112', '192.168.0.112/bridge/');
Dovete ora sostituire questa stringa con quella che identifica il vostro robot. Per trovarla collegate il vostro robot al sito di Hotblack, aprite una qualunque webapp e aprite la sorgente della pagina (tasto destro):
All'interno del codice sorgente cercate la stringa start_ros('#...');
, copiatela al posto di quella presente nel file html (aperto con il blocco note) keyboardteleop e salvate il tutto.
Possiamo ora testare la nostra app: aprite il file keyboardteleop nel browser e aprite la console cliccando col tasto destro del mouse e selezionando seleziona. Refreshate la pagina (F5) e ogni volta che premete uno dei pulsanti wasd la console dovrebbe restituirvi, stampandola a video, l'azione connessa al pulsante premuto.
Sketch ROS
Scriviamo ora lo sketch in Ros che farà comunicare il nostro robot con la webapp. Importiamo l'oggetto Robot
dalla libreria gpiozero
per gestirne il movimento e costruiamo le coppie di PIN GPIO a cui sono collegate i due motori, sfruttando i parametri left e right:
self.robot = Robot(left=(16, 19), right=(20, 26))
Sottoscriviamoci ad un Topic ROS e usiamo le Callback
Andiamo ad implementare una funzione di callback, chiamata keyb_wasd
. Questa funzione (come tutte le funzioni di callback) avrà la seguente forma:
def keyb_wasd(self, msg):
pass
I due parametri che la funzione sfrutta sono self
(che rappresenta il nodo) e msg
, che conterrà il messaggio scambiato dal topic.
Il messaggio geometry_msgs/Twist
contiene 2 valori a noi utili:
linear.x
che varia nell'intervallo+20
e-20
linear.z
che varia nell'intervallo+1
e-1
La classe Robot
funziona in modo simile, ma i valori di velocità delle ruote possono variare tra -1.0
(massima velocit‡ all'indietro) e 1.0
(massima velocità in avanti). La prima cosa che dovrà fare la funzione, quindi, è convertire questi valori e controllare che i valori finali siano nell'intervallo [-1, 1]
.
def on_speed(self, msg):
v_dx = (msg.linear.x/20) - msg.linear.z
v_sx = (msg.linear.x/20) + msg.linear.z
Una volta generati i due comandi di velocità (v_dx
e v_sx
), aggiungiamo una stringa per stamparne a video i valori finali utilizzando la funzione print
:
def on_speed(self, msg):
#...
print 'v_dx', v_dx
print 'v_sx', v_sx
stdout.flush()
#...
Ricordate di aggiungere sempre la linea di codice stdout.flush()
(ed importare il modulo flush
con la stringa from sys import flush
per forzare la stampa effettiva sulla shell.
Ora non ci resta che settare questi valori per far muovere le ruote. Per farlo, utilizziamo il prametro Robot.value
dell'oggetto Robot
self.robot.value = (v_sx, v_dx)
La funzione keyb_wasd
, quindi, verrà completata in questo modo:
def keyb_wasd(self, msg):
v_dx = (msg.linear.x/20) - msg.linear.z
v_sx = (msg.linear.x/20) + msg.linear.z
#stampo a video i valori di v_dx e v_sx
print 'v_dx', v_dx
print 'v_sx', v_sx
stdout.flush()
#controllo del robot
self.robot.value = (v_dx, v_sx)
Sottoscrizione al topic
Una volta implementata la funzione di callback, non ci resta che sottoscriverci al topic keyboard
per poterla correttamente utilizzare. Per farlo, nella funzione setup
, aggiungiamo la seguente linea di codice:
dotbot_ros.Subscriber('keyboard', Twist, self.keyb_wasd)
ricordandoci di importare l'oggetto Twist
da geometry_msgs.msg
from geometry_msgs.msg import Twist
Codice completo
Ecco il codice completo del nostro programma
import dotbot_ros
from sys import stdout
from geometry_msgs.msg import Twist
from gpiozero import Robot
class Node(dotbot_ros.DotbotNode):
node_name = 'keyboard'
def setup(self):
self.robot = Robot(left=(16, 19), right=(20, 26))
dotbot_ros.Subscriber('keyboard', Twist, self.keyb_wasd)
def keyb_wasd(self, msg):
print msg.linear.x
stdout.flush()
v_dx = (msg.linear.x/20) - msg.linear.z
v_sx = (msg.linear.x/20) + msg.linear.z
print v_dx
print v_sx
stdout.flush()
self.robot.value = (v_dx, v_sx)
stdout.flush()
Per inviare i comandi dobbiamo aprire la nostra webapp, la console ROS e lanciare il nostro nodo. A questo punto refreshando la webapp dovrebbe comparire sulla console il topic nomerobot/keyboard
. Premendo sul pulsante echo
ci comparirà una schermata che mostrerà il variare dei valori del messaggio pubblicato come topic dalla webapp.
Refreshiamo un'ultima volta la pagina della webapp e siamo pronti a comandare il nostro robot dalla tastiera!