Clean out the Pi Zero leftovers, rewrite the README, and add the one installer
Wi-Fi-off acceptance passed: with Wi-Fi blocked, live and after a reboot, the Pi came up on the USB link alone, every node ran, and hermes mcp test robot and look() worked. (A temporary guard that would have unblocked Wi-Fi was the safety net and is removed; Wi-Fi is back on.) Delete what the ROS design superseded: the Picamera2 MCP server and its unit, the old installer and requirements, and the duplicate platform check. Move omarchy/ to host/omarchy/. Rewrite README.md for this build: parts, physical steps (including the Audio switch), setup, daily use, the troubleshooting learned the hard way, and the security model. pi/install.sh is now the single installer for a fresh Ubuntu 24.04 image, built from the steps done by hand: ROS, the libcamera fork at a pinned commit, camera_ros, the venv and models, the workspace, USB gadget, audio overlay, firewall (before PipeWire opens a port), PipeWire, mixer and services. Run twice on the live robot, the second run changed nothing and everything stayed healthy. It has not been run on a blank card. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AFN8nRRCiDiMN7ChBpHJhs
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
# ~/.config/pipewire/pipewire.conf.d/50-robot-tunnel.conf (on Omarchy)
|
||||
#
|
||||
# Makes the robot's speaker and microphone appear here as ordinary audio devices,
|
||||
# "Robot speaker" and "Robot microphone". The robot is 10.55.0.2 on the USB link, a fixed address;
|
||||
# the robot's firewall accepts port 4713 only over that link, from 10.55.0.1.
|
||||
#
|
||||
# Apply with: systemctl --user restart pipewire pipewire-pulse wireplumber
|
||||
|
||||
context.modules = [
|
||||
{ name = libpipewire-module-pulse-tunnel
|
||||
args = {
|
||||
tunnel.mode = sink
|
||||
pulse.server.address = "tcp:10.55.0.2:4713"
|
||||
#pulse.device = "robot_ec_sink" # only with the Pi's optional echo-cancel config
|
||||
pulse.latency = 200 # ms; lower is snappier but may crackle on weak Wi-Fi
|
||||
reconnect.interval.ms = 5000 # keep retrying while the robot is off
|
||||
stream.props = {
|
||||
node.name = "robot_speaker"
|
||||
node.description = "Robot speaker"
|
||||
}
|
||||
}
|
||||
}
|
||||
{ name = libpipewire-module-pulse-tunnel
|
||||
args = {
|
||||
tunnel.mode = source
|
||||
pulse.server.address = "tcp:10.55.0.2:4713"
|
||||
#pulse.device = "robot_ec_source" # only with the Pi's optional echo-cancel config
|
||||
pulse.latency = 200
|
||||
reconnect.interval.ms = 5000
|
||||
stream.props = {
|
||||
node.name = "robot_mic"
|
||||
node.description = "Robot microphone"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,24 @@
|
||||
# Merge these into ~/.hermes/config.yaml on Omarchy.
|
||||
# The robot is at 10.55.0.2 on the USB link (the host is 10.55.0.1; see host/omarchy/robot-usb-link.sh).
|
||||
# Put the token in ~/.hermes/.env as: ROBOT_MCP_TOKEN=<64 hex characters>
|
||||
# It lives only on the Pi, in /etc/robot-mcp.env (read it with: ssh hermes@10.55.0.2 sudo cat /etc/robot-mcp.env).
|
||||
# The robot's firewall accepts this port only over the USB link, from 10.55.0.1.
|
||||
# While Hermes holds a connection the robot's face is awake; when it stops, the face falls asleep after
|
||||
# about 40 seconds. A robot with no head fitted offers only look(); turn_head appears when servos do.
|
||||
|
||||
mcp_servers:
|
||||
robot:
|
||||
url: "http://10.55.0.2:8765/mcp"
|
||||
headers:
|
||||
Authorization: "Bearer ${ROBOT_MCP_TOKEN}"
|
||||
connect_timeout: 15
|
||||
timeout: 30 # look() normally answers in about a second
|
||||
|
||||
voice:
|
||||
auto_tts: true # speak replies whenever voice mode is on
|
||||
# The robot's mic sits beside its own speaker. If Hermes interrupts itself,
|
||||
# raise this (default 3.0) or enable the Pi's optional echo-cancel config.
|
||||
barge_in_threshold_multiplier: 4.0
|
||||
# If the level bar barely moves when you speak, lower this (default 200)
|
||||
# or raise the mic volume on the Pi (see README).
|
||||
silence_threshold: 200
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# hermes-robot: start Hermes with the robot as the default speaker and microphone,
|
||||
# then put your usual devices back when Hermes exits.
|
||||
#
|
||||
# Install: install -Dm755 hermes-robot ~/.local/bin/hermes-robot
|
||||
# Use: hermes-robot (any arguments are passed through to hermes)
|
||||
set -uo pipefail
|
||||
|
||||
SINK=robot_speaker
|
||||
SOURCE=robot_mic
|
||||
|
||||
has() { pactl list short "$1" | awk '{print $2}' | grep -qxF "$2"; }
|
||||
if ! has sinks "$SINK" || ! has sources "$SOURCE"; then
|
||||
echo "hermes-robot: the robot's audio devices aren't present." >&2
|
||||
echo " Is the robot powered and plugged in over USB (ping 10.55.0.2)? Check with: pactl list short sources" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
prev_sink="$(pactl get-default-sink)"
|
||||
prev_source="$(pactl get-default-source)"
|
||||
restore() {
|
||||
pactl set-default-sink "$prev_sink" 2>/dev/null
|
||||
pactl set-default-source "$prev_source" 2>/dev/null
|
||||
}
|
||||
trap restore EXIT INT TERM
|
||||
|
||||
pactl set-default-sink "$SINK"
|
||||
pactl set-default-source "$SOURCE"
|
||||
|
||||
hermes "$@"
|
||||
Reference in New Issue
Block a user