From e0184a6e14add1a679e0c96f92c513b07fa1568a Mon Sep 17 00:00:00 2001 From: CaoWangrenbo Date: Thu, 4 Jun 2026 20:37:58 +0800 Subject: [PATCH] fix: make start_ros_container.sh executable Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- start_ros_container.sh | 244 ++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 124 deletions(-) mode change 100644 => 100755 start_ros_container.sh diff --git a/start_ros_container.sh b/start_ros_container.sh old mode 100644 new mode 100755 index 4c4a007..263dbe6 --- a/start_ros_container.sh +++ b/start_ros_container.sh @@ -1,143 +1,139 @@ #!/bin/bash -# ROS Podman容器启动脚本 -# 作者自动生成 -# 功能:启动ROS容器,挂载当前目录,设置环境变量,安装pip3,错误不退出 +# ROS Podman 容器启动脚本 — 用于 rosbag 可视化 +# 用法: +# ./start_ros_container.sh # 启动交互式 shell +# ./start_ros_container.sh play # 自动播放 bag + 启动 rviz -set +e # 遇到错误时不退出 +set -euo pipefail -# 颜色定义(用于美化输出) -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m' -# 配置参数 -CONTAINER_IMAGE="69a38b2c0905" # ROS Noetic Desktop Full镜像ID -WORKSPACE_DIR="$(pwd)" # 当前工作目录 -MOUNT_POINT="/mnt" # 容器内挂载点 +# ─── 配置 ─────────────────────────────────────────────────────────────────── +# 使用镜像名而非 ID,更可读;优先用本地 custom 镜像,fallback 到官方 +CONTAINER_IMAGE="docker.io/osrf/ros:noetic-desktop-full" +# 如果本地有 custom 镜像,优先用它(可自行修改) +if podman image exists localhost/custom-ros-noetic:v1.0 2>/dev/null; then + CONTAINER_IMAGE="localhost/custom-ros-noetic:v1.0" +fi -# ROS环境变量设置 -ROS_ENV_VARS=( - "ROS_DISTRO=noetic" - "ROS_PYTHON_VERSION=3" - "ROS_VERSION=1" - "ROS_ETC_DIR=/opt/ros/noetic/etc/ros" - "ROS_ROOT=/opt/ros/noetic/share/ros" - "ROS_PACKAGE_PATH=/opt/ros/noetic/share" - "PYTHONIOENCODING=utf-8" - "TZ=Asia/Shanghai" +WORKSPACE_DIR="$(pwd)" +MOUNT_POINT="/workspace" +BAG_DIR="$WORKSPACE_DIR/bags" +CONTAINER_NAME="ros_$(date +%s)" + +# ─── 前置检查 ─────────────────────────────────────────────────────────────── +if ! command -v podman &> /dev/null; then + echo -e "${RED}错误: 未安装 podman${NC}"; exit 1 +fi + +if ! podman image exists "$CONTAINER_IMAGE"; then + echo -e "${YELLOW}正在拉取镜像 $CONTAINER_IMAGE ...${NC}" + podman pull "$CONTAINER_IMAGE" +fi + +# ─── X11 配置 ──────────────────────────────────────────────────────────────── +# 你的 DISPLAY=localhost:10.0,容器内需要能访问宿主机 X11 socket +# 方案: host 网络 + 挂载 X11 socket +if [ -z "${DISPLAY:-}" ]; then + echo -e "${YELLOW}警告: DISPLAY 未设置,GUI 应用可能无法启动${NC}" +fi + +# 临时允许本地 X11 连接(仅当前用户) +xhost +SI:localuser:$USER 2>/dev/null || true + +# ─── 构建 podman 参数 ────────────────────────────────────────────────────── +ENV_ARGS=( + -e DISPLAY="$DISPLAY" + -e QT_X11_NO_MITSHM=1 + -e ROS_DISTRO=noetic + -e ROS_MASTER_URI=http://localhost:11311 + -e TZ=Asia/Shanghai ) +VOLUME_ARGS=( + -v "$WORKSPACE_DIR:$MOUNT_POINT:rw" + -v "/tmp/.X11-unix:/tmp/.X11-unix:rw" +) + +# host 网络模式: 容器直接使用宿主机网络栈,X11 和 ros master 通信都正常 +NET_ARGS=(--network=host) + +# ─── 打印配置 ──────────────────────────────────────────────────────────────── echo -e "${GREEN}========================================${NC}" -echo -e "${GREEN}ROS Podman容器启动脚本${NC}" +echo -e "${GREEN}ROS Podman 容器 — rosbag 可视化${NC}" +echo -e "${GREEN}========================================${NC}" +echo -e " 镜像: ${CYAN}$CONTAINER_IMAGE${NC}" +echo -e " 工作目录: $WORKSPACE_DIR → $MOUNT_POINT" +echo -e " DISPLAY: $DISPLAY" +echo -e " 网络模式: host" +echo -e " Bag 目录: $BAG_DIR" echo -e "${GREEN}========================================${NC}" -# 检查Podman是否安装 -if ! command -v podman &> /dev/null; then - echo -e "${RED}错误: Podman未安装,请先安装Podman${NC}" - echo -e "${YELLOW}Ubuntu/Debian: sudo apt-get install podman${NC}" - echo -e "${YELLOW}CentOS/RHEL: sudo yum install podman${NC}" - exit 1 -fi +# ─── 执行 ──────────────────────────────────────────────────────────────────── +# 根据参数决定模式 +if [ "${1:-}" = "play" ] && [ -n "${2:-}" ]; then + BAG_FILE="$BAG_DIR/${2}_davis_with_gt.bag" + if [ ! -f "$BAG_FILE" ]; then + echo -e "${RED}错误: bag 文件不存在: $BAG_FILE${NC}" + echo -e "${YELLOW}可用的 bag 文件:${NC}" + ls -1 "$BAG_DIR"/*.bag 2>/dev/null | xargs -n1 basename | sed 's/_davis_with_gt.bag//' + exit 1 + fi -# 检查镜像是否存在 -echo -e "${YELLOW}检查容器镜像...${NC}" -if ! podman image exists $CONTAINER_IMAGE; then - echo -e "${RED}警告: 镜像 $CONTAINER_IMAGE 不存在${NC}" - echo -e "${YELLOW}可用的ROS镜像:${NC}" - podman image list | grep ros - echo -e "${YELLOW}继续使用指定镜像,如果启动失败请更换镜像ID${NC}" -fi + echo -e "${GREEN}启动 rosbag play + rviz 模式${NC}" + echo -e " Bag: ${CYAN}$(basename "$BAG_FILE")${NC}" + echo -e "${YELLOW}容器启动后会自动播放 bag 并打开 rviz${NC}" + echo -e "${YELLOW}按 Ctrl+C 停止${NC}" + echo -e "${GREEN}========================================${NC}" -# 构建环境变量参数 -ENV_ARGS="" -for env_var in "${ROS_ENV_VARS[@]}"; do - ENV_ARGS="$ENV_ARGS -e $env_var" -done + podman run -it --rm --name "$CONTAINER_NAME" \ + "${VOLUME_ARGS[@]}" \ + "${ENV_ARGS[@]}" \ + "${NET_ARGS[@]}" \ + "$CONTAINER_IMAGE" \ + /bin/bash -c " + set -e + source /opt/ros/noetic/setup.bash + echo '启动 roscore...' + roscore & + ROSCORE_PID=\$! + sleep 2 -# 添加额外的环境变量(如果用户需要) -ENV_ARGS="$ENV_ARGS -e DISPLAY=$DISPLAY" # 支持GUI应用 -ENV_ARGS="$ENV_ARGS -e QT_X11_NO_MITSHM=1" + echo '播放 bag: ${2}_davis_with_gt.bag' + rosbag play --clock \"$MOUNT_POINT/bags/${2}_davis_with_gt.bag\" & + BAG_PID=\$! + sleep 1 -# X11支持(用于GUI应用) -if [ -n "$DISPLAY" ]; then - echo -e "${YELLOW}启用X11支持,用于GUI应用...${NC}" - xhost +local:root 2>/dev/null - ENV_ARGS="$ENV_ARGS --volume /tmp/.X11-unix:/tmp/.X11-unix:rw" -fi + echo '启动 rviz...' + rviz -d \"$MOUNT_POINT/visualize/default.rviz\" 2>/dev/null || rviz -echo -e "${GREEN}配置信息:${NC}" -echo -e " 工作目录: $WORKSPACE_DIR" -echo -e " 挂载点: $MOUNT_POINT" -echo -e " 镜像ID: $CONTAINER_IMAGE" -echo -e " ROS发行版: noetic" - -echo -e "${YELLOW}正在启动容器...${NC}" - -# 启动容器的命令 -# 使用bash -c来执行多个命令,确保pip3安装即使失败也不会退出容器 -PODMAN_CMD="podman run -it \ - --rm \ - --name ros_noetic_container_$(date +%s) \ - -v $WORKSPACE_DIR:$MOUNT_POINT:rw \ - $ENV_ARGS \ - $CONTAINER_IMAGE \ - /bin/bash -c \"\ - echo '========================================' && \ - echo 'ROS容器已启动' && \ - echo '========================================' && \ - echo '工作目录已挂载到: $MOUNT_POINT' && \ - echo '当前ROS版本: ' && \ - echo \\\$ROS_DISTRO && \ - echo '' && \ - echo '正在检查并安装pip3...' && \ - if command -v pip3 &> /dev/null; then \ - echo 'pip3已安装,版本: ' && \ - pip3 --version; \ - else \ - echo 'pip3未安装,正在安装...' && \ - apt-get update 2>/dev/null && \ - apt-get install -y python3-pip 2>/dev/null; \ - if [ \\\$? -eq 0 ]; then \ - echo 'pip3安装成功!'; \ - pip3 --version; \ - else \ - echo '警告: pip3安装失败,请手动安装'; \ - fi; \ - fi && \ - echo '' && \ - echo '========================================' && \ - echo '环境变量已设置:' && \ - env | grep ROS_ && \ - echo '========================================' && \ - echo '容器已准备就绪,进入交互式shell...' && \ - echo '提示: 输入exit退出容器' && \ - echo '========================================' && \ - pip config set global.index-url https://mirrors.ustc.edu.cn/pypi/simple && \ - source /ros_entrypoint.sh && \ - cd $MOUNT_POINT && \ - exec /bin/bash -l\"" - -# 执行命令 -echo -e "${GREEN}执行启动命令...${NC}" -# echo -e "${YELLOW}命令详情:${NC}" -# echo "$PODMAN_CMD" -echo -e "${YELLOW}========================================${NC}" - -# 运行容器 -eval $PODMAN_CMD - -# 检查退出状态 -if [ $? -ne 0 ]; then - echo -e "${RED}容器已退出(退出码非0)${NC}" + # 等待 bag 播放完成 + wait \$BAG_PID 2>/dev/null || true + kill \$ROSCORE_PID 2>/dev/null || true + " else - echo -e "${GREEN}容器正常退出${NC}" + # 交互式 shell 模式 + echo -e "${GREEN}启动交互式 shell${NC}" + echo -e "${YELLOW}提示: 进入后执行以下命令播放 bag${NC}" + echo -e " source /opt/ros/noetic/setup.bash" + echo -e " roscore &" + echo -e " rosbag play --clock $MOUNT_POINT/bags/indoor_forward_3_davis_with_gt.bag" + echo -e " rviz" + echo -e "${GREEN}========================================${NC}" + + podman run -it --rm --name "$CONTAINER_NAME" \ + "${VOLUME_ARGS[@]}" \ + "${ENV_ARGS[@]}" \ + "${NET_ARGS[@]}" \ + "$CONTAINER_IMAGE" \ + /bin/bash -c " + source /opt/ros/noetic/setup.bash + cd $MOUNT_POINT + exec /bin/bash -l + " fi -# 清理X11权限 -if [ -n "$DISPLAY" ]; then - xhost -local:root 2>/dev/null -fi - -echo -e "${GREEN}脚本执行完成${NC}" \ No newline at end of file +# ─── 清理 ──────────────────────────────────────────────────────────────────── +xhost -SI:localuser:$USER 2>/dev/null || true +echo -e "${GREEN}容器已退出${NC}"