Files
2026-07-25 15:00:14 +08:00

244 lines
7.8 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -Eeuo pipefail
# ============================================
# 配置项
# ============================================
PROJECT_DIR="${PROJECT_DIR:-$HOME/release/ctag2f-90d-sdk}"
WARMUP_DIR="${WARMUP_DIR:-$HOME/release/orisys-sdk}"
CONDA_ENV="${CONDA_ENV:-py311}"
RENDER_MODE="${RENDER_MODE:-auto}"
GRIPPER_CONFIG="${GRIPPER_CONFIG:-$PROJECT_DIR/config/gripper.json}"
# ============================================
# 检测 USB 摄像头并返回主设备索引(整数)
# ============================================
detect_cameras() {
declare -A cam_nodes
declare -A cam_paths
for dev in /dev/video*; do
[[ -e "$dev" ]] || continue
local dev_num="${dev##*/video}"
local info
info=$(udevadm info -n "$dev" 2>/dev/null || true)
# 检查是否为 USB 摄像头(根据 ID_MODEL 或 ID_VENDOR)
if echo "$info" | grep -qi "ID_MODEL.*USB Camera" || \
echo "$info" | grep -qi "ID_VENDOR.*1bcf" ; then
local id_path
id_path=$(echo "$info" | grep -i "ID_PATH=" | cut -d'=' -f2 || true)
if [[ -z "$id_path" ]]; then
id_path=$(udevadm info -q path -n "$dev" 2>/dev/null || true)
fi
local key="$id_path"
if [[ -z "${cam_nodes[$key]:-}" ]]; then
cam_nodes[$key]="$dev_num"
else
local current="${cam_nodes[$key]}"
if (( dev_num < current )); then
cam_nodes[$key]="$dev_num"
fi
fi
cam_paths[$key]="$id_path"
fi
done
if [[ ${#cam_nodes[@]} -lt 2 ]]; then
echo "错误:找到 ${#cam_nodes[@]} 个 USB 摄像头,需要 2 个。" >&2
return 1
fi
local cam_left=""
local cam_right=""
for key in "${!cam_nodes[@]}"; do
local path="$key"
local num="${cam_nodes[$key]}"
if [[ "$path" == *"xhci-hcd.0"* ]] || [[ "$path" == *"usb1"* ]]; then
cam_left="$num"
elif [[ "$path" == *"xhci-hcd.1"* ]] || [[ "$path" == *"usb2"* ]]; then
cam_right="$num"
else
if [[ -z "$cam_left" ]] || (( num < cam_left )); then
cam_right="$cam_left"
cam_left="$num"
else
cam_right="$num"
fi
fi
done
if [[ -z "$cam_left" ]] || [[ -z "$cam_right" ]]; then
local nums=()
for n in "${cam_nodes[@]}"; do nums+=("$n"); done
IFS=$'\n' sorted=($(sort -n <<<"${nums[*]}"))
cam_left="${sorted[0]}"
cam_right="${sorted[1]}"
fi
echo "$cam_left $cam_right"
}
# ============================================
# 更新 gripper.json 中的 video 路径
# ============================================
update_config() {
local cam_right_idx="$1"
local cam_left_idx="$2"
local config_file="$GRIPPER_CONFIG"
# 检查 jq 是否安装
if ! command -v jq &> /dev/null; then
echo "jq 未安装,正在安装..."
sudo apt update && sudo apt install -y jq
fi
# 构建设备路径
local video1="/dev/video$cam_left_idx"
local video2="/dev/video$cam_right_idx"
echo "更新配置文件: $config_file"
echo " video1 = $video1"
echo " video2 = $video2"
# 使用 jq 更新字段
jq --arg v1 "$video1" --arg v2 "$video2" \
'.video1 = $v1 | .video2 = $v2' "$config_file" > "$config_file.tmp"
mv "$config_file.tmp" "$config_file"
echo "✅ 配置文件已更新。"
}
# ============================================
# 加载 conda 环境
# ============================================
load_conda() {
for conda_sh in \
"$HOME/miniconda3/etc/profile.d/conda.sh" \
"$HOME/anaconda3/etc/profile.d/conda.sh" \
"/opt/conda/etc/profile.d/conda.sh"; do
if [[ -f "$conda_sh" ]]; then
# shellcheck disable=SC1090
source "$conda_sh"
break
fi
done
if ! command -v conda >/dev/null 2>&1; then
echo "Conda not found." >&2
exit 1
fi
conda activate "$CONDA_ENV"
echo "✅ Conda environment '$CONDA_ENV' activated."
}
# ============================================
# 主逻辑
# ============================================
main() {
# 检查项目目录
if [[ ! -d "$PROJECT_DIR" ]]; then
echo "错误:项目目录不存在: $PROJECT_DIR" >&2
exit 1
fi
if [[ ! -d "$WARMUP_DIR" ]]; then
echo "警告:warmup 目录不存在: $WARMUP_DIR,跳过预热。" >&2
WARMUP_DIR=""
fi
load_conda
# 移除不兼容的 PyOpenGL-accelerate
if python -c 'import OpenGL_accelerate' >/dev/null 2>&1; then
echo "移除不兼容的 PyOpenGL-accelerate ..."
python -m pip uninstall -y PyOpenGL-accelerate
fi
# 检测摄像头
echo "正在检测 USB 摄像头..."
CAMERAS=$(detect_cameras)
if [[ -z "$CAMERAS" ]]; then
echo "错误:无法检测到两个 USB 摄像头。" >&2
exit 1
fi
CAM_LEFT=$(echo "$CAMERAS" | awk '{print $1}')
CAM_RIGHT=$(echo "$CAMERAS" | awk '{print $2}')
echo "左摄像头索引: $CAM_LEFT"
echo "右摄像头索引: $CAM_RIGHT"
# --- 更新配置文件 ---
update_config "$CAM_LEFT" "$CAM_RIGHT"
# ---------- 执行 warmup ----------
if [[ -n "$WARMUP_DIR" ]]; then
echo "============================================="
echo "🧪 开始传感器预热 (sensor warmup)"
echo " 目录: $WARMUP_DIR"
echo "============================================="
cd "$WARMUP_DIR"
echo ">>> 执行: python warmup.py -v $CAM_LEFT"
python warmup.py -v "$CAM_LEFT"
echo "✅ warmup 左摄像头完成"
echo ">>> 执行: python warmup.py -v $CAM_RIGHT"
python warmup.py -v "$CAM_RIGHT"
echo "✅ warmup 右摄像头完成"
cd "$PROJECT_DIR"
echo "============================================="
echo "✅ 传感器预热全部完成"
echo "============================================="
fi
# ---------- 设置渲染模式 ----------
if [[ "$RENDER_MODE" == "auto" ]]; then
wayland_plugin="$(find "${CONDA_PREFIX:-/nonexistent}" -type f \
-path '*/platforms/libqwayland*.so' -print -quit 2>/dev/null || true)"
if [[ -n "$wayland_plugin" && -n "${WAYLAND_DISPLAY:-}" ]]; then
RENDER_MODE=wayland
else
echo "Conda Qt 没有 Wayland 插件;使用 XWayland 和软件 OpenGL。"
RENDER_MODE=software
fi
fi
case "$RENDER_MODE" in
wayland)
if [[ -z "${WAYLAND_DISPLAY:-}" ]]; then
echo "WAYLAND_DISPLAY 为空。请在 Ubuntu 桌面终端中运行此脚本。" >&2
exit 1
fi
export QT_QPA_PLATFORM=wayland
export PYOPENGL_PLATFORM=egl
unset QT_OPENGL LIBGL_ALWAYS_SOFTWARE QT_XCB_GL_INTEGRATION
;;
software)
export QT_QPA_PLATFORM=xcb
export QT_OPENGL=software
export LIBGL_ALWAYS_SOFTWARE=1
export PYOPENGL_PLATFORM=glx
export QT_XCB_GL_INTEGRATION=xcb_glx
;;
xcb)
export QT_QPA_PLATFORM=xcb
export PYOPENGL_PLATFORM=glx
export QT_XCB_GL_INTEGRATION=xcb_glx
unset QT_OPENGL LIBGL_ALWAYS_SOFTWARE
;;
*)
echo "未知的 RENDER_MODE: $RENDER_MODE (可用: auto, wayland, software, xcb)" >&2
exit 2
;;
esac
# ---------- 启动主程序 ----------
echo "🚀 启动 gripper visualizer: mode=$RENDER_MODE, conda=$CONDA_ENV"
exec python -m gripper.visualizer "$@"
}
# ============================================
# 执行主函数
# ============================================
main "$@"