2026-08-04 16:09:17 +04:00

45 lines
1.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Container entrypoint: supervised inspire_g1 + hand_bridge + Flask dashboard.
set -u
cd /opt/hand
export HAND_REPO=/opt/hand
IFACE="${IFACE:-eth0}"
echo "[inspire-hand] iface=$IFACE ttyUSB: $(ls /dev/ttyUSB* 2>/dev/null | tr '\n' ' ')"
# Supervisor: (re)start inspire_g1 whenever the CH340 adapters are present but the
# service isn't running. Self-heals across the flaky-hub disconnect/reconnect cycles.
(
while true; do
if ! pgrep -x inspire_g1 >/dev/null 2>&1; then
if ls /dev/ttyUSB* >/dev/null 2>&1; then
echo "[supervisor] adapters present, starting inspire_g1: $(ls /dev/ttyUSB* | tr '\n' ' ')"
./build/inspire_g1 >/tmp/inspire_g1.log 2>&1 &
sleep 2
sed 's/^/[inspire_g1] /' /tmp/inspire_g1.log
fi
fi
sleep 3
done
) &
# TCP->DDS bridge for the dashboard (stays up regardless; commands no-op if service down)
setsid ./build/hand_bridge "$IFACE" 7799 >/tmp/hand_bridge.log 2>&1 </dev/null &
sleep 1
sed 's/^/[bridge] /' /tmp/hand_bridge.log
# Seed the arm home pose into the mounted takes dir on first run. run.sh bind-mounts
# DataG1 from the host, which hides the copy baked into the image — without this every
# take would skip its return-to-home and print "home file not found".
if [ -f /opt/recorder/seed/arm_home.jsonl ] && [ ! -f /opt/recorder/DataG1/arm_home.jsonl ]; then
mkdir -p /opt/recorder/DataG1 && cp /opt/recorder/seed/arm_home.jsonl /opt/recorder/DataG1/ \
&& echo "[inspire-hand] seeded arm_home.jsonl into DataG1"
fi
if [ -f /opt/recorder/g1_record_replay.py ]; then
echo "[inspire-hand] recorder: /opt/recorder ($(ls /opt/recorder/DataG1/*.jsonl 2>/dev/null | grep -vc arm_home) takes)"
else
echo "[inspire-hand] recorder: NOT in image — record/replay panel disabled"
fi
echo "[inspire-hand] dashboard on :8088"
exec python3 web/hand_web.py --port 8088