Notes for people and agents who pick up this project later: what the system looks like now, how it got there, what was tried and dropped, the measurements behind decisions and the incidents with their root causes. The how-to material (deploying, operating, developing) lives in AGENTS.md, .claude/skills/* and workspaces/forge/README.md; this folder is the history and the reasoning.
Open questions, unresolved problems and on-robot checks: open-issues.md. What to do next: roadmap.md.
Conventions: dates in file names and timestamps are UTC unless marked otherwise; the robot and its owner are in Sydney (AEST, UTC+10, AEDT from 4 October 2026). Commit hashes refer to this repository. Everything after commit b36435d (2026-10-02 00:49 UTC) was uncommitted when these notes were written (2026-10-03); those entries name files instead of commits. Reports referred to as ~/projects/rabbit/data/offline/... are kept outside the repo because they contain maps and data of the flat.
What's next: roadmap.md.
| Entry | Topic |
|---|---|
| 2025-05-18 hardware and stack history | hardware, the move from Raspberry Pi to Jetson, ROS 2 → NATS, state after five months off |
| 2026-10-01 revival and telemetry | node rewrite, RoboClaw/INA/IMU telemetry, jetson_clocks, TLS and Chrome |
| 2026-10-01 ZED spatial mapping | SDK 5.5, room map, memory, quality tuning, mesh filter, chunk format (superseded) |
| 2026-10-01 driving, nav and safety | nav node, missions, swept-arc guard, wall crash, calibration, rear-axle tracking |
| 2026-10-01 exploration and Hybrid A* | frontier exploration and the planner kernels |
| 2026-10-01 Forge | ClickHouse writer, slabs, MCP, chat agent, anomalies, moving onto the robot |
| 2026-10-01 HUD | 3D HUD, chat panel, minimap, voxel map, objects |
| 2026-10-01 lag and Wi-Fi | the lag hunt, Wi-Fi drops, TX power |
| 2026-10-01 public access | Cloudflare tunnel, access links, HTTP/2 |
| 2026-10-01 map resets | every map reset or loss and its cause |
| 2026-10-01 deploy and agent workflow | deploy script, parallel agent sessions |
| 2026-10-02 Jetson performance | clocks, IRQs, headless, the clock-floor incident, OC3, JetPack assessment |
| 2026-10-02 ZED optimisation | CPU, GIL, frame rates, depth, GEN_3 keyframe leak, map modes |
| 2026-10-02 nvblox | nvblox extension, clearance grid, reflections, debris |
| 2026-10-02 floor estimation | floor origin, per-frame floor plane, robot on a table |
| 2026-10-02 route planner | rabbit-planner: trips to points, places and objects; replay |
| 2026-10-02 object detector | YOLOE in the ZED SDK, filtering, objects in Forge |
| 2026-10-02 voice agent | Realtime voice, spoken approvals, robot prompt |
| 2026-10-02 relocalization | millimetre poses, false relocalization, give-up rules |
| 2026-10-02 odom/map split | nav on continuous odometry |
| 2026-10-02 operator heartbeat removal | the HUD is a viewer |
| 2026-10-02 NATS/Docker latency | latency audit and NATS settings |
| 2026-10-02 SLAM survey and benchmark | cuVSLAM / RTAB-Map vs ZED GEN_3 (in progress) |
| 2026-10-03 motor slew limit | smoothing bursty joystick commands |
| 2026-10-03 Forge on Parquet and chDB | ClickHouse server replaced by Parquet files and embedded chDB: design, parity, memory |
| 2026-10-03 Jetson diet and Python 3.12 | trimming host services, journald, logrotate, image pruning; Python 3.12 patch |
| 2026-10-03 field session | boot after a move, recordings, nav safety trips, far-floor phantom obstacles |
| 2026-10-03 power rails | battery, motor, servo and Jetson currents from telemetry; the motor buck at its limit, the battery shunt near its range |
| 2026-10-03 Rabbit 2.0 made buildable | Pi 4 body: BOM, pinout and buses, fail-safe E-stop, NATS hub + leaf, INA4235 channels and shunts, wiring diagrams |
| 2026-10-03 nav replay | offline replay of the day's trips: recovery along the trail, turnaround loops, stuck, IMU thresholds |
| 2026-10-03 full-stack simulator | rabbit-sim + local NATS + the real nav/planner/explore on the Mac, end-to-end tests |
| 2026-10-03 observability | structured events with reasons and ids, node metrics, start snapshots, events / node_starts / node_metrics / nats_server in Forge |
| 2026-10-03 phase 0 tools | INA per-channel shunts and clipped, duty cap 12 V / V_supply, RoboClaw config tool (3 A, NVM), encoder check |
| 2026-10-03 printed mounts | Rabbit 2.0 brackets in cad/brackets/: ToF pairs, compliant bumpers with D2F switches, lidar mast (scan plane 230 mm), button pod, rear camera mount, body-PCB clips and grommets; fit checks against the 3-deck stack with the PCB STEP; the USB hub has no place yet |
| 2026-10-03 body PCB | deck-2 board for Rabbit 2.0 generated by code (KiCad 10 + Freerouting): Pi, RoboClaw, regulators, fuses, INA4235, PCA9685; stack heights, current paths, DRC clean, JLCPCB outputs |
| 2026-10-03 body PCB review | independent pre-order review of rev A: pin-by-pin checks pass; fixed input TVS, ToF and 5 V rail resistance, motor star, stale net classes, ZED cut-out, INA4235 paste, BOM; PCA9685/INA4235 stock blocks JLC assembly; factory-assembly options and rev B lessons |
| 2026-10-03 BLDC drive study | why the 37D 70:1 is slow and loud, torque/speed needs per wheel, the motor mount measured in the chassis model, BLDC/brushed/gimbal options, DRV8316 + STM32G4 on the body PCB, regen with a V-mount BMS; report reports/2026-10-03-bldc-drive.md |
| 2026-10-03 BLDC drive mount | final BLDC choice (maxon ECX FLAT 22 L + GPX 22 LN 16:1 + ENX 22 MILE; Faulhaber 3216 fallback), new 6061 bracket with its own wheel bearings and an Oldham coupling inside a hollow stub axle, printed test-fit variant, fit check in the widened chassis, wiring to the rev B connectors; cad/drive/ |
| 2026-10-10 BLDC drop-in | BLDC that fits the existing 37D bracket and wheel hub: Pololu face re-measured from the STEP, JGB37 bare-BLDC makers (Kechen, Chihai), adapter-plate route for maxon GPX 22 UP / Faulhaber 22GPT; report reports/2026-10-10-bldc-drop-in.md |
| 2026-10-10 body PCB rev C | RoboClaw removed; deck-2 board (140 × 314 mm, ZED 2i on the nose) with STM32G474 + 2 × DRV8243 for the kit JGB37-520 motors, an eFuse with current readback on every load (10 × TPS25947, 2 × TPS16630, LM5069 motor bus, 2 × ADS7128), 4 × INA238, 6 ToF ports on brackets (mux on Pi I2C6), 3 lidar (XH-5), 8 servo ports, xArm 1S bus, vertical connectors only, Pi 4 on board powered over USB-C; two review rounds; 667 parts, all 159 BOM lines in JLC stock; 8 layers, routing in progress; spec reports/2026-10-10-body-pcb-rev-c.md, project pcb/rabbit-body-c |
| 2026-10-11 rev C bring-up plan | step-by-step first power-up of rev C: pre-power resistances (workspaces/bench/pcb-bringup/rail_resistance.py), rails, eFuses, MCU, motors, servos, arm, sensors; expected values with sources; risks P29–P34 |
| 2026-10-10 ToF carrier | 22 × 18 mm VL53L8CX carrier for the body board's GH-6 ToF ports: 3.3 V alone is not allowed (CORE/IOVDD 1.98 V max), so LP5907 1.8 V with an RC-delayed enable for the DS slew rule and an LSF0204 translator; routed, DRC clean, JLC outputs; port J1 is the HCTL HC-GH-6PLT (GH-compatible, in JLC stock) like the body board's six ToF ports; project pcb/rabbit-tof |
| 2026-10-11 blog SEO | rabbit0.dev: a page per post, canonical/hreflang per language, JSON-LD, sitemap, Atom feeds, icons, 404; 640/1280 px previews with a PhotoSwipe lightbox; built in CI, outputs gitignored; dependencies updated |
| 2026-10-03 body software | Rabbit 2.0 body written offline: rabbit-lidar (RPLIDAR C1 protocol, timestamps, de-skew), rabbit-tof (VL53L8CX ×4, floor rejection), rabbit-safety (50 Hz arbiter, caps by clearance and input freshness, E-stop line self-test), rabbit-power (shutdown state machine), fake GPIO/serial/ToF backend, lidar/ToF/bumpers in the simulator, nav and planner on the lidar scan, Forge tables, Pi compose and deploy; Raspberry Pi kernels keep GPIO outputs after a crash |
| 2026-10-03 body PCB rev B | deck-2 board rev B: STM32G474 + 2× DRV8316 BLDC drive with hardware E-stop and brake chopper, LM74800 soft-latch switch, LM61495 bucks, TPS16630 Jetson eFuse, 4× INA226, SMD fuses, GND_MOT island; everything JLC-stocked and JLC-assembled; Freerouting fed filled pours |
lessons.md collects the hard-won rules in one list.
Jetson Orin Nano Super 8 GB (MAXN_SUPER, clocks pinned, headless), ZED 2i on USB, RoboClaw 2x30A on the UART, PCA9685 steering servo, INA4235 power monitor, 99 Wh 4S Li-ion pack, Wi-Fi only. Wheel encoders do not count; speed comes from the camera pose. Details in the hardware entry.
| Service | Role |
|---|---|
nats, nats-init, nats-dashboard |
message bus; KV bucket rabbit, JetStream LOGS (7 days) |
rabbit-zed |
the only camera process: GEN_3 tracking and relocalization, depth (NEURAL_LIGHT, every 2nd frame), nvblox mapping (C++/CUDA extension), floor estimation, obstacle scan, YOLOE object detection, preview, SVO recording, health |
rabbit-nav |
missions (move, turn, goto, path), path tracking on the rear axle in the odometry frame (curvature feedforward + feedback), swept-footprint collision guard with blind-zone memory, stall and bump trips |
rabbit-planner |
Hybrid A* trips to points, saved places and objects; replanning and recovery |
rabbit-explore |
exploration by expected information gain per metre, through planner trips |
rabbit-roboclaw, rabbit-steering |
motors (electronic differential, slew limiting, kill switch) and the servo |
rabbit-ina, rabbit-telemetry |
power at 50 Hz; Jetson, containers and Wi-Fi at 1 Hz |
forge |
NATS → Parquet writer, compaction, chDB queries, chat/voice agent API, in one process |
rabbit-web |
nginx: the built HUD, /api → chat, /nats → NATS websocket, access-link gate |
tunnel |
Cloudflare tunnel (HTTP/2) to https://live.rabbit0.dev |
All rabbit-* nodes share one image with the code bind-mounted; a code change needs a container recreate, not a rebuild.
- Sensors:
rabbit.zed.pose(map pose plus anodomsub-object; floor at y = 0, camera at y ≈ 0.137),rabbit.zed.imu,rabbit.zed.obstacle(48-bin scan over ±60°, obstacles 4–45 cm above a per-frame floor plane),rabbit.zed.objects,rabbit.health.zed(fps,spatial_memory_status,relocalizing,map_mode,map_id, nvblox timings),rabbit.roboclaw,rabbit.ina,rabbit.steering,rabbit.telemetry. - Commands:
rabbit.cmd.joy(owns the motors for 1 s),rabbit.cmd.drive,rabbit.nav.mission,rabbit.nav.cancel,rabbit.nav.explore,rabbit.planner.goal(request/reply,preview),rabbit.planner.places*,rabbit.zed.wake,rabbit.zed.record. - Map:
rabbit.map.chunks/rabbit.map.snapshot(mesh blocks,<IIIfffheader, int16 mm vertices relative to a per-chunk origin),rabbit.map.grid/.snapshot(int16 mm clearance, 5 cm cells),rabbit.map.save,rabbit.map.reset,rabbit.map.extend(request/reply). - State:
rabbit.nav.state(10 Hz),rabbit.planner.state,rabbit.explore.state, logs onrabbit.log.<node>. rabbit.operator.heartbeatonly raises the idle camera rate; nothing depends on the HUD being open.- Rabbit 2.0 body (written and simulated, not deployed):
rabbit.lidar.scan(binary rotation, Pi clock),rabbit.tof(per-sensor frames with obstacle points),rabbit.safety.drive/.state/.estop/.reset,rabbit.power.state/.request/.jetson,rabbit.health.lidar/.tof; contracts in log/2026-10-03-body-software.md. nav and the planner already takerabbit.lidar.scanwhen it appears.
ZED depth + GEN_3 pose → plausibility filter (millimetre poses, jump gate) → floor estimator → nvblox TSDF/ESDF on the GPU (5 cm voxels, rays clipped at the floor, integration up to 5 m) → mesh blocks for the HUD and the 2D clearance grid for the planner. The SDK area memory (room.area) provides relocalization after restarts; map_mode keeps it in localization by default and extends it only for a new map or exploration (GEN_3 keeps adding keyframes otherwise). Saved state in data/map/: room.area, room.nvblx, room.id, room.ply, archive/ (last 5). Relocalization counts after 10 s of a localized status; it gives up after 3 m of travel or 45 s and starts a new map.
Hybrid A* (numba) on the clearance grid with asymmetric curvature tables, costs that keep to the middle of gaps, reverse only into mapped space, Dijkstra heuristic; plans in 5–80 ms typically on the Jetson. Trips replan on new obstacles, pose jumps and blocks, back up along their own trail, and hold before long detours. Object goals come from Forge's object memory.
Parquet files on the robot (one file per table and hour every 10 s, merged hourly), queried in-process with chDB; one container of about 300 MB instead of ClickHouse, writer and chat (600–850 MB). See 2026-10-03 Forge on Parquet and chDB. Slabs, a static SQL gate plus EXPLAIN, a metric graph with investigate, Chronos-2 anomaly detection, MCP tools, a chat agent (OpenAI via the Vercel AI SDK) and a Realtime voice agent, both with approval cards for motion. Every node records its decisions as structured events with a reason, ids and the measured values (events), its start snapshot (node_starts) and its process health (node_metrics); conventions in reports/2026-10-03-observability.md.
React/three.js at https://jetson.rabbit (LAN) and https://live.rabbit0.dev (access link required): 3D view with a voxel or surface map, minimap, objects, panels with uPlot charts, gamepad/keyboard driving, AI LINK chat with voice.
- Forge storage cutover to Parquet + chDB is staged but not switched (runbook:
reports/2026-10-03-forge-cutover-runbook.md). Until it's done, don't runscripts/deploy.shwithout arguments or withforge-*: the working tree's Forge code no longer runs in the old alpine containers. Deployingrabbit-*services is safe.forge-shadow(the new writer) starts on boot. - Localization replacement: odometry from cuVSLAM or ZED VIO plus RTAB-Map as the global localizer, being benchmarked on recorded SVOs; ground-truth floor markers and wake-up sessions still to record.
- Commit the work since
b36435d(planner node, nvblox extension, detector, voice, access links, relocalization fixes, odom split). - Make
rabbit-zedsurvive an nvblox CUDA out-of-memory. - Wi-Fi in the far part of the flat (router RSSI settings, antennas or another card).
- Actual clocks and OC counters in Forge; Python 3.12; Docker image cleanup; RTC battery and persistent journal.
poseEuler angles in Forge: rows recorded before the writer fix of 2026-10-03 hold yaw inpitch_deg, roll inyaw_degand pitch inroll_deg(ZEDeuler_degis rotation about x, y, z in the Y-up frame: pitch, yaw, roll); newer rows are correct.- Encoders read 0; the magnetometer is not calibrated.
- Rabbit 2.0 body software (
safety,power,lidar,tofnodes,workspaces/body/) waits for the parts; bring-up checks are open-issues V7–V12. - Body PCB rev B (
pcb/rabbit-body/, BLDC drive on board) is designed, not ordered; it needs MCU firmware andina.pyfor INA226 before it can replace the RoboClaw setup (reports/2026-10-03-body-pcb-rev-b.md§12).