|
|
f66035cf81
|
feat(arch): align CAN/UART bridges with SAUL-TEE-SYSTEM-REFERENCE.md spec
Update CAN and serial bridge code to match authoritative protocol spec
from docs/SAUL-TEE-SYSTEM-REFERENCE.md §5-6 (hal, 2026-04-04).
mamba_protocol.py (CAN, Orin ↔ ESP32 BALANCE):
- 0x300 DRIVE: [speed:i16][steer:i16][mode:u8][flags:u8][_:u16] — combined frame
- 0x301 ARM: [arm:u8]
- 0x302 PID: [kp:f16][ki:f16][kd:f16][_:u16] — half-float gains
- 0x303 ESTOP: [0xE5] — magic byte cut
- 0x400 ATTITUDE: [pitch:f16][speed:f16][yaw_rate:f16][state:u8][flags:u8]
- 0x401 BATTERY: [vbat_mv:u16][fault_code:u8][rssi:i8]
- Add VESC STATUS1/4/5 decode helpers; VESC IDs 56 (left) / 68 (right)
can_bridge_node.py:
- /cmd_vel → encode_drive_cmd (speed/steer int16, MODE_DRIVE)
- /estop → encode_estop_cmd (magic 0xE5); clear → DISARM
- /saltybot/arm → encode_arm_cmd (new subscription)
- Watchdog sends DRIVE(0,0,MODE_IDLE) when /cmd_vel silent
- ATTITUDE (0x400) → /saltybot/attitude + /saltybot/balance_state JSON
- BATTERY (0x401) → /can/battery BatteryState
- VESC STATUS1 frames → /can/vesc/left|right/state
stm32_cmd_node.py — rewritten for inter-board protocol API:
- Imports from updated stm32_protocol (BAUD_RATE=460800, new frame types)
- RX: RcChannels → /saltybot/rc_channels, SensorData → /saltybot/sensors
- TX: encode_led_cmd, encode_output_cmd from /saltybot/leds + /saltybot/outputs
- HEARTBEAT (0x20) timer replaces old SPEED_STEER/ARM logic
stm32_cmd_params.yaml: serial_port=/dev/esp32-io, baud=460800
stm32_cmd.launch.py: updated defaults and description
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-04-04 08:32:00 -04:00 |
|
|
|
30be0d8cd3
|
feat(bridge): binary STM32 command protocol (Issue #119)
Add stm32_protocol.py — pure-Python binary frame codec:
- Frame: STX(0x02)+TYPE+LEN+PAYLOAD+CRC16-CCITT(BE)+ETX(0x03)
- CRC covers TYPE+LEN+PAYLOAD; polynomial 0x1021, init 0xFFFF
- Encoders: HEARTBEAT, SPEED_STEER(-1000..+1000 int16), ARM, SET_MODE, PID_UPDATE
- Telemetry decoders: ImuFrame, BatteryFrame, MotorRpmFrame, ArmStateFrame, ErrorFrame
- FrameParser: streaming byte-by-byte state machine, resync on corrupt data
Add stm32_cmd_node.py — ROS2 bidirectional bridge node:
- /cmd_vel → SPEED_STEER at up to 50 Hz
- HEARTBEAT timer (default 200ms); STM32 watchdog fires at 500ms
- Jetson-side watchdog: no /cmd_vel for 500ms → send SPEED_STEER(0,0)
- /saltybot/arm service (SetBool) → ARM frame
- /saltybot/pid_update topic → PID_UPDATE frame
- Telemetry RX: IMU→/saltybot/imu, BATTERY→/saltybot/telemetry/battery,
MOTOR_RPM→/saltybot/telemetry/motor_rpm, ARM_STATE→/saltybot/arm_state,
ERROR→/saltybot/error
- Auto-reconnect on USB disconnect (serial.SerialException caught)
- Zero-speed + disarm sent on node shutdown
- /diagnostics with serial health, frame counts, last cmd age
Add test_stm32_protocol.py (60+ tests):
- CRC16-CCITT correctness, known test vectors
- All encoder output structures and payload values
- FrameParser: all telemetry types, bad CRC, bad ETX, resync, streaming,
oversized payload, frame counters, reset
Add test_stm32_cmd_node.py (30+ tests):
- MockSerial: TX/RX byte-level testing without hardware
- Speed/steer clamping, scaling, frame structure
- Watchdog fires/doesn't fire relative to timeout
- CRC error counted, resync after garbage
Add stm32_cmd_params.yaml, stm32_cmd.launch.py.
Update package.xml (add std_srvs, geometry_msgs deps).
Update setup.py (add stm32_cmd_node entry point + new config/launch).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
2026-03-02 09:17:04 -05:00 |
|