sl-android
9b1f3ddaf0
feat: GPS waypoint logger and route planner (Issue #617 )
...
Add phone/waypoint_logger.py — interactive Termux CLI for recording,
managing, and publishing GPS waypoints:
GPS acquisition
- termux-location with gps/network/passive provider selection
- Falls back to network provider on GPS timeout
- Optional --live-gps flag: subscribes to saltybot/phone/gps MQTT
topic (sensor_dashboard.py stream) to avoid redundant GPS calls
Waypoint operations
- Record: acquires GPS fix, prompts for name + tags, appends to route
- List: table with lat/lon/alt/accuracy/tags + inter-waypoint
distance (haversine) and bearing (8-point compass)
- Delete: by index with confirmation prompt
- Clear: entire route with confirmation
- Rename: route name
Persistence
- Routes saved as JSON to ~/saltybot_route.json (configurable)
- Auto-loads on startup; survives session restarts
MQTT publish (saltybot/phone/route, QoS 1, retained)
- Full waypoint list with metadata
- nav2_poses array: flat-earth x/y (metres from origin),
quaternion yaw facing next waypoint (last faces prev)
- Compatible with Nav2 FollowWaypoints action input
Geo maths
- haversine_m(): great-circle distance
- bearing_deg(): initial bearing with 8-point compass label
- flat_earth_xy(): ENU metres for Nav2 pose export (<1% error <100km)
Flags: --broker, --port, --file, --route, --provider, --live-gps,
--no-mqtt, --debug
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 10:05:57 -04:00
sl-android
08bc23f6df
feat: Phone video streaming bridge (Issue #585 )
...
Phone side — phone/video_bridge.py:
- MJPEG streaming server for Android/Termux phone camera
- Dual camera backends: OpenCV VideoCapture (V4L2) with automatic
fallback to termux-camera-photo for unmodified Android
- WebSocket server (ws://0.0.0.0:8765) — binary JPEG frames + JSON
info/error control messages; supports multiple concurrent clients
- HTTP server (http://0.0.0.0:8766 ):
/stream — multipart/x-mixed-replace MJPEG
/snapshot — single JPEG
/health — JSON stats (frame count, dropped, resolution, fps)
- Thread-safe single-slot FrameBuffer; CaptureThread rate-limited with
wall-clock accounting for capture latency
- Flags: --ws-port, --http-port, --width, --height, --fps, --quality,
--device, --camera-id, --no-http, --debug
Jetson side — saltybot_phone/phone_camera_node.py:
- ROS2 node: receives JPEG frames, publishes:
/saltybot/phone/camera sensor_msgs/Image (bgr8)
/saltybot/phone/camera/compressed sensor_msgs/CompressedImage
/saltybot/phone/camera/info std_msgs/String (stream metadata)
- WebSocket client (primary); HTTP MJPEG polling fallback on WS failure
- Auto-reconnect loop (default 3 s) for both transports
- Latency warning when frame age > latency_warn_ms (default 200 ms)
- 10 s diagnostics log: received/published counts + last frame age
- Registered as phone_camera_node console script in setup.py
- Added to phone_bringup.py launch with phone_host / phone_cam_enabled args
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 12:20:28 -04:00
sl-android
814624045a
feat: Termux sensor dashboard (Issue #574 )
...
Add phone/sensor_dashboard.py — publishes phone sensors to SaltyBot MQTT:
- IMU → saltybot/phone/imu @ 5 Hz (accelerometer + gyroscope via
termux-sensor -s <name> -n 1)
- GPS → saltybot/phone/gps @ 1 Hz (lat/lon/alt/accuracy/speed/bearing
via termux-location; GPS→network fallback on cold start)
- Battery → saltybot/phone/battery @ 1 Hz (pct/charging/temp/health/plugged
via termux-battery-status)
- paho-mqtt with loop_start() + on_connect/on_disconnect callbacks for
automatic reconnect (exponential back-off, max 60 s)
- Each sensor runs in its own daemon thread (SensorPoller); rate enforced
by wall-clock sleep accounting for read latency
- 30 s status log: per-poller publish/error counts + MQTT state
- Flags: --broker, --port, --imu-hz, --gps-hz, --bat-hz, --qos,
--no-imu, --no-gps, --no-battery, --debug
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 11:53:04 -04:00
sl-android
c249b2d74e
feat: Phone voice command interface (Issue #553 )
...
Add phone/voice_commander.py — Termux-based voice command listener for SaltyBot:
- Continuous wake word detection ('Hey Salty') via Whisper STT on short audio clips
- Command recording after wake word, transcribed with local Whisper (tiny/base/small)
- Parses go forward/back/left/right, stop, follow me, go home, look at me
- Publishes JSON to /saltybot/voice/cmd via ROS2 (rclpy) or rosbridge WebSocket
- TTS confirmation via termux-tts-speak; 'Yes?' prompt on wake word
- Fuzzy token-overlap fallback for wake word matching
- Flags: --host, --port, --model, --threshold, --record-sec, --no-tts, --debug
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 10:26:38 -04:00
e4116dffc0
feat: Remove ELRS arm requirement for autonomous operation (Issue #512 )
...
Enable Jetson autonomous arming while keeping RC as optional override.
Changes:
- RC kill switch (CH5 OFF) now triggers emergency stop instead of disarm
→ Allows Jetson-armed robots to remain armed when RC disconnects
→ Maintains kill switch safety for emergency situations
- RC disarm only triggers on explicit CH5 falling edge (RC still alive)
→ RC disconnect doesn't disarm Jetson-controlled missions
→ RC failsafe timer (500ms) handles signal loss separately
- Jetson arming via CDC 'A' command works independently of RC state
→ Robots can operate fully autonomous without RC transmitter
→ Heartbeat timeout (500ms) prevents runaway if Jetson crashes
Safety maintained:
- Arming hold timer: 500ms (prevents accidental arm)
- Tilt limit: ±10° level required
- IMU calibration: Required before any arm attempt
- Remote E-stop: Blocks all arming
- RC failsafe: 500ms signal loss = disarm
- Jetson timeout: 500ms heartbeat = zero motors
Command protocol (unchanged):
- Jetson: A=arm, D=disarm, E=estop, Z=clear estop
- RC: CH5 switch (optional override)
- Heartbeat: H command every ≤500ms
- Drive: C<speed>,<steer> every ≤200ms
See AUTONOMOUS_ARMING.md for complete protocol and testing checklist.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-06 11:45:12 -05:00
sl-android
df49eec21f
feat: Android/Termux OpenClaw node (Issue #420 )
...
Add complete phone node infrastructure:
ROS2 Package (saltybot_phone):
- camera_node: /phone/camera/image_raw (320x240, 15 FPS)
- gps_node: /phone/gps (NavSatFix via termux-api)
- imu_node: /phone/imu (accelerometer data)
- openclaw_chat_node: Local LLM inference
Subscribes /saltybot/speech_text
Publishes /saltybot/chat_response
- ws_bridge: WebSocket bridge to Jetson Orin (:9090)
Phone Scripts:
- termux-bootstrap.sh: Complete Termux setup
- power-management.sh: Battery/thermal monitoring
- README.md: Setup documentation
Architecture:
- Termux on Android phone
- WiFi/USB tether to Jetson Orin
- ROS2 topic bridge for sensors
- Local LLM for on-device chat (Phi-2)
- Termux:Boot auto-start
- Power management for extended runtime
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-05 08:55:47 -05:00