Files

342 lines
10 KiB
Bash
Raw Permalink Normal View History

2026-06-05 14:20:30 +08:00
#!/usr/bin/env bash
# Start the real-vehicle Autoware stack and one preset-route tool mode.
#
# 用法:
# ./run_preset_route_real_vehicle.sh [模式] [站点文件] [是否启动RViz] [地图目录] [车型]
#
# 位置参数都可以省略,省略时使用下面的默认值或对应环境变量:
# 模式: ui-only
# 可选 record | replay | mission | none | ui-only
# 站点文件: $PRESET_ROUTE_STATIONS_FILE
# 默认 src/UI/preset_route_cruise/paths/recorded_stations.yaml
# RViz: $PRESET_ROUTE_RVIZ
# 非ui-only模式默认 trueui-only打开UI时默认 false,可选 true | false
# 地图目录: $PRESET_ROUTE_MAP_PATH
# 默认 /home/nvidia/FaRui-test/map/School06
# 车型: $PRESET_ROUTE_VEHICLE_MODEL
# 默认 ecar_vehicle
#
# 常用示例:
# 只打开UI,不启动主板Autoware:
# ./run_preset_route_real_vehicle.sh
#
# 只启动主板Autoware,不启动预设路线工具:
# ./run_preset_route_real_vehicle.sh none
#
# 启动主板Autoware并关闭RViz:
# ./run_preset_route_real_vehicle.sh mission "" false
#
# 使用指定地图:
# ./run_preset_route_real_vehicle.sh mission "" true /home/nvidia/FaRui-test/map/School06
#
# 启动主板Autoware + 站点任务管理器:
# ./run_preset_route_real_vehicle.sh mission
#
# 常用环境变量:
# PRESET_ROUTE_MAP_PATH=/path/to/map
# PRESET_ROUTE_RVIZ=false
# PRESET_ROUTE_NO_UI=true
# PRESET_ROUTE_SKIP_MAIN_STACK=true
# PRESET_ROUTE_START_ON_LAUNCH=true
# PRESET_ROUTE_LOOP_MISSION=true
# PRESET_ROUTE_START_STATION_INDEX=0
# PRESET_ROUTE_AUTOWARE_LAUNCH_FILE=/path/to/ecar_master.launch.xml
#
# 双Orin说明:
# 本脚本用于主板,默认启动 src/Launcher/farui_launch/launch/ecar_master.launch.xml。
# 主板默认不启动 system、vehicle、control;这些由从板脚本负责。
set -euo pipefail
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
find_workspace_root() {
if [[ -n "${PRESET_ROUTE_WORKSPACE_ROOT:-}" ]]; then
echo "${PRESET_ROUTE_WORKSPACE_ROOT}"
return
fi
local candidates=(
"${PWD}"
"${script_dir}"
"${script_dir}/../../../.."
"${script_dir}/../../../../.."
)
for candidate in "${candidates[@]}"; do
if [[ -f "${candidate}/install/setup.bash" ]]; then
(cd "${candidate}" && pwd)
return
fi
done
echo "${PWD}"
}
kill_process_group() {
local pid="$1"
local signal="${2:-TERM}"
if [[ -z "${pid}" ]] || ! kill -0 "${pid}" 2>/dev/null; then
return 0
fi
local pgid
pgid="$(ps -o pgid= -p "${pid}" 2>/dev/null | tr -d ' ')"
if [[ -n "${pgid}" ]]; then
kill "-${signal}" -- "-${pgid}" 2>/dev/null || true
else
kill "-${signal}" "${pid}" 2>/dev/null || true
fi
}
launch_preset_route_ui() {
local source_ui="${WORKSPACE_ROOT}/src/UI/preset_route_cruise/scripts/preset_route_operator.py"
if [[ -f "${source_ui}" ]]; then
log_info "Launching preset route UI from source."
python3 "${source_ui}"
return
fi
local installed_ui="${WORKSPACE_ROOT}/install/preset_route_cruise/lib/preset_route_cruise/preset_route_operator.py"
if [[ -f "${installed_ui}" ]]; then
log_warn "preset_route_operator.py is not registered as a ros2 executable; launching installed script."
python3 "${installed_ui}"
return
fi
if ros2 pkg executables preset_route_cruise 2>/dev/null | awk '{print $2}' | grep -qx "preset_route_operator.py"; then
ros2 run preset_route_cruise preset_route_operator.py
return
fi
log_error "Preset route UI executable not found. Expected ros2 executable, ${source_ui}, or ${installed_ui}"
return 1
}
find_default_map_path() {
echo "/home/nvidia/FaRui-test/map/School06"
}
WORKSPACE_ROOT="$(find_workspace_root)"
DEFAULT_STATIONS_FILE="${WORKSPACE_ROOT}/src/UI/preset_route_cruise/paths/recorded_stations.yaml"
DEFAULT_MAP_PATH="$(find_default_map_path)"
DEFAULT_VEHICLE_MODEL="ecar_vehicle"
DEFAULT_AUTOWARE_LAUNCH_FILE="${WORKSPACE_ROOT}/src/Launcher/farui_launch/launch/ecar_master.launch.xml"
ROUTE_MODE="${1:-ui-only}"
STATIONS_FILE="${2:-${PRESET_ROUTE_STATIONS_FILE:-${DEFAULT_STATIONS_FILE}}}"
RVIZ="${3:-${PRESET_ROUTE_RVIZ:-true}}"
MAP_PATH="${4:-${PRESET_ROUTE_MAP_PATH:-${DEFAULT_MAP_PATH}}}"
VEHICLE_MODEL="${5:-${PRESET_ROUTE_VEHICLE_MODEL:-${DEFAULT_VEHICLE_MODEL}}}"
UI_START_RECORDING_ON_LAUNCH="${PRESET_ROUTE_START_RECORDING_ON_LAUNCH:-false}"
UI_AUTO_SEND_ON_START="${PRESET_ROUTE_AUTO_SEND_ON_START:-false}"
UI_MISSION_START_ON_LAUNCH="${PRESET_ROUTE_START_ON_LAUNCH:-false}"
UI_ALLOW_GOAL_MODIFICATION="${PRESET_ROUTE_ALLOW_GOAL_MODIFICATION:-false}"
UI_MISSION_LOOP="${PRESET_ROUTE_LOOP_MISSION:-false}"
UI_MISSION_START_STATION_INDEX="${PRESET_ROUTE_START_STATION_INDEX:-0}"
UI_SKIP_MAIN_STACK="${PRESET_ROUTE_SKIP_MAIN_STACK:-false}"
UI_RECORD_CLEAR_ON_START="${PRESET_ROUTE_RECORD_CLEAR_ON_START:-false}"
UI_RECORD_APPEND_EXISTING="${PRESET_ROUTE_RECORD_APPEND_EXISTING:-true}"
AUTOWARE_LAUNCH_FILE="${PRESET_ROUTE_AUTOWARE_LAUNCH_FILE:-${DEFAULT_AUTOWARE_LAUNCH_FILE}}"
case "${ROUTE_MODE}" in
record|replay|mission|none|ui-only)
;;
*)
log_error "Unsupported route mode: ${ROUTE_MODE}. Expected record, replay, mission, none, or ui-only."
exit 1
;;
esac
case "${RVIZ}" in
true|false)
;;
*)
log_error "RVIZ must be true or false, got: ${RVIZ}"
exit 1
;;
esac
if [[ ("${ROUTE_MODE}" == "replay" || "${ROUTE_MODE}" == "mission") && ! -f "${STATIONS_FILE}" ]]; then
log_error "Stations file not found: ${STATIONS_FILE}"
exit 1
fi
if [[ "${UI_SKIP_MAIN_STACK}" != "true" && ! -d "${MAP_PATH}" ]]; then
log_error "Map path not found: ${MAP_PATH}"
exit 1
fi
if [[ ! -f "${WORKSPACE_ROOT}/install/setup.bash" ]]; then
log_error "Workspace setup file not found: ${WORKSPACE_ROOT}/install/setup.bash"
exit 1
fi
if [[ "${UI_SKIP_MAIN_STACK}" != "true" && "${ROUTE_MODE}" != "ui-only" && ! -f "${AUTOWARE_LAUNCH_FILE}" ]]; then
log_error "Autoware launch file not found: ${AUTOWARE_LAUNCH_FILE}"
exit 1
fi
log_info "Workspace: ${WORKSPACE_ROOT}"
log_info "Mode: ${ROUTE_MODE}, stations: ${STATIONS_FILE}"
log_info "Autoware launch: ${AUTOWARE_LAUNCH_FILE}"
log_info "Map path: ${MAP_PATH}"
cd "${WORKSPACE_ROOT}"
set +u
source install/setup.bash
set -u
AUTOWARE_STACK_PID=""
EXTRA_TOOL_PID=""
UI_PID=""
if [[ "${UI_SKIP_MAIN_STACK}" != "true" && "${ROUTE_MODE}" != "ui-only" ]]; then
log_info "Launching master Orin Autoware stack."
setsid ros2 launch "${AUTOWARE_LAUNCH_FILE}" \
map_path:="${MAP_PATH}" \
vehicle_model:="${VEHICLE_MODEL}" \
launch_planning:=true \
launch_system:=false \
launch_vehicle:=false \
launch_control:=false \
launch_api:=true \
use_sim_time:=false \
rviz:="${RVIZ}" \
rviz_respawn:=false &
AUTOWARE_STACK_PID=$!
else
log_info "Main stack launch skipped by PRESET_ROUTE_SKIP_MAIN_STACK=true."
fi
if [[ "${ROUTE_MODE}" != "ui-only" ]]; then
if [[ "${ROUTE_MODE}" == "record" ]]; then
log_info "Launching station recorder."
setsid ros2 launch preset_route_cruise record_stations_from_rviz.launch.xml \
output_file:="${STATIONS_FILE}" \
clear_file_on_start:="${UI_RECORD_CLEAR_ON_START}" \
append_existing:="${UI_RECORD_APPEND_EXISTING}" \
write_on_each_point:=true \
start_recording_on_launch:="${UI_START_RECORDING_ON_LAUNCH}" \
use_sim_time:=false &
EXTRA_TOOL_PID=$!
fi
if [[ "${ROUTE_MODE}" == "replay" ]]; then
log_info "Launching preset route sender."
setsid ros2 launch preset_route_cruise preset_route_cruise.launch.xml \
stations_file:="${STATIONS_FILE}" \
clear_route_before_send:=true \
allow_goal_modification:="${UI_ALLOW_GOAL_MODIFICATION}" \
auto_shutdown_after_send:=false \
auto_send_on_start:="${UI_AUTO_SEND_ON_START}" \
use_sim_time:=false &
EXTRA_TOOL_PID=$!
fi
if [[ "${ROUTE_MODE}" == "mission" ]]; then
log_info "Launching station mission manager."
setsid ros2 launch preset_route_cruise station_mission_manager.launch.xml \
stations_file:="${STATIONS_FILE}" \
loop_mission:="${UI_MISSION_LOOP}" \
auto_start_on_each_leg:=false \
manual_start_first_leg_only:=true \
clear_route_before_send:=true \
allow_goal_modification:="${UI_ALLOW_GOAL_MODIFICATION}" \
start_on_launch:="${UI_MISSION_START_ON_LAUNCH}" \
start_station_index:="${UI_MISSION_START_STATION_INDEX}" \
auto_shutdown_on_finish:=false \
use_sim_time:=false &
EXTRA_TOOL_PID=$!
fi
if [[ "${ROUTE_MODE}" == "none" ]]; then
log_info "Extra preset-route tool launch skipped."
fi
else
log_info "UI-only mode: main stack and tools will be started from UI."
fi
# 启动 UI 界面
if [[ "${PRESET_ROUTE_NO_UI:-false}" != "true" ]]; then
export PRESET_ROUTE_MAP_PATH="${MAP_PATH}"
export PRESET_ROUTE_STATIONS_FILE="${STATIONS_FILE}"
export PRESET_ROUTE_VEHICLE_MODEL="${VEHICLE_MODEL}"
if [[ "${ROUTE_MODE}" == "ui-only" ]]; then
log_info "Launching preset route UI (UI-only mode)."
PRESET_ROUTE_RVIZ="${PRESET_ROUTE_RVIZ:-false}" launch_preset_route_ui &
UI_PID=$!
else
UI_LAUNCH_DELAY="${PRESET_ROUTE_UI_LAUNCH_DELAY:-3}"
log_info "UI will launch in ${UI_LAUNCH_DELAY} seconds..."
(
sleep "${UI_LAUNCH_DELAY}"
log_info "Launching preset route UI."
launch_preset_route_ui
) &
UI_PID=$!
fi
fi
cleanup() {
trap - EXIT INT TERM
local pids=()
if [[ -n "${UI_PID}" ]]; then
pids+=("${UI_PID}")
fi
if [[ -n "${EXTRA_TOOL_PID}" ]]; then
pids+=("${EXTRA_TOOL_PID}")
fi
if [[ -n "${AUTOWARE_STACK_PID}" ]]; then
pids+=("${AUTOWARE_STACK_PID}")
fi
if [[ ${#pids[@]} -eq 0 ]]; then
return
fi
log_info "Shutting down launched processes."
for pid in "${pids[@]}"; do
kill_process_group "${pid}" TERM
done
sleep 2
for pid in "${pids[@]}"; do
kill_process_group "${pid}" KILL
done
wait "${pids[@]}" 2>/dev/null || true
}
trap cleanup EXIT INT TERM
WAIT_PIDS=()
if [[ -n "${AUTOWARE_STACK_PID}" ]]; then
WAIT_PIDS+=("${AUTOWARE_STACK_PID}")
fi
if [[ -n "${EXTRA_TOOL_PID}" ]]; then
WAIT_PIDS+=("${EXTRA_TOOL_PID}")
fi
if [[ -n "${UI_PID}" ]]; then
WAIT_PIDS+=("${UI_PID}")
fi
if [[ ${#WAIT_PIDS[@]} -gt 0 ]]; then
wait "${WAIT_PIDS[@]}"
fi