bash
#!/bin/bash
# ============================================================================
# ROS2 工控机部署包创建脚本(验证版)
# 用途:在 ~/deploy 目录创建并验证完整的部署包
# 使用:./create_deploy_verified.sh
# ============================================================================
set +e # 遇到错误立即退出
# =========================== 配置区域 ===========================
WORKSPACE_DIR="/home/work/ros2_ws"
DEPLOY_DIR=~/deploy
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
PACKAGE_NAME="ros2_deploy_${TIMESTAMP}.tar.gz"
# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
# =========================== 工具函数 ===========================
print_header() {
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ $1${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════╝${NC}"
echo ""
}
print_step() {
echo -e "${YELLOW}>>> $1${NC}"
}
print_success() {
echo -e "${GREEN}✓ $1${NC}"
}
print_error() {
echo -e "${RED}✗ $1${NC}"
}
print_info() {
echo -e "${CYAN} → $1${NC}"
}
# =========================== 主程序 ===========================
print_header " ROS2 工控机部署包创建工具(验证版) "
# 步骤1:清理并创建部署目录
print_step "[1/10] 准备部署目录"
if [ -d "$DEPLOY_DIR" ]; then
print_info "清理旧的部署目录..."
rm -rf "$DEPLOY_DIR"
fi
mkdir -p "$DEPLOY_DIR"
print_success "部署目录已创建: $DEPLOY_DIR"
echo ""
# 步骤2:检查工作空间
print_step "[2/10] 检查工作空间"
if [ ! -d "$WORKSPACE_DIR/install" ]; then
print_error "找不到 install 目录"
echo "请先编译项目:"
echo " cd $WORKSPACE_DIR"
echo " colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release"
exit 1
fi
print_success "工作空间检查通过"
echo ""
# 步骤3:复制 install 目录(核心)
print_step "[3/10] 复制 install 目录"
print_info "正在复制所有编译后的包..."
cp -r "$WORKSPACE_DIR/install" "$DEPLOY_DIR/"
INSTALL_SIZE=$(du -sh "$DEPLOY_DIR/install" | cut -f1)
print_success "install 目录已复制 (大小: $INSTALL_SIZE)"
echo ""
# 步骤4:复制头文件(如果需要在工控机上进行二次开发)
print_step "[4/10] 复制头文件"
if [ -d "$WORKSPACE_DIR/install/n_v_master_supervisor/include" ]; then
print_info "包含的头文件目录已在 install 中"
print_success "头文件已包含在 install/*/include/ 中"
else
print_info "未找到独立的头文件目录(正常情况)"
fi
echo ""
# 步骤5:复制lib库
print_step "[5/10] 检查并复制第三方库"
if [ -d "$WORKSPACE_DIR/lib" ]; then
print_info "复制第三方库目录..."
cp -r "$WORKSPACE_DIR/lib" "$DEPLOY_DIR/"
LIB_SIZE=$(du -sh "$DEPLOY_DIR/lib" | cut -f1)
print_success "第三方库已复制 (大小: $LIB_SIZE)"
# 检查spdlog
if [ -d "$DEPLOY_DIR/lib/x86_64-linux-gnu/spdlog" ]; then
print_info "✓ spdlog 库已包含"
fi
else
print_info "未找到独立的 lib/ 目录(库可能已在 install 中)"
fi
echo ""
# 步骤6:复制Python脚本
print_step "[6/10] 复制Python脚本"
PYTHON_SCRIPTS=(
"position_monitor.py"
"publish_manual_state.py"
"publish_manual_state_robust.py"
"publish_manual_state_robust_operation_figure-8.py"
"publish_manual_state_robust_operation_line.py"
"publish_manual_state_robust_operation_rectangley.py"
)
mkdir -p "$DEPLOY_DIR/scripts"
COPIED_SCRIPTS=0
for script in "${PYTHON_SCRIPTS[@]}"; do
if [ -f "$WORKSPACE_DIR/$script" ]; then
cp "$WORKSPACE_DIR/$script" "$DEPLOY_DIR/scripts/"
print_info "✓ $script"
((COPIED_SCRIPTS++))
fi
done
print_success "Python脚本已复制 ($COPIED_SCRIPTS 个文件)"
echo ""
# 步骤7:验证关键文件
print_step "[7/10] 验证关键文件"
# 验证可执行文件
MASTER_SUPERVISOR_PATH="$DEPLOY_DIR/install/n_v_master_supervisor/lib/n_v_master_supervisor/master_supervisor"
if [ -f "$MASTER_SUPERVISOR_PATH" ]; then
FILE_SIZE=$(du -h "$MASTER_SUPERVISOR_PATH" | cut -f1)
print_success "可执行文件: master_supervisor (大小: $FILE_SIZE)"
# 检查是否可执行
if [ -x "$MASTER_SUPERVISOR_PATH" ]; then
print_info "✓ 可执行权限正常"
else
print_error "可执行权限缺失"
chmod +x "$MASTER_SUPERVISOR_PATH"
print_info "已修复执行权限"
fi
# 检查依赖库
print_info "检查共享库依赖..."
MISSING_LIBS=$(ldd "$MASTER_SUPERVISOR_PATH" 2>&1 | grep "not found" || true)
if [ -z "$MISSING_LIBS" ]; then
print_success "所有库依赖满足"
else
print_error "发现缺失的库:"
echo "$MISSING_LIBS"
fi
else
print_error "找不到可执行文件: $MASTER_SUPERVISOR_PATH"
exit 1
fi
# 验证配置文件
CONFIG_DIR="$DEPLOY_DIR/install/n_v_master_supervisor/share/n_v_master_supervisor/config"
if [ -d "$CONFIG_DIR" ]; then
CONFIG_COUNT=$(find "$CONFIG_DIR" -name "*.yaml" | wc -l)
print_success "配置文件目录存在 ($CONFIG_COUNT 个 yaml 文件)"
find "$CONFIG_DIR" -name "*.yaml" -exec basename {} \; | while read file; do
print_info "✓ $file"
done
else
print_info "配置文件目录: $CONFIG_DIR (未找到)"
fi
# 验证消息包
print_info "检查消息包..."
MSG_PACKAGES=(
"n_v_msgs"
"chassis_control_tohw_msgs"
"chassis_hardware_msgs"
"amr_decision_msgs"
"custom_pose_msgs"
"common_msgs"
"msg_border_point"
"msg_obj"
"msg_v_state"
"obj_fuse_msgs"
"safety_diagn_msgs"
)
MSG_COUNT=0
for pkg in "${MSG_PACKAGES[@]}"; do
if [ -d "$DEPLOY_DIR/install/$pkg" ]; then
print_info "✓ $pkg"
((MSG_COUNT++))
fi
done
print_success "消息包已包含 ($MSG_COUNT/${#MSG_PACKAGES[@]} 个)"
echo ""
# 步骤8:创建环境设置脚本
print_step "[8/10] 创建环境设置脚本"
cat > "$DEPLOY_DIR/setup_env.bash" << 'EOF'
#!/bin/bash
# ============================================================================
# ROS2 环境设置脚本
# 用途:设置运行环境
# 使用:source setup_env.bash
# ============================================================================
# 获取脚本所在目录
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "=== ROS2 环境设置 ==="
# Source ROS2基础环境
if [ -f "/opt/ros/humble/setup.bash" ]; then
source /opt/ros/humble/setup.bash
echo "✓ ROS2 Humble 环境已加载"
elif [ -f "/opt/ros/foxy/setup.bash" ]; then
source /opt/ros/foxy/setup.bash
echo "✓ ROS2 Foxy 环境已加载"
else
echo "⚠ 警告:未找到ROS2环境"
echo " 请手动执行: source /opt/ros/<distro>/setup.bash"
fi
# Source 工作空间环境
if [ -f "$SCRIPT_DIR/install/setup.bash" ]; then
source "$SCRIPT_DIR/install/setup.bash"
echo "✓ 工作空间环境已加载"
else
echo "✗ 错误:未找到 install/setup.bash"
return 1
fi
# 设置Python脚本路径
if [ -d "$SCRIPT_DIR/scripts" ]; then
export PYTHONPATH="$SCRIPT_DIR/scripts:$PYTHONPATH"
echo "✓ Python脚本路径已设置"
fi
# 设置第三方库路径
if [ -d "$SCRIPT_DIR/lib" ]; then
# 查找所有可能的lib路径
for libdir in "$SCRIPT_DIR/lib" "$SCRIPT_DIR/lib/x86_64-linux-gnu/spdlog/lib"; do
if [ -d "$libdir" ]; then
export LD_LIBRARY_PATH="$libdir:$LD_LIBRARY_PATH"
fi
done
echo "✓ 第三方库路径已设置"
fi
echo ""
echo "环境设置完成!"
echo ""
echo "可用命令:"
echo " ros2 run n_v_master_supervisor master_supervisor"
echo " ros2 launch n_v_master_supervisor <your_launch_file>.launch.py"
echo " python3 scripts/position_monitor.py"
echo ""
EOF
chmod +x "$DEPLOY_DIR/setup_env.bash"
print_success "setup_env.bash 已创建"
echo ""
# 步骤9:创建快速启动脚本
print_step "[9/10] 创建快速启动脚本"
cat > "$DEPLOY_DIR/run_master_supervisor.sh" << 'EOF'
#!/bin/bash
# ============================================================================
# Master Supervisor 快速启动脚本
# ============================================================================
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "=== 启动 Master Supervisor ==="
echo ""
# 加载环境
source "$SCRIPT_DIR/setup_env.bash"
# 运行节点
echo "正在启动 master_supervisor..."
echo ""
ros2 run n_v_master_supervisor master_supervisor
EOF
chmod +x "$DEPLOY_DIR/run_master_supervisor.sh"
print_success "run_master_supervisor.sh 已创建"
# 创建测试脚本
cat > "$DEPLOY_DIR/test_deployment.sh" << 'EOF'
#!/bin/bash
# ============================================================================
# 部署包测试脚本
# ============================================================================
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "=== 部署包测试 ==="
echo ""
# 加载环境
source "$SCRIPT_DIR/setup_env.bash"
# 测试1:检查节点是否可以找到
echo ">>> 测试1: 检查节点"
if ros2 pkg executables n_v_master_supervisor | grep -q "master_supervisor"; then
echo "✓ master_supervisor 节点可用"
else
echo "✗ 未找到 master_supervisor 节点"
fi
echo ""
# 测试2:检查消息类型
echo ">>> 测试2: 检查消息类型"
if ros2 interface list | grep -q "n_v_msgs"; then
echo "✓ n_v_msgs 消息可用"
ros2 interface list | grep "n_v_msgs" | head -3
else
echo "✗ 未找到 n_v_msgs"
fi
echo ""
# 测试3:检查可执行文件
echo ">>> 测试3: 检查可执行文件"
EXEC_PATH="$SCRIPT_DIR/install/n_v_master_supervisor/lib/n_v_master_supervisor/master_supervisor"
if [ -x "$EXEC_PATH" ]; then
echo "✓ 可执行文件存在且可执行"
echo " 路径: $EXEC_PATH"
echo " 大小: $(du -h "$EXEC_PATH" | cut -f1)"
else
echo "✗ 可执行文件不存在或无执行权限"
fi
echo ""
# 测试4:检查配置文件
echo ">>> 测试4: 检查配置文件"
CONFIG_DIR="$SCRIPT_DIR/install/n_v_master_supervisor/share/n_v_master_supervisor/config"
if [ -d "$CONFIG_DIR" ]; then
CONFIG_COUNT=$(find "$CONFIG_DIR" -name "*.yaml" | wc -l)
echo "✓ 找到 $CONFIG_COUNT 个配置文件"
find "$CONFIG_DIR" -name "*.yaml" -exec basename {} \;
else
echo "! 配置目录不存在"
fi
echo ""
# 测试5:快速运行测试(--help)
echo ">>> 测试5: 测试可执行文件"
echo "运行: master_supervisor --help"
timeout 3 "$EXEC_PATH" --help 2>&1 || echo "(节点可能不支持 --help 参数,这是正常的)"
echo ""
echo "=== 测试完成 ==="
EOF
chmod +x "$DEPLOY_DIR/test_deployment.sh"
print_success "test_deployment.sh 已创建"
echo ""
# 步骤10:测试可执行文件
print_step "[10/10] 测试可执行文件"
print_info "加载环境并测试运行..."
# 创建临时测试脚本
cat > /tmp/test_master_supervisor.sh << EOF
#!/bin/bash
source /opt/ros/humble/setup.bash 2>/dev/null || source /opt/ros/foxy/setup.bash 2>/dev/null || true
source "$DEPLOY_DIR/install/setup.bash"
# 设置库路径
if [ -d "$DEPLOY_DIR/lib" ]; then
export LD_LIBRARY_PATH="$DEPLOY_DIR/lib:\$LD_LIBRARY_PATH"
fi
if [ -d "$DEPLOY_DIR/lib/x86_64-linux-gnu/spdlog/lib" ]; then
export LD_LIBRARY_PATH="$DEPLOY_DIR/lib/x86_64-linux-gnu/spdlog/lib:\$LD_LIBRARY_PATH"
fi
# 测试运行(3秒后自动结束)
timeout 3 "$MASTER_SUPERVISOR_PATH" 2>&1 || true
EOF
chmod +x /tmp/test_master_supervisor.sh
print_info "执行 3 秒快速测试..."
echo "----------------------------------------"
/tmp/test_master_supervisor.sh || true
echo "----------------------------------------"
print_success "可执行文件测试完成"
rm -f /tmp/test_master_supervisor.sh
echo ""
# 生成部署清单
print_step "生成部署清单"
cat > "$DEPLOY_DIR/MANIFEST.txt" << EOF
=================================================================
ROS2 工控机部署包清单
生成时间: $(date '+%Y-%m-%d %H:%M:%S')
=================================================================
1. 目录结构:
$(tree -L 3 -d "$DEPLOY_DIR" 2>/dev/null || find "$DEPLOY_DIR" -type d -maxdepth 3)
2. 可执行文件:
- master_supervisor: $MASTER_SUPERVISOR_PATH
大小: $(du -h "$MASTER_SUPERVISOR_PATH" | cut -f1)
3. 配置文件:
$(find "$DEPLOY_DIR/install/n_v_master_supervisor" -name "*.yaml" 2>/dev/null | sed 's/^/ - /')
4. Python脚本:
$(find "$DEPLOY_DIR/scripts" -name "*.py" 2>/dev/null | xargs -n1 basename | sed 's/^/ - /')
5. 消息包:
$(ls "$DEPLOY_DIR/install" | grep -E "msg|Msg" | sed 's/^/ - /')
6. 库文件:
$(find "$DEPLOY_DIR/lib" -name "*.so*" 2>/dev/null | wc -l) 个共享库文件
7. 总大小:
install/: $(du -sh "$DEPLOY_DIR/install" | cut -f1)
lib/: $(du -sh "$DEPLOY_DIR/lib" 2>/dev/null | cut -f1 || echo "N/A")
scripts/: $(du -sh "$DEPLOY_DIR/scripts" 2>/dev/null | cut -f1 || echo "N/A")
总计: $(du -sh "$DEPLOY_DIR" | cut -f1)
=================================================================
EOF
print_success "部署清单已生成: MANIFEST.txt"
echo ""
# 创建README
cat > "$DEPLOY_DIR/README.txt" << 'EOF'
=================================================================
ROS2 工控机部署包使用说明
=================================================================
📦 快速开始:
1. 设置环境:
source setup_env.bash
2. 测试部署:
./test_deployment.sh
3. 运行程序:
./run_master_supervisor.sh
或者:
ros2 run n_v_master_supervisor master_supervisor
4. 运行Python脚本:
python3 scripts/position_monitor.py
=================================================================
📋 文件说明:
- install/ : 所有编译后的包(C++可执行文件、消息、配置)
- scripts/ : Python脚本
- lib/ : 第三方库(包括spdlog)
- setup_env.bash : 环境设置脚本(必须先执行)
- run_master_supervisor.sh : 快速启动脚本
- test_deployment.sh : 部署测试脚本
- MANIFEST.txt : 详细的文件清单
=================================================================
⚙️ 工控机要求:
1. 操作系统: Ubuntu 22.04 (ROS2 Humble) 或 20.04 (ROS2 Foxy)
2. CPU架构: 必须与编译机器相同 (x86_64)
3. ROS2环境: 已安装相应版本的ROS2
安装ROS2:
sudo apt update
sudo apt install ros-humble-desktop
=================================================================
🔧 故障排查:
问题1: 找不到共享库
检查: ldd install/n_v_master_supervisor/lib/n_v_master_supervisor/master_supervisor
解决: 安装缺失的库
问题2: 找不到消息类型
检查: source setup_env.bash
验证: ros2 interface list | grep n_v_msgs
问题3: 无法运行
检查: 确保已经 source setup_env.bash
验证: echo $ROS_DISTRO
=================================================================
EOF
print_success "README.txt 已创建"
echo ""
# 打包
print_step "打包部署目录"
cd ~
tar -czf "$PACKAGE_NAME" -C "$(dirname "$DEPLOY_DIR")" "$(basename "$DEPLOY_DIR")"
PACKAGE_SIZE=$(du -sh ~/"$PACKAGE_NAME" | cut -f1)
print_success "部署包已创建: ~/$PACKAGE_NAME (大小: $PACKAGE_SIZE)"
echo ""
# 最终总结
print_header " 部署包创建完成 "
echo -e "${GREEN}✓ 部署目录: $DEPLOY_DIR${NC}"
echo -e "${GREEN}✓ 打包文件: ~/$PACKAGE_NAME${NC}"
echo ""
echo -e "${CYAN}📋 验证清单:${NC}"
echo -e " ${GREEN}✓${NC} install/ 目录 (大小: $INSTALL_SIZE)"
echo -e " ${GREEN}✓${NC} 可执行文件: master_supervisor"
echo -e " ${GREEN}✓${NC} 消息包: $MSG_COUNT 个"
echo -e " ${GREEN}✓${NC} Python脚本: $COPIED_SCRIPTS 个"
if [ -d "$DEPLOY_DIR/lib" ]; then
echo -e " ${GREEN}✓${NC} 第三方库: 包括 spdlog"
fi
echo -e " ${GREEN}✓${NC} 配置文件"
echo -e " ${GREEN}✓${NC} 启动脚本"
echo ""
echo -e "${CYAN}🧪 本地测试:${NC}"
echo -e " cd $DEPLOY_DIR"
echo -e " ./test_deployment.sh"
echo ""
echo -e "${CYAN}🚀 部署到工控机:${NC}"
echo -e " 1. 传输: scp ~/$PACKAGE_NAME user@工控机IP:/home/user/"
echo -e " 2. 解压: tar -xzf $PACKAGE_NAME"
echo -e " 3. 测试: cd $(basename "$DEPLOY_DIR") && ./test_deployment.sh"
echo -e " 4. 运行: ./run_master_supervisor.sh"
echo ""
echo -e "${CYAN}📖 详细信息:${NC}"
echo -e " 查看清单: cat $DEPLOY_DIR/MANIFEST.txt"
echo -e " 查看说明: cat $DEPLOY_DIR/README.txt"
echo ""
print_success "所有操作完成!"