1ae600ead4
feat: Orin serial OTA_CHECK + OTA_UPDATE commands, version reporting (bd-1s1s)
...
Extends the bd-66hx serial protocol with two new Orin→ESP32 commands:
CMD_OTA_CHECK (0x10): triggers gitea_ota_check_now(), responds with
TELEM_VERSION_INFO (0x84) for Balance and IO (current + available ver).
CMD_OTA_UPDATE (0x11): uint8 target (0=balance, 1=io, 2=both) — triggers
uart_ota_trigger() for IO or ota_self_trigger() for Balance.
NACK with ERR_OTA_BUSY or ERR_OTA_NO_UPDATE on failure.
New telemetry: TELEM_OTA_STATUS (0x83, target+state+progress+err),
TELEM_VERSION_INFO (0x84, target+current[16]+available[16]).
Wires OTA stack into app_main: ota_self_health_check on boot,
gitea_ota_init + ota_display_init after peripherals ready.
CMakeLists updated with all OTA component dependencies.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
e73674f161
feat: GC9A01 OTA notification badge + progress ring UI (bd-1yr8)
...
Adds ota_display_task (5 Hz) on GC9A01 240×240 round LCD:
- Idle: orange dot badge at top-right when update available, version text
- Progress: arc sweeping 0→360° around display perimeter with phase label
- States: Downloading/Verifying/Applying/Rebooting (Balance) and
Downloading/Sending/Done (IO via UART)
- Error: red arc + "FAILED RETRY?" prompt
Display primitives (fill_rect, draw_string, draw_arc) are stubs called
from the GC9A01 SPI driver layer (separate driver bead).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
972db16635
feat: UART OTA protocol Balance→IO board, 1 KB chunk + ACK (bd-21hv)
...
Balance side (uart_ota.c): downloads io-firmware.bin from Gitea to RAM,
computes SHA256, then streams to IO over UART1 (GPIO17/18, 460800 baud)
as OTA_BEGIN/OTA_DATA/OTA_END frames with CRC8 + per-chunk ACK/retry (×3).
IO side (uart_ota_recv.c): receives frames, writes to inactive OTA partition
via esp_ota_write, verifies SHA256 on OTA_END, sets boot partition, reboots.
IO board main.c + CMakeLists.txt scaffold included.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
5250ce67ad
feat: Balance self-OTA download, SHA256 verify, rollback (bd-18nb)
...
Downloads balance-firmware.bin from Gitea release URL to inactive OTA
partition, streams SHA256 verification via mbedTLS, sets boot partition
and reboots. Auto-rollback via CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE if
ota_self_health_check() not called within 30 s of boot. Progress 0-100%
in g_ota_self_progress for display task.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
d2175bf7d0
feat: Gitea release version checker with WiFi (bd-3hte)
...
Adds gitea_ota_check_task on Balance board: fetches Gitea releases API
every 30 min and on boot, filters by esp32-balance/ and esp32-io/ tag
prefixes, compares semver against embedded FW version, stores update info
(version string, download URL, SHA256) in g_balance_update / g_io_update.
WiFi credentials read from NVS namespace "wifi"; falls back to compile-time
DEFAULT_WIFI_SSID/PASS if NVS is empty.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:52 -04:00
2a13c3e18b
feat: partition tables + OTA setup for Balance and IO boards (bd-3gwo)
...
Add dual OTA partitions (ota_0/ota_1 × 1.75 MB each) and otadata to
both esp32s3/balance/ and esp32s3/io/ on 4 MB flash layouts.
Enable CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE and OTA HTTP on Balance.
Create esp32s3/io/ project scaffold with config.h pin assignments.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 23:10:51 -04:00
3f0508815d
Merge pull request 'ci: OTA release pipeline — build + attach firmware binaries (bd-9kod)' ( #730 ) from sl-jetson/bd-9kod-ota-ci into main
2026-04-17 23:10:26 -04:00
d9e7acfa0d
Merge pull request 'feat: ESP32 Balance UART/USB protocol for Orin + VESC proxy (bd-66hx)' ( #729 ) from sl-firmware/bd-66hx-esp32-uart-orin into main
2026-04-17 23:10:15 -04:00
c02faf3ac2
Merge pull request 'feat: Here4 GPS DroneCAN on Orin via CANable2 (bd-p47c)' ( #728 ) from sl-perception/bd-p47c-here4-can-gps into main
2026-04-17 23:10:05 -04:00
61f241ae1d
Merge pull request 'feat: Orin UART/USB serial comms with ESP32 Balance (bd-wim1)' ( #727 ) from sl-perception/bd-wim1-orin-uart-esp32 into main
2026-04-17 23:09:53 -04:00
2fa097e3d6
ci: OTA release pipeline — build + attach firmware binaries (bd-9kod)
...
Adds .gitea/workflows/ota-release.yml: triggered on esp32-balance/vX.Y.Z
or esp32-io/vX.Y.Z tags, builds the corresponding ESP32-S3 project with
espressif/idf:v5.2.2, and attaches <app>_<version>.bin + .sha256 to the
Gitea release for OTA download.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 22:11:33 -04:00
b830420efc
feat: add UART/USB serial protocol for Orin comms, proxy VESC CAN (bd-66hx)
...
Replaces Orin↔ESP32-S3 BALANCE CAN comms (0x300-0x303 / 0x400-0x401)
with binary serial framing over CH343 USB-CDC at 460800 baud.
Protocol matches bd-wim1 (sl-perception) exactly:
Frame: [0xAA][LEN][TYPE][PAYLOAD][CRC8-SMBUS]
CRC covers LEN+TYPE+PAYLOAD, big-endian multi-byte fields.
Commands (Orin→ESP32): HEARTBEAT/DRIVE/ESTOP/ARM/PID
Telemetry (ESP32→Orin): TELEM_STATUS, TELEM_VESC_LEFT (ID 56),
TELEM_VESC_RIGHT (ID 68), ACK/NACK
VESC CAN TWAI kept for motor control; drive commands from Orin
forwarded to VESCs via SET_RPM. Hardware note: SN65HVD230
rewired from IO43/44 to IO2/IO1 to free IO43/44 for CH343.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 22:09:12 -04:00
9d6c72bd24
feat: Here4 GPS DroneCAN integration via CANable2 (bd-p47c)
...
Implements saltybot_dronecan_gps ROS2 package — DroneCAN/UAVCAN v0
bridge that publishes Here4 GPS, IMU, magnetometer, and barometer data
to ROS2. CANable2 freed from ESP32 BALANCE comms (bd-wim1) now runs
Here4 at 1 Mbps DroneCAN.
Key features:
- dronecan_parser.py: pure-Python DSDL converters (Fix2, RawIMU, Mag,
StaticPressure, StaticTemperature, NodeStatus, RTCMStream chunks),
testable without dronecan library or CAN hardware
- here4_node.py: ROS2 node, auto-discovers Here4 node ID on first Fix2,
publishes /gps/fix + /gps/velocity for navsat_transform EKF fusion,
HDOP-based NavSatStatus upgrade (RTK/SBAS), RTCM injection via
/rtcm (ByteMultiArray) or /rtcm_hex (String hex fallback)
- 39 unit tests, all passing
- bring_up_can:=true parameter to configure SocketCAN at launch
Resolves bd-p47c
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 21:49:00 -04:00
9b460e34db
feat: Orin UART/USB serial interface for ESP32 Balance (bd-wim1)
...
New package saltybot_esp32_serial replaces saltybot_can_bridge
(CANable2/python-can) with direct USB-CDC serial to ESP32-S3 BALANCE
(CH343 chip, 1a86:55d3, /dev/esp32-balance @ 460800 baud).
Framing: [0xAA][LEN][TYPE][PAYLOAD][CRC8-SMBUS] matching bd-66hx spec.
esp32_balance_protocol.py — codec + streaming FrameParser (state-machine)
- Commands: HEARTBEAT(0x01), DRIVE(0x02), ESTOP(0x03), ARM(0x04), PID(0x05)
- Telemetry: STATUS(0x80), VESC_LEFT(0x81), VESC_RIGHT(0x82), ACK/NACK
esp32_balance_node.py — ROS2 node
- Subs: /cmd_vel, /estop, /saltybot/arm, /saltybot/pid_update
- Pubs: /saltybot/attitude, /saltybot/balance_state, /can/battery,
/can/vesc/{left,right}/state, /can/connection_status
- 500ms /cmd_vel watchdog → CMD_DRIVE(0,0)
- 200ms CMD_HEARTBEAT keepalive timer
- Auto-reconnect on serial disconnect
Proxied VESC telemetry: erpm, voltage, current, temp for IDs 56(L)/68(R).
Frees CANable2 for bd-p47c (Here4 GPS).
33 unit tests — all pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 19:38:38 -04:00
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