2025-08-29 16:37:57 +08:00
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
# ros2_nodes.sh
|
2025-09-02 17:16:28 +08:00
|
|
|
|
# 一键启动 / 停止 / 重启 / 状态查询 6 个 ROS 2 节点(或仅核心 4 节点)
|
2025-08-29 16:37:57 +08:00
|
|
|
|
# 用法:
|
2025-09-02 17:16:28 +08:00
|
|
|
|
# ./ros2_nodes.sh start # 默认启动全部 6 节点
|
2025-08-29 16:37:57 +08:00
|
|
|
|
# ./ros2_nodes.sh start all # 同上
|
|
|
|
|
|
# ./ros2_nodes.sh start core # 仅启动 4 个核心节点
|
|
|
|
|
|
# ./ros2_nodes.sh stop # 停止
|
|
|
|
|
|
# ./ros2_nodes.sh restart [core] # 重启(可选 core / all)
|
|
|
|
|
|
# ./ros2_nodes.sh status # 查看状态
|
|
|
|
|
|
# ./ros2_nodes.sh rotate # 手动轮换日志
|
|
|
|
|
|
###############################################################################
|
|
|
|
|
|
|
|
|
|
|
|
##== 基本路径与环境 ===========================================================
|
2025-09-02 17:16:28 +08:00
|
|
|
|
WORKSPACE_PATH="/home/nvidia/Downloads/sweeper_whu"
|
2025-08-29 16:37:57 +08:00
|
|
|
|
source "$WORKSPACE_PATH/install/setup.bash"
|
|
|
|
|
|
|
|
|
|
|
|
##== 日志目录与轮换配置 =======================================================
|
|
|
|
|
|
LOG_DIR="/var/log/ros2"
|
|
|
|
|
|
MAX_LOG_SIZE="10M" # 单个日志大小
|
|
|
|
|
|
MAX_LOG_FILES=5 # 保留文件数
|
|
|
|
|
|
|
|
|
|
|
|
##== 节点命令列表 ==============================================================
|
|
|
|
|
|
|
2025-09-02 17:16:28 +08:00
|
|
|
|
# 1) 全量 6 节点(键名 = 节点标识 , 值 = 启动命令)
|
2025-08-29 16:37:57 +08:00
|
|
|
|
declare -A NODES_ALL=(
|
2025-09-02 17:16:28 +08:00
|
|
|
|
["mc"]="ros2 run mc mc_node"
|
2025-08-29 16:37:57 +08:00
|
|
|
|
["radio_ctrl"]="ros2 run radio_ctrl radio_ctrl_node"
|
|
|
|
|
|
["ctrl_arbiter"]="ros2 run ctrl_arbiter ctrl_arbiter_node"
|
|
|
|
|
|
["mqtt_report"]="ros2 run mqtt_report mqtt_report_node"
|
|
|
|
|
|
["rtk"]="ros2 run rtk rtk_node"
|
|
|
|
|
|
["pub_gps"]="ros2 run pub_gps pub_gps_node"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 2) 核心节点名称数组(便于 core 模式筛选)
|
|
|
|
|
|
CORE_NAMES=(mc radio_ctrl ctrl_arbiter mqtt_report)
|
|
|
|
|
|
|
|
|
|
|
|
##== 函数 =====================================================================
|
|
|
|
|
|
|
|
|
|
|
|
# 预启动环境准备:CAN、USB 权限、日志目录与 logrotate
|
|
|
|
|
|
setup_environment() {
|
|
|
|
|
|
echo "[INFO] 设置 CAN0 波特率为 500K..."
|
|
|
|
|
|
sudo ip link set can0 down 2>/dev/null
|
|
|
|
|
|
sudo ip link set can0 type can bitrate 500000
|
|
|
|
|
|
sudo ip link set can0 up
|
|
|
|
|
|
echo "[INFO] CAN0 配置完成。"
|
|
|
|
|
|
|
|
|
|
|
|
echo "[INFO] 设置 /dev/ttyUSB0 权限为 777..."
|
|
|
|
|
|
sudo chmod 777 /dev/ttyUSB0
|
|
|
|
|
|
echo "[INFO] ttyUSB0 权限设置完成。"
|
|
|
|
|
|
|
|
|
|
|
|
echo "[INFO] 设置 /dev/ttyTHS1 权限为 777..."
|
|
|
|
|
|
sudo chmod 777 /dev/ttyTHS1
|
|
|
|
|
|
echo "[INFO] ttyTHS1 权限设置完成。"
|
|
|
|
|
|
|
|
|
|
|
|
# 日志目录
|
|
|
|
|
|
echo "[INFO] 创建日志目录: $LOG_DIR"
|
|
|
|
|
|
sudo mkdir -p "$LOG_DIR"
|
|
|
|
|
|
sudo chown -R nvidia:nvidia "$LOG_DIR"
|
|
|
|
|
|
|
|
|
|
|
|
# logrotate 配置
|
|
|
|
|
|
local LOGROTATE_CONF="/etc/logrotate.d/ros2_nodes"
|
|
|
|
|
|
echo "[INFO] 配置 logrotate: $LOGROTATE_CONF"
|
|
|
|
|
|
sudo bash -c "cat > $LOGROTATE_CONF" <<EOF
|
|
|
|
|
|
$LOG_DIR/*.log {
|
|
|
|
|
|
su nvidia nvidia
|
|
|
|
|
|
daily
|
|
|
|
|
|
maxsize $MAX_LOG_SIZE
|
|
|
|
|
|
rotate $MAX_LOG_FILES
|
|
|
|
|
|
missingok
|
|
|
|
|
|
notifempty
|
|
|
|
|
|
compress
|
|
|
|
|
|
delaycompress
|
|
|
|
|
|
sharedscripts
|
|
|
|
|
|
copytruncate
|
|
|
|
|
|
}
|
|
|
|
|
|
EOF
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 启动节点:start_nodes [core|all]
|
|
|
|
|
|
start_nodes() {
|
|
|
|
|
|
local mode=${1:-all} # 默认 all
|
|
|
|
|
|
setup_environment
|
|
|
|
|
|
|
|
|
|
|
|
# 选择节点集合
|
|
|
|
|
|
local names=()
|
|
|
|
|
|
if [[ "$mode" == "core" ]]; then
|
|
|
|
|
|
names=("${CORE_NAMES[@]}")
|
|
|
|
|
|
else
|
|
|
|
|
|
names=("${!NODES_ALL[@]}")
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
echo "[INFO] 启动模式: $mode"
|
|
|
|
|
|
echo "[INFO] 节点列表: ${names[*]}"
|
|
|
|
|
|
echo "[INFO] 每个节点启动间隔 0.1s"
|
|
|
|
|
|
|
|
|
|
|
|
for name in "${names[@]}"; do
|
|
|
|
|
|
echo "[START] $name"
|
|
|
|
|
|
local log_file="${LOG_DIR}/${name}.log"
|
|
|
|
|
|
|
|
|
|
|
|
#=====================================================================
|
|
|
|
|
|
${NODES_ALL[$name]} >> "$log_file" 2>&1 &
|
|
|
|
|
|
# gnome-terminal --title="$name" \
|
|
|
|
|
|
# -- bash -c "source $WORKSPACE_PATH/install/setup.bash && ${NODES_ALL[$name]}; exec bash" &
|
|
|
|
|
|
#=====================================================================
|
|
|
|
|
|
|
|
|
|
|
|
local pid=$!
|
|
|
|
|
|
echo $pid > "/tmp/$name.pid"
|
|
|
|
|
|
echo "[INFO] $name PID: $pid | 日志: $log_file"
|
|
|
|
|
|
|
|
|
|
|
|
sleep 0.1 # 每个节点之间暂停 0.1 秒
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
echo "[INFO] 所有节点已启动 (${mode})."
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 停止全部正在运行的节点
|
|
|
|
|
|
stop_nodes() {
|
|
|
|
|
|
echo "[INFO] 停止 ROS 2 节点..."
|
|
|
|
|
|
for pidfile in /tmp/*.pid; do
|
|
|
|
|
|
[ -e "$pidfile" ] || continue
|
|
|
|
|
|
local name=$(basename "$pidfile" .pid)
|
|
|
|
|
|
local pid=$(cat "$pidfile")
|
|
|
|
|
|
if ps -p "$pid" > /dev/null 2>&1; then
|
|
|
|
|
|
kill -SIGINT "$pid" && echo "[STOP] $name (PID $pid) - 发送 SIGINT"
|
|
|
|
|
|
local timeout=5
|
|
|
|
|
|
while kill -0 "$pid" 2>/dev/null && [ $timeout -gt 0 ]; do
|
|
|
|
|
|
sleep 0.5; ((timeout--))
|
|
|
|
|
|
done
|
|
|
|
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
|
|
|
|
kill -9 "$pid" && echo "[STOP] $name (PID $pid) - 强制终止"
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
rm -f "$pidfile"
|
|
|
|
|
|
done
|
|
|
|
|
|
echo "[INFO] 所有节点已停止。"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 手动触发日志轮换
|
|
|
|
|
|
rotate_logs() {
|
|
|
|
|
|
echo "[INFO] 手动轮换日志..."
|
|
|
|
|
|
sudo logrotate -f /etc/logrotate.d/ros2_nodes
|
|
|
|
|
|
echo "[INFO] 日志轮换完成。"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# 查看节点运行状态
|
|
|
|
|
|
show_status() {
|
|
|
|
|
|
echo "[INFO] 节点状态:"
|
|
|
|
|
|
for name in "${!NODES_ALL[@]}"; do
|
|
|
|
|
|
if [ -f "/tmp/$name.pid" ]; then
|
|
|
|
|
|
local pid=$(cat "/tmp/$name.pid")
|
|
|
|
|
|
if ps -p "$pid" > /dev/null 2>&1; then
|
|
|
|
|
|
echo "[RUNNING] $name (PID $pid)"
|
|
|
|
|
|
else
|
|
|
|
|
|
echo "[DEAD] $name (PID $pid)"
|
|
|
|
|
|
fi
|
|
|
|
|
|
else
|
|
|
|
|
|
echo "[STOPPED] $name"
|
|
|
|
|
|
fi
|
|
|
|
|
|
done
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
##== 主入口 ===================================================================
|
|
|
|
|
|
|
|
|
|
|
|
case "$1" in
|
|
|
|
|
|
start)
|
|
|
|
|
|
# 用法: ./ros2_nodes.sh start [core|all]
|
|
|
|
|
|
start_nodes "${2:-all}"
|
|
|
|
|
|
;;
|
|
|
|
|
|
stop)
|
|
|
|
|
|
stop_nodes
|
|
|
|
|
|
;;
|
|
|
|
|
|
restart)
|
|
|
|
|
|
stop_nodes
|
|
|
|
|
|
sleep 1
|
|
|
|
|
|
start_nodes "${2:-all}"
|
|
|
|
|
|
;;
|
|
|
|
|
|
rotate)
|
|
|
|
|
|
rotate_logs
|
|
|
|
|
|
;;
|
|
|
|
|
|
status)
|
|
|
|
|
|
show_status
|
|
|
|
|
|
;;
|
|
|
|
|
|
*)
|
|
|
|
|
|
echo "Usage: $0 {start|stop|restart|rotate|status} [core|all]"
|
|
|
|
|
|
echo " core : 仅启动 4 个核心节点 (mc radio_ctrl ctrl_arbiter mqtt_report)"
|
2025-09-02 17:16:28 +08:00
|
|
|
|
echo " all : 启动全部 6 个节点 (默认)"
|
2025-08-29 16:37:57 +08:00
|
|
|
|
;;
|
|
|
|
|
|
esac
|