File size: 9,322 Bytes
c26f879 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | #!/usr/bin/env bash
# install_camera_server.sh
# Sets up the .venv_camera venv for running the composed camera server
# on the robot computer.
#
# Installs gear_sonic[camera] which includes the ZMQ-based camera server
# framework and the depthai SDK (OAK cameras). For other camera SDKs
# (e.g. pyrealsense2), install them into the venv after setup.
#
# Usage: bash install_scripts/install_camera_server.sh (run from repo root)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# ββ 0. Print detected architecture βββββββββββββββββββββββββββββββββββββββββββ
ARCH="$(uname -m)"
echo "[OK] Architecture: $ARCH"
# ββ 1. Ensure uv is installed and available ββββββββββββββββββββββββββββββββββ
if ! command -v uv &>/dev/null; then
echo "[INFO] uv not found β installing via official installer β¦"
curl -LsSf https://astral.sh/uv/install.sh | sh
if [ -f "$HOME/.local/bin/env" ]; then
# shellcheck disable=SC1091
source "$HOME/.local/bin/env"
elif [ -f "$HOME/.cargo/env" ]; then
# shellcheck disable=SC1091
source "$HOME/.cargo/env"
else
export PATH="$HOME/.local/bin:$PATH"
fi
if ! command -v uv &>/dev/null; then
echo "[ERROR] uv installation succeeded but binary not found on PATH."
echo " Please add ~/.local/bin (or ~/.cargo/bin) to your PATH and re-run."
exit 1
fi
fi
echo "[OK] uv $(uv --version)"
# ββ 2. Install a uv-managed Python 3.10 βββββββββββββββββββββββββββββββββββββ
echo "[INFO] Installing uv-managed Python 3.10 β¦"
uv python install 3.10
MANAGED_PY="$(uv python find --no-project 3.10)"
echo "[OK] Using Python: $MANAGED_PY"
# ββ 3. Clean previous venv (if any) βββββββββββββββββββββββββββββββββββββββββ
cd "$REPO_ROOT"
echo "[INFO] Removing old .venv_camera (if present) β¦"
rm -rf .venv_camera
# ββ 4. Create venv & install camera extra ββββββββββββββββββββββββββββββββββββ
echo "[INFO] Creating .venv_camera with uv-managed Python 3.10 β¦"
uv venv .venv_camera --python "$MANAGED_PY" --prompt gear_sonic_camera
# shellcheck disable=SC1091
source .venv_camera/bin/activate
echo "[INFO] Installing gear_sonic[camera] β¦"
uv pip install -e "gear_sonic[camera]"
echo ""
echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
echo " Camera server venv setup complete!"
echo " depthai (OAK cameras) is included by default."
echo ""
echo " Activate the venv with:"
echo " source .venv_camera/bin/activate"
echo ""
echo " For other camera SDKs, install into the venv:"
echo " pip install pyrealsense2 # Intel RealSense"
echo ""
echo " See docs/source/tutorials/data_collection.md for full setup."
echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
# ββ 5. Optionally install the systemd service ββββββββββββββββββββββββββββββββ
SERVICE_TEMPLATE="$REPO_ROOT/systemd/composed_camera_server.service"
SERVICE_NAME="composed_camera_server.service"
if [ ! -f "$SERVICE_TEMPLATE" ]; then
echo ""
echo "[WARN] systemd template not found at $SERVICE_TEMPLATE β skipping."
exit 0
fi
echo ""
read -rp "Install the camera server as a systemd service (auto-start on boot)? [y/N] " INSTALL_SERVICE
if [[ ! "$INSTALL_SERVICE" =~ ^[Yy]$ ]]; then
echo ""
echo " Skipped systemd install. You can run the camera server manually:"
echo " source .venv_camera/bin/activate"
echo " python -m gear_sonic.camera.composed_camera --ego-view-camera oak --port 5555"
echo ""
exit 0
fi
# Gather configuration
echo ""
echo "ββ Camera service configuration ββ"
echo " Each camera needs a type and a device ID so the server knows"
echo " which physical camera maps to each mount position (ego, wrist, etc.)."
echo ""
detect_oak_cameras() {
"${REPO_ROOT}/.venv_camera/bin/python" -c "
import depthai as dai
devices = dai.Device.getAllAvailableDevices()
if not devices:
exit(1)
for i, d in enumerate(devices):
# Try to get actual MxID; fall back to string representation
mxid = None
for attr in ['mxid', 'getMxId']:
if hasattr(d, attr):
val = getattr(d, attr)
mxid = val() if callable(val) else val
if mxid:
break
state = d.state.name if hasattr(d, 'state') else 'N/A'
name = getattr(d, 'name', '')
if mxid and mxid != name:
print(f' [{i}] MxId: {mxid} port: {name} state: {state}')
else:
# MxID not available; show all useful attributes
print(f' [{i}] device: {d} state: {state}')
print(f' attributes: {[a for a in dir(d) if not a.startswith(\"_\")]}')
" 2>&1
}
while true; do
echo " Detecting connected OAK cameras β¦"
OAK_DEVICES="$(detect_oak_cameras)" && OAK_FOUND=true || OAK_FOUND=false
if $OAK_FOUND && [ -n "$OAK_DEVICES" ]; then
echo "$OAK_DEVICES"
break
else
echo " (no OAK devices detected)"
if [ -n "$OAK_DEVICES" ]; then
echo " depthai output: $OAK_DEVICES"
fi
echo ""
read -rp " Retry detection? [Y/n] (or 'n' to enter device IDs manually): " RETRY
if [[ "$RETRY" =~ ^[Nn]$ ]]; then
break
fi
echo ""
fi
done
echo ""
# Build ExecStart args incrementally
CAMERA_ARGS=""
# --- Ego-view camera (required) ---
read -rp " Ego-view camera type (oak, oak_mono, realsense, usb) [oak]: " EGO_TYPE
EGO_TYPE="${EGO_TYPE:-oak}"
read -rp " Ego-view device ID (MxID or /dev/video index): " EGO_DEVICE_ID
CAMERA_ARGS="--ego-view-camera ${EGO_TYPE}"
if [ -n "$EGO_DEVICE_ID" ]; then
CAMERA_ARGS="${CAMERA_ARGS} --ego-view-device-id ${EGO_DEVICE_ID}"
fi
# --- Left wrist camera (optional) ---
echo ""
read -rp " Add a left-wrist camera? [y/N]: " ADD_LEFT
if [[ "$ADD_LEFT" =~ ^[Yy]$ ]]; then
read -rp " Left-wrist camera type [oak]: " LEFT_TYPE
LEFT_TYPE="${LEFT_TYPE:-oak}"
read -rp " Left-wrist device ID (MxID): " LEFT_DEVICE_ID
CAMERA_ARGS="${CAMERA_ARGS} --left-wrist-camera ${LEFT_TYPE}"
if [ -n "$LEFT_DEVICE_ID" ]; then
CAMERA_ARGS="${CAMERA_ARGS} --left-wrist-device-id ${LEFT_DEVICE_ID}"
fi
fi
# --- Right wrist camera (optional) ---
echo ""
read -rp " Add a right-wrist camera? [y/N]: " ADD_RIGHT
if [[ "$ADD_RIGHT" =~ ^[Yy]$ ]]; then
read -rp " Right-wrist camera type [oak]: " RIGHT_TYPE
RIGHT_TYPE="${RIGHT_TYPE:-oak}"
read -rp " Right-wrist device ID (MxID): " RIGHT_DEVICE_ID
CAMERA_ARGS="${CAMERA_ARGS} --right-wrist-camera ${RIGHT_TYPE}"
if [ -n "$RIGHT_DEVICE_ID" ]; then
CAMERA_ARGS="${CAMERA_ARGS} --right-wrist-device-id ${RIGHT_DEVICE_ID}"
fi
fi
echo ""
read -rp " ZMQ port [5555]: " CFG_PORT
CFG_PORT="${CFG_PORT:-5555}"
CAMERA_ARGS="${CAMERA_ARGS} --port ${CFG_PORT}"
EXEC_START="${REPO_ROOT}/.venv_camera/bin/python -m gear_sonic.camera.composed_camera ${CAMERA_ARGS}"
echo ""
echo " ExecStart command:"
echo " $EXEC_START"
echo ""
read -rp " Look correct? [Y/n]: " CONFIRM
if [[ "$CONFIRM" =~ ^[Nn]$ ]]; then
echo " Aborted. Edit systemd/composed_camera_server.service manually."
exit 0
fi
# Generate unit file directly (avoids fragile sed on multi-line ExecStart)
TMPUNIT="$(mktemp)"
cat > "$TMPUNIT" <<UNIT
[Unit]
Description=SONIC Composed Camera Server (ZMQ)
After=network.target
[Service]
Type=simple
User=$USER
Environment="HOME=$HOME"
Environment="REPO_DIR=$REPO_ROOT"
WorkingDirectory=$REPO_ROOT
ExecStart=$EXEC_START
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
UNIT
echo ""
echo "[INFO] Installing systemd service β¦"
sudo cp "$TMPUNIT" "/etc/systemd/system/$SERVICE_NAME"
rm -f "$TMPUNIT"
sudo systemctl daemon-reload
sudo systemctl enable "$SERVICE_NAME"
sudo systemctl start "$SERVICE_NAME"
echo ""
echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
echo " systemd service installed and started!"
echo ""
echo " Check status:"
echo " sudo systemctl status $SERVICE_NAME"
echo ""
echo " View logs:"
echo " journalctl -u $SERVICE_NAME -f"
echo ""
echo " To reconfigure, edit and re-run this script, or:"
echo " sudo systemctl edit $SERVICE_NAME"
echo " sudo systemctl restart $SERVICE_NAME"
echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
|