这个项目搭建了一个完整的ROS 2机器人仿真与控制环境,整合了Gazebo物理引擎、PX4飞控系统、QGC地面站和DDS通信中间件,实现了基于Offboard模式的无人机控制示例。对于想要学习无人机自主控制或机器人仿真的开发者来说,这套工具链提供了一个理想的实验平台。
我在实际搭建过程中发现,虽然每个组件单独使用都有详细文档,但将它们整合在一起时会出现各种兼容性问题。本文将分享从环境配置到最终实现的完整流程,重点解决那些官方文档没有明确说明的"坑"。
这个项目的核心挑战在于各组件版本的兼容性。经过多次测试,我推荐以下版本组合:
| 组件名称 | 推荐版本 | 关键依赖 |
|---|---|---|
| ROS 2 | Humble | Ubuntu 22.04 |
| PX4 | v1.14.0 | Gazebo Fortress |
| QGC | v4.2.4 | Qt 5.15.2 |
| Fast-DDS | 2.6.0 | CMake 3.22 |
注意:PX4对Gazebo版本有严格要求,使用非官方推荐的版本可能导致物理引擎异常
首先在Ubuntu 22.04上安装ROS 2 Humble:
bash复制sudo apt update && sudo apt install curl gnupg lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
sudo apt update && sudo apt install ros-humble-desktop
安装Gazebo Fortress:
bash复制sudo apt install wget
wget https://packages.osrfoundation.org/gazebo.gpg -O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
sudo apt update && sudo apt install gazebo-fortress
克隆PX4固件并切换到稳定分支:
bash复制git clone https://github.com/PX4/PX4-Autopilot.git --recursive
cd PX4-Autopilot && git checkout v1.14.0
make submodulesclean
编译支持Gazebo的固件:
bash复制make px4_sitl gazebo-classic
安装PX4-ROS 2桥接包:
bash复制sudo apt install ros-humble-px4-msgs ros-humble-px4-ros-com
配置环境变量:
bash复制echo 'source /opt/ros/humble/setup.bash' >> ~/.bashrc
echo 'export PX4_AUTOPILOT_DIR=~/PX4-Autopilot' >> ~/.bashrc
source ~/.bashrc
安装Fast-DDS:
bash复制sudo apt install ros-humble-rmw-fastrtps-cpp
创建Fast-DDS配置文件fastdds_config.xml:
xml复制<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<participant profile_name="px4_participant" is_default_profile="true">
<rtps>
<builtin>
<domainId>0</domainId>
<discovery_config>
<discoveryProtocol>SERVER</discoveryProtocol>
</discovery_config>
</builtin>
</rtps>
</participant>
</profiles>
设置环境变量使用Fast-DDS:
bash复制export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export FASTRTPS_DEFAULT_PROFILES_FILE=~/fastdds_config.xml
创建ROS 2包:
bash复制mkdir -p ~/px4_ros_ws/src
cd ~/px4_ros_ws/src
ros2 pkg create --build-type ament_cmake offboard_control
编写控制节点offboard_control.cpp:
cpp复制#include <px4_msgs/msg/offboard_control_mode.hpp>
#include <px4_msgs/msg/trajectory_setpoint.hpp>
#include <rclcpp/rclcpp.hpp>
using namespace std::chrono_literals;
class OffboardControl : public rclcpp::Node {
public:
OffboardControl() : Node("offboard_control") {
offboard_control_mode_publisher_ = this->create_publisher<px4_msgs::msg::OffboardControlMode>(
"/fmu/in/offboard_control_mode", 10);
trajectory_setpoint_publisher_ = this->create_publisher<px4_msgs::msg::TrajectorySetpoint>(
"/fmu/in/trajectory_setpoint", 10);
timer_ = this->create_wall_timer(
100ms, std::bind(&OffboardControl::timer_callback, this));
}
private:
void timer_callback() {
publish_offboard_control_mode();
publish_trajectory_setpoint();
}
void publish_offboard_control_mode() {
auto msg = px4_msgs::msg::OffboardControlMode();
msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
msg.position = true;
msg.velocity = false;
msg.acceleration = false;
offboard_control_mode_publisher_->publish(msg);
}
void publish_trajectory_setpoint() {
auto msg = px4_msgs::msg::TrajectorySetpoint();
msg.timestamp = this->get_clock()->now().nanoseconds() / 1000;
msg.x = 5.0;
msg.y = 5.0;
msg.z = -5.0;
msg.yaw = 1.5708; // 90度
trajectory_setpoint_publisher_->publish(msg);
}
rclcpp::Publisher<px4_msgs::msg::OffboardControlMode>::SharedPtr offboard_control_mode_publisher_;
rclcpp::Publisher<px4_msgs::msg::TrajectorySetpoint>::SharedPtr trajectory_setpoint_publisher_;
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char *argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<OffboardControl>());
rclcpp::shutdown();
return 0;
}
修改package.xml添加依赖:
xml复制<depend>px4_msgs</depend>
<depend>rclcpp</depend>
修改CMakeLists.txt:
cmake复制find_package(ament_cmake REQUIRED)
find_package(px4_msgs REQUIRED)
find_package(rclcpp REQUIRED)
add_executable(offboard_control src/offboard_control.cpp)
ament_target_dependencies(offboard_control px4_msgs rclcpp)
install(TARGETS offboard_control
DESTINATION lib/${PROJECT_NAME})
ament_package()
编译并运行:
bash复制cd ~/px4_ros_ws
colcon build --packages-select offboard_control
source install/setup.bash
ros2 run offboard_control offboard_control
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| PX4无法启动 | Gazebo版本不匹配 | 确认使用Gazebo Fortress |
| ROS 2节点无法连接PX4 | DDS配置错误 | 检查fastdds_config.xml和RMW_IMPLEMENTATION |
| Offboard指令被拒绝 | 安全设置限制 | 检查COM_RCL_EXCEPT参数 |
| 位置控制不稳定 | 坐标系不一致 | 确认所有节点使用NED坐标系 |
bash复制cd ~/PX4-Autopilot
make px4_sitl gazebo-classic
bash复制ros2 topic list
ros2 topic echo /fmu/out/vehicle_status
bash复制ros2 daemon stop
FASTRTPS_DEFAULT_PROFILES_FILE=fastdds_config.xml ros2 run offboard_control offboard_control
通过修改DDS配置可以实现多无人机协同:
xml复制<domainId>0</domainId> <!-- 主控端 -->
<domainId>1</domainId> <!-- 无人机1 -->
<domainId>2</domainId> <!-- 无人机2 -->
在Gazebo模型中添加摄像头:
xml复制<sensor name="camera" type="camera">
<update_rate>30</update_rate>
<camera>
<horizontal_fov>1.047</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
</image>
</camera>
</sensor>
结合ROS 2的nav2包实现自主导航:
python复制from nav2_simple_commander.robot_navigator import BasicNavigator
navigator = BasicNavigator()
navigator.goToPose(goal_pose)
在实际部署中发现,PX4的Offboard模式对控制指令的频率有严格要求,必须保持在10Hz以上才能维持稳定控制。建议在开发控制算法时添加心跳机制,确保在通信中断时能自动切换回安全模式。