Primi passi con unitree_sdk2_python: il primo programma per il Go2
Guida pratica all'SDK Python ufficiale di Unitree: installazione con CycloneDDS, rete Ethernet, l'esempio go2_sport_client e un primo script che fa alzare, salutare e camminare il Go2, e poi ne legge lo stato.
- Livello
- Intermedio
- Lettura
- 4 min
- Robot
- Unitree Go2 EDU
- Pubblicato
In questa guida installiamo unitree_sdk2_python, la versione Python dell'SDK ufficiale di Unitree, e scriviamo un primo programma che fa alzare, salutare e camminare il Go2. Alla fine leggiamo anche lo stato del robot in tempo reale. Se non sai ancora quale modo di collegamento fa per te, parti dalla guida Come si comanda un Unitree Go2.
Sicurezza prima di tutto
Il robot pesa circa 15 kg e si muove davvero. Lavora in uno spazio libero, senza persone o animali vicini, e tieni a portata di mano il radiocomando per fermarlo. Prima di ogni prova sul movimento, l'esempio ufficiale chiede di confermare che intorno al robot non ci siano ostacoli: fallo sul serio.
Cosa serve#
- Un Go2 EDU: l'SDK è supportato ufficialmente sulla EDU, e in parte sulla X. Su Air e Pro non è supportato.
- Un PC Linux collegato al robot con un cavo Ethernet. Gli esempi ufficiali usano Ubuntu e nomi di interfaccia come
enp2s0. - Python 3.8 o successivo,
gitepip.
Le dipendenze dichiarate nel README sono cyclonedds==0.10.2, numpy e opencv-python.
Installazione#
Clona il repository e installalo in modalità sviluppo:
sudo apt install python3-pip
git clone https://github.com/unitreerobotics/unitree_sdk2_python.git
cd unitree_sdk2_python
pip3 install -e .
Se l'installazione si ferma con l'errore Could not locate cyclonedds. Try to set CYCLONEDDS_HOME or CMAKE_PREFIX_PATH, devi prima compilare CycloneDDS 0.10.x e poi ripetere l'installazione:
cd ~
git clone https://github.com/eclipse-cyclonedds/cyclonedds -b releases/0.10.x
cd cyclonedds && mkdir build install && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=../install
cmake --build . --target install
cd ~/unitree_sdk2_python
export CYCLONEDDS_HOME=~/cyclonedds/install
pip3 install -e .
Configurare la rete#
Il robot e il PC devono stare sulla rete interna 192.168.123.0/24. Assegna al PC l'indirizzo 192.168.123.99 con maschera 255.255.255.0 sull'interfaccia collegata al robot.
ip link # trova il nome dell'interfaccia, es. enp2s0
sudo ip addr add 192.168.123.99/24 dev enp2s0
sudo ip link set enp2s0 up
ping -c 3 192.168.123.161 # unità di controllo del robot
Nelle impostazioni della connessione cablata scegli IPv4 Manuale e inserisci indirizzo 192.168.123.99 e maschera 255.255.255.0. Il gateway puoi lasciarlo vuoto.
Annota il nome dell'interfaccia, per esempio enp2s0: l'SDK comunica tramite DDS e va collegato a un'interfaccia di rete, non a un indirizzo IP.
L'esempio ufficiale#
Il repository contiene un esempio interattivo per i comandi di alto livello. Il nome dell'interfaccia si passa come argomento:
python3 example/go2/high_level/go2_sport_client.py enp2s0
Lo script mostra un avviso di sicurezza e aspetta che premi Enter. Poi ti chiede il comando da eseguire, per numero o per nome: per esempio 1 (stand_up), 2 (stand_down), 3 (move forward), 6 (stop_move), 9 (balanced stand) o 10 (recovery).
README e repository
Il README cita ancora percorsi come example/high_level/sportmode_test.py, che nel repository attuale non ci sono più. Gli esempi per il Go2 si trovano in example/go2/.
Il primo script#
Ora scriviamo un programma nostro. La classe centrale è SportClient, che manda al robot i comandi di alto livello: gli stessi movimenti dell'app, ma da codice.
import sys
import time
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
from unitree_sdk2py.go2.sport.sport_client import SportClient
def main():
if len(sys.argv) < 2:
print(f"Uso: python3 {sys.argv[0]} <interfaccia> (es. enp2s0)")
sys.exit(1)
# 0 = dominio DDS, poi l'interfaccia collegata al robot
ChannelFactoryInitialize(0, sys.argv[1])
sport = SportClient()
sport.SetTimeout(10.0) # secondi di attesa per ogni comando
sport.Init()
input("Spazio libero intorno al robot? Premi Invio per iniziare...")
sport.StandUp()
time.sleep(1.5)
sport.BalanceStand() # equilibrio attivo: pronto a muoversi
time.sleep(1.0)
sport.Hello() # saluta con la zampa
time.sleep(3.0)
# cammina in avanti a 0,3 m/s per 2 secondi, inviando il comando a 10 Hz
start = time.time()
while time.time() - start < 2.0:
sport.Move(0.3, 0.0, 0.0) # vx [m/s], vy [m/s], vyaw [rad/s]
time.sleep(0.1)
sport.StopMove()
time.sleep(1.0)
sport.StandDown()
if __name__ == "__main__":
main()
python3 primo_go2.py enp2s0
Move(vx, vy, vyaw) imposta tre velocità: in avanti (vx), di lato (vy) e di rotazione sul posto (vyaw). Parti da valori piccoli. StopMove() ferma il movimento. Tra gli altri metodi di SportClient ci sono Damp(), che disattiva i motori come arresto morbido, RecoveryStand(), che rialza il robot dopo una caduta, Sit(), Stretch() e SpeedLevel(level).
Perché il comando Move dentro un ciclo
Inviare Move a frequenza costante, invece di una volta sola, rende il comportamento prevedibile: il robot va alla velocità indicata finché il programma continua a mandarla, e il StopMove() finale lo ferma in modo esplicito. Se lo script si interrompe, non resta in sospeso un comando di movimento senza controllo.
Leggere lo stato del robot#
Oltre a ricevere comandi, il robot pubblica il proprio stato sul topic DDS rt/sportmodestate: modalità, posizione stimata, velocità, assetto. Per leggerlo ti iscrivi al topic con un ChannelSubscriber:
import sys
import time
from unitree_sdk2py.core.channel import ChannelFactoryInitialize, ChannelSubscriber
from unitree_sdk2py.idl.unitree_go.msg.dds_ import SportModeState_
def on_state(msg: SportModeState_):
x, y, z = msg.position
vx, vy, vz = msg.velocity
print(f"modo={msg.mode} pos=({x:.2f}, {y:.2f}, {z:.2f}) vel=({vx:.2f}, {vy:.2f})")
ChannelFactoryInitialize(0, sys.argv[1])
sub = ChannelSubscriber("rt/sportmodestate", SportModeState_)
sub.Init(on_state, 10) # callback e dimensione della coda
while True:
time.sleep(1)
Il nome del topic è quello usato dall'esempio ufficiale in C++ (go2_sport_client.cpp). Il tipo di messaggio SportModeState_ è lo stesso che importa l'esempio Python. Interrompi lo script con Ctrl+C.
Prossimi passi#
- Controllo di basso livello: nella cartella
example/go2/low_level/c'è un esempio che comanda i singoli motori. Prima di usarlo, il README chiede di disattivare dall'app il servizio di movimento di alto livello (sport_mode), per evitare comandi in conflitto. Per questo tipo di controllo usa sempre il cavo: un'interruzione del Wi-Fi può bloccare il ciclo di controllo. - Telecamera frontale: in
example/go2/front_camera/trovi un esempio per leggere le immagini. Serve un ambiente grafico, e si esce con il tasto ESC. - ROS 2: se il tuo progetto cresce, valuta il pacchetto ufficiale
unitree_ros2.
Fonti#
- unitreerobotics/unitree_sdk2_python (GitHub): README,
example/go2/high_level/go2_sport_client.py,unitree_sdk2py/go2/sport/sport_client.py - unitreerobotics/unitree_sdk2 (GitHub):
example/go2/go2_sport_client.cpp - unitreerobotics/unitree_ros2 (GitHub): configurazione di rete
- Unitree Go2: versioni e specifiche