HomeRobot is a personal robotics project focused on creating an autonomous vacuum robot. The system uses a "Smart Server, Dumb Robot" philosophy: the robot handles real-time hardware control and data streaming, while the high-level Rust server handles complex processing like SLAM, path planning, and odometry.
- Robot Firmware (
robot/): The primary firmware for the ESP32-C6, developed using Zephyr RTOS. It manages:- Sensors: IMU (BMI160), LiDAR (RP-Lidar A1M8), Encoders (PCNT), and Battery (ADC).
- Actuators: Differential drive motors with PID speed control.
- Communication: Bidirectional Protobuf over TCP/IP (Wi-Fi). Includes a lightweight RPC Dispatcher for synchronous commands.
- Self-Diagnostics: Integrated module to verify hardware health (Battery, IMU, Motors/Encoders) on boot or via remote RPC.
- Control Server (
server/): A Rust application that:- Consumes telemetry (IMU, raw Encoder ticks, Lidar scans).
- Performs Server-side Odometry and eventually SLAM.
- Issues real-time movement commands and RPC requests (e.g., remote diagnostics).
- Protobuf (
proto/): Standardized definitions inmessages.proto. Communication uses a 2-byte Big-Endian length prefix for framing.
- MCU: ESP32-C6 (Main controller)
- Motor Driver: L298N H-bridge
- LiDAR: RP-Lidar A1M8 (360-degree point cloud)
- UART: UART1 (TX: GPIO 6, RX: GPIO 7)
- Motor Enable: GPIO 15
- IMU: BMI160 (6-axis Accel/Gyro)
- I2C: I2C0 (SDA: GPIO 4, SCL: GPIO 5)
- Actuators: 2x LEGO NXT 9842 Interactive Servo Motors (Differential Drive)
- Gear Ratio: 1:48 (internal reduction)
- Torque: 16.7 N·cm (stall at 9V)
- Motor SX: Forward: GPIO 19 (PWM), Backward: GPIO 18 (PWM)
- Motor DX: Forward: GPIO 11 (PWM), Backward: GPIO 10 (PWM)
- Encoders: 2x Incremental Encoders (Internal to NXT Motors)
- Resolution: 360 ticks per revolution (1 degree per tick)
- Encoder SX: A: GPIO 21, B: GPIO 20 (PCNT Unit 0)
- Encoder DX: A: GPIO 23, B: GPIO 22 (PCNT Unit 1)
- Power: 4x Li-Ion 26650 batteries (4S configuration)
- Battery Sense: ADC0 Channel 2 (GPIO 2)
- Encoders: Uses a C wrapper (
pcnt_reader.c) to access low-level ESP32-C6 PCNT hardware units directly, bypassing Zephyr's Unit 0 limitation. - Motors (L298N): 2-pin PWM scheme (PWM on FWD or BWD pin, other pin LOW).
- Stop Behavior: Implements "Coast" stopping (both pins LOW). No active electromagnetic braking is currently used; deceleration depends on the mechanical friction of the 1:48 gearboxes.
- Console: UART0 (GPIO 0/1) via CH343 USB bridge.
The Makefile is strictly reserved for build, install, and flash actions. It MUST NOT be used for operational tasks like starting simulation components, monitoring logs, or running tests. This ensures a clean separation between development/deployment and runtime operations.
The AI coding agent has direct connectivity to the robot hardware via the local development environment. It can autonomously:
- Build: Compile the Zephyr firmware and Rust server.
- Flash: Deploy firmware to the ESP32-C6 via
make flash. - Verify: Use dedicated tools (e.g.,
tools/regression_test.py,cmd_sender) to validate behavior.
make all: Builds proto, server, and ESP32-C6 firmware.make server: Builds the Rust control server.make build-sim: Builds the Zephyr-based robot application for native simulation.make build-c6 FLASH=8M: Build specifically for 8MB flash hardware (defaults to 16M).make flash: Flashes the Zephyr app to the ESP32-C6.make proto: Generates Python Protobuf bindings.make test: Runs server unit tests and Gazebo regression tests.
Navigate to tools/cmd_sender/ to send direct Protobuf commands:
cargo run -- move --left 100 --right 100: Move forward at 100 power.cargo run -- stop: Send an immediate emergency stop.cargo run -- diag: Trigger the remote diagnostic suite.cargo run -- interactive: Enter WASD mode for manual navigation (Esc to exit).- Add
--proxyif testing via therobot_proxybridge.
To get immediate feedback after a code change (e.g., PID adjustment or sensor logic update):
- Flash: Run
make flashto deploy the change. - Observe: In a dedicated terminal, monitor the logs using
west espressif monitor(hardware) or by checking the simulation logs inlogs/sim/. - Trigger Action: Use
cmd_senderto move the robot (e.g.,cargo run -- move --left 50 --right 50). - Analyze: Observe the PID error and encoder ticks to verify the hardware response matches expectations.
- Diagnostic: Run
cargo run -- diagto perform a comprehensive health check and verify that all systems are still operational.
Navigate to server/:
cargo build: Build the server.cargo run: Start the server (listens on port 12345).
- Sensors: Located in
src/sensors/. They only handle data acquisition (e.g.,Encodersreturns raw ticks). - Actuators: Located in
src/actuator/. They handle hardware actions (e.g.,Motorhandles PWM and local PID). - Communication:
ProtobufHandlermanages serialization and framing logic.
-
Odometry is Server-Side: The robot sends raw encoder ticks; the server calculates
$(x, y, \theta)$ . -
Remote Configuration: PID gains and motor limits are tunable via
RobotConfigmessages without reflashing.
- Transport: TCP Sockets.
- Framing:
[Length: 2 bytes (BE)][Protobuf Payload: N bytes]. - RPC System: Uses
RpcRequestandRpcResponseenvelopes within the Protobuf stream to handle synchronous command/response patterns without disrupting the asynchronous telemetry flow. - Config Sync: The robot is programmed to transmit its current
RobotConfig(PID gains, etc.) immediately upon a successful TCP connection. This ensures the Server Dashboard is always synchronized with the hardware state without manual querying.
- Main Thread: Dedicated exclusively to the GTK4 Event Loop (
app.run()). - Background Thread (Networking): Manages the TCP listener and per-connection
handle_connectionloops. - Input Handling: Managed via GTK
EventControllerKeyon the main window. Supports WASD for movement, 'L' for LiDAR, and 'T' for Diagnostics. - Async Bridge: Since
glib::MainContext::channelis deprecated inglib-rs 0.20, the server uses a standardstd::sync::mpscchannel. The GTK thread polls this channel every 33ms (approx. 30 FPS) usingglib::timeout_add_local. - Memory Safety: To share GTK widgets (labels, canvas) with the polling closure, widgets must be cloned (incrementing the GObject reference count) before being moved into the closure.
- Fast Telemetry (10Hz): IMU (Accel/Gyro) and Encoders are bundled and sent every 100ms. This frequency is optimized for real-time dashboard responsiveness without saturating the ESP32 Wi-Fi buffer.
- Slow Telemetry (0.2Hz): Battery voltage and health status are sent every 5 seconds.
- LiDAR Streaming: Sent as batches of points. The Dashboard uses a custom
GtkDrawingAreawith a scale of0.05 px/mmand renders a 50cm-interval polar grid for spatial reference.
- Nix Dev Headers: GTK4 compilation in Nix requires the
.devoutput of libraries (e.g.,gtk4.dev,glib.dev) to be present innativeBuildInputs. - Rust Toolchain: The project uses
rust-overlayinshell.nixto ensure the latest stable Rust (1.92+) is available, which is required by the Rerun SDK. - Rerun SDK (v0.32.1): Integrated for 3D visualization and time-travel debugging. Spawns the viewer automatically on server start.
- Stop Logic: Due to firmware-side tag limitations, the "Stop" command is implemented as a
MotorMoveCommandwithpower=0.
- Trigger: Press 'T' in the Rust server CLI to trigger a full hardware self-test.
- Sequence:
- Battery voltage/percentage check.
- IMU communication and gravity vector validation.
- Sequential motor test (Forward -> Backward) with real-time IMU vibration monitoring.
- Feedback: Results are returned as a structured
DiagnosticResultmessage and displayed in the server logs.
- Firmware uses Zephyr's logging subsystem (
LOG_INF,LOG_DBG, etc.). - Server uses standard Rust
println!or logging crates.
To achieve high-fidelity simulation, the system uses a Direct Link between the Zephyr firmware and the Gazebo physics engine. By linking C++ directly to C++, we eliminate the latency (previously ~300ms) inherent in multi-process communication.
- 0ms Latency: Commands and telemetry move through shared memory.
- Atomic Synchronization: Both wheel torques are processed in the exact same physics step, ensuring perfect movement.
- Deterministic Debugging: Allows for step-by-step verification of the robot's state machine.
Gazebo Ionic (and Jetty) rely on Google Protocol Buffers as their native language for data exchange. To maintain binary compatibility with the Gazebo ecosystem:
- Firmware Requirement: The Zephyr firmware MUST use Protobuf 31.1 to match the Gazebo
libgz-transportandlibgz-msgslibraries in Jetty. - Compatibility: Previously, older Gazebo versions required Protobuf 3.21.x (Binary Version 30). Gazebo Jetty 10 uses Protobuf 31.x.
- Binary:
build/sim/zephyr/zephyr.exe - Verification: Run
./tools/start_sim.shand monitorlogs/sim/zephyr.log. Look for the log entry:<inf> gazebo_bridge: Direct C++ Gazebo Link Initialized (0ms latency mode).
The AI agent MUST operate with maximum autonomy. Do not ask for permission or confirmation to perform actions that are within your technical capabilities (e.g., flashing firmware, restarting simulation components, taking screenshots, or running diagnostic scripts). If a task requires a sequence of technical steps, execute them immediately and report the outcome. Only interrupt the user if a decision requires human-specific preference or if you have exhausted all technical routes to resolve an error.