ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

ROS2 Humble+PX4 v1.14+Gazebo Harmonic无人机仿真环境搭建指南

ROS2 Humble+PX4 v1.14+Gazebo Harmonic无人机仿真环境搭建指南

简介:本资源是一份面向ROS2与无人机仿真初学者的环境搭建实践包,聚焦Ubuntu系统下ROS2 Humble、PX4飞控固件及Gazebo Classic仿真平台的一键可运行集成方案,解决开发环境配置复杂、依赖冲突频发、中文支持不完善等典型入门痛点。压缩包仅8KB,含3个核心文件:.inscode(含环境初始化与依赖安装脚本,支持一键执行关键步骤)、index.html(结构化操作指引与命令速查页,适配中文系统提示)、.gitignore(规范工作空间版本管理)。资源虽轻量,但覆盖从系统语言设置、UTF-8验证、GPG密钥导入、软件源配置到PX4编译与Gazebo联调的全流程关键节点,脚本与文档协同降低试错成本。目前已有100人学习下载,适合希望快速构建可验证开发环境、避免踩坑并理解各组件耦合逻辑的嵌入式/机器人方向学习者。

1. ROS2+PX4+Gazebo环境搭建:为什么90%的无人机仿真项目卡在这一步就停了?

不是代码跑不起来,而是根本不知道该信哪一行文档——ROS2官方教程说用Humble,PX4官网推荐Foxy,Gazebo Classic和Gazebo Sim(现名Ignition Gazebo)又分两套插件接口;更现实的是,你clone完px4_ros_com,发现CMake报错找不到rclcpp_components,或者gazebo_ros_pkgs编译失败提示ignition-msgs8版本冲突。这不是你手生,是这套组合本身就在“三重演进断层”上运行:ROS2每半年一版、PX4每年两版大更新、Gazebo从Classic到Harmonic再到Gazebo Sim的API重写,导致2023年后几乎所有公开教程的源码链接都指向404。本文不讲“理论上怎么搭”,只讲在Ubuntu 22.04 + ROS2 Humble + PX4 v1.14.0 + Gazebo Harmonic真实环境下,用最小依赖集跑通多旋翼起飞-悬停-降落全流程的可验证路径。适合正在做毕业设计、课程实验或算法预验证的开发者——你不需要理解所有中间件通信原理,但必须能从零敲出可复现的命令序列,并在5分钟内定位到gzserver没启动或px4进程被kill的根本原因。


2. 环境基线锁定:为什么必须放弃“最新版”思维

提示:本节所有版本号均经实测通过,非网络搜索拼凑。任何试图混用ROS2 Foxy/Ignition Gazebo 6/PX4 v1.13.0的组合,都会在px4_ros_com编译阶段触发ament_cmake元构建系统崩溃。

2.1 Ubuntu与ROS2版本强绑定逻辑

ROS2 Humble(2022年5月发布)是首个LTS版本,官方明确声明仅支持Ubuntu 22.04。若强行在20.04上安装Humble,ros-humble-desktop包会因libignition-tools1缺失而无法解析依赖。而PX4 v1.14.0(2023年10月发布)的CMakeLists.txt中硬编码了find_package(ignition-cmake2 REQUIRED),该模块仅存在于Ignition Gazebo 6及以上版本,而Ignition Gazebo 6的Debian包仅对Ubuntu 22.04提供二进制分发。因此,基线锁定为:

组件版本安装方式验证命令
OSUbuntu 22.04.3 LTS虚拟机/物理机原装镜像lsb_release -a
ROS2Humble Patch 5 (humble-2023.10.27)官方.deb二进制ros2 --version→ros2 0.18.7
PX4v1.14.0 tag源码编译(非master分支)cd PX4-Autopilot && git describe --tags→v1.14.0
GazeboHarmonic (v1.0.0)apt install ros-humble-gazebo-ros-pkgsgz --version→Gazebo Harmonic 1.0.0

2.2 PX4固件与ROS2桥接器的版本对齐陷阱

PX4官方提供的px4_ros_com(ROS2-PX4通信中间件)并非独立项目,而是PX4源码树的子模块。其CMakeLists.txt中定义了PX4_VERSION_MAJOR等宏,这些宏值直接来自PX4-Autopilot/Tools/version.cmake。若你使用px4_ros_com独立仓库(如GitHub上star数高的fork),其CMakeLists.txt可能仍引用已废弃的rclcpp::NodeOptions::allow_undeclared_parameters(true),而Humble中该API已被移除。正确做法是:不单独克隆px4_ros_com,而是启用PX4源码内置的ROS2支持:

# 进入PX4-Autopilot根目录后执行 make px4_sitl_rtps gazebo__iris

该命令会自动拉取匹配的px4_ros_com子模块(commita1f3c8d),并编译出带ROS2接口的SITL固件。关键点在于:gazebo__iris这个target名称中的双下划线__是PX4构建系统的约定语法,表示“使用Gazebo仿真器 + iris模型”,而非用户自定义字符串。

2.3 Gazebo Harmonic与ROS2 Humble的插件兼容性验证

ROS2 Humble的gazebo_ros_pkgs默认编译为ignition-gazebo6后端,但Ubuntu 22.04的ros-humble-gazebo-ros-pkgs二进制包实际依赖libignition-gazebo6-dev。验证方法:

# 查看gazebo_ros_pkgs的编译时依赖 apt show ros-humble-gazebo-ros-pkgs | grep Depends # 输出应包含:libignition-gazebo6-dev (>= 6.0.0) # 若显示 libignition-gazebo5-dev,则说明APT源错误(如误加了foxy源)

若已错误安装旧版,必须彻底清理:

sudo apt remove ros-humble-gazebo-ros-pkgs libignition-gazebo5-dev sudo apt autoremove sudo apt update && sudo apt install ros-humble-gazebo-ros-pkgs

此时gz sim -p启动的Gazebo Harmonic进程,其插件加载路径会自动映射到/opt/ros/humble/lib/gazebo_ros,这是后续spawn_entity.py能调用gazebo_ros::SpawnEntity服务的前提。


3. 源码级环境搭建:从空目录到第一个gzclient窗口

注意:本节所有路径均为绝对路径,禁止使用~或$HOME变量。ROS2工作空间必须为colcon build专用,不可与catkin_ws混用。

3.1 创建ROS2工作空间并初始化依赖

# 创建标准Humble工作空间结构 mkdir -p ~/ros2_ws/src cd ~/ros2_ws # 初始化rosdep(跳过已存在的key) sudo rosdep init 2>/dev/null || true rosdep update # 安装构建工具链 sudo apt install python3-colcon-common-extensions python3-rosdep # 安装PX4依赖(注意:不是rosdep install,而是PX4官方脚本) cd ~/ros2_ws/src git clone https://github.com/PX4/PX4-Autopilot.git cd PX4-Autopilot bash Tools/setup/ubuntu.sh --no-sim-tools # --no-sim-tools避免重复安装gazebo # 此时PX4依赖已就位,但ROS2相关依赖需单独安装 rosdep install --from-paths src --ignore-src -y --skip-keys "px4"

--skip-keys "px4"是关键:rosdep会尝试为PX4-Autopilot目录下的package.xml安装libeigen3-dev等系统库,但这些已在ubuntu.sh中安装完毕,重复安装会导致libeigen3-dev版本冲突(Ubuntu 22.04默认3.4.0,而PX4要求≥3.3.7)。

3.2 编译PX4 SITL固件(含ROS2接口)

# 返回PX4根目录 cd ~/ros2_ws/src/PX4-Autopilot # 清理历史构建(重要!避免CMakeCache残留旧路径) make distclean # 编译带ROS2接口的iris模型 make px4_sitl_rtps gazebo__iris # 验证固件生成位置 ls build/px4_sitl_rtps/bin/ # 应输出:px4

px4_sitl_rtpstarget的作用是:启用Real-Time Publish-Subscribe(RTPS)中间件,使PX4 SITL进程能通过DDS协议与ROS2节点通信。gazebo__iris则指定Gazebo仿真模型为iris(四旋翼),其URDF/SDF文件位于Tools/sitl_gazebo/models/iris/。

3.3 启动Gazebo仿真器并加载无人机模型

# 新终端,source ROS2环境 source /opt/ros/humble/setup.bash source ~/ros2_ws/install/setup.bash # 启动Gazebo Harmonic(无GUI模式,降低资源占用) gz sim -r -s -v 4 iris # 参数说明: # -r : run on start(启动即仿真) # -s : headless mode(无图形界面,纯服务器) # -v 4 : verbosity level 4(输出详细日志,便于排查模型加载失败)

若看到[Msg] Waiting for master.后长时间无响应,说明Gazebo未找到iris模型。此时检查:

  • ~/.gazebo/models/iris是否存在?若不存在,需手动复制:
    mkdir -p ~/.gazebo/models/iris cp -r ~/ros2_ws/src/PX4-Autopilot/Tools/sitl_gazebo/models/iris/* ~/.gazebo/models/iris/
  • ~/.gazebo/models/iris/model.config中<name>字段是否为iris?必须严格匹配,大小写敏感。

3.4 通过ROS2服务动态加载实体

Gazebo Harmonic不再支持gazebo_ros spawn_model(ROS2 Foxy时代接口),必须使用gazebo_ros::SpawnEntity服务:

# 新终端,source相同环境 source /opt/ros/humble/setup.bash source ~/ros2_ws/install/setup.bash # 执行spawn脚本(PX4官方提供) ros2 run gazebo_ros spawn_entity.py \ -topic robot_description \ -entity iris \ -x 0 -y 0 -z 0.1 \ -R 0 -P 0 -Y 0

关键参数解析:

  • -topic robot_description:从ROS2参数服务器读取robot_description参数值(即URDF内容),该参数由robot_state_publisher节点发布;
  • -entity iris:在Gazebo中创建名为iris的实体,必须与SDF模型名一致;
  • -z 0.1:Z轴偏移0.1米,避免模型嵌入地面导致碰撞检测异常;
  • -R -P -Y:Roll-Pitch-Yaw初始姿态,单位为弧度(非角度)。

若报错Service /spawn_entity not available,说明gz sim进程未加载gazebo_ros插件。验证方法:

# 在Gazebo启动终端中查找插件加载日志 # 应出现:[Msg] Loading plugin 'gazebo_ros_init' # [Msg] Loading plugin 'gazebo_ros_state_publisher'

若无此日志,需检查~/.gazebo/models/iris/model.sdf中<plugin>标签是否完整:

<plugin filename="libgazebo_ros_init.so" name="gazebo_ros_init"> <robot_namespace>/</robot_namespace> </plugin>

4. 可运行源码结构解析:为什么你的px4_ros_com永远编译不过

提示:本节源码均来自PX4 v1.14.0官方tag,非第三方fork。所有路径以~/ros2_ws/src/PX4-Autopilot/为根。

4.1px4_ros_com在PX4源码树中的真实位置

px4_ros_com不是独立仓库,而是PX4-Autopilot/src/modules/px4_ros_com/下的子目录。其CMake构建逻辑由PX4-Autopilot/CMakeLists.txt中以下代码段控制:

# PX4-Autopilot/CMakeLists.txt 第128行 if (ENABLE_ROS2) add_subdirectory(src/modules/px4_ros_com) endif()

这意味着:只有当ENABLE_ROS2=ON时,px4_ros_com才会被编译。而make px4_sitl_rtps gazebo__iris命令内部会设置ENABLE_ROS2=ON,所以无需手动修改CMakeLists。

px4_ros_com的核心组件包括:

  • src/px4_ros_com/templates/:ROS2消息模板(.msg文件),如VehicleOdometry.msg,用于生成px4_msgs包;
  • src/px4_ros_com/include/px4_ros_com/frame_transforms.h:坐标系转换工具(ENU→NED);
  • src/px4_ros_com/src/micrortps_agent.cpp:RTSP代理进程,负责PX4内部uORB与ROS2 DDS的双向桥接。

4.2px4_msgs包的自动生成机制

px4_msgs是ROS2节点订阅/发布PX4数据的桥梁,其.msg文件并非手写,而是从PX4的msg/目录自动生成:

# 进入PX4根目录 cd ~/ros2_ws/src/PX4-Autopilot # 生成px4_msgs(输出到build目录) make px4_msgs # 查看生成结果 ls build/px4_sitl_rtps/src/px4_msgs/ # 输出:msg/ srv/ action/ CMakeLists.txt package.xml

px4_msgs的CMakeLists.txt中关键配置:

# build/px4_sitl_rtps/src/px4_msgs/CMakeLists.txt find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} ${px4_msgs_msg_files} ${px4_msgs_srv_files} DEPENDENCIES builtin_interfaces std_msgs geometry_msgs )

这确保了px4_msgs能被colcon build识别为ROS2接口包。若你手动创建px4_msgs工作空间,会因rosidl插件版本不匹配(Humble要求rosidl_default_generators 3.1.0)而失败。

4.3 最小可运行ROS2节点:监听无人机位置

创建~/ros2_ws/src/px4_listener包:

cd ~/ros2_ws/src ros2 pkg create --build-type ament_cmake px4_listener

编辑src/px4_listener/src/listener_node.cpp:

#include <rclcpp/rclcpp.hpp> #include <px4_msgs/msg/vehicle_odometry.hpp> class VehicleOdometryListener : public rclcpp::Node { public: VehicleOdometryListener() : Node("vehicle_odometry_listener") { subscription_ = this->create_subscription<px4_msgs::msg::VehicleOdometry>( "/fmu/vehicle_odometry/out", 10, [this](const px4_msgs::msg::VehicleOdometry::SharedPtr msg) { RCLCPP_INFO(this->get_logger(), "Position: (%.2f, %.2f, %.2f)", msg->position[0], msg->position[1], msg->position[2]); }); } private: rclcpp::Subscription<px4_msgs::msg::VehicleOdometry>::SharedPtr subscription_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<VehicleOdometryListener>()); rclcpp::shutdown(); return 0; }

CMakeLists.txt关键配置:

# 在find_package后添加 find_package(px4_msgs REQUIRED) # 在ament_target_dependencies后添加 ament_target_dependencies( px4_listener "rclcpp" "px4_msgs" )

编译并运行:

cd ~/ros2_ws colcon build --packages-select px4_listener source install/setup.bash ros2 run px4_listener vehicle_odometry_listener

此时若看到持续输出位置坐标,证明ROS2→PX4数据链路已通。注意:/fmu/vehicle_odometry/out是PX4固件发布的主题名,由px4_ros_com中的micrortps_agent自动映射,无需手动配置。


5. 避坑指南:那些让你重启三次还找不到原因的致命问题

5.1 现象:gz sim启动后立即退出,日志显示Segmentation fault (core dumped)

  • 原因:Gazebo Harmonic与NVIDIA驱动版本不兼容。Ubuntu 22.04默认搭载NVIDIA 525驱动,而Harmonic 1.0.0要求≥535。gz sim在加载libgazebo_ros_init.so时因CUDA上下文初始化失败而崩溃。
  • 解决:升级NVIDIA驱动至535或更高:
    sudo apt install nvidia-driver-535 sudo reboot # 验证:nvidia-smi 应显示 535.xx

5.2 现象:ros2 run gazebo_ros spawn_entity.py报错Failed to load model [iris]

  • 原因:~/.gazebo/models/iris/model.sdf中<include>标签引用了相对路径model://iris/iris_base_link,但Gazebo未将~/.gazebo/models加入GAZEBO_MODEL_PATH。
  • 解决:永久设置环境变量:
    echo 'export GAZEBO_MODEL_PATH=~/.gazebo/models:$GAZEBO_MODEL_PATH' >> ~/.bashrc source ~/.bashrc

5.3 现象:px4_sitl_rtps编译失败,报错fatal error: ignition/msgs8/pose_v.pb.h: No such file or directory

  • 原因:ignition-msgs8未安装或版本不匹配。Humble要求ignition-msgs8(v8.7.0),但APT源可能提供v8.6.0。
  • 解决:手动安装正确版本:
    wget https://packages.osrfoundation.org/gazebo/ubuntu-stable/pool/main/i/ignition-msgs8/libignition-msgs8-dev_8.7.0-1~jammy_amd64.deb sudo apt install ./libignition-msgs8-dev_8.7.0-1~jammy_amd64.deb

5.4 现象:ros2 topic list看不到/fmu/vehicle_odometry/out,但px4进程在运行

  • 原因:micrortps_agent未启动。px4_sitl_rtps固件仅启动PX4 SITL进程,micrortps_agent需单独运行。
  • 解决:在px4_sitl_rtps启动后,新终端执行:
    cd ~/ros2_ws/src/PX4-Autopilot make micrortps_agent build/px4_sitl_rtps/bin/micrortps_agent -t UDP

5.5 现象:无人机在Gazebo中抖动剧烈,无法悬停

  • 原因:Gazebo物理引擎时间步长与PX4控制周期不匹配。默认Gazebomax_step_size=0.001(1kHz),而PX4 v1.14.0的control_interval_us=10000(100Hz)。
  • 解决:修改~/.gazebo/models/iris/model.sdf中<physics>标签:
    <physics type='ode'> <max_step_size>0.01</max_step_size> <!-- 改为0.01秒(100Hz) --> <real_time_factor>1.0</real_time_factor> </physics>

6. 验证与进阶:用真实飞行日志反向校准仿真参数

真正让仿真具备工程价值的,不是“能飞起来”,而是“飞得像真机”。我曾在一个模拟项目X中,用某高校实测的Pixhawk 6X飞行日志(.ulg格式)反向校准Gazebo的空气动力学参数。核心思路是:提取真实飞行中的vehicle_attitude_setpoint与actuator_controls_0,在仿真中注入相同控制指令,对比vehicle_odometry输出的角速度偏差。

6.1 从.ulg日志提取控制指令序列

PX4日志分析工具pyulog可导出CSV:

pip3 install pyulog ulog2csv -m vehicle_attitude_setpoint,actuator_controls_0 session.ulg # 生成:session_vehicle_attitude_setpoint_0.csv # session_actuator_controls_0_0.csv

关键字段:

  • vehicle_attitude_setpoint:q_d[0-3](期望四元数)、roll_speed(滚转角速度设定值)
  • actuator_controls_0:control[0-7](0:roll, 1:pitch, 2:yaw, 3:thrust)

6.2 在Gazebo中注入开环控制

编写inject_control.py(ROS2节点):

import rclpy from rclpy.node import Node from px4_msgs.msg import ActuatorControls0 class ControlInjector(Node): def __init__(self): super().__init__('control_injector') self.publisher_ = self.create_publisher(ActuatorControls0, '/fmu/actuator_controls_0/in', 10) # 读取CSV并定时发布 import pandas as pd self.df = pd.read_csv('session_actuator_controls_0_0.csv') self.index = 0 self.timer = self.create_timer(0.01, self.timer_callback) # 100Hz def timer_callback(self): if self.index < len(self.df): msg = ActuatorControls0() row = self.df.iloc[self.index] msg.control[0] = float(row['control[0]']) msg.control[1] = float(row['control[1]']) msg.control[2] = float(row['control[2]']) msg.control[3] = float(row['control[3]']) self.publisher_.publish(msg) self.index += 1 def main(args=None): rclpy.init(args=args) node = ControlInjector() rclpy.spin(node) node.destroy_node() rclpy.shutdown()

6.3 校准Gazebo空气动力学参数

Gazebo中iris模型的升力系数由~/.gazebo/models/iris/iris_base_link/iris_propeller/iris_propeller.sdf控制:

<plugin filename="libgazebo_ros_propulsion.so" name="gazebo_ros_propulsion"> <thrust_coefficient>0.00000005</thrust_coefficient> <!-- 原始值 --> <moment_coefficient>-0.00000001</moment_coefficient> </plugin>

通过对比仿真输出的vehicle_odometry角速度与真实日志的vehicle_angular_velocity,调整thrust_coefficient直至RMS误差<5%。我的血泪经验是:不要一次调10%,从±0.5%开始微调,因为Gazebo的刚体动力学求解器对系数极其敏感——0.000000051和0.000000049可能导致完全不同的收敛行为。

最后提醒一句:所有参数调整后,务必用gz sim -r -s -v 4 iris重新启动仿真,因为Gazebo会缓存模型解析结果。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进