#!/usr/bin/env bash # Orisys 通止规工位桌面程序(窗口,不是网页)。 # # bash ~/桌面/orisys_arm/station/run_station.sh set -eo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" case "${1:-}" in -h|--help) echo "用法:bash station/run_station.sh [--offline | --self-test]" echo "默认启动工位和独立后端;--offline 禁止设备访问;--self-test 运行离线回归。" exit 0 ;; esac # 这份搬迁的 symlink-install 在 /tmp/orisys_mnt 构建;只在私有挂载空间恢复它, # 否则工位虽然能开,ROS 消息和相机桥的安装链接却失效。 _arm_hook="${ROOT}/install/arm_msgs/share/arm_msgs/local_setup.bash" if [[ "${ROOT}" != /tmp/orisys_mnt && -L "${_arm_hook}" && ! -e "${_arm_hook}" && "$(readlink "${_arm_hook}")" == /tmp/orisys_mnt/* ]]; then exec unshare -rm bash -c ' set -e mkdir -p /tmp/orisys_mnt mount --bind "$1" /tmp/orisys_mnt shift exec bash /tmp/orisys_mnt/station/run_station.sh "$@" ' bash "${ROOT}" "$@" fi unset _arm_hook export XDG_CACHE_HOME="${XDG_CACHE_HOME:-${HOME}/.cache}" # shellcheck disable=SC1091 source "${ROOT}/scripts/env.sh" # 源码在最前。conda 的 site-packages 要排在 Humble 的 python3.10 之前, # 否则 3.11 的解释器会去加载 cpython-310 的 rclpy,相机预览线程直接失败。 _conda_site="" if [[ -n "${CONDA_PREFIX:-}" ]]; then _py_mm="$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')" if [[ -d "${CONDA_PREFIX}/lib/python${_py_mm}/site-packages" ]]; then _conda_site="${CONDA_PREFIX}/lib/python${_py_mm}/site-packages" fi fi export PYTHONPATH="${ROOT}/station/src:${ROOT}/src/arm_application${_conda_site:+:${_conda_site}}${PYTHONPATH:+:${PYTHONPATH}}" unset _conda_site _py_mm # 屏幕跟当前登录会话走。这台工控机是 :1,别的 Linux 桌面常常是 :0。 if [[ -n "${DISPLAY:-}" ]]; then _disp="${DISPLAY#:}" _disp="${_disp%%.*}" if [[ ! -S "/tmp/.X11-unix/X${_disp}" ]]; then unset DISPLAY fi unset _disp fi if [[ -z "${DISPLAY:-}" ]]; then _seat="$(who | awk -v u="$(id -un)" '$1==u && $2 ~ /^:/ {print $2; exit}')" _seat="${_seat%%.*}" _n="${_seat#:}" if [[ -n "${_n}" && -S "/tmp/.X11-unix/X${_n}" ]]; then export DISPLAY="${_seat}" else for _sock in /tmp/.X11-unix/X*; do if [[ -S "${_sock}" ]]; then export DISPLAY=":${_sock##*/X}" break fi done fi unset _seat _n _sock fi # 有真实屏幕时不要留在 offscreen,否则 OpenGL 窗口起不来,模型也不会画到显卡上。 if [[ "${QT_QPA_PLATFORM:-}" == "offscreen" && -n "${DISPLAY:-}" ]]; then _disp="${DISPLAY#:}" _disp="${_disp%%.*}" if [[ -S "/tmp/.X11-unix/X${_disp}" ]]; then unset QT_QPA_PLATFORM fi unset _disp fi if [[ -z "${XAUTHORITY:-}" ]]; then if [[ -r "${HOME}/.Xauthority" ]]; then export XAUTHORITY="${HOME}/.Xauthority" elif [[ -r "/run/user/$(id -u)/gdm/Xauthority" ]]; then export XAUTHORITY="/run/user/$(id -u)/gdm/Xauthority" fi fi # Qt 6.5 起 xcb 插件依赖 libxcb-cursor。系统没装这个包时,用用户目录里单独放的那一份, # 不要把整个 conda lib 塞进 LD_LIBRARY_PATH(会和系统的 glib/pango 撞符号)。 _cursor_dir="${HOME}/.local/lib/xcb-cursor" if [[ ! -e /usr/lib/x86_64-linux-gnu/libxcb-cursor.so.0 && -e "${_cursor_dir}/libxcb-cursor.so.0" ]]; then export LD_LIBRARY_PATH="${_cursor_dir}${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" fi unset _cursor_dir # 工位单独固定 Qt 绑定版本,不修改 ROS/conda 内的包。 source "${ROOT}/scripts/lib/qt_env.sh" orisys_qt_env if [[ "${1:-}" == "--self-test" ]]; then export QT_QPA_PLATFORM=offscreen exec python3 -m unittest discover -s "${ROOT}/station/test" -v fi exec python3 -m station.operator_app "$@"