Bring every doc up to date, and give the repo a Wi-Fi template that exists
CONTEXT.md had grown by appending and contradicted itself (all four nodes vs six, a retracted CPU figure, "no calibration", "nobody enrolled", "audio untested as a service", the Wi-Fi-off boot as not done, a class the tracker replaced). Rewritten as one current-state document organised by subsystem, with fresh measurements, the owner's decisions, the gotchas, the neck's arrival-day plan and what is genuinely still open. README: status, speakers not fitted, new-session note for Hermes, the calibration section (shipped calibration, coverage hints, outlier dropping, --from-views), running the tests, the docs row. HANDOFF.md gets a status banner listing where the original brief has drifted. CLAUDE.md starts at CONTEXT.md. The echo-cancel config no longer talks about a Pi Zero, and the enclosure guide no longer tells you to centre a servo with a tool that does not exist yet. pi/network-config.example is a tracked, credentials-free first-boot template: the README pointed at pi/50-cloud-init.yaml, which is gitignored and so missing from a fresh clone. The dead IdentityCache (replaced by the tracker) is removed. Docstrings corrected: audio scope publishing, the MCP health topics, and what the calibration tool does. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AFN8nRRCiDiMN7ChBpHJhs
This commit is contained in:
@@ -9,7 +9,7 @@ through MCP.
|
||||
connected), idle, listening, thinking, looking, speaking. The mouth draws the actual voice, and the
|
||||
eyes glance toward whoever the camera sees.
|
||||
- **Ears and voice:** the HAT's two microphones and speakers, shared with your computer as ordinary
|
||||
audio devices.
|
||||
audio devices (the speakers are not fitted yet; the microphones work).
|
||||
- **Neck:** pan and tilt servos (`turn_head`), once they are fitted.
|
||||
- **One cable:** USB-C carries power and a private network link to your computer. Wi-Fi is a fallback.
|
||||
|
||||
@@ -21,8 +21,8 @@ only speaks MCP.
|
||||
| Works and is tested | Waiting on hardware |
|
||||
|---|---|
|
||||
| Face on the display, always on at power-up, with a sleeping pose | Servos: `turn_head`, `head_position`, the pan/tilt URDF |
|
||||
| Camera, face detection, opt-in recognition of people you enrol | Speakers: playback, echo cancel, Hermes talking out loud |
|
||||
| Eyes follow faces; mouth draws your live voice | Fan (the Pi runs at about 62 °C open-air without one) |
|
||||
| Camera (calibrated), face detection, opt-in recognition of people you enrol | Speakers: playback, echo cancel, Hermes talking out loud |
|
||||
| Eyes follow faces; mouth draws your live voice | Fan (the Pi runs at about 60 °C open-air without one) |
|
||||
| MCP bridge: `hermes mcp test robot` passes, real Hermes turns call `look()` and `faces()` | USB-C splitter (the Pi is powered from your computer's port for now) |
|
||||
| Thermal guard: slows the camera, face and detector before the Pi throttles | |
|
||||
| USB network link, firewall, boots and works with Wi-Fi off | Printed enclosure (`enclosure/`) |
|
||||
@@ -71,8 +71,8 @@ door.
|
||||
1. **Flash** Ubuntu Server 24.04 for the Pi (arm64, preinstalled image) and check its SHA256.
|
||||
2. **Configure first boot** on the card's `system-boot` partition. In `user-data`, create the user
|
||||
`hermes` with key-only login and the hostname `hermes-bot`. For Wi-Fi, put the access point in
|
||||
`network-config` (a template is `pi/50-cloud-init.yaml`; it holds your password, so it is
|
||||
gitignored). cloud-init applies these on the *first* boot only: to change Wi-Fi later, edit
|
||||
`network-config` (copy `pi/network-config.example` and fill it in; keep a filled copy out of the repo: `pi/50-cloud-init.yaml`
|
||||
is gitignored for that). cloud-init applies these on the *first* boot only: to change Wi-Fi later, edit
|
||||
`/etc/netplan/50-cloud-init.yaml` on the Pi.
|
||||
3. **Boot, then copy this repo to the Pi and run the installer:**
|
||||
|
||||
@@ -90,9 +90,10 @@ door.
|
||||
|
||||
1. **Network link:** `sudo host/omarchy/robot-usb-link.sh` gives your end of the link `10.55.0.1/30`,
|
||||
matched by the gadget's fixed MAC, so any port and any machine works. The robot is `10.55.0.2`.
|
||||
2. **Hermes:** the token is in `/etc/robot-mcp.env` on the Pi. Put it in `~/.hermes/.env` as
|
||||
`ROBOT_MCP_TOKEN=`, and merge `host/omarchy/hermes-config-snippet.yaml` into
|
||||
`~/.hermes/config.yaml`.
|
||||
2. **Hermes:** the token is in `/etc/robot-mcp.env` on the Pi (`ssh hermes@10.55.0.2 sudo cat
|
||||
/etc/robot-mcp.env`). Put it in `~/.hermes/.env` as `ROBOT_MCP_TOKEN=`, and merge
|
||||
`host/omarchy/hermes-config-snippet.yaml` into `~/.hermes/config.yaml`. Start a new Hermes session
|
||||
afterwards: a session keeps the tool list it started with.
|
||||
3. **Audio (optional, needs the speakers):** `host/omarchy/50-robot-tunnel.conf` makes the robot's
|
||||
microphone and speaker appear as devices; `host/omarchy/hermes-robot` starts Hermes with them as
|
||||
the defaults.
|
||||
@@ -137,27 +138,37 @@ give MCP images to the main model: it saves the photo to its image cache and the
|
||||
restart robot`.
|
||||
- **Enrol yourself** so the eyes prefer you (numbers only are stored, never photos, in
|
||||
`~/.local/share/hermes/faces.json`): on the Pi, with the robot running and after `source
|
||||
~/robot-env.sh`, `python3 -m hermes_vision.people enroll YOURNAME`. `list` shows who is enrolled, `forget YOURNAME` removes you.
|
||||
~/robot-env.sh`, `python3 -m hermes_vision.people enroll YOURNAME`. `list` shows who is enrolled;
|
||||
`forget YOURNAME` removes you. Enrolling is deliberately not an MCP tool: a prompt must not be able to
|
||||
teach the robot a face.
|
||||
- **Update the code:** `rsync -a --delete --exclude __pycache__ ros/ hermes@<pi>:~/ros_ws/src/`, then
|
||||
`colcon build --symlink-install` in `~/ros_ws`, then `sudo systemctl restart robot`.
|
||||
- **Run a node by hand:** `source ~/robot-env.sh` first: it puts the libcamera fork and the right
|
||||
OpenCV on the path, and keeps ROS local.
|
||||
- **Run the tests:** on the Pi, after `source ~/robot-env.sh`, `python3 -m pytest test` in each package
|
||||
under `~/ros_ws/src/` (the face suite takes about a minute). A shell that sourced the environment
|
||||
before a package was built cannot import it: source again.
|
||||
|
||||
## Calibrating the camera
|
||||
|
||||
Needed once, and again if you change the lens focus or the image size. Set the focus first (the lens
|
||||
turns if it is not glued: focus at the distance you will use), then show `docs/checkerboard-9x6.png`
|
||||
on a screen (or print it) and measure one square with a ruler. With the robot running, on the Pi, after
|
||||
`source ~/robot-env.sh`:
|
||||
This camera's calibration ships in `pi/calibration/` and the installer restores it, so a fresh install is
|
||||
already calibrated. Redo it if you change the lens focus, the image size or the camera: a changed focus
|
||||
invalidates it. Set the focus first (the lens turns if it is not glued: focus at the distance you will
|
||||
use), then show `docs/checkerboard-9x6.png` on a screen (or print it) and measure one square with a
|
||||
ruler. With the robot running, on the Pi, after `source ~/robot-env.sh`:
|
||||
|
||||
```
|
||||
python3 -m hermes_vision.calibrate --cols 9 --rows 6 --square-mm <measured>
|
||||
```
|
||||
|
||||
Hold the camera 25 to 60 cm from the board and vary distance, tilt and position, keeping all of it in
|
||||
view. It collects 20 different views, solves with OpenCV and writes
|
||||
`~/.ros/camera_info/ov5647__base_soc_i2c0mux_i2c_1_ov5647_36_1296x972.yaml`. A reprojection error under
|
||||
about 0.5 px is good. `sudo systemctl restart robot` to load it.
|
||||
Hold the camera 25 to 60 cm from the board and vary distance, tilt and position, **including the edges
|
||||
and corners of the camera's view** (the tool says which regions are still uncovered), and hold still:
|
||||
blurred views are dropped as outliers. It collects 24 different views, solves with OpenCV (holding the
|
||||
`k3` distortion term at zero, which a lens this mild does not need) and writes
|
||||
`~/.ros/camera_info/ov5647__base_soc_i2c0mux_i2c_1_ov5647_36_1296x972.yaml`, plus the collected views so
|
||||
`--from-views FILE` can re-solve them without recapturing. A reprojection error under about 0.5 px is good.
|
||||
The square size only scales distances, not the lens model, so an approximate measurement is fine.
|
||||
`sudo systemctl restart robot` to load it, and copy the YAML into `pi/calibration/` to keep it.
|
||||
|
||||
## Tuning and troubleshooting
|
||||
|
||||
@@ -205,5 +216,5 @@ about 0.5 px is good. `sudo systemctl restart robot` to load it.
|
||||
| `pi/` | Everything installed on the Pi: `install.sh` and its parts, services, firewall, overlays. |
|
||||
| `host/` | Your computer's side: the USB link script, Hermes and PipeWire config, a platform check. |
|
||||
| `enclosure/` | OpenSCAD model, STLs and the print guide. Built from estimates: measure before printing. |
|
||||
| `docs/face-prototype.html` | The browser prototype the face was ported from. |
|
||||
| `docs/` | `face-prototype.html` (the browser prototype the face was ported from) and `checkerboard-9x6.png` (for calibration). |
|
||||
| `HANDOFF.md` | The original implementation brief. `CONTEXT.md` tracks where things really stand. |
|
||||
|
||||
Reference in New Issue
Block a user