c297d24a48
Merge pull request 'fix: Rename sultee-tracker → saul-tee-tracker' ( #724 ) from sl-webui/fix-tracker-rename into main
2026-04-04 11:23:02 -04:00
885a66f24b
Merge pull request 'feat: MQTT bridge for iOS GPS on /saltybot/ios/gps (Issue #681 )' ( #723 ) from sl-jetson/issue-681-ios-gps-bridge into main
2026-04-04 11:21:14 -04:00
fbc88f5c2a
fix: correct rclpy logger calls to use f-strings (pre-existing bugs)
...
rclpy RcutilsLogger.info/warning/debug() do not accept printf-style
positional format args. Also fix p["use_phone_timestamp"] → p["use_phone_ts"]
key mismatch in __init__ log line.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 11:20:58 -04:00
0122957b6b
feat: Add iOS phone GPS MQTT-to-ROS2 bridge topic (Issue #681 )
...
- Add _TOPIC_IOS_GPS = 'saltybot/ios/gps' constant
- Subscribe to saltybot/ios/gps in _on_mqtt_connect
- Dispatch to _handle_ios_gps() in _dispatch()
- _handle_ios_gps(): same logic as _handle_gps(), frame_id='ios_gps',
publishes to /saltybot/ios/gps via self._ios_gps_pub
- Add rx/pub/err/last_rx_ts counters for the new topic
- Add /saltybot/ios/gps to rosbridge_params.yaml topics_glob
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 11:20:58 -04:00
759277a7e0
fix: Rename sultee-tracker to saul-tee-tracker (typo fix)
2026-04-04 11:19:35 -04:00
b1e8da4403
Merge pull request 'feat: iOS phone GPS via rosbridge topic /saltybot/ios/gps (Issue #681 )' ( #722 ) from sl-webui/issue-681-ios-gps-rosbridge into main
2026-04-04 11:15:13 -04:00
dd8afb480f
Merge pull request 'fix: add phone bridge and GPS topics to rosbridge whitelist (Issue #681 )' ( #721 ) from sl-webui/issue-681-fix-gps-topics into main
2026-04-04 11:15:12 -04:00
43fb3f1147
feat: Route iOS phone GPS through rosbridge instead of raw WebSocket (Issue #681 )
2026-04-04 11:11:15 -04:00
416a393134
fix: correct delay_between_messages type to float in rosbridge_params
...
rclpy expects DOUBLE for this param; integer 0 raises InvalidParameterTypeException.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 10:58:09 -04:00
60f500c206
fix: add phone bridge and GPS topics to rosbridge whitelist (Issue #681 )
...
Add /saltybot/phone/gps, /saltybot/phone/imu, /saltybot/phone/battery,
/saltybot/phone/bridge/status, /gps/fix, /gps/vel to topics_glob so
the browser GPS dashboard can receive phone-bridged GPS data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 10:56:06 -04:00
b1cd15327f
Merge pull request 'fix: GPS tracker subscribes to correct phone bridge topic (Issue #681 )' ( #720 ) from sl-webui/issue-681-fix-gps-topics into main
2026-04-04 10:07:10 -04:00
b72e435bf3
fix: Update tracker GPS topic to match phone bridge (Issue #681 )
2026-04-04 10:01:57 -04:00
9cf98830c6
Merge pull request 'feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only' ( #715 ) from sl-firmware/cleanup-legacy-hw into main
2026-04-04 09:00:55 -04:00
a1233dbd04
fix: scrub remaining Mamba references in can_bridge and e2e test protocol files
...
- balance_protocol.py: Mamba→Orin / Mamba→VESC comments → ESP32-S3 BALANCE
- can_bridge_node.py: docstring and inline comments
- __init__.py: package description
- protocol_defs.py: all Mamba references in docstring and comments
- test_fc_vesc_broadcast.py, test_drive_command.py: test comments
Zero Mamba/STM32F722/BlackPill/stm32_protocol/mamba_protocol references
now exist outside legacy/stm32/.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 09:00:44 -04:00
fa75c442a7
feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only
...
Archive STM32 firmware to legacy/stm32/:
- src/, include/, lib/USB_CDC/, platformio.ini, test stubs, flash_firmware.py
- test/test_battery_adc.c, test_hw_button.c, test_pid_schedule.c, test_vesc_can.c, test_can_watchdog.c
- USB_CDC_BUG.md
Rename: stm32_protocol → esp32_protocol, mamba_protocol → balance_protocol,
stm32_cmd_node → esp32_cmd_node, stm32_cmd_params → esp32_cmd_params,
stm32_cmd.launch.py → esp32_cmd.launch.py,
test_stm32_protocol → test_esp32_protocol, test_stm32_cmd_node → test_esp32_cmd_node
Content cleanup across all files:
- Mamba F722S → ESP32-S3 BALANCE
- BlackPill → ESP32-S3 IO
- STM32F722/F7xx → ESP32-S3
- stm32Mode/Version/Port → esp32Mode/Version/Port
- STM32 State/Mode labels → ESP32 State/Mode
- Jetson Nano → Jetson Orin Nano Super
- /dev/stm32 → /dev/esp32
- stm32_bridge → esp32_bridge
- STM32 HAL → ESP-IDF
docs/SALTYLAB.md:
- Update "Drone FC Details" to describe ESP32-S3 BALANCE board (Waveshare ESP32-S3 Touch LCD 1.28)
- Replace verbose "Self-Balancing Control" STM32 section with brief note pointing to SAUL-TEE-SYSTEM-REFERENCE.md
TEAM.md: Update Embedded Firmware Engineer role to ESP32-S3 / ESP-IDF
No new functionality — cleanup only.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 09:00:38 -04:00
fe84ff6039
Merge pull request 'feat(arch): CAN/UART bridge update for SAUL-TEE ESP32 architecture' ( #714 ) from sl-controls/esp32-can-bridge-update into main
2026-04-04 09:00:10 -04:00
fda6ab99ff
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:59:45 -04:00
308be74330
feat(arch): implement SAUL-TEE ESP32 protocol specs from hal reference doc
...
Spec source: docs/SAUL-TEE-SYSTEM-REFERENCE.md (hal, 2026-04-04)
stm32_protocol.py — rewritten for inter-board UART protocol (ESP32 BALANCE ↔ IO):
- Frame: [0xAA][LEN][TYPE][PAYLOAD][CRC8] @ 460800 baud (was STX/ETX/CRC16)
- CRC-8 poly 0x07 over LEN+TYPE+PAYLOAD
- New message types: RC_CHANNELS(0x01), SENSORS(0x02), LED_CMD(0x10),
OUTPUT_CMD(0x11), MOTOR_CMD(0x12), HEARTBEAT(0x20)
mamba_protocol.py — updated CAN IDs and frame formats:
- Orin→BALANCE: DRIVE(0x300) f32×2 LE, MODE(0x301), ESTOP(0x302), LED(0x303)
- BALANCE→Orin: FC_STATUS(0x400) pitch/vbat/state, FC_VESC(0x401) rpm/current
- VESC node IDs: Left=56, Right=68 (authoritative per §8)
- VESC extended frames: STATUS1(cmd=9), STATUS4(cmd=16), STATUS5(cmd=27)
- Replaced old MAMBA_CMD_*/MAMBA_TELEM_* constants
can_bridge_node.py — updated to use new IDs:
- ORIN_CMD_DRIVE/MODE/ESTOP replace MAMBA_CMD_VELOCITY/MODE/ESTOP
- FC_STATUS handler: publishes pitch→/can/imu, vbat_mv→/can/battery
- FC_VESC handler: publishes rpm/cur→/can/vesc/left|right/state
- VESC STATUS1 extended frames decoded per node ID (56/68)
- Removed PID CAN command (not in new spec)
CLAUDE.md — updated with ESP32-S3 BALANCE/IO hardware summary + key protocols
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:59:28 -04:00
19be6bbe11
Merge pull request 'docs: SAUL-TEE full ESP32-S3 system reference (arch migration)' ( #712 ) from sl-firmware/arch-esp32-migration into main
2026-04-04 08:57:11 -04:00
5ef1f7e365
docs: full SAUL-TEE ESP32-S3 spec — pins, CAN, UART, RC mapping
...
Complete hardware reference from hal@Orin spec (2026-04-04):
- docs/SAUL-TEE-SYSTEM-REFERENCE.md: authoritative pin/protocol/CAN reference
ESP32-S3 BALANCE: QMI8658 SPI(IO38-42), GC9A01 LCD, SN65HVD230 CAN(IO43/44),
inter-board UART(IO17/18)
ESP32-S3 IO: Crossfire UART0(IO43/44), ELRS UART2(IO16/17), BTS7960(IO1-8),
I2C(IO11/12), WS2812(IO13), buzzer/headlight/fan, arming btn, kill-sw, UART(IO18/21)
- Inter-board binary protocol: [0xAA][LEN][TYPE][PAYLOAD][CRC8] @ 460800 baud
- CAN: VESC L=68, R=56; Orin cmds 0x300-0x303; telemetry 0x400-0x401 @ 10Hz
- RC: CH5=ARM, CH6=ESTOP, CH7=speed-limit; CRSF loss >100ms = motors cut
- CLAUDE.md, TEAM.md, docs/AGENTS.md, docs/SALTYLAB.md updated with full spec
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:25:24 -04:00
bfca6d1d92
docs: Add SAUL-TEE system reference + update wiring diagram
...
- docs/SAUL-TEE-SYSTEM-REFERENCE.md: authoritative architecture doc for
the new 4-wheel wagon. Covers ESP32-S3 BALANCE (Waveshare LCD 1.28,
QMI8658, SN65HVD230 CAN), ESP32-S3 IO (TBS Crossfire, ELRS, BTS7960,
NFC/baro/ToF, WS2812), inter-board UART protocol (460800 baud,
[0xAA][len][type][payload][crc8]), CAN IDs (VESCs 68/56, Orin
0x300-0x303 cmd / 0x400-0x401 telemetry), RC channel map, power
architecture, safety systems, and firmware layout.
- docs/wiring-diagram.md: banner pointing to new reference doc;
old Mamba F722S UART summary marked OBSOLETE.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:25:24 -04:00
f71dad5344
feat(arch): migrate all STM32/Mamba/BlackPill refs to ESP32 BALANCE/IO + fix roslib@1.4.0
...
Architecture change (2026-04-03): Mamba F722S (STM32F722) and BlackPill
replaced by ESP32 BALANCE (PID loop) and ESP32 IO (motors/sensors/comms).
- Update CLAUDE.md, docs, chassis BOM/ASSEMBLY, pinout, power-budget,
wiring-diagram, TEAM.md, AUTONOMOUS_ARMING.md, docker-compose
- Update all ROS2 package comments, config labels, launch args
(stm32_port→esp32_port, /dev/stm32-bridge→/dev/esp32-bridge)
- Update WebUI: stm32Mode→esp32Mode, stm32Version→esp32Version,
"STM32 State/Mode" labels → "ESP32 State/Mode" (ControlMode, SettingsPanel)
- Add TODO(esp32-migration) markers on stm32_protocol.py and mamba_protocol.py
binary frame layouts — pending ESP32 protocol spec from max
- Fix roslib CDN 1.3.0→1.4.0 in all 11 HTML panels (fixes ROS2 Humble
rosbridge "Received a message without an op" incompatibility)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:25:24 -04:00
5e97676703
docs: Update chassis docs for ESP32 architecture (retire Mamba F722S)
...
Replace Mamba F722S / STM32F722 references in BOM.md and ASSEMBLY.md
with ESP32 BALANCE + ESP32 IO. Board dimensions marked TBD pending
spec from max.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:25:24 -04:00
30b0f245e1
docs: retire Mamba F722S/BlackPill, adopt ESP32 BALANCE + ESP32 IO architecture
...
Effective 2026-04-03: STM32F722 flight controller no longer used.
New architecture:
- ESP32 BALANCE: PID balance loop
- ESP32 IO: motors, sensors, comms
Updated: CLAUDE.md, TEAM.md, docs/AGENTS.md, docs/SALTYLAB.md
Legacy src/ STM32 firmware is archived — not extended.
Source code migration pending ESP32 hardware spec from max.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:25:24 -04:00
7db6158ada
Merge pull request 'feat: Robot GPS live map panel (Issue #709 companion)' ( #711 ) from sl-webui/robot-gps-map into main
2026-04-03 22:43:56 -04:00
f0d9fead74
Merge pull request 'feat: Sul-Tee GPS live tracking dashboard (Issue #709 )' ( #710 ) from sl-webui/issue-709-gps-tracker into main
2026-04-03 22:43:55 -04:00
811a2ccc5c
fix(sultee-tracker): subscribe to proper ROS GPS topics for robot marker
...
Switch robot GPS subscription from custom saltybot/gps/* std_msgs/String
topics to the canonical /gps/fix (sensor_msgs/NavSatFix) and /gps/vel
(geometry_msgs/TwistStamped) published by the SIM7600X GPS driver node.
- /gps/fix: read msg.latitude/longitude/altitude/status.status directly
- /gps/vel: compute speed (sqrt(vx²+vy²) * 3.6 km/h) and heading
(angular.z radians → degrees) from ENU velocity components
Closes #709
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 22:41:47 -04:00
bb354336c3
feat(sultee-tracker): add dual device map — phone (blue) + robot (orange)
...
Previously showed only phone GPS. Now also subscribes via ROSLIB to
saltybot/gps/fix + saltybot/gps/vel on the same rosbridge URL for
robot (SAUL-TEE) position. Blue marker+trail for phone (raw WS
{type:gps}), orange marker+trail for robot (ROS topics). Sidebar shows
phone speed/alt/heading/accuracy + robot lat/lon/speed + distance
between the two. FIT ALL button auto-zooms to show both. Status bar
badges for phone staleness and robot fix/vel freshness.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 22:38:28 -04:00
6d047ca50c
feat(gps-map): add phone/user GPS as second marker on robot GPS map
...
Subscribes to saltybot/phone/gps (JSON: {ts, lat, lon, alt_m,
accuracy_m, speed_ms, bearing_deg, provider}) and renders a blue
Leaflet marker + blue breadcrumb trail alongside the robot's
orange/cyan marker. Status bar now shows PHONE badge with stale
detection. Sidebar adds phone lat/lon/speed/accuracy/provider section.
Clear button resets both trails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 22:34:44 -04:00
f384cc4810
feat: Robot GPS live map panel (Issue #709 companion)
...
Adds gps_map_panel.html/css/js — standalone dashboard panel:
- Leaflet.js + OpenStreetMap with dark CSS filter (matches dashboard theme)
- Heading-aware SVG robot marker (orange arrow shows direction of travel)
- Orange breadcrumb trail polyline (up to 2000 pts, CLEAR button)
- FOLLOW mode auto-pan; drag map to switch to FREE mode
- Sidebar: speed (km/h, color-coded), altitude, heading compass rose,
fix status (0=NO FIX…4=RTK), fix count, lat/lon, trail log
- Exponential backoff auto-reconnect (2s→30s cap)
- Stale detection at 5s for fix + velocity badges
Subscribes via rosbridge to:
saltybot/gps/fix std_msgs/String JSON — {lat, lon, alt, stat, t}
saltybot/gps/vel std_msgs/String JSON — {spd, hdg, t}
index.html: new GPS MAP card (🛰️ , #709 ) before CAN MONITOR
dashboard.js: gpsWatch subscription + 'gps' panel entry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 22:28:44 -04:00
2560718b39
feat: Sul-Tee GPS live tracking dashboard (Issue #709 )
...
Single-file vanilla JS dashboard at ui/sultee-tracker.html:
- Connects to ws://100.64.0.2:9090 (configurable, saved in localStorage)
- Parses {"type":"gps","data":{...},"timestamp":...} JSON frames from iPhone
- Leaflet.js + OpenStreetMap tiles with dark CSS filter
- Live position marker (cyan pulsing dot SVG icon)
- Orange polyline trail (up to 2000 points)
- Auto-centers on first GPS fix; FOLLOW/FREE toggle; drag disables follow
- Sidebar: speed (km/h, color-coded), altitude, heading, compass rose canvas,
h-accuracy bar (green/amber/red), coordinate display, fix count
- Scrollable trail log with timestamp + coords + speed per fix
- Exponential backoff auto-reconnect (2s→30s cap)
- CLEAR button resets trail, marker, log, fix count
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 18:12:37 -04:00
e220797c07
Merge pull request 'feat: CAN bus watchdog and error recovery (Issue #694 )' ( #708 ) from sl-firmware/issue-694-can-watchdog into main
2026-03-20 17:59:02 -04:00
b5354e1ac0
Merge pull request 'feat: PID tuning interface via CAN/ROS2 (Issue #693 )' ( #707 ) from sl-controls/issue-693-pid-tuning into main
2026-03-20 17:58:34 -04:00
f59bc9931e
feat: CAN bus watchdog and error recovery (Issue #694 )
...
- CAN1_SCE_IRQHandler: detects bus-off/error-passive/error-warning from ESR
- can_driver_watchdog_tick(): polls ESR each cycle, auto-restarts after CAN_WDOG_RESTART_MS (200ms)
- can_wdog_t: tracks restart_count, busoff_count, errpassive_count, errwarn_count, tec, rec
- JLink TLM code 0x8F (JLINK_TLM_CAN_WDOG) with jlink_send_can_wdog_tlm()
- main.c: calls watchdog_tick() each loop, sends CAN wdog TLM at 1 Hz
- TEST_HOST: inject_esr() stub + busoff_pending flag fixes t=0 sentinel ambiguity
- test/test_can_watchdog.c: 23 unit tests, all pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:39:01 -04:00
de4d1bbe3a
feat: PID tuning interface via CAN/ROS2 (Issue #693 )
...
- Mamba (STM32): add ORIN_CAN_ID_PID_SET (0x305) handler in orin_can.c.
Receives kp/ki/kd as uint16*100 (BE), applies to running balance loop,
replies with FC_PID_ACK (0x405) echoing clamped gains. Gains persist in
RAM until reboot; not saved to flash.
- Jetson: expose pid/kp, pid/ki, pid/kd as ROS2 parameters in
can_bridge_node. Parameter changes trigger encode_pid_set_cmd() and
send CAN frame 0x305 immediately. ACK frame 0x405 logged at DEBUG.
- mamba_protocol.py: add ORIN_CAN_ID_PID_SET / FC_PID_ACK IDs,
PidGains dataclass, encode_pid_set_cmd(), decode_pid_ack().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:39:00 -04:00
d235c414e0
Merge pull request 'feat: SLAM map persistence for AMCL (Issue #696 )' ( #705 ) from sl-perception/issue-696-slam-map-persistence into main
2026-03-20 17:38:29 -04:00
62d7525df7
Merge pull request 'feat: VESC dual ESC mount bracket for T-slot (Issue #699 )' ( #704 ) from sl-mechanical/issue-699-vesc-mount into main
2026-03-20 17:38:27 -04:00
2b3f3584a9
Merge pull request 'feat: End-to-end CAN integration tests (Issue #695 )' ( #703 ) from sl-jetson/issue-695-can-e2e-test into main
2026-03-20 17:38:25 -04:00
7a100b2d14
Merge pull request 'feat: WebSocket bridge for CAN monitor dashboard (Issue #697 )' ( #702 ) from sl-webui/issue-697-websocket-bridge into main
2026-03-20 17:38:23 -04:00
37b646780d
Merge pull request 'feat: Android BLE pairing UI for UWB tag (Issue #700 )' ( #701 ) from sl-android/issue-700-ble-pairing-ui into main
2026-03-20 17:38:22 -04:00
2d60aab79c
feat: SLAM map persistence for AMCL (Issue #696 )
...
- New map_persistence.launch.py: launches map_saver_server lifecycle node
(nav2_map_server) + saltybot_map_saver helper node + lifecycle_manager.
Configurable map_dir (default /mnt/nvme/saltybot/maps) and map_name.
- New map_saver_node.py: ROS2 node providing /saltybot/save_map (Trigger
service) that calls nav2_map_server map_saver_cli. On startup logs whether
a saved map is present. Auto-saves map on shutdown (auto_save_on_shutdown).
- New config/map_saver_params.yaml: map_saver_server params
(save_map_timeout=5s, free/occupied thresholds, transient-local QoS).
- nav2_slam_bringup.launch.py: adds map_dir + map_name args; includes
map_persistence.launch.py so map_saver_server runs during SLAM sessions.
- nav2_amcl_bringup.launch.py: adds map_dir arg; auto-detects saved map at
/mnt/nvme/saltybot/maps/saltybot_map.yaml at launch time and uses it as
the AMCL map; falls back to placeholder if not found.
- setup.py: registers map_persistence.launch.py, map_saver_params.yaml,
map_saver_node console_scripts entry point.
- test_nav2_amcl.py: 21 new tests covering params, launch syntax,
node service/shutdown behaviour, SLAM bringup inclusion, AMCL auto-detect.
Workflow:
1. ros2 launch saltybot_nav2_slam nav2_slam_bringup.launch.py (build map)
2. ros2 service call /saltybot/save_map std_srvs/srv/Trigger {} (save)
3. ros2 launch saltybot_nav2_slam nav2_amcl_bringup.launch.py (auto-loads)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 16:27:52 -04:00
af982bb575
feat: VESC dual ESC mount bracket (Issue #699 )
...
3D-printable PETG cradle for FSESC 6.7 Pro Mini Dual on 2020 T-slot rail.
4x M5 T-nut mounting, open-top heatsink exposure, XT60/XT30/CAN cutouts,
floor grille and side louvre ventilation, M3 heat-set insert posts for
board retention. No supports required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 16:26:07 -04:00
6d59baa30e
feat: End-to-end CAN integration tests (Issue #695 )
...
Add saltybot_can_e2e_test package with 64 tests covering the full
Orin↔Mamba↔VESC CAN pipeline: drive commands, heartbeat timeout,
e-stop escalation, mode switching, and FC_VESC status broadcasts.
Tests run with plain pytest — no ROS2 or real CAN hardware required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 16:25:23 -04:00
1ec4d3fc58
feat: WebSocket bridge for CAN monitor dashboard (Issue #697 )
...
rosbridge config:
- rosbridge_params.yaml: add /saltybot/barometer, /vesc/left/state,
/vesc/right/state to topics_glob whitelist (were missing, blocked
the CAN monitor panel from receiving data)
- can_monitor.launch.py: new lightweight launch — rosbridge only,
whitelist scoped to the 5 CAN monitor topics, port overridable via
launch arg (ros2 launch saltybot_bringup can_monitor.launch.py port:=9091)
can_monitor_panel.js auto-reconnect:
- Exponential backoff: 2s → 3s → 4.5s → ... → 30s cap (×1.5 factor)
- Countdown displayed in conn-label ("Retry in Xs…") during wait
- Backoff resets to 2s on successful connection
- Manual CONNECT / Enter resets backoff and cancels pending timer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 16:23:27 -04:00
sl-android
c6cf64217d
feat: Android BLE pairing UI for UWB tag (Issue #700 )
...
- UwbTagBleActivity: BLE scan filtered to 'UWB_TAG_XXXX' device names
- Connects to GATT service 12345678-1234-5678-1234-56789abcdef0
- Read/write JSON config char: sleep_timeout_s, display_brightness,
tag_name, uwb_channel, ranging_interval_ms, battery_report
- Subscribes to status + battery notification characteristics
- Material Design UI with scan list, config form, and live status
- Runtime BLE permission handling for API 26+ / API 31+
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 16:21:45 -04:00
5906af542b
Merge pull request 'feat: BME280 baro pressure & ambient temp (Issue #672 )' ( #673 ) from sl-firmware/issue-672-bme280-baro-temp into main
2026-03-18 08:27:39 -04:00
4318589496
feat: BME280 baro pressure & ambient temp driver (Issue #672 )
...
- New baro module (include/baro.h, src/baro.c): reads BME280/BMP280
at 1 Hz on I2C1, computes pressure altitude (ISA formula), publishes
JLINK_TLM_BARO (0x8D) telemetry to Orin. Runs entirely on Mamba F722S
with no Orin dependency. baro_get_alt_cm() exposes altitude to balance
PID slope compensation.
- New JLink telemetry frame 0x8D (jlink_tlm_baro_t, 12 bytes packed):
pressure_pa (int32), temp_x10 (int16), alt_cm (int32),
humidity_pct_x10 (int16; -1 = BMP280/absent).
- Wire into main.c: baro_init() after bmp280_init(), baro_tick(now)
each ms (self-rate-limits to 1 Hz).
- Unit tests (test/test_baro.c): 31 tests, all pass. Build:
gcc -I include -I test/stubs -DTEST_HOST -lm -o /tmp/test_baro test/test_baro.c
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 08:25:07 -04:00
441c56b1d9
Merge pull request 'feat: Hardware button park/disarm/re-arm (Issue #682 )' ( #688 ) from sl-firmware/issue-682-hw-button into main
2026-03-18 08:21:55 -04:00
334ab9249c
Merge pull request 'feat: CAN sensor remote monitor panel (Issue #681 )' ( #687 ) from sl-webui/issue-681-can-monitor into main
2026-03-18 08:10:41 -04:00
4affd6d0cb
feat: Hardware button park/disarm/re-arm (Issue #682 )
...
Add hw_button driver (PC2 active-low, 20ms debounce) with gesture detection:
- Single short press + 500ms quiet -> BTN_EVENT_PARK
- SHORT+SHORT+LONG combo (within 3s) -> BTN_EVENT_REARM_COMBO
New BALANCE_PARKED state: PID frozen, motors off, quick re-arm via button
combo without the 3-second arm interlock required from DISARMED.
FC_BTN (0x404) CAN frame sent to Orin on each event:
event_id 1=PARKED, 2=UNPARKED, 3=UNPARK_FAILED (pitch > 20 deg)
Includes 11 unit tests (1016 assertions) exercising debounce, bounce
rejection, short/long classification, sequence detection, and timeout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 08:10:10 -04:00