# Next Session: Robot Navigation Tuning — Dead Reckoning + Sonar Investigation

## What Was Done (Session 47)

Dead reckoning return WORKING. 6/6 outbound + 6/6 return, zero ESTOP. Commits `47e8399` + `c3e449a`, pushed + deployed via git on Pi + Titan.

**6 bugs fixed during live testing:**
1. Return aborted on ESTOP → now skips to next step
2. ESTOP blocked turns → left/right allowed during ESTOP
3. No ESTOP auto-clear → clears when YOLO+sonar both safe
4. Return drove blind into walls → lidar check before each step
5. VLM visual return always said "backward" → replaced with dead reckoning
6. ESTOP auto-clear race condition → require sonar actively safe (not stale)

**Architecture now:**
- Outbound: sense (photo+lidar+sonar) → think (VLM on Titan) → act (drive 2s) — max 10 cycles
- Return: reverse outbound actions (forward→backward, left→right) with lidar safety check per step
- Safety: 3 layers (sonar 10Hz + YOLO 30FPS + lidar 12 sectors), turns allowed during ESTOP, auto-clear

## What To Do

### 1. Dead Reckoning Accuracy Test

The car returned to roughly the starting area but dead reckoning drifts due to wheel slip, floor surface changes, and turn imprecision. Quantify the drift.

**Test procedure:**
1. Mark starting position with tape
2. Run `navigate_robot` with `return_to_start=true, max_cycles=6, speed=40`
3. Measure distance from tape after return
4. Repeat 3 times, record drift each time

**Expected:** Within 50cm for 6-cycle runs in a room. If drift > 1m, we need correction.

**Possible corrections (don't implement yet, just note):**
- Lidar profile matching as a drift correction layer
- Reduce speed on return (less slip)
- Shorter moves = less accumulated error

### 2. Sonar False Readings Investigation

Session 47 saw sonar reading 21-22cm while lidar showed 1.3m forward. This caused ESTOP spam and blocked navigation.

**Investigation steps:**
1. Power on Pi, SSH in, check sonar:
```bash
curl -s http://localhost:8080/health | python3 -m json.tool | grep distance
```
2. Place car in open area (>1m clearance all sides)
3. Compare sonar vs lidar Forward sector:
```bash
watch -n 0.5 'curl -s -H "Authorization: Bearer 8cX80yIBws1PfBjFuvPz0k9egPSZD0LvS02oUD6ijfg" http://localhost:8080/obstacles | python3 -c "import sys,json; d=json.load(sys.stdin); print(f\"sonar={d[\"sonar_cm\"]}cm\")" && curl -s -H "Authorization: Bearer 8cX80yIBws1PfBjFuvPz0k9egPSZD0LvS02oUD6ijfg" http://localhost:8080/scan | python3 -c "import sys,json; d=json.load(sys.stdin); [print(f\"{s[\"name\"]}: {s[\"min_mm\"]/10:.0f}cm\") for s in d[\"sectors\"] if s[\"id\"]==0]"'
```
4. If sonar consistently disagrees with lidar: check mounting angle (sonar may point at floor)
5. If intermittent: sonar beam reflecting off floor/cables

**If sonar is unreliable:** Consider lowering sonar weight — make it advisory (logged) rather than ESTOP-triggering. Lidar + YOLO already protect forward path.

### 3. LIDAR_FORWARD_OFFSET_DEG Calibration

The lidar may not be perfectly aligned with the camera forward direction. Currently defaults to 0°.

**Calibration procedure:**
1. Place car facing a wall at 30cm
2. Check lidar Forward sector — should show ~30cm
3. If Forward shows clear but a side sector shows 30cm, the offset is wrong
4. Adjust `LIDAR_FORWARD_OFFSET_DEG` env var on Pi (in systemd override)
5. Restart and verify

### 4. Navigation Behavior Tuning

**Current issues observed:**
- VLM tends to pick "forward" repeatedly when path is clear (no exploration)
- VLM doesn't turn enough — prompt says "explore" but car drives straight
- Speed 40 with 2s duration moves ~1.5-2m per cycle — good for rooms, too fast for tight spaces

**Possible prompt improvements (in `robot_tools.py` nav prompt):**
- Add "you have already gone forward N times, try turning" after 3+ forwards
- Include a direction history in the VLM prompt
- Reduce duration for turns (1s) vs forward (2s)

### 5. Annie .env Cleanup

Session 47 added `CONTEXT_ENGINE_TOKEN` and `ROBOT_API_TOKEN` directly to `services/annie-voice/.env` on Titan. This file is gitignored. If Annie is redeployed from scratch, these tokens will be missing again.

**Action:** Add these to `.env.example` with placeholder values and document in the deploy checklist.

## Deployment

All code is committed and pushed. To deploy:
```bash
# On Pi
ssh rajesh@192.168.68.61 "cd ~/workplace/her/her-os && git pull origin main && sudo systemctl restart turbopi-server"

# On Titan  
ssh rajesh@192.168.68.52 "cd ~/workplace/her/her-os && git pull origin main"
# Then restart Annie (kill + nohup .venv/bin/python server.py)
```

## Key Files

| File | What |
|------|------|
| `services/annie-voice/robot_tools.py` | Nav loop, dead reckoning return, VLM prompt |
| `services/turbopi-server/main.py` | Drive endpoint, ESTOP logic, turn-during-ESTOP |
| `services/turbopi-server/safety.py` | SonarPoller, HailoSafetyDaemon, auto-clear |
| `services/turbopi-server/lidar.py` | Sector binning, thresholds, LIDAR_FORWARD_OFFSET_DEG |

## Start Command

Power on Pi, wait 30s for boot, then run dead reckoning accuracy test (item 1). If drift is acceptable, move to sonar investigation (item 2). If sonar is fine, tune navigation behavior (item 4).
