Files
hivecore_robot_os1/launch_robot.sh
2026-01-22 20:12:02 +08:00

252 lines
8.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# ./launch_robot.sh [node_names...] # launch specific nodes
# ./launch_robot.sh all # launch all nodes in launch.conf
# Safer bash defaults for this script
set -Eeuo pipefail
# Argument check
TARGET_NODES=()
LAUNCH_ALL=false
if [ $# -eq 0 ]; then
echo "Error: No target nodes specified."
echo "Usage: $0 [node1 node2 ...] | all"
exit 1
fi
if [[ "$1" == "all" ]]; then
LAUNCH_ALL=true
else
TARGET_NODES=("$@")
fi
# Workspace directory defaults to the current working directory when the script is run
WS_DIR="${WS_DIR:-$PWD}"
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
CONFIG_FILE="${CONFIG_FILE:-${SCRIPT_DIR}/launch.conf}"
# 获取日期和时间戳函数
date_day() { date +"%Y%m%d"; }
readable_timestamp() { date +"%Y%m%d_%H%M%S"; }
# 1. 自动创建当天的日志根目录并包含本次启动的时间子目录
DAILY_LOG_ROOT="${WS_DIR}/logs/$(date_day)"
LOG_DIR="${DAILY_LOG_ROOT}/robot_logs_$(readable_timestamp)"
# LOG_ORIGIN_DIR="${LOG_DIR}/origin"
mkdir -p "${LOG_DIR}"
# mkdir -p "${LOG_ORIGIN_DIR}"
# 2. 导出相关环境变量
#export ROS_LOG_DIR="${LOG_ORIGIN_DIR}"
# ROS 2 无法原生完全禁用文件日志,将其指向 /tmp 下的临时目录以避免持久化保存
export ROS_LOG_DIR="/tmp/ros_log_discard_$(readable_timestamp)"
export PYTHONUNBUFFERED=1
export RCUTILS_LOGGING_BUFFERED_STREAM=1
export RCUTILS_COLORIZED_OUTPUT=0
# title|mode|package|target|args
# mode: run => ros2 run <pkg> <executable>
# launch => ros2 launch <pkg> <launch_file.py>
if [[ -f "${CONFIG_FILE}" ]]; then
mapfile -t COMPONENTS < <(grep -vE '^\s*#' "${CONFIG_FILE}" | sed '/^\s*$/d')
else
echo "no configuration file found at ${CONFIG_FILE}, exiting." >&2
exit 1
fi
compose_terminal_script() {
local title="$1" cmds_block="$2"
cat <<EOF
echo Launching Robot ${title}
cd "${WS_DIR}"
set +u; source install/setup.bash || { echo "Workspace not built (missing install/setup.bash). Run: colcon build" >&2; }; set -u;
# Freeze terminal title so it won't be changed by shell rc/profile
printf '\033]0;%s\007' "${title}"
${cmds_block}
echo "All processes launched for: Launching Robot ${title}"
exec bash --noprofile --norc
EOF
}
launch_with_gnome_terminal() {
# Build unique title list
local unique_titles=()
for entry in "${COMPONENTS[@]}"; do
IFS='|' read -r title mode pkg target args <<<"$entry"
# --- Filter Logic ---
if [ "$LAUNCH_ALL" = false ]; then
local match_found=false
for node_filter in "${TARGET_NODES[@]}"; do
# Match against package name or executable name
if [[ "$node_filter" == "$pkg" ]] || [[ "$node_filter" == "$target" ]]; then
match_found=true
break
fi
done
if [ "$match_found" = false ]; then
continue
fi
fi
# --------------------
local found=0
for t in "${unique_titles[@]:-}"; do
if [[ "$t" == "$title" ]]; then found=1; break; fi
done
if [[ $found -eq 0 ]]; then unique_titles+=("$title"); fi
done
# For each title, gather commands and open a terminal
for title in "${unique_titles[@]}"; do
local cmds_block=""
for entry in "${COMPONENTS[@]}"; do
IFS='|' read -r etitle mode pkg target args <<<"$entry"
[[ "$etitle" != "$title" ]] && continue
# --- Filter Logic (Repeated for execution block) ---
if [ "$LAUNCH_ALL" = false ]; then
local match_found=false
for node_filter in "${TARGET_NODES[@]}"; do
# Match against package name or executable name
if [[ "$node_filter" == "$pkg" ]] || [[ "$node_filter" == "$target" ]]; then
match_found=true
break
fi
done
if [ "$match_found" = false ]; then
continue
fi
fi
# --------------------
args="${args:-}"
local ros_cmd
if [[ "${pkg}" == "ethercat_control" ]]; then
ros_cmd="taskset -c 7 ./cpu7.sh"
elif [[ "$mode" == "launch" ]]; then
ros_cmd="ros2 launch ${pkg} ${target} ${args}"
else
ros_cmd="ros2 run ${pkg} ${target} ${args}"
fi
if [[ "${pkg}" == "robot_control" ]]; then
ros_cmd="echo 'Waiting for EtherCAT slaves to be OP...'; while ! ethercat slaves 2>&1 | grep -q 'OP' || ethercat slaves 2>&1 | grep -v 'OP' | grep -q .; do sleep 2; done; ${ros_cmd}"
fi
# 3. 为每个组件生成带明文时间戳的日志文件名并添加重定向
local log_file="${LOG_DIR}/${etitle}_${target}_$(readable_timestamp).log"
ros_cmd="{ ${ros_cmd}; } 2>&1 | tee \"${log_file}\""
cmds_block+="${ros_cmd} &"$'\n'
done
# If no commands collected for this title (because all were filtered out), skip launching terminal
if [[ -z "$cmds_block" ]]; then continue; fi
# Compose the final script for this terminal
local cmd
cmd=$(compose_terminal_script "$title" "$cmds_block")
# gnome-terminal --title="${title}" -- bash -lc "$cmd" &
bash -c "$cmd" &
sleep 3
done
}
launch_with_xterm() {
local unique_titles=()
for entry in "${COMPONENTS[@]}"; do
IFS='|' read -r title mode pkg target args <<<"$entry"
# --- Filter Logic ---
if [ "$LAUNCH_ALL" = false ]; then
local match_found=false
for node_filter in "${TARGET_NODES[@]}"; do
# Match against package name or executable name
if [[ "$node_filter" == "$pkg" ]] || [[ "$node_filter" == "$target" ]]; then
match_found=true
break
fi
done
if [ "$match_found" = false ]; then
continue
fi
fi
# --------------------
local found=0
for t in "${unique_titles[@]:-}"; do
if [[ "$t" == "$title" ]]; then found=1; break; fi
done
if [[ $found -eq 0 ]]; then unique_titles+=("$title"); fi
done
for title in "${unique_titles[@]}"; do
local cmds_block=""
for entry in "${COMPONENTS[@]}"; do
IFS='|' read -r etitle mode pkg target args <<<"$entry"
[[ "$etitle" != "$title" ]] && continue
# --- Filter Logic (Repeated for execution block) ---
if [ "$LAUNCH_ALL" = false ]; then
local match_found=false
for node_filter in "${TARGET_NODES[@]}"; do
# Match against package name or executable name
if [[ "$node_filter" == "$pkg" ]] || [[ "$node_filter" == "$target" ]]; then
match_found=true
break
fi
done
if [ "$match_found" = false ]; then
continue
fi
fi
# --------------------
args="${args:-}"
local ros_cmd
if [[ "${pkg}" == "ethercat_control" ]]; then
ros_cmd="taskset -c 7 ./cpu7.sh"
elif [[ "$mode" == "launch" ]]; then
ros_cmd="ros2 launch ${pkg} ${target} ${args}"
else
ros_cmd="ros2 run ${pkg} ${target} ${args}"
fi
if [[ "${pkg}" == "robot_control" ]]; then
ros_cmd="echo 'Waiting for EtherCAT slaves to be OP...'; while ! ethercat slaves 2>&1 | grep -q 'OP' || ethercat slaves 2>&1 | grep -v 'OP' | grep -q .; do sleep 2; done; ${ros_cmd}"
fi
# 3. 为每个组件生成带明文时间戳的日志文件名并添加重定向
local log_file="${LOG_DIR}/${etitle}_${target}_$(readable_timestamp).log"
ros_cmd="{ ${ros_cmd}; } 2>&1 | tee \"${log_file}\""
cmds_block+="${ros_cmd} &"$'\n'
done
# If no commands collected for this title (because all were filtered out), skip launching terminal
if [[ -z "$cmds_block" ]]; then continue; fi
local cmd
cmd=$(compose_terminal_script "$title" "$cmds_block")
xterm -T "${title}" -hold -e bash -lc "$cmd" &
done
}
main() {
echo "Starting robot components..."
if command -v gnome-terminal >/dev/null 2>&1; then
echo "Using gnome-terminal"
launch_with_gnome_terminal
elif command -v xterm >/dev/null 2>&1; then
echo "Using xterm"
launch_with_xterm
else
echo "No terminal emulator found (gnome-terminal or xterm). Proceeding with background execution." >&2
launch_with_gnome_terminal
fi
}
main "$@"