diff --git a/CONTEXT.md b/CONTEXT.md index 645df06..07a957f 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -311,7 +311,7 @@ unrelated photo scored 0.16. **Nobody is enrolled yet**; the owner enrols themse resolution). The solver recovers a known synthetic camera to within 1%. It needs the owner holding a board in front of the camera, and the lens focus set first (the lens turns if not glued; earlier close-range frames were blurry). V2's perception needs the result. -2. Waiting on hardware: the servos (`hermes_head`, the pan/tilt URDF, then `head: true`), the speakers +2. Waiting on hardware: the servos (see "Arrival day" above), the speakers (playback, echo cancel, the `robot_mic` naming on the host, Hermes talking aloud), the fan (before any enclosure), the splitter, the printed enclosure (measure first, see `enclosure/README.md`). 3. Still open: replug and second-host recovery of the USB link, the serial console login, an @@ -321,6 +321,39 @@ unrelated photo scored 0.16. **Nobody is enrolled yet**; the owner enrols themse 4. A new Omarchy host with a GPU (it runs the local `ornith` model) is arriving: it needs only `host/omarchy/robot-usb-link.sh` and its SSH key added to the Pi. +## Arrival day: the neck (servos), planned and deliberately not built ahead of the hardware + +The servos are expected Thursday or Friday at the earliest. The real unknowns cannot be faked (which +`pwmchip` the overlay creates, its permissions on Ubuntu, each servo's real pulse range, whether the +servos brown out the Pi), so `hermes_head` waits for the hardware. The order, with what to verify at +each step: + +1. **Wire it:** pan servo to the HAT's GPIO12 port, tilt to GPIO13; the "3pin Volt" jumper is already + verified at 5 V. Power matters: servo spikes on a host USB port may brown the Pi out, so use the + 5.1 V 3 A supply through the splitter if it has arrived. Horns off for the first moves. +2. **Overlay (needs a reboot, ask first):** add `dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4` under + `[all]` in `/boot/firmware/config.txt` (`dtparam=audio=off` is already set; the Pi's headphone audio + shares PWM hardware). Add it to `pi/install-*.sh`, not by hand. +3. **sysfs:** find the chip (`/sys/class/pwm/pwmchip*`; it was not assumed to be 0), export channels 0 + and 1, `period=20000000`. Add a udev rule that gives a group (not root) write access, as Ubuntu's + defaults differ from Raspberry Pi OS. +4. **Measure each servo:** centre (1.5 ms), then find the safe min and max pulse with the horn off; set + `ROBOT_SERVO_MIN_US` / `MAX_US` per servo (start 500 / 2400), the pan and tilt trims and invert flags. +5. **Write `hermes_head`:** `PwmHead` on sysfs, a ~0.3 s interpolated move, PWM off after ~1 s idle (stops + hold-jitter), limits (pan 80, tilt 45), `/joint_states` for `pan_joint` / `tilt_joint` in radians. + Convention (the MCP contract): positive pan = the robot's left, positive tilt = up. Unit-test the + logic against a fake sysfs tree, then verify on the Pi: `vcgencmd get_throttled` must stay `0x0` + through a full sweep while the face is running. +6. **Wire it in:** the bridge refuses `head: true` today. Give it a head backend that calls + `hermes_head`, set `head: true` in `robot.yaml`, and check `turn_head` / `head_position` appear and + that a new Hermes session sees them. Check the face's eyes follow the real joints the right way + (the sign was fixed in software, never seen with a moving head). +7. **URDF:** `hermes_description` from the enclosure STLs' `pose_*` parts, frames `base_link`, + `pan_link`, `tilt_link`, `camera_link`, `camera_optical_frame`, so `/tf` follows the head. +8. **Mounted camera:** set the flip (`orientation` parameter) for how it is actually mounted, re-check + the focus (a changed focus invalidates `pi/calibration/`), and set `ROBOT_FACE_ROTATION` if the + display ends up mounted differently from the portrait pose. + ## Repository Branch `master`. `.gitignore` covers `.remember/`, caches, `.venv/`, `*.orig`, `*.rej` and