refactor: clean up all remaining stm32_protocol/mamba_protocol string refs
Update test files, conftest, protocol_defs, docstrings, and inline comments to use the new module names: esp32_protocol and balance_protocol. - saltybot_can_e2e_test tests + conftest: mamba_protocol → balance_protocol - saltybot_bridge tests: stm32_protocol → esp32_protocol - esp32_protocol.py + balance_protocol.py self-referencing comments fixed - jlink_gimbal.py comment updated - test_balance_protocol_invalid_mode_raises (was test_mamba_...) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
34162784ab
commit
40bbf31ba5
@ -39,7 +39,7 @@ import serial
|
||||
from diagnostic_msgs.msg import DiagnosticArray, DiagnosticStatus, KeyValue
|
||||
from std_msgs.msg import String
|
||||
|
||||
from .stm32_protocol import (
|
||||
from .esp32_protocol import (
|
||||
BAUD_RATE,
|
||||
FrameParser,
|
||||
RcChannels,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
"""stm32_protocol.py — Inter-board UART frame codec (ESP32 BALANCE ↔ ESP32 IO).
|
||||
"""esp32_protocol.py — Inter-board UART frame codec (ESP32 BALANCE ↔ ESP32 IO).
|
||||
|
||||
File name retained for import compatibility. This module implements the binary
|
||||
serial protocol that runs between the two ESP32-S3 embedded boards.
|
||||
@ -16,7 +16,7 @@ CRC8 covers: LEN + TYPE + PAYLOAD (polynomial 0x07, init 0x00).
|
||||
Max payload: 64 bytes. No ETX byte.
|
||||
|
||||
Note: the Orin communicates with ESP32 BALANCE via CAN (CANable2/slcan0),
|
||||
NOT via this serial protocol. See mamba_protocol.py for the CAN frame codec.
|
||||
NOT via this serial protocol. See balance_protocol.py for the CAN frame codec.
|
||||
|
||||
Message types — IO → BALANCE:
|
||||
0x01 RC_CHANNELS — raw RC channel values (CRSF or ELRS)
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
"""
|
||||
remote_estop_node.py -- Remote e-stop bridge: MQTT -> STM32 USB CDC
|
||||
remote_estop_node.py -- Remote e-stop bridge: MQTT -> ESP32-S3 IO USB CDC
|
||||
|
||||
{"kill": true} -> writes 'E\n' to STM32 (ESTOP_REMOTE, immediate motor cutoff)
|
||||
{"kill": false} -> writes 'Z\n' to STM32 (clear latch, robot can re-arm)
|
||||
{"kill": true} -> writes 'E\n' to ESP32-S3 IO (ESTOP_REMOTE, immediate motor cutoff)
|
||||
{"kill": false} -> writes 'Z\n' to ESP32-S3 IO (clear latch, robot can re-arm)
|
||||
|
||||
Cellular watchdog: if MQTT link drops for > cellular_timeout_s while in
|
||||
AUTO mode, automatically sends 'F\n' (ESTOP_CELLULAR_TIMEOUT).
|
||||
@ -26,7 +26,7 @@ class RemoteEstopNode(Node):
|
||||
def __init__(self):
|
||||
super().__init__('remote_estop_node')
|
||||
|
||||
self.declare_parameter('serial_port', '/dev/stm32-bridge')
|
||||
self.declare_parameter('serial_port', '/dev/esp32-io')
|
||||
self.declare_parameter('baud_rate', 921600)
|
||||
self.declare_parameter('mqtt_host', 'mqtt.example.com')
|
||||
self.declare_parameter('mqtt_port', 1883)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
"""
|
||||
Unit tests for Jetson→STM32 command serialization logic.
|
||||
Unit tests for Jetson→ESP32-S3 IO command serialization logic.
|
||||
Tests Twist→speed/steer conversion and frame formatting.
|
||||
Run with: pytest jetson/ros2_ws/src/saltybot_bridge/test/test_cmd.py
|
||||
"""
|
||||
|
||||
@ -139,10 +139,10 @@ class TestModeGate:
|
||||
MODE_ASSISTED = 1
|
||||
MODE_AUTONOMOUS = 2
|
||||
|
||||
def _apply_mode_gate(self, stm32_mode, current_speed, current_steer,
|
||||
def _apply_mode_gate(self, balance_mode, current_speed, current_steer,
|
||||
target_speed, target_steer, step=10):
|
||||
"""Mirror of _control_cb mode gate logic."""
|
||||
if stm32_mode != self.MODE_AUTONOMOUS:
|
||||
if balance_mode != self.MODE_AUTONOMOUS:
|
||||
# Reset ramp state, send zero
|
||||
return 0, 0, 0, 0 # (current_speed, current_steer, sent_speed, sent_steer)
|
||||
new_s = _ramp_toward(current_speed, target_speed, step)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
"""
|
||||
Unit tests for STM32 telemetry parsing logic.
|
||||
Unit tests for ESP32-S3 IO telemetry parsing logic.
|
||||
Run with: pytest jetson/ros2_ws/src/saltybot_bridge/test/test_parse.py
|
||||
"""
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
"""test_stm32_cmd_node.py — Unit tests for Stm32CmdNode with mock serial port.
|
||||
"""test_stm32_cmd_node.py — Unit tests for Esp32IoCmdNode with mock serial port.
|
||||
|
||||
Tests:
|
||||
- Serial open/close lifecycle
|
||||
@ -12,7 +12,7 @@ Tests:
|
||||
- Zero-speed sent on node shutdown
|
||||
- CRC errors counted correctly
|
||||
|
||||
Run with: pytest test/test_stm32_cmd_node.py -v
|
||||
Run with: pytest test/test_stm32_cmd_node.py -v # (file name kept for history)
|
||||
No ROS2 runtime required — uses mock Node infrastructure.
|
||||
"""
|
||||
|
||||
@ -29,7 +29,7 @@ import pytest
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
from saltybot_bridge.stm32_protocol import (
|
||||
from saltybot_bridge.esp32_protocol import (
|
||||
STX, ETX, CmdType, TelType,
|
||||
encode_speed_steer, encode_heartbeat, encode_arm, encode_pid_update,
|
||||
_build_frame, _crc16_ccitt,
|
||||
@ -219,10 +219,10 @@ class TestMockSerialTX:
|
||||
class TestMockSerialRX:
|
||||
"""Test RX parsing path using MockSerial with pre-loaded telemetry data."""
|
||||
|
||||
from saltybot_bridge.stm32_protocol import FrameParser
|
||||
from saltybot_bridge.esp32_protocol import FrameParser
|
||||
|
||||
def test_rx_imu_frame(self):
|
||||
from saltybot_bridge.stm32_protocol import FrameParser, ImuFrame
|
||||
from saltybot_bridge.esp32_protocol import FrameParser, ImuFrame
|
||||
raw = _imu_frame_bytes(pitch=500, roll=-200, yaw=100, ax=0, ay=0, az=981)
|
||||
ms = MockSerial(rx_data=raw)
|
||||
parser = FrameParser()
|
||||
@ -241,7 +241,7 @@ class TestMockSerialRX:
|
||||
assert f.accel_z == pytest.approx(9.81)
|
||||
|
||||
def test_rx_battery_frame(self):
|
||||
from saltybot_bridge.stm32_protocol import FrameParser, BatteryFrame
|
||||
from saltybot_bridge.esp32_protocol import FrameParser, BatteryFrame
|
||||
raw = _battery_frame_bytes(v_mv=10500, i_ma=1200, soc=45)
|
||||
ms = MockSerial(rx_data=raw)
|
||||
parser = FrameParser()
|
||||
@ -257,7 +257,7 @@ class TestMockSerialRX:
|
||||
assert f.soc_pct == 45
|
||||
|
||||
def test_rx_multiple_frames_in_one_read(self):
|
||||
from saltybot_bridge.stm32_protocol import FrameParser
|
||||
from saltybot_bridge.esp32_protocol import FrameParser
|
||||
raw = (_imu_frame_bytes() + _arm_state_frame_bytes() + _battery_frame_bytes())
|
||||
ms = MockSerial(rx_data=raw)
|
||||
parser = FrameParser()
|
||||
@ -271,7 +271,7 @@ class TestMockSerialRX:
|
||||
assert parser.frames_error == 0
|
||||
|
||||
def test_rx_bad_crc_counted_as_error(self):
|
||||
from saltybot_bridge.stm32_protocol import FrameParser
|
||||
from saltybot_bridge.esp32_protocol import FrameParser
|
||||
raw = bytearray(_arm_state_frame_bytes(state=1))
|
||||
raw[-3] ^= 0xFF # corrupt CRC
|
||||
ms = MockSerial(rx_data=bytes(raw))
|
||||
@ -282,7 +282,7 @@ class TestMockSerialRX:
|
||||
assert parser.frames_error == 1
|
||||
|
||||
def test_rx_resync_after_corrupt_byte(self):
|
||||
from saltybot_bridge.stm32_protocol import FrameParser, ArmStateFrame
|
||||
from saltybot_bridge.esp32_protocol import FrameParser, ArmStateFrame
|
||||
garbage = b"\xDE\xAD\x00\x00"
|
||||
valid = _arm_state_frame_bytes(state=1)
|
||||
ms = MockSerial(rx_data=garbage + valid)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
"""test_stm32_protocol.py — Unit tests for binary STM32 frame codec.
|
||||
"""test_esp32_protocol.py — Unit tests for binary STM32 frame codec.
|
||||
|
||||
Tests:
|
||||
- CRC16-CCITT correctness
|
||||
@ -12,7 +12,7 @@ Tests:
|
||||
- Speed/steer clamping in encode_speed_steer
|
||||
- Round-trip encode → decode for all known telemetry types
|
||||
|
||||
Run with: pytest test/test_stm32_protocol.py -v
|
||||
Run with: pytest test/test_esp32_protocol.py -v
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@ -25,7 +25,7 @@ import os
|
||||
# ── Path setup (no ROS2 install needed) ──────────────────────────────────────
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
from saltybot_bridge.stm32_protocol import (
|
||||
from saltybot_bridge.esp32_protocol import (
|
||||
STX, ETX,
|
||||
CmdType, TelType,
|
||||
ImuFrame, BatteryFrame, MotorRpmFrame, ArmStateFrame, ErrorFrame,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Unit tests for saltybot_can_bridge.mamba_protocol.
|
||||
Unit tests for saltybot_can_bridge.balance_protocol.
|
||||
|
||||
No ROS2 or CAN hardware required — tests exercise encode/decode round-trips
|
||||
and boundary conditions entirely in Python.
|
||||
@ -11,7 +11,7 @@ Run with: pytest test/test_can_bridge.py -v
|
||||
import struct
|
||||
import unittest
|
||||
|
||||
from saltybot_can_bridge.mamba_protocol import (
|
||||
from saltybot_can_bridge.balance_protocol import (
|
||||
MAMBA_CMD_ESTOP,
|
||||
MAMBA_CMD_MODE,
|
||||
MAMBA_CMD_VELOCITY,
|
||||
|
||||
@ -6,7 +6,7 @@ Orin↔Mamba↔VESC integration test suite.
|
||||
All IDs and payload formats are derived from:
|
||||
include/orin_can.h — Orin↔FC (Mamba) protocol
|
||||
include/vesc_can.h — VESC CAN protocol
|
||||
saltybot_can_bridge/mamba_protocol.py — existing bridge constants
|
||||
saltybot_can_bridge/balance_protocol.py — existing bridge constants
|
||||
|
||||
CAN IDs used in tests
|
||||
---------------------
|
||||
@ -22,7 +22,7 @@ FC (Mamba) → Orin telemetry (standard 11-bit, matching orin_can.h):
|
||||
FC_IMU 0x402 8 bytes
|
||||
FC_BARO 0x403 8 bytes
|
||||
|
||||
Mamba ↔ VESC internal commands (matching mamba_protocol.py):
|
||||
Mamba ↔ VESC internal commands (matching balance_protocol.py):
|
||||
MAMBA_CMD_VELOCITY 0x100 8 bytes left_mps (f32) | right_mps (f32) big-endian
|
||||
MAMBA_CMD_MODE 0x101 1 byte mode (0=idle,1=drive,2=estop)
|
||||
MAMBA_CMD_ESTOP 0x102 1 byte 0x01=stop
|
||||
@ -54,7 +54,7 @@ FC_IMU: int = 0x402
|
||||
FC_BARO: int = 0x403
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Mamba → VESC internal command IDs (from mamba_protocol.py)
|
||||
# Mamba → VESC internal command IDs (from balance_protocol.py)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
MAMBA_CMD_VELOCITY: int = 0x100
|
||||
@ -136,14 +136,14 @@ def build_estop_cmd(action: int = 1) -> bytes:
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Frame builders — Mamba velocity commands (mamba_protocol.py encoding)
|
||||
# Frame builders — Mamba velocity commands (balance_protocol.py encoding)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def build_velocity_cmd(left_mps: float, right_mps: float) -> bytes:
|
||||
"""
|
||||
Build a MAMBA_CMD_VELOCITY payload (8 bytes, 2 × float32 big-endian).
|
||||
|
||||
Matches encode_velocity_cmd() in mamba_protocol.py.
|
||||
Matches encode_velocity_cmd() in balance_protocol.py.
|
||||
"""
|
||||
return struct.pack(">ff", float(left_mps), float(right_mps))
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ _pkg_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
if _pkg_root not in sys.path:
|
||||
sys.path.insert(0, _pkg_root)
|
||||
|
||||
# Also add the saltybot_can_bridge package so we can import mamba_protocol.
|
||||
# Also add the saltybot_can_bridge package so we can import balance_protocol.
|
||||
_bridge_pkg = os.path.join(
|
||||
os.path.dirname(_pkg_root), "saltybot_can_bridge"
|
||||
)
|
||||
@ -60,7 +60,7 @@ def loopback_can_bus():
|
||||
@pytest.fixture(scope="function")
|
||||
def bridge_components():
|
||||
"""
|
||||
Return the mamba_protocol encode/decode callables and a fresh mock bus.
|
||||
Return the balance_protocol encode/decode callables and a fresh mock bus.
|
||||
|
||||
Yields a dict with keys:
|
||||
bus — MockCANBus instance
|
||||
@ -69,7 +69,7 @@ def bridge_components():
|
||||
encode_estop — encode_estop_cmd(stop) → bytes
|
||||
decode_vesc — decode_vesc_state(data) → VescStateTelemetry
|
||||
"""
|
||||
from saltybot_can_bridge.mamba_protocol import (
|
||||
from saltybot_can_bridge.balance_protocol import (
|
||||
encode_velocity_cmd,
|
||||
encode_mode_cmd,
|
||||
encode_estop_cmd,
|
||||
|
||||
@ -28,7 +28,7 @@ from saltybot_can_e2e_test.protocol_defs import (
|
||||
parse_velocity_cmd,
|
||||
parse_fc_vesc,
|
||||
)
|
||||
from saltybot_can_bridge.mamba_protocol import (
|
||||
from saltybot_can_bridge.balance_protocol import (
|
||||
encode_velocity_cmd,
|
||||
encode_mode_cmd,
|
||||
)
|
||||
|
||||
@ -32,7 +32,7 @@ from saltybot_can_e2e_test.protocol_defs import (
|
||||
parse_velocity_cmd,
|
||||
parse_fc_status,
|
||||
)
|
||||
from saltybot_can_bridge.mamba_protocol import (
|
||||
from saltybot_can_bridge.balance_protocol import (
|
||||
encode_velocity_cmd,
|
||||
encode_mode_cmd,
|
||||
encode_estop_cmd,
|
||||
|
||||
@ -30,7 +30,7 @@ from saltybot_can_e2e_test.protocol_defs import (
|
||||
parse_fc_vesc,
|
||||
parse_vesc_status,
|
||||
)
|
||||
from saltybot_can_bridge.mamba_protocol import (
|
||||
from saltybot_can_bridge.balance_protocol import (
|
||||
VESC_TELEM_STATE as BRIDGE_VESC_TELEM_STATE,
|
||||
decode_vesc_state,
|
||||
)
|
||||
|
||||
@ -33,7 +33,7 @@ from saltybot_can_e2e_test.protocol_defs import (
|
||||
build_velocity_cmd,
|
||||
parse_velocity_cmd,
|
||||
)
|
||||
from saltybot_can_bridge.mamba_protocol import (
|
||||
from saltybot_can_bridge.balance_protocol import (
|
||||
encode_velocity_cmd,
|
||||
encode_mode_cmd,
|
||||
encode_estop_cmd,
|
||||
|
||||
@ -27,7 +27,7 @@ from saltybot_can_e2e_test.protocol_defs import (
|
||||
build_velocity_cmd,
|
||||
parse_velocity_cmd,
|
||||
)
|
||||
from saltybot_can_bridge.mamba_protocol import (
|
||||
from saltybot_can_bridge.balance_protocol import (
|
||||
encode_velocity_cmd,
|
||||
encode_mode_cmd,
|
||||
encode_estop_cmd,
|
||||
@ -189,7 +189,7 @@ class TestModeCommandEncoding:
|
||||
"""build_mode_cmd in protocol_defs must produce identical bytes."""
|
||||
for mode in (MODE_IDLE, MODE_DRIVE, MODE_ESTOP):
|
||||
assert build_mode_cmd(mode) == encode_mode_cmd(mode), \
|
||||
f"protocol_defs.build_mode_cmd({mode}) != mamba_protocol.encode_mode_cmd({mode})"
|
||||
f"protocol_defs.build_mode_cmd({mode}) != balance_protocol.encode_mode_cmd({mode})"
|
||||
|
||||
|
||||
class TestInvalidMode:
|
||||
@ -218,8 +218,8 @@ class TestInvalidMode:
|
||||
accepted = sm.set_mode(-1)
|
||||
assert accepted is False
|
||||
|
||||
def test_mamba_protocol_invalid_mode_raises(self):
|
||||
"""mamba_protocol.encode_mode_cmd must raise on invalid mode."""
|
||||
def test_balance_protocol_invalid_mode_raises(self):
|
||||
"""balance_protocol.encode_mode_cmd must raise on invalid mode."""
|
||||
with pytest.raises(ValueError):
|
||||
encode_mode_cmd(99)
|
||||
with pytest.raises(ValueError):
|
||||
|
||||
@ -13,7 +13,7 @@ Telemetry type (STM32 → Jetson):
|
||||
uint16 pan_speed_raw + uint16 tilt_speed_raw +
|
||||
uint8 torque_en + uint8 rx_err_pct (10 bytes)
|
||||
|
||||
Frame format (shared with stm32_protocol.py):
|
||||
Frame format (shared with esp32_protocol.py):
|
||||
[STX=0x02][CMD][LEN][PAYLOAD...][CRC16_hi][CRC16_lo][ETX=0x03]
|
||||
CRC16-CCITT: poly=0x1021, init=0xFFFF, covers CMD+LEN+PAYLOAD bytes.
|
||||
"""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user