ca95489b1d
feat: Nav2 SLAM integration with RPLIDAR + RealSense (Issue #422 )
...
Complete autonomous navigation stack for SaltyBot:
- SLAM Toolbox: online_async 2D LIDAR SLAM from RPLIDAR A1M8
- RealSense D435i: depth → pointcloud → costmap obstacle layer
- Nav2 stack: controllers, planners, behavior server, lifecycle management
- DWB planner: tuned for 20km/h (5.5 m/s) max velocity operation
- VESC odometry bridge: motor telemetry → nav_msgs/Odometry
- Costmap integration: LIDAR + depth for global + local costmaps
- TF tree: complete setup with base_link→laser, camera_link, odom
- Goal interface: /navigate_to_pose action for autonomous goals
Configuration:
- slam_toolbox_params: loop closure, scan matching, fine/coarse search
- nav2_params: AMCL, controllers, planners, behavior trees, lifecycle
- Global costmap: static layer + LIDAR obstacle layer + inflation
- Local costmap: rolling window + LIDAR + RealSense depth + inflation
- DWB planner: 20 vx samples, 40 theta samples, 1.7s horizon
Nodes and launch files:
- vesc_odometry_bridge: integrates motor RPM to wheel odometry
- nav2_slam_bringup: main integrated launch entry point
- depth_to_costmap: RealSense depth processing pipeline
- odometry_bridge: VESC telemetry bridge
Hardware support:
- RPLIDAR A1M8: 5.5 Hz, 12m range, 360° omnidirectional
- RealSense D435i: 15 Hz RGB-D, 200 Hz IMU, depth range 5m
- VESC Flipsky FSESC 4.20: dual motor control via UART
- SaltyBot 2-wheel balancer: 0.35m radius, hoverboard motors
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 23:35:15 -05:00
33fcc9d935
feat: remote monitoring WebSocket relay (Issue #424 )
...
Implement WebSocket telemetry relay with:
- 2Hz JSON aggregation (battery, motors, IMU, GPS, health, social)
- Port 9091 with token authentication
- msgpack compression option
- 5-minute circular history buffer
- Mobile-friendly responsive HTML UI
- Auto-reconnect WebSocket with fallback
- Critical alerts: low battery (< 15%), high temps, node crash
- Real-time dashboard with telemetry gauges
Features:
- Battery monitoring with SOC/voltage/current
- Motor command visualization (L/R duty)
- IMU attitude display (roll/pitch/yaw)
- CPU/GPU temperature with thresholds
- RAM/Disk usage progress bars
- GPS coordinates (lat/lon/alt)
- Social state (speaking, face tracking)
- Alert history with severity levels
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 23:33:31 -05:00
a06821a8c8
Merge pull request 'feat: sensor feeds in HUD (Issue #413 )' ( #419 ) from sl-webui/issue-413-sensor-hud into main
2026-03-04 23:21:34 -05:00
eff69b2037
feat(hud): add sensor feeds (GPS, LIDAR, RealSense) (Issue #413 )
...
Add tabbed sensor feed interface to the HUD center viewport:
GPS Map Panel:
- Fetches location data from /gps HTTP endpoint on port 8888
- Renders OpenStreetMap with real-time location marker
- Displays: coordinates, altitude, accuracy
LIDAR Point Cloud Visualization:
- Subscribes to /scan topic via rosbridge WebSocket
- 2D polar plot with grid, cardinal directions, forward indicator
- Real-time point cloud rendering with range statistics
- Displays: point count, max range (0-30m)
RealSense Dual Stream:
- Subscribes to /camera/color/image_raw/compressed (RGB)
- Subscribes to /camera/depth/image_rect_raw/compressed (Depth)
- Side-by-side canvas rendering with independent scaling
- FPS counter and resolution display
Tab System:
- 4-way view switching: 3D Model ↔ GPS ↔ LIDAR ↔ RealSense
- Persistent tab state, lazy initialization on demand
- Dark theme with cyan/orange accent colors
- Status indicators for each sensor (loading/error/ready)
Architecture:
- Browser native canvas for LIDAR visualization
- WebSocket rosbridge integration for sensor subscriptions
- Fetch API for HTTP GPS data (localhost:8888)
- Leaflet.js for OSM map rendering (CDN)
- 2s polling interval for GPS updates
Rosbridge Endpoints (assumes localhost:9090):
- /scan (sensor_msgs/LaserScan) — 1Hz LIDAR
- /camera/color/image_raw/compressed — RGB stream
- /camera/depth/image_rect_raw/compressed — Depth stream
HTTP Endpoints (assumes localhost:8888):
- GET /gps → { lat, lon, alt, accuracy, timestamp }
Integration:
- Preserves existing 3D HUD viewport and controls
- Left/right sidebars remain unchanged
- Bottom PID control bar operational
- Tab switching preserves center panel size/aspect ratio
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 22:57:10 -05:00
4cb3ac7fe7
Merge remote-tracking branch 'origin/sl-webui/issue-412-ops-dashboard'
...
# Conflicts:
# ui/social-bot/src/components/OpsDashboard.jsx
2026-03-04 22:47:57 -05:00
6aca138af1
Merge pull request 'feat: auto-dock (Issue #410 )' ( #417 ) from sl-mechanical/issue-410-auto-dock into main
2026-03-04 22:46:50 -05:00
8981b0b87a
Merge pull request 'feat: voice commands (Issue #409 )' ( #416 ) from sl-perception/issue-409-voice-commands into main
2026-03-04 22:46:45 -05:00
8070dcd4b1
Merge pull request 'feat: VESC balance PID controller with tilt safety (Issue #407 )' ( #415 ) from sl-controls/issue-407-vesc-balance into main
2026-03-04 22:46:40 -05:00
2fad597976
Merge pull request 'feat: ROS2 bag recording service (Issue #411 )' ( #414 ) from sl-jetson/issue-411-bag-recording into main
2026-03-04 22:46:36 -05:00
3746a5b92d
feat(webui): live operations dashboard (Issue #412 )
...
Comprehensive real-time telemetry dashboard consolidating:
- Battery state & power (10Hz): voltage, current, SOC
- Motor PWM control (10Hz): left/right duty cycle display
- IMU attitude gauges (10Hz): roll, pitch, yaw visualization
- LIDAR polar map (1Hz): 360° obstacle visualization
- Social state (1Hz): speech detection, face ID
- System health (1Hz): CPU/GPU temps, RAM/disk usage
- 2D odometry trail (10Hz): position history map
Responsive 3-column grid layout (1-3 cols based on viewport).
Dark theme with mobile optimization. Canvas-based visualizations.
Real-time ROS subscriptions via rosbridge. Auto-scaling meters.
Quaternion to Euler angle conversion. 500-point trail history.
ROS Topics (10Hz critical / 1Hz system):
- /saltybot/imu → sensor_msgs/Imu (attitude)
- /diagnostics → diagnostic_msgs/DiagnosticArray (power, temps)
- /saltybot/balance_state → std_msgs/String (motor commands)
- /scan → sensor_msgs/LaserScan (LIDAR)
- /odom → nav_msgs/Odometry (position trail)
- /social/speech/is_speaking → std_msgs/Bool (voice activity)
- /social/face/active → std_msgs/String (face ID)
Build: ✓ 126 modules, 281.64 KB main bundle
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 22:45:24 -05:00
fdc44f7025
feat: Issue #410 - Auto-dock charging with 20% SoC trigger and charging animation
...
- Update battery_low_pct from 15% to 20% for auto-dock trigger (Issue #410 requirement)
- Add social mood publisher for charging animation display
- Trigger face charging animation (happy mood) when entering CHARGING state
- ArUco marker ID 42 detection via RealSense D435i (already configured)
- Approach sequence: detect → align → slow → contact → verify charging
- 360° search then expand capability (DETECTING state handles search)
- Safety abort timeouts already implemented in FSM state machine
- IR beacon fallback detection also available
2026-03-04 22:44:15 -05:00
4e6ecacd37
feat: Issue #410 - Auto-dock charging with 20% SoC trigger and charging animation
...
- Update battery_low_pct from 15% to 20% for auto-dock trigger (Issue #410 )
- Add social mood publisher for charging animation display
- Trigger face charging animation (happy mood) when entering CHARGING state
- ArUco marker ID 42 detection via RealSense D435i (already configured)
- Approach sequence: detect → align → slow → contact → verify charging
- 360° search then expand capability (DETECTING state handles search)
- Safety abort timeouts already implemented in FSM state machine
2026-03-04 22:44:04 -05:00
250c71d930
feat: Add Issue #409 - Voice command interpreter
...
Implement lightweight voice command system with:
- Simple keyword + fuzzy matching parser for 7 basic commands
- Voice command node subscribing to /saltybot/speech_text
- VoiceCommand message publishing to /saltybot/voice_command
- Command router executing intents with TTS confirmation via Piper
- Support for: follow me, stop, come here, go home, battery, spin, quiet mode
- Configuration parameters for confidence thresholding
- Launch file for integrated voice command pipeline
- Unit tests for parser (keyword + fuzzy matching + normalization)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 22:43:04 -05:00
c86abdd1b8
feat: Add VESC balance PID controller with tilt safety (Issue #407 )
...
- ROS2 node for balance mode PID parameter management via pyvesc UART
- Tilt safety kill switch: ±45° pitch > 500ms triggers motor cutoff
- Startup ramp: gradual acceleration from 0 to full output over configurable duration
- IMU integration: subscribe to /imu/data for pitch/roll angle computation
- State publishing: /saltybot/balance_state with tilt angles, PID values, motor telemetry
- Data logging: /saltybot/balance_log publishes CSV-formatted IMU + motor data
- Configurable parameters: PID gains, tilt thresholds, ramp duration, control frequency
- Test suite: quaternion to Euler conversion, tilt safety checks, startup ramp
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 22:40:40 -05:00
f69c02880e
feat: Add VESC balance PID controller with tilt safety (Issue #407 )
...
- ROS2 node for balance mode PID parameter management via pyvesc UART
- Tilt safety kill switch: ±45° pitch > 500ms triggers motor cutoff
- Startup ramp: gradual acceleration from 0 to full output over configurable duration
- IMU integration: subscribe to /imu/data for pitch/roll angle computation
- State publishing: /saltybot/balance_state with tilt angles, PID values, motor telemetry
- Data logging: /saltybot/balance_log publishes CSV-formatted IMU + motor data
- Configurable parameters: PID gains, tilt thresholds, ramp duration, control frequency
- Test suite: quaternion to Euler conversion, tilt safety checks, startup ramp
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 22:40:26 -05:00
88deacb337
feat: ROS2 bag recording service (Issue #411 )
...
Implement circular buffer bag recorder with:
- Configurable topics recording
- Last N minutes circular buffer (default 30min)
- Manual save trigger via /saltybot/save_bag service
- Auto-save on crash with signal handlers
- Storage management (7-day TTL, 50GB quota)
- Compression via zstd
- Optional rsync to NAS for backup
- Periodic maintenance (cleanup expired, enforce quota)
Saves to /home/seb/rosbags/ by default.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 22:40:19 -05:00
9257f4c7de
Merge branch 'origin/sl-firmware/issue-400-encounter-enrollment' into main
...
Resolved conflicts in social_enrollment_node.py by keeping comprehensive
docstring and imports from both versions.
2026-03-04 13:32:20 -05:00
1222532971
Merge pull request 'feat: encounter offline queue sync service (Issue #400 )' ( #406 ) from sl-mechanical/issue-400-encounter-queue into main
2026-03-04 13:31:03 -05:00
a9d66ddcc1
Merge pull request 'feat: first encounter orchestrator (Issue #400 )' ( #402 ) from sl-jetson/issue-400-encounter-launch into main
social-bot integration tests / Lint (flake8 + pep257) (push) Failing after 9s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (push) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (push) Has been cancelled
2026-03-04 13:30:15 -05:00
136ca1fb9c
feat: Add Issue #400 - Encounter offline queue sync service
...
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 4s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
Implement EncounterSyncService ROS2 node for managing offline-first
encounter data syncing. Features:
- Monitors /home/seb/encounter-queue/ for JSON files
- Uploads to configurable cloud API when connectivity detected
- Exponential backoff retry with max 5 attempts
- Moves synced files to /home/seb/encounter-queue/synced/
- Publishes status on /social/encounter_sync_status topic
- Connectivity check via HTTP ping (configurable URL)
- Handles offline operation gracefully
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 13:16:00 -05:00
020adf1b94
feat: Add Issue #400 - Encounter offline queue sync service
...
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 4s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
Implement EncounterSyncService ROS2 node for managing offline-first
encounter data syncing. Features:
- Monitors /home/seb/encounter-queue/ for JSON files
- Uploads to configurable cloud API when connectivity detected
- Exponential backoff retry with max 5 attempts
- Moves synced files to /home/seb/encounter-queue/synced/
- Publishes status on /social/encounter_sync_status topic
- Connectivity check via HTTP ping (configurable URL)
- Handles offline operation gracefully
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 13:14:44 -05:00
86c60f48e6
feat: First Encounter social interaction launch (Issue #400 )
...
social-bot integration tests / Lint (flake8 + pep257) (push) Failing after 19s
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 17s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (push) Has been skipped
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (push) Has been cancelled
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
Add encounter.launch.py orchestrating all First Encounter nodes:
- encounter_sync_service (offline queue backend)
- social_enrollment_node (face/voice enrollment)
- first_encounter_node (interaction orchestrator)
- wake_word_node (speech detection)
- face_display_bridge_node (UI frontend)
Include in full_stack.launch.py at t=9s with enable_encounter flag.
Add encounter_params.yaml with configurable greeting, TTS voice,
enrollment thresholds, database paths, and cloud sync settings.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 13:13:22 -05:00
c85619b8da
feat: first encounter orchestrator state machine (Issue #400 )
...
social-bot integration tests / Lint (flake8 + pep257) (push) Failing after 2s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (push) Has been skipped
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 13s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (push) Has been cancelled
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
Implement state machine for detecting and enrolling unknown persons.
Manages workflow: DETECT → GREET → ASK_NAME → SMALL_TALK → ENROLL → FAREWELL
Features:
- Subscribes to /saltybot/person_tracker for unknown face detection
- Unknown person threshold configurable (default: 30% confidence)
- State machine with Piper TTS triggers for each state
- Captures STT responses for name and conversation context
- Publishes /social/orchestrator/state for coordination with other nodes
- Handles person interruptions gracefully (walks away)
- Auto-enrolls person to face gallery (configurable)
- Stores encounter data as JSON in /home/seb/encounter-queue/
- Tracks duration, responses, interests, and enrollment success
Encounter data structure:
{
person_id, timestamp, state, name, context, greeting_response,
interests[], enrollment_success, duration_sec, notes
}
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 13:12:47 -05:00
b2c8f76114
Merge pull request 'feat: hey salty wake word model (Issue #393 )' ( #401 ) from sl-perception/issue-393-wake-word into main
2026-03-04 13:11:30 -05:00
65ec1151f8
Merge pull request 'feat: face display bridge (Issue #394 )' ( #399 ) from sl-controls/issue-394-face-bridge into main
social-bot integration tests / Lint (flake8 + pep257) (push) Failing after 4s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (push) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (push) Has been cancelled
2026-03-04 13:11:01 -05:00
7bc2b64c1d
Merge pull request 'fix: MeshPeer namespace reserved keyword (Issue #392 )' ( #398 ) from sl-webui/issue-392-meshpeer-fix into main
social-bot integration tests / Core integration tests (mock sensors, no GPU) (push) Has been cancelled
social-bot integration tests / Latency profiling (GPU, Orin) (push) Has been cancelled
social-bot integration tests / Lint (flake8 + pep257) (push) Has been cancelled
2026-03-04 13:10:50 -05:00
39258f465b
feat: hey salty wake word template (Issue #393 )
...
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 24s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
Creates log-mel spectrogram template for 'hey salty' wake word detection
using synthetic speech generation. Template generated from 5 synthetic
audio samples with varying pitch to improve robustness.
- generate_wake_word_template.py: Script to synthesize and generate template
- hey_salty.npy: 40-band log-mel template (40, 61) shape
- wake_word_params.yaml: Updated template_path
- README.md: Documentation for template usage and retraining procedures
The template is used by wake_word_node.py via cosine similarity matching
against incoming audio. Configurable sensitivity via match_threshold.
Future work: Collect real training recordings to improve accuracy.
2026-03-04 12:44:36 -05:00
82cb2bde79
feat: face display bridge node (Issue #394 )
...
Implement ROS2 node bridging orchestrator state to face display expressions.
Maps /social/orchestrator/state and /saltybot/wake_word_detected to HTTP API.
Features:
- Subscribes to /social/orchestrator/state (JSON: IDLE, LISTENING, THINKING, SPEAKING, THROTTLED)
- Subscribes to /saltybot/wake_word_detected for immediate Alert response
- HTTP GET requests to face display server (configurable localhost:3000/face/{id})
- State to expression mapping:
* IDLE → 0 (Tracking)
* LISTENING → 1 (Alert)
* THINKING → 3 (Searching)
* SPEAKING → 4 (Social)
* Wake word → 1 (Alert, immediate override)
- Publishes /face/state with JSON: {face_id, orchestrator_state, timestamp}
- Configurable face_server_url parameter
- Fallback to urllib if requests library unavailable
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 12:44:33 -05:00
fc6151ae16
fix: rename MeshPeer namespace field to ros_namespace (Issue #392 )
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 3s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
2026-03-04 12:43:00 -05:00
7a17b1bf16
fix: rename MeshPeer namespace field to ros_namespace (Issue #392 )
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 10s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
2026-03-04 12:42:35 -05:00
858ae1e7b9
Merge pull request 'feat: 360 obstacle avoidance with RPLIDAR (Issue #364 )' ( #396 ) from sl-firmware/issue-364-obstacle-avoidance into main
2026-03-04 12:39:46 -05:00
a4351d0da3
Merge pull request 'feat: accessibility communication UI (Issue #371 )' ( #391 ) from sl-webui/issue-371-accessibility into main
2026-03-04 12:39:20 -05:00
19017eca37
Merge pull request 'feat: pan/tilt camera head (Issue #384 )' ( #390 ) from sl-controls/issue-384-pan-tilt into main
2026-03-04 12:39:07 -05:00
55c8f387ab
Merge pull request 'feat: STM32 watchdog timer driver (Issue #300 )' ( #386 ) from sl-mechanical/issue-300-watchdog into main
2026-03-04 12:39:05 -05:00
e35bd949c0
feat: Integrate 360° LIDAR obstacle avoidance into full_stack (Issue #364 )
...
Adds saltybot_lidar_avoidance node to the launch sequence at t=3s.
The RPLIDAR A1M8 node was already fully implemented with:
- Emergency stop if obstacle detected within 0.5m
- Speed-dependent safety zones (0.6m @ 0 m/s → 3.0m @ 5.56 m/s)
- Forward scanning window (±30° cone)
- Debounced obstacle detection (2-frame debounce)
- Publishes /cmd_vel_safe with filtered velocity commands
Integrates seamlessly with Nav2 stack and cmd_vel_mux multiplexer.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 12:23:43 -05:00
9fc3e9894e
feat: deaf/accessibility communication UI (Issue #371 )
2026-03-04 12:19:28 -05:00
170c64eec1
feat: Add watchdog reset detection and status reporting (Issue #300 )
...
- Detect if MCU was reset by IWDG watchdog timeout at startup
- Log watchdog reset events to debug terminal (USB CDC)
- Store watchdog reset flag for status reporting to Jetson
- Watchdog timer configured with 2-second timeout in safety_init()
- Main loop calls safety_refresh() to kick the watchdog every iteration
The IWDG (Independent Watchdog) resets the MCU if the main loop
hangs and fails to call safety_refresh() within the timeout window.
This provides hardware-enforced detection of software failures.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 12:17:56 -05:00
93756f5248
feat: Add FC↔Orin UART verification (Issue #362 )
...
Implements UART bridge verification between Flight Controller (STM32F722)
and Jetson Orin.
Changes:
1. jetson/scripts/uart_test.py (12.7 KB)
- Opens /dev/ttyTHS1 at 921600 baud
- Sends jlink binary test frames (PING, VERSION, ECHO)
- Verifies CRC16-CCITT frame integrity
- Logs transactions with timestamps
- JSON result export and optional MQTT publishing
2. jetson/ros2_ws/src/saltybot_bridge/launch/uart_bridge.launch.py
- ROS2 launch file for serial_bridge_node on UART port
- Configurable port (default /dev/ttyTHS1), baud rate (921600)
- Bridges FC telemetry to /saltybot/imu, /saltybot/balance_state
- Publishes diagnostics to /diagnostics
Usage:
Test: sudo python3 jetson/scripts/uart_test.py
Launch: ros2 launch saltybot_bridge uart_bridge.launch.py
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 12:17:56 -05:00
3c93a72d01
Merge pull request 'refactor: ESC abstraction layer with pluggable backends (Issue #388 )' ( #389 ) from sl-firmware/issue-388-esc-abstraction into main
2026-03-04 11:36:24 -05:00
844504e92e
refactor: ESC abstraction layer with pluggable backends (Issue #388 )
...
BREAKING CHANGE: Hoverboard implementation moved to pluggable vtable architecture.
## Implementation
### New Files
- include/esc_backend.h: Abstract interface (vtable) with:
- esc_telemetry_t struct (voltage, current, temp, speed, steer, fault)
- esc_backend_t vtable (init, send, estop, resume, get_telemetry)
- Runtime registration (esc_backend_register/get)
- Convenience wrappers (esc_init, esc_send, esc_estop, etc)
- src/esc_backend.c: Backend registry and wrapper implementations
- src/esc_hoverboard.c: Hoverboard backend implementing vtable
- USART2 @ 115200 baud configuration
- EFeru FOC packet encoding (0xABCD start, XOR checksum)
- Backward-compatible hoverboard_init/send wrappers
- Telemetry stub (future: add RX feedback parsing)
- src/esc_vesc.c: VESC backend stub (filled by Issue #383 )
- Placeholder functions for FSESC 4.20 Plus integration
- Public vesc_backend_register_impl() for runtime registration
- Ready for pyvesc protocol implementation
### Modified Files
- src/motor_driver.c: Changed from direct hoverboard_send() calls to esc_send()
- No logic changes, ESC-agnostic via vtable
- include/config.h: Added ESC_BACKEND define
- Compile-time selection (default: HOVERBOARD)
- Comments document architecture for future VESC support
### Removed Files
- src/hoverboard.c: Original implementation merged into esc_hoverboard.c
## Architecture Benefits
1. **Backend Pluggability**: Support multiple ESC types without code duplication
2. **Zero Direct Dependencies**: motor_driver.c never calls hoverboard functions directly
3. **Clean Testing**: Each backend can be tested/stubbed independently
4. **Future-Ready**: VESC integration (Issue #383 ) just implements the vtable
5. **Backward Compatible**: Existing code calling hoverboard_init/send still works
## Testing
- pio run: ✅ PASS (55.4KB Flash, 16.9KB RAM)
- Hoverboard backend tested via existing balance tests (unchanged logic)
- VESC backend stub compiles and links (no-op until #383 fills implementation)
## Blocks
- Issue #383 (VESC integration) — ready to implement vtable functions
- Issue #384 (pan/tilt servo) — may use independent PWM (not blocked)
## Dependencies
- None — this is pure refactoring, no API changes for callers
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 10:36:35 -05:00
985e03a26d
Merge pull request 'fix: add missing bno055.h include in main.c' ( #387 ) from sl-firmware/fix-bno055-include into main
2026-03-04 09:54:56 -05:00
d52e7af554
fix: Add missing bno055.h include to resolve implicit declaration warnings
...
Adds #include "bno055.h" to src/main.c to resolve implicit declaration
warnings for bno055_read(), bno055_calib_status(), and bno055_temperature().
Functions were properly implemented but header was missing from includes.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 08:45:51 -05:00
7cfb98aec1
feat: Add pan/tilt camera head servo control (Issue #384 )
...
Implement SCS/STS serial protocol driver for Waveshare ST3215 servos
at 1Mbps daisy-chain configuration. Pan and tilt servos on single UART.
Features:
- SCSServoBus class: Low-level protocol handler with packet construction
- Position write commands with configurable speed (0-1000)
- Position and temperature readback from servos
- PanTiltNode: ROS2 node with target tracking control loop
- Subscribes to /saltybot/target_track for centroid position
- Proportional control to keep target centered in D435i FOV
- Publishes /pan_tilt/state with angles and temperatures
- Publishes /pan_tilt/command for servo position monitoring
- 30 Hz control loop, 1 Hz telemetry loop
- Configurable servo limits and speeds
Servos: 0.24° resolution, 0-4095 position range
Camera: 87° × 58° field of view
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 08:44:51 -05:00
ce1a5e5fee
Merge pull request 'feat: VESC UART driver node with pyvesc (Issue #383 )' ( #385 ) from sl-controls/issue-383-vesc into main
2026-03-04 08:40:15 -05:00
a11722e872
feat: Implement VESC UART driver node (Issue #383 )
...
ROS2 driver for Flipsky FSESC 4.20 Plus (VESC dual ESC) motor control.
Replaces hoverboard ESC communication with pyvesc library.
Features:
- UART serial communication (configurable port/baud)
- Dual command modes: duty_cycle (-100 to 100) and RPM setpoint
- Telemetry publishing: voltage, current, RPM, temperature, fault codes
- Command timeout: auto-zero throttle if no cmd_vel received
- Heartbeat-based connection management
- Comprehensive error handling and logging
Topics:
- Subscribe: /cmd_vel (geometry_msgs/Twist)
- Publish: /vesc/state (JSON telemetry)
- Publish: /vesc/raw_telemetry (debug)
Launch: ros2 launch saltybot_vesc_driver vesc_driver.launch.py
Config: config/vesc_params.yaml
Next phase: Integrate with cmd_vel_mux + safety layer.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-04 07:05:46 -05:00
bc3ed1a0c7
Merge pull request 'fix: resolve all compile errors across 6 files (Issue #337 )' ( #382 ) from sl-controls/issue-337-build-fix into main
2026-03-03 19:58:54 -05:00
f4e71777ec
fix: Resolve all compile and linker errors (Issue #337 )
...
Fixed 7 compile errors across 6 files:
1. servo.c: Removed duplicate ServoState typedef, updated struct definition in header
2. watchdog.c: Fixed IWDG handle usage - moved to global scope for IRQHandler access
3. ultrasonic.c: Fixed timer handle type mismatches - use TIM_HandleTypeDef instead of TIM_TypeDef, replaced HAL_TIM_IC_Init_Compat with proper HAL functions
4. main.c: Replaced undefined functions - imu_calibrated() → mpu6000_is_calibrated(), crsf_is_active() → manual state check
5. ina219.c: Stubbed I2C functions pending HAL implementation
Build now passes with ZERO errors.
- RAM: 6.5% (16964 bytes / 262144)
- Flash: 10.6% (55368 bytes / 524288)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-03 19:00:12 -05:00
6df453e8d0
Merge pull request 'feat: deaf/accessibility mode (Issue #371 )' ( #381 ) from sl-controls/issue-371-accessibility into main
2026-03-03 18:51:30 -05:00
5604670646
feat: Implement deaf/accessibility mode with STT, touch keyboard, TTS (Issue #371 )
...
Accessibility mode for hearing-impaired users:
- Speech-to-text display: Integrates with saltybot_social speech_pipeline_node
- Touch keyboard overlay: 1024x600 optimized for MageDok 7in display
- TTS output: Routes to MageDok speakers via PulseAudio
- Web UI server: Responsive keyboard interface with real-time display updates
- Auto-confirm: Optional TTS feedback for spoken input
- Physical keyboard support: Both touch and physical input methods
Features:
- Keyboard buffer with backspace/clear/send controls
- Transcript history display (max 10 entries)
- Status indicators for STT/TTS ready state
- Number/symbol support (1-5, punctuation)
- HTML/CSS responsive design optimized for touch
- ROS2 integration via /social/speech/transcript and /social/conversation/request
Launch: ros2 launch saltybot_accessibility_mode accessibility_mode.launch.py
UI Port: 8080 (MageDok display access)
Config: config/accessibility_params.yaml
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-03 18:17:41 -05:00
b942bb549a
Merge pull request 'feat: 360° LIDAR obstacle avoidance (Issue #364 )' ( #380 ) from sl-controls/issue-364-lidar-avoidance into main
2026-03-03 18:15:28 -05:00