本文面向第一次接触 ROS、Docker 和无人机仿真的用户。目标是让用户能够:
- 根据自己的电脑选择“本机 ROS1”或“ROS1 Docker”运行方式。
- 编译并启动 ROS Noetic + Unity 仿真。
- 在 RViz 和 Unity 中观察无人机、地图和轨迹。
- 修改参数或 C++/Python 代码,并在仿真中验证结果。
本文基于官方 2026robotics 分支和本项目当前可运行的工作区整理。官方链接:
https://github.com/DifferentialRobotics/Aerial_Autonomy_Challenge/tree/2026robotics
官方仿真器下载链接(官方 README 提供):
https://pan.baidu.com/s/1rCioYJQSKhKqadkiC0CGdA?pwd=hs5p
本文优先支持 Ubuntu/Linux。电脑已经安装 ROS Noetic 时,可以完全不使用 Docker;没有 ROS1 时,再使用 ROS1 Docker。Windows 或 macOS 上使用 Docker Desktop 需要额外的图形转发配置,本文不作为主要支持路径。
1. 先理解这套系统
这不是一个只运行 Unity 的程序,而是多个 ROS 节点共同组成的闭环:
Unity 仿真器
├── 目标点列表 /publish_point (PoseArray)
│ ↓
│ sequential_waypoint_bridge.sh
│ ↓ /goal (PoseStamped)
│ Diff-Planner 规划器
│ ↓ /drone_0_planning/trajectory
│ traj_server 轨迹采样
│ ↓ /drone_0_planning/pos_cmd
│ cascadePID 控制器
│ ↓ /quad_0/cmdRPM
│ quadrotor_dynamics 动力学仿真
│ ↓ /quad_0/lidar_slam/odom
│ Unity 和航点到达判断
│
└── 点云 /drone_0_pcl_render_node/cloud
↓
GridMap 障碍物地图
启动脚本是 sh_files/run_unity.sh,它按顺序启动:
- ROS-TCP-Endpoint:让 Unity 通过 TCP 连接 ROS,默认端口为 10000。
- Unity 可执行仿真器。
- ROS 仿真节点、规划器、控制器和动力学。
- 多航点桥接脚本。
- RViz 可视化。
2. 安装前检查
2.1 宿主机建议配置
官方验证环境为 Ubuntu 20.04、ROS Noetic、NVIDIA RTX 4060。其他配置也可能运行,但图形驱动和编译时间会不同。
建议准备:
- 64 位 Linux,建议 Ubuntu 20.04。
- 支持 OpenGL 的显卡;推荐 NVIDIA 显卡和已安装的 NVIDIA 驱动。
- 至少 16 GB 内存;编译时使用 -j1 可以降低内存压力。
- 至少 30 GB 可用磁盘空间。
- Docker Engine(仅在选择 Docker 路径时需要)。
- ROS Noetic(仅在选择本机 ROS1 路径时需要)。
- 能够显示 X11 图形窗口的桌面环境。
在宿主机执行以下检查:
uname -m
lsb_release -a
echo "$DISPLAY"
如果使用 NVIDIA 显卡,再执行 nvidia-smi 检查驱动。DISPLAY 通常类似 :0 或 :1;Docker 图形配置必须使用实际输出的显示编号,不能盲目写成 :0。
2.2 选择运行路径
请先在准备运行仿真的环境中执行:
source /opt/ros/noetic/setup.bash
rosversion -d
如果输出 noetic,说明该环境已经有 ROS1,可以直接使用本机 ROS1 路径,不需要 Docker。
如果提示文件不存在,或者电脑没有 ROS1,则使用 Docker 路径。Docker 只是在一个隔离环境中提供 Ubuntu 20.04 和 ROS Noetic,项目代码仍然可以挂载在宿主机上保存。
两条路径后面的代码下载、Unity 仿真器放置、catkin 编译和运行逻辑相同,主要区别是命令在哪个环境执行:
| 情况 | 代码和编译位置 | 是否需要 Docker 图形配置 |
|---|---|---|
| 本机已安装 ROS Noetic | 宿主机工作区 | 不需要 X11 socket 挂载 |
| 本机没有 ROS1 | ROS1 Docker 容器内 | 需要 DISPLAY、X11 socket 和 GPU 转发 |
2.3 安装 Docker(仅 Docker 路径需要)
如果宿主机还没有 Docker,可以先安装 Ubuntu 软件源中的版本:
sudo apt update
sudo apt install -y docker.io
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
执行 usermod 后需要重新登录,或者临时执行:
newgrp docker
docker run --rm hello-world
2.4 NVIDIA Docker 支持(仅 Docker 路径需要)
想让 Unity 使用显卡,需要在宿主机安装 NVIDIA Container Toolkit,并保证以下命令能工作:
docker run --rm --gpus all nvidia/cuda:12.0.0-base-ubuntu20.04 nvidia-smi
如果该命令报 could not select device driver,说明 Docker 还没有配置 GPU 运行时。先根据 NVIDIA 官方文档安装 Container Toolkit,再继续本指南。没有 GPU 时可以尝试软件渲染,但 Unity 和 RViz 可能无法正常显示或性能很差。
3. 获取代码和 Unity 仿真器
3.1 获取代码
mkdir -p ~/aerial_ws
cd ~/aerial_ws
git clone --branch 2026robotics https://github.com/DifferentialRobotics/Aerial_Autonomy_Challenge.git
cd Aerial_Autonomy_Challenge
如果代码已经存在,只需要确认分支:
git branch --show-current
git status --short
3.2 放置 Unity 仿真器
从官方网盘下载并解压仿真器,将整个目录放到:
Aerial_Autonomy_Challenge/src/AerialAutonomyChallenge-Simulator/
必须能看到以下文件:
ls -l src/AerialAutonomyChallenge-Simulator/AerialAutonomyChallenge-Simulator.x86_64
赋予执行权限:
chmod +x src/AerialAutonomyChallenge-Simulator/AerialAutonomyChallenge-Simulator.x86_64
如果文件不存在,ROS 节点可以编译成功,但 Unity 场景不会启动。
4. 根据环境继续安装
4.1 电脑已经安装 ROS1:直接使用本机环境
这是最简单的路径。所有 ROS 节点、Unity 和 RViz 都直接运行在宿主机上,不需要创建 Docker 容器,也不需要挂载 X11 socket。
在宿主机打开一个终端,执行:
source /opt/ros/noetic/setup.bash
rosversion -d
which roscore
which roslaunch
which rviz
rosversion -d 应输出 noetic。本项目官方环境是 ROS Noetic;如果是 ROS Melodic 或其他 ROS1 版本,不能保证所有依赖和 C++ ABI 兼容,建议使用 Noetic。
如果 ROS 已安装但缺少编译工具或常用依赖,可以在宿主机补齐:
sudo apt update
sudo apt install -y ros-noetic-desktop-full zsh git build-essential python3-rosdep \
python3-catkin-tools libeigen3-dev libpcl-dev
ros-noetic-desktop-full 用于补齐 RViz、常用消息和桌面工具;如果已经完整安装,apt 会直接跳过已存在的包。每个新终端都要 source ROS 环境,也可以将下面一行加入 ~/.bashrc:
source /opt/ros/noetic/setup.bash
首次使用 rosdep 时初始化并安装工作区依赖:
sudo rosdep init 2>/dev/null || true
rosdep update
cd ~/aerial_ws/Aerial_Autonomy_Challenge
rosdep install --from-paths src --ignore-src --rosdistro noetic -r -y
如果代码放在其他目录,将上面的工作区路径替换为实际路径。然后编译:
cd ~/aerial_ws/Aerial_Autonomy_Challenge
source /opt/ros/noetic/setup.bash
catkin_make -j1
source devel/setup.bash
本机运行 Unity 时,通常不需要执行 xhost,因为 Unity 和 RViz 与当前桌面用户使用同一个显示会话。确认显示变量存在:
echo "$DISPLAY"
echo "$XDG_RUNTIME_DIR"
如果 DISPLAY 为空,说明当前终端不是图形桌面会话,应在桌面终端中运行。若 XDG_RUNTIME_DIR 为空,可临时设置:
mkdir -p /tmp/xdg-runtime-$(id -u)
chmod 700 /tmp/xdg-runtime-$(id -u)
export XDG_RUNTIME_DIR=/tmp/xdg-runtime-$(id -u)
最后在工作区根目录运行:
cd ~/aerial_ws/Aerial_Autonomy_Challenge
chmod +x src/AerialAutonomyChallenge-Simulator/AerialAutonomyChallenge-Simulator.x86_64
./sh_files/run_unity.sh
脚本第一行使用 /bin/zsh。即使本机已经安装 ROS,也需要确认本机有 zsh;没有时执行 sudo apt install -y zsh。
4.2 电脑没有 ROS1:使用 Docker
4.2.1 推荐的容器启动方式
先在宿主机授权当前图形显示。下面的 root 是因为示例容器以 root 用户运行;如果容器使用普通用户,需要授权对应用户名。
xhost +SI:localuser:root
在包含工作区的父目录执行:
cd ~/aerial_ws
docker run --name aerial_ros1 \
--gpus all \
--net=host \
--ipc=host \
-e DISPLAY="$DISPLAY" \
-e QT_X11_NO_MITSHM=1 \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
-v "$PWD/Aerial_Autonomy_Challenge":/workspace/Aerial_Autonomy_Challenge \
-it osrf/ros:noetic-desktop-full bash
说明:
- --gpus all 把 NVIDIA GPU 交给容器。
- --net=host 让 Unity、ROS TCP endpoint 和宿主机更容易互通。
- -e DISPLAY 和 /tmp/.X11-unix 是显示 Unity/RViz 窗口所需的 X11 配置。
- 工作区挂载到 /workspace/Aerial_Autonomy_Challenge,容器删除后代码仍保留在宿主机。
如果已经有可以使用的 ROS1 容器,不需要重新创建,只要确认它具有 ROS Noetic、zsh、RViz、X11 socket 和 GPU 权限即可。
4.2.2 容器内安装工具和依赖
进入容器后执行:
apt update
apt install -y zsh git build-essential python3-pip python3-rosdep \
python3-catkin-tools libeigen3-dev libpcl-dev
检查 ROS 和 zsh:
source /opt/ros/noetic/setup.bash
rosversion -d
which zsh
ls -l /bin/zsh
预期 ROS 版本为 noetic,并且 /bin/zsh 存在。
4.2.3 使用 rosdep 安装 ROS 依赖
在容器内的工作区根目录执行:
cd /workspace/Aerial_Autonomy_Challenge
rosdep init 2>/dev/null || true
rosdep update
rosdep install --from-paths src --ignore-src --rosdistro noetic -r -y
rosdep 会根据每个 ROS 包的 package.xml 安装消息、PCL、OpenCV、Eigen、RViz 等依赖。网络受限时,rosdep update 可能失败;此时需要在可联网环境执行,或使用已经准备好依赖的 ROS 镜像。
5. 编译工作区
选择与自己环境对应的工作区路径:
# 本机 ROS1 路径
cd ~/aerial_ws/Aerial_Autonomy_Challenge
# Docker 路径
cd /workspace/Aerial_Autonomy_Challenge
进入工作区后编译:
source /opt/ros/noetic/setup.bash
catkin_make -j1
source devel/setup.bash
官方使用 -j1 是为了降低并行编译的内存占用。确认关键程序已经生成:
test -x devel/lib/diff_planner/diff_planner_node && echo planner_ok
test -x devel/lib/diff_planner/traj_server && echo traj_server_ok
test -x devel/lib/cascadePID/cascadePID_node && echo pid_ok
test -x devel/lib/mars_drone_sim/quadrotor_dynamics_node && echo dynamics_ok
编译常见问题:
| 现象 | 处理方式 |
|---|---|
| Eigen3Config.cmake 找不到 | 安装 libeigen3-dev,重新执行 catkin_make -j1 |
| PCL/OpenCV 头文件找不到 | 重新执行 rosdep install,确认使用 ROS Noetic 镜像 |
| Permission denied 执行 Unity | 对 .x86_64 执行 chmod +x |
| 编译中途被系统杀掉 | 使用 catkin_make -j1,增加 Docker 内存或宿主机交换空间 |
| 修改了 C++ 但运行行为没变化 | 重新编译并重新 source devel/setup.bash |
当前工作区的 src/user_command/multipoint/CMakeLists.txt 已包含 Eigen3 查找配置。如果从干净仓库重新构建时该包报 Eigen 错误,应保留该配置或安装 libeigen3-dev。
6. 配置图形显示
本机 ROS1 路径通常不需要额外配置:在 Ubuntu 桌面终端中运行即可。下面的 X11 授权和 socket 挂载只针对 Docker 路径,也是本项目实际遇到过的重点问题。
6.1 本机 ROS1 路径
echo "$DISPLAY"
echo "$XDG_RUNTIME_DIR"
DISPLAY 有值时直接启动即可,不要执行 Docker 的 socket 挂载命令。如果从 SSH 远程登录,需要配置 ssh -X/ssh -Y 或远程桌面;仅设置 DISPLAY 并不能凭空创建图形会话。
6.2 Docker 路径:宿主机操作
在宿主机执行:
echo "$DISPLAY"
xhost +SI:localuser:root
例如输出为 :1,容器内就应使用 DISPLAY=:1。如果容器启动时没有挂载 X11 socket,需要重新创建容器并加入:
-e DISPLAY=:1 \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw
6.3 Docker 路径:容器内操作
export DISPLAY=:1
test -S /tmp/.X11-unix/X1 && echo x11_socket_ok
mkdir -p /tmp/xdg-runtime-root
chmod 700 /tmp/xdg-runtime-root
export XDG_RUNTIME_DIR=/tmp/xdg-runtime-root
export QT_X11_NO_MITSHM=1
将 :1 替换成宿主机 echo "$DISPLAY" 的真实结果。如果 X1 不存在,不能只设置环境变量,必须重新挂载 socket。
运行成功后,可以在宿主机撤销授权:
xhost -SI:localuser:root
7. 启动仿真
7.1 一键启动
本机 ROS1 用户在宿主机执行:
cd ~/aerial_ws/Aerial_Autonomy_Challenge
source /opt/ros/noetic/setup.bash
source devel/setup.bash
./sh_files/run_unity.sh
Docker 用户在容器内执行:
cd /workspace/Aerial_Autonomy_Challenge
source /opt/ros/noetic/setup.bash
source devel/setup.bash
./sh_files/run_unity.sh
终端通常是 Bash,因此手动准备环境使用 setup.bash;run_unity.sh 自身会用 zsh 启动,并 source setup.zsh。实际运行脚本的环境中必须存在 /bin/zsh。正常情况下可以看到:
- ros_tcp_endpoint 在 0.0.0.0:10000 启动。
- Unity 出现仿真窗口。
- 规划器输出 FSM ... WAIT_TARGET。
- 轨迹服务器输出 [Traj server]: ready.。
- 航点桥输出 [WaypointBridge] 启动成功。
- RViz 窗口出现。
7.2 分窗口启动(调试推荐)
一键脚本会同时启动多个后台进程,出错时日志不容易区分。调试时可以打开多个终端;本机 ROS1 用户直接打开桌面终端,Docker 用户可用 docker exec -it aerial_ros1 bash 打开多个容器终端。
每个终端先进入实际工作区并加载环境。本机 ROS1 用户执行:
cd ~/aerial_ws/Aerial_Autonomy_Challenge
source /opt/ros/noetic/setup.bash
source devel/setup.bash
Docker 用户执行:
cd /workspace/Aerial_Autonomy_Challenge
source /opt/ros/noetic/setup.bash
source devel/setup.bash
然后分别运行:
# 终端 1:TCP endpoint
roslaunch ros_tcp_endpoint endpoint.launch
# 终端 2:Unity
./src/AerialAutonomyChallenge-Simulator/AerialAutonomyChallenge-Simulator.x86_64
# 终端 3:ROS 仿真、规划器和控制器
roslaunch diff_planner run_sim_unity.launch
# 终端 4:多航点桥
./sh_files/sequential_waypoint_bridge.sh
# 终端 5:RViz
roslaunch diff_planner exp_rviz.launch
停止仿真时优先在启动窗口按 Ctrl-C,然后检查:
rosnode list
如果旧节点仍然存在,先停止旧容器或结束对应 ROS launch,再启动下一轮测试,避免多个 ROS master 或重复节点互相干扰。
8. 用话题确认系统是否正常
rostopic list
rostopic hz /quad_0/lidar_slam/odom
rostopic hz /drone_0_pcl_render_node/cloud
rostopic hz /drone_0_planning/pos_cmd
rostopic info /goal
rosnode list
rqt_graph
关键话题:
| 话题 | 类型 | 作用 |
|---|---|---|
| /publish_point | geometry_msgs/PoseArray | Unity 发布一组目标点 |
| /goal | geometry_msgs/PoseStamped | 当前目标点,规划器的输入 |
| /drone_0_pcl_render_node/cloud | sensor_msgs/PointCloud2 | 障碍物点云 |
| /quad_0/lidar_slam/odom | nav_msgs/Odometry | 动力学仿真的真实状态 |
| /drone_0_quad_0/lidar_slam/odom | nav_msgs/Odometry | poscmd_2_odom 生成的理想状态 |
| /drone_0_planning/trajectory | traj_utils/PolyTraj | 规划器生成的轨迹 |
| /drone_0_planning/pos_cmd | quadrotor_msgs/PositionCommand | 轨迹服务器采样后的位置指令 |
| /quad_0/cmdRPM | std_msgs/Float32MultiArray | PID 输出的电机转速 |
| /drone_0_traj_server/heartbeat | std_msgs/Empty | 规划器和轨迹服务器的存活信号 |
直接测试单个目标点:
rostopic pub -1 /goal geometry_msgs/PoseStamped \
"{header: {frame_id: world}, pose: {position: {x: 2.0, y: 0.0, z: 1.0}, orientation: {w: 1.0}}}"
9. 代码包说明
src/
├── AerialAutonomyChallenge-Simulator/ Unity 二进制仿真器
├── Simulator-bridge/ Unity ↔ ROS TCP 桥
├── diff_planner/ 主要规划与控制代码
│ ├── plan_env/ 点云和占据栅格地图
│ ├── path_searching/ 动态 A* 初始路径搜索
│ ├── traj_opt/ 多项式轨迹优化
│ ├── plan_manage/ FSM、规划管理、轨迹服务器
│ ├── cascadePID/ 位置/姿态 PID 和电机控制
│ └── mars_drone_sim/ 四旋翼动力学和风场
├── uav_simulator/ 通用模拟器和局部感知节点
├── Utils/ 消息、RViz 工具、可视化工具
└── user_command/multipoint/ YAML 航点工具
9.1 修改参数:最快的实验方式
先修改 src/diff_planner/plan_manage/launch/include/advanced_param_sim.xml:
- manager/max_vel:最大速度。
- manager/max_acc:最大加速度。
- planning_horizon:规划时域。
- grid_map/obstacles_inflation:障碍物膨胀距离。
- optimization/obstacle_clearance:轨迹与障碍物的安全距离。
- optimization/weight_obstacle:避障代价权重。
- use_multitopology_trajs:是否尝试多种拓扑轨迹。
这些是 launch 参数,修改后不需要编译,但需要停止并重新启动 roslaunch diff_planner run_sim_unity.launch。
9.2 修改规划算法
建议按以下顺序阅读:
- src/diff_planner/plan_manage/src/diff_planner_node.cpp:程序入口,只负责初始化 FSM。
- src/diff_planner/plan_manage/src/diff_replan_fsm.cpp:处理目标、里程计、碰撞检查、重规划和紧急停止。
- src/diff_planner/plan_manage/src/planner_manager.cpp:组织初始路径、轨迹候选和优化结果。
- src/diff_planner/path_searching/src/dyn_a_star.cpp:搜索无碰路径。
- src/diff_planner/traj_opt/src/poly_traj_optimizer.cpp:根据地图和约束优化轨迹。
修改这些 C++ 文件后:
catkin_make -j1
source devel/setup.bash
推荐一次只改一个变量或一个逻辑块,先记录基线,再比较修改前后的规划时间、轨迹长度、最小障碍距离和实际跟踪误差。
9.3 修改控制器或动力学
- 修改 src/diff_planner/cascadePID/src/cascadePID_node.cpp:改变位置误差到姿态/电机转速的控制逻辑。
- 修改 src/diff_planner/mars_drone_sim/src/quadrotor_dynamics_node.cpp:改变质量、动力学、风力模型和传感器输出。
- 修改 src/uav_simulator/fake_drone/src/poscmd_2_odom.cpp:改变规划器使用的理想状态模型。
这些模块都会影响闭环行为,修改后必须重新编译并重新启动完整仿真。
9.4 修改航点逻辑
sh_files/sequential_waypoint_bridge.sh 内嵌了一段 Python:
- 订阅 Unity 的 /publish_point。
- 将每个点转换为 /goal。
- 通过真实里程计判断是否到达。
- 到达后发送下一个点。
- 新任务开始前可先返回原点。
修改默认高度、到达距离或离开距离时,不需要编译;重新运行脚本即可。当前脚本默认 DEFAULT_Z=0.0,如果目标点没有有效高度,可能把目标发到地面,建议根据任务设为飞行高度,例如 1.0。
9.5 Unity 的修改边界
仓库中只有 Unity 的 Linux 可执行文件,没有 Unity 工程和场景源码。因此可以通过 ROS 话题和参数改变算法行为,但不能直接修改 Unity 界面、障碍物生成逻辑或场景资源。若要修改 Unity 本身,需要向仿真器提供方索取 Unity 工程。
10. 建议的开发和测试流程
10.1 保留基线
开始实验前:
git switch -c experiment/my-first-change
git status --short
运行产生的 pycache 和 cascadePID/data/log_0.txt 属于生成文件,不要混入功能提交。当前工作区已有 src/user_command/multipoint/CMakeLists.txt 的 Eigen3 修改,保留或单独记录它,不要误删用户自己的改动。
10.2 做一组可比较的实验
每次实验固定:
- Unity 场景和障碍物布局。
- 起始位置和目标点。
- 仿真时长。
- ROS 参数和版本。
记录基线数据:
rosbag record -O baseline.bag \
/goal \
/quad_0/lidar_slam/odom \
/drone_0_planning/pos_cmd \
/drone_0_planning/trajectory \
/drone_0_pcl_render_node/cloud
停止录包后,可以使用 rqt_plot 对比指令位置和动力学实际位置:
/drone_0_planning/pos_cmd/position/x
/quad_0/lidar_slam/odom/pose/pose/position/x
10.3 安全检查
任何控制器、动力学或目标判断修改,都要先在低速、小范围、无障碍场景测试。确认以下条件后再使用复杂场景:
- 目标超出地图时会被拒绝。
- 轨迹碰撞时会触发重规划或紧急停止。
- 丢失规划器 heartbeat 时轨迹服务器会停止继续发送旧轨迹。
- 无人机不会因为目标高度为 0 而撞地。
11. 本项目已发现的已知问题
这些问题不一定阻止启动,但会影响实验结果,建议在正式交付前修正并重新编译/测试:
- src/diff_planner/plan_manage/launch/sim/run_sim_unity.launch 第 43 行的风区 max_x 为 11.68.0,应改成合法数字。
- 风区 min_y=-2.88、max_y=-4.14 的边界顺序相反;当前 isInWindZone 使用“位置大于等于 min 且小于等于 max”的判断,风区可能永远不成立。
- src/diff_planner/plan_manage/launch/include/advanced_param_sim.xml 没有设置 waypoint1_y。
- 航点桥订阅 /drone_0_planning/fsm_state,但当前规划器没有发布这个话题;实际到达判断主要依赖 /quad_0/lidar_slam/odom。
- 日志中的 Package name "cascadePID" does not follow the naming conventions 是 ROS 包命名警告,不是启动失败原因。
- 规划器使用 poscmd_2_odom 生成的理想里程计,而 PID、Unity 和航点桥使用动力学真实里程计。测试控制效果时应比较这两条状态链。
12. 实际遇到过的报错和解决办法
12.1 /bin/zsh: bad interpreter: No such file or directory
报错示例:
./sh_files/run_unity.sh: /bin/zsh: bad interpreter: No such file or directory
原因是脚本第一行是 #!/bin/zsh,但实际运行脚本的环境中没有这个文件。本机 ROS1 路径需要在宿主机安装;Docker 路径需要在容器内安装。宿主机安装 zsh 不会自动安装到容器内。
本机 ROS1 用户在宿主机执行:
sudo apt update
sudo apt install -y zsh
ls -l /bin/zsh
Docker 用户在容器内执行:
apt update
apt install -y zsh
ls -l /bin/zsh
如果文件已经存在但仍报错,检查脚本是否是 Windows 换行符:
head -n 1 sh_files/run_unity.sh | od -An -t x1
首行结尾应为 0a,不能有 0d 0a。有 0d 时执行:
sed -i 's/\r$//' sh_files/*.sh
12.2 Authorization required、could not connect to display
报错示例:
Authorization required, but no authorization protocol specified
qt.qpa.xcb: could not connect to display unix:1
这个问题主要出现在 Docker 路径中:容器可以找到显示编号,但没有得到宿主机 X11 授权,或没有挂载 X11 socket。本机 ROS1 用户在桌面终端运行时通常不会遇到它。
宿主机执行:
echo "$DISPLAY"
xhost +SI:localuser:root
创建容器时包含:
-e DISPLAY="$DISPLAY" \
-e QT_X11_NO_MITSHM=1 \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw
容器内执行:
export DISPLAY=:1
test -S /tmp/.X11-unix/X1
mkdir -p /tmp/xdg-runtime-root
chmod 700 /tmp/xdg-runtime-root
export XDG_RUNTIME_DIR=/tmp/xdg-runtime-root
如果 X1 不存在,需要重新创建容器并挂载 socket。测试结束后,宿主机可以撤销授权:
xhost -SI:localuser:root
12.3 RViz 退出,但 ROS 节点已启动
如果日志显示规划器和动力学都启动,只有 RViz 出现 process has died,通常仍是 X11 或 OpenGL 配置问题,不是规划算法错误。先检查 DISPLAY、XDG_RUNTIME_DIR、X11 socket 和 GPU,再重新启动。
12.4 ROS 找不到包或可执行文件
确保每个新终端都执行:
source /opt/ros/noetic/setup.bash
# 本机 ROS1 路径
cd ~/aerial_ws/Aerial_Autonomy_Challenge
# 或 Docker 路径
cd /workspace/Aerial_Autonomy_Challenge
source devel/setup.bash
rospack find diff_planner
如果 rospack find 失败,说明工作区没有成功编译,或当前终端没有 source 正确的 devel/setup。
13. 交付给客户前的检查清单
建议先完成“固定场景 + 单个目标点”的基线测试,再逐步修改参数、规划器、控制器和动力学。这样客户可以清楚区分“环境没有配置好”和“代码修改改变了飞行结果”这两类问题。