ReachyPi / docker /stage-cm5-fixes.sh
Domotick's picture
v1.1.0
d177e5f
Raw
History Blame Contribute Delete
3.14 kB
#!/bin/bash -e
# CM5 fixes baked into the image, kept outside the Python package so daemon updates don't wipe them.
# Target: a CM5 swapped into the Reachy Mini Wireless carrier (issue geerlingguy/raspberry-pi-pcie-devices#800).
# Same BCM2712+RP1 silicon as the Pi 5; the camera path is where the two variants differ:
# the Wireless camera is CSI (imx708) and NEEDS libcamera, so unlike stage-pi5-fixes.sh
# nothing is disabled here, and the WebRTC encoder goes software (no HW encoder on BCM2712).
echo "Fix 1/3: motor port -> /dev/ttyAMA3 (udev)"
# the carrier's motor bus is on GPIO4/5: RP1 uart2 on the CM5 (ttyAMA2), not the CM4's uart3
install -d -m 0755 /etc/udev/rules.d
cat > /etc/udev/rules.d/99-reachy-cm5-motor.rules <<'RULE'
# /dev/ttyAMA3 = whichever motor bus exists (USB controller, or GPIO uart2)
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d3", SYMLINK+="ttyAMA3", GROUP="dialout", MODE="0660"
KERNEL=="ttyAMA2", SYMLINK+="ttyAMA3", GROUP="dialout", MODE="0660"
RULE
echo "Fix 2/3: shutdown button -> gpiozero lgpio backend"
install -d -m 0755 /etc/systemd/system/gpio-shutdown-daemon.service.d
cat > /etc/systemd/system/gpio-shutdown-daemon.service.d/10-cm5-lgpio.conf <<'DROP'
[Service]
Environment=GPIOZERO_PIN_FACTORY=lgpio
DROP
source /opt/uv/env 2>/dev/null || true
if [ -f /venvs/mini_daemon/bin/activate ]; then
source /venvs/mini_daemon/bin/activate
uv pip install lgpio || pip install lgpio || true
fi
echo "Fix 3/3: software H264 encoder for the WebRTC stream"
# the daemon's CSI path hardcodes v4l2h264enc, a hardware element the CM5 does not have:
# swap that one method for an x264enc version at import time
cat > /venvs/mini_daemon/lib/python3.12/site-packages/sitecustomize.py <<'PY'
# ReachyPi CM5: no hardware H264 encoder on BCM2712 -> encode the WebRTC branch in software
def _sw_encoder():
try:
from reachy_mini.media import media_server as ms
from gi.repository import Gst
except Exception:
return
def sw_branch(self, queue_webrtc, pipeline, webrtcsink):
convert = Gst.ElementFactory.make("videoconvert")
x264 = Gst.ElementFactory.make("x264enc")
caps_h264 = Gst.ElementFactory.make("capsfilter")
if not all([convert, x264, caps_h264]):
raise RuntimeError("Failed to create x264 encoder elements")
Gst.util_set_object_arg(x264, "tune", "zerolatency")
Gst.util_set_object_arg(x264, "speed-preset", "ultrafast")
x264.set_property("bitrate", 5000) # kbit/s, same 5 Mb/s as the hardware branch
x264.set_property("key-int-max", 60) # same keyframe period
caps_h264.set_property("caps", Gst.Caps.from_string(
"video/x-h264,stream-format=byte-stream,alignment=au,"
"level=(string)3.1,profile=(string)constrained-baseline"))
for elem in (convert, x264, caps_h264):
pipeline.add(elem)
queue_webrtc.link(convert)
convert.link(x264)
x264.link(caps_h264)
caps_h264.link(webrtcsink)
ms.GstMediaServer._build_rpi_encoder_branch = sw_branch
_sw_encoder()
PY
echo "CM5 fixes applied."