Zum Inhalt springen

Software ​

Diagramm wird gezeichnet…

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) ​

TopicTypRichtungHinweise
/cmd_velgeometry_msgs/Twisteinvx, vy [m/s], wz [rad/s]; Grenzen 0,30 / 0,15 / 1,0; 0,5 s Timeout → Stehen
/leg_controller/commandsstd_msgs/Float64MultiArrayintern12 Gelenkwinkel [rad] in Go2-Reihenfolge FL, FR, RL, RR × Hüfte, Oberschenkel, Unterschenkel
/joint_statessensor_msgs/JointStateausGo2-Gelenknamen (FL_hip_joint …). Roboter: Winkel, die die MCU nach dem Begrenzen anwendet (Hobby-Servos haben keine Rückmeldung)
/imu/datasensor_msgs/ImuausOrientierung (Mahony auf der MCU), Winkelgeschwindigkeit, Beschleunigung; Frame imu_link; wird nicht veröffentlicht, solange die IMU einen Fehler meldet
/scansensor_msgs/LaserScanausRPLIDAR C1, Frame lidar_link, 10 Hz
/camera/image_rawsensor_msgs/ImageausCamera Module 3 Wide, Frame camera_optical_frame
/battery_statesensor_msgs/BatteryStateausAkkupackspannung + Strom des Logikzweigs (INA260), negativ = Entladen
/odom + TF odom→base_linknav_msgs/OdometryausKoppelnavigation aus der kommandierten Geschwindigkeit (nur gait_node)
/strido/estopstd_msgs/Booleintrue = verriegelter Halt (Servoausgänge aus), false = Freigabe
/strido/relaxstd_msgs/Booleintrue = Servos kraftlos
/strido/facestd_msgs/UInt8einLCD-Gesichtsausdruck
/diagnosticsdiagnostic_msgs/DiagnosticArrayausMCU-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 ​

PfadInhalt
ros2/strido_descriptionURDF/xacro und Meshes aus CAD generiert (strido_cad.models), ros2_control-Controllerkonfiguration, display.launch.py
ros2/strido_bringupgazebo.launch.py, robot.launch.py, Welt, udev-Regeln
ros2/strido_controlgait_node, policy_node, mcu_bridge, walk_smoke
packages/strido-corereiner 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_esp32s3PlatformIO-Firmware; lib/strido_core enthält den portablen Kinematik-/Protokoll-/Sicherheitscode mit nativen Unit-Tests

Starten:

bash
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 RViz

Firmware ​

PlatformIO, Arduino-ESP32 3.x auf dem Seeed XIAO ESP32-S3:

bash
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.

TypNamePayload
0x01JOINT_COMMANDseq u16, mode u8 (0 kraftlos, 1 Position), q[12] f32
0x02SERVO_PULSE_COMMANDseq u16, pulse_us[12] u16 (0 = aus) – nur Kalibrierung
0x03SET_CALIBRATIONjoint u8, direction i8, neutral_us u16, zero_rad f32, min_us u16, max_us u16
0x04SAVE_CALIBRATION–
0x05REQUEST_CALIBRATION– → 12 × CALIBRATION
0x06ESTOPengaged u8
0x07DISPLAYexpression u8, length u8, text
0x81STATE (100 Hz)last seq u16, time_ms u32, flags u8, q[12], quat wxyz[4], gyro[3], accel[3], Bus-V, Strom A (f32)
0x82CALIBRATIONwie SET_CALIBRATION
0x83LOGASCII

Prüfstand-Werkzeug ​

strido-cli (installiert mit packages/strido-core) kommuniziert ohne ROS mit dem Controller:

bash
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/pitch

Raspberry-Pi-Einrichtung ​

  1. Ubuntu Server 24.04 (arm64) oder Raspberry Pi OS Bookworm 64-bit; Docker Engine.
  2. docker compose -f docker/compose.yaml build ros (ROS 2 Jazzy, Gazebo-Bibliotheken, sllidar_ros2 fixiert, die Pakete dieses Repos).
  3. Stromversorgungs- und udev-Konfiguration: siehe electronics.md.
  4. Kamera: Der Kamera-Stack des Pi 5 benötigt den libcamera-Fork von Raspberry Pi; bauen Sie camera_ros auf dem Host dagegen (Raspberry Pi OS liefert ihn mit) oder verwenden Sie rpicam-vid + eine GStreamer-Bridge, und starten Sie dann mit camera:=true (Standard false; das Docker-Image enthält keinen Kamera-Node).

MIT-Lizenz. Mechanik abgeleitet von Yertle (Jerome Graves). CAD, Simulation und native Tests sind kein Hardware-Nachweis – siehe Verifikation.