Software
Dasselbe Topic /leg_controller/commands wird in Gazebo von ros2_control und am Roboter von mcu_bridge verarbeitet, sodass jeder Node oberhalb der Bridge unverändert in der Simulation und auf der Hardware läuft.
ROS-2-Schnittstelle (Go2-Stil)
| Topic | Typ | Richtung | Hinweise |
|---|---|---|---|
/cmd_vel | geometry_msgs/Twist | ein | vx, vy [m/s], wz [rad/s]; Grenzen 0,30 / 0,15 / 1,0; 0,5 s Timeout → Stehen |
/leg_controller/commands | std_msgs/Float64MultiArray | intern | 12 Gelenkwinkel [rad] in Go2-Reihenfolge FL, FR, RL, RR × Hüfte, Oberschenkel, Unterschenkel |
/joint_states | sensor_msgs/JointState | aus | Go2-Gelenknamen (FL_hip_joint …). Roboter: Winkel, die die MCU nach dem Begrenzen anwendet (Hobby-Servos haben keine Rückmeldung) |
/imu/data | sensor_msgs/Imu | aus | Orientierung (Mahony auf der MCU), Winkelgeschwindigkeit, Beschleunigung; Frame imu_link; wird nicht veröffentlicht, solange die IMU einen Fehler meldet |
/scan | sensor_msgs/LaserScan | aus | RPLIDAR C1, Frame lidar_link, 10 Hz |
/camera/image_raw | sensor_msgs/Image | aus | Camera Module 3 Wide, Frame camera_optical_frame |
/battery_state | sensor_msgs/BatteryState | aus | Akkupackspannung + Strom des Logikzweigs (INA260), negativ = Entladen |
/odom + TF odom→base_link | nav_msgs/Odometry | aus | Koppelnavigation aus der kommandierten Geschwindigkeit (nur gait_node) |
/strido/estop | std_msgs/Bool | ein | true = verriegelter Halt (Servoausgänge aus), false = Freigabe |
/strido/relax | std_msgs/Bool | ein | true = Servos kraftlos |
/strido/face | std_msgs/UInt8 | ein | LCD-Gesichtsausdruck |
/diagnostics | diagnostic_msgs/DiagnosticArray | aus | MCU-Flags: estop, relaxed, watchdog, imu_ok, power_ok, pwm_ok, clamped |
Frames folgen REP-103 (base_link: x nach vorne, y nach links, z nach oben); Gelenk-Nullstellung = Bein gerade nach unten, Oberschenkel positiv = Fuß nach hinten, Unterschenkel negativ = Knie gebeugt (Go2-Konvention).
Code von einem Unitree Go2 portieren
Gelenknamen, Vorzeichen, Frames und /cmd_vel folgen der Go2-ROS-2-Beschreibung, daher laufen Stacks auf Geschwindigkeitsebene (Teleop, Nav2, SLAM mit /scan) unverändert. Unterschiede: Die Reihenfolge des Befehlsarrays ist FL, FR, RL, RR (die Motorindex-Reihenfolge des Unitree SDK ist FR, FL, RR, RL: Zuordnung über den Gelenknamen, nicht über den Index), es gibt keine Topics für Fußkontakt oder Motordrehmoment, /joint_states sind kommandierte Werte, der Geschwindigkeitsbereich liegt bei ≈ 0,3 m/s, und die Low-Level-Messages unitree_go werden nicht bereitgestellt.
Pakete
| Pfad | Inhalt |
|---|---|
ros2/strido_description | URDF/xacro und Meshes aus CAD generiert (strido_cad.models), ros2_control-Controllerkonfiguration, display.launch.py |
ros2/strido_bringup | gazebo.launch.py, robot.launch.py, Welt, udev-Regeln |
ros2/strido_control | gait_node, policy_node, mcu_bridge, walk_smoke |
packages/strido-core | reiner Python-Kern, gemeinsam genutzt von ROS, MuJoCo und Tests: generierte Geometrie, Bein-/Koppelgetriebe-Kinematik, Trot-Gait, MCU-Protokoll, numpy-Policy-Laufzeit, strido-cli |
firmware/strido_esp32s3 | PlatformIO-Firmware; lib/strido_core enthält den portablen Kinematik-/Protokoll-/Sicherheitscode mit nativen Unit-Tests |
Starten:
ros2 launch strido_bringup gazebo.launch.py headless:=false # simulation with GUI
ros2 launch strido_bringup robot.launch.py # on the robot (add camera:=true once camera_ros is installed)
ros2 launch strido_bringup robot.launch.py use_policy:=true policy:=/path/policy.npz # learned controller
ros2 launch strido_description display.launch.py # model + joint sliders in RVizFirmware
PlatformIO, Arduino-ESP32 3.x auf dem Seeed XIAO ESP32-S3:
cd firmware/strido_esp32s3
pio test -e native # kinematics, protocol, safety unit tests on the host
pio run -e xiao_esp32s3 -t upload- 200-Hz-Schleife: Befehl → koppelgetriebegenaue Gelenk→Servo-Abbildung (
servo_map, generierte Geometrie) → Änderungsratenbegrenzung 6 rad/s → PCA9685-Pulse (200 Hz PWM). - Sicherheit: Nur Gelenkbefehle speisen den Watchdog (keine Keep-alive-Message): 200 ms kein Befehl → Halten, weitere 2 s → kraftlos schalten; verriegelter Not-Halt; PCA9685-OE-Pin wird beim Kraftlosschalten/Not-Halt auf High gezogen (plus ein Hardware-Pull-up für Resets); Akkuwarnung bei 6,8 V, Abschaltung nach 5 aufeinanderfolgenden Messwerten unter 6,4 V; kein Fahren ohne den INA260; nicht-endliche Befehle werden verworfen; Gelenk- und Kniekurbelgrenzen aus dem CAD-Bewegungsbereich-Sweep.
- Die Kalibrierung (Neutralpuls, Richtung, Grenzen pro Gelenk) wird im Flash gespeichert (
Preferences).
Protokoll (USB CDC)
Frames: COBS(type | payload | CRC16-CCITT-FALSE little endian) 0x00. Payloads sind gepackte Little-Endian-Structs, gespiegelt in packages/strido-core/src/strido/protocol.py und firmware/.../protocol.h.
| Typ | Name | Payload |
|---|---|---|
| 0x01 | JOINT_COMMAND | seq u16, mode u8 (0 kraftlos, 1 Position), q[12] f32 |
| 0x02 | SERVO_PULSE_COMMAND | seq u16, pulse_us[12] u16 (0 = aus) – nur Kalibrierung |
| 0x03 | SET_CALIBRATION | joint u8, direction i8, neutral_us u16, zero_rad f32, min_us u16, max_us u16 |
| 0x04 | SAVE_CALIBRATION | – |
| 0x05 | REQUEST_CALIBRATION | – → 12 × CALIBRATION |
| 0x06 | ESTOP | engaged u8 |
| 0x07 | DISPLAY | expression u8, length u8, text |
| 0x81 | STATE (100 Hz) | last seq u16, time_ms u32, flags u8, q[12], quat wxyz[4], gyro[3], accel[3], Bus-V, Strom A (f32) |
| 0x82 | CALIBRATION | wie SET_CALIBRATION |
| 0x83 | LOG | ASCII |
Prüfstand-Werkzeug
strido-cli (installiert mit packages/strido-core) kommuniziert ohne ROS mit dem Controller:
strido-cli center # 1500 µs on every channel: the assembly reference (fit horns now; raw pulses bypass joint limits)
strido-cli pulse FL_thigh 1600 # one joint
strido-cli calibrate # trim each joint's neutral (±5/±25 µs), saved to flash
strido-cli monitor # battery, flags, roll/pitchRaspberry-Pi-Einrichtung
- Ubuntu Server 24.04 (arm64) oder Raspberry Pi OS Bookworm 64-bit; Docker Engine.
docker compose -f docker/compose.yaml build ros(ROS 2 Jazzy, Gazebo-Bibliotheken, sllidar_ros2 fixiert, die Pakete dieses Repos).- Stromversorgungs- und udev-Konfiguration: siehe electronics.md.
- Kamera: Der Kamera-Stack des Pi 5 benötigt den libcamera-Fork von Raspberry Pi; bauen Sie
camera_rosauf dem Host dagegen (Raspberry Pi OS liefert ihn mit) oder verwenden Sierpicam-vid+ eine GStreamer-Bridge, und starten Sie dann mitcamera:=true(Standard false; das Docker-Image enthält keinen Kamera-Node).