mavros实战(一):从offboard到自主飞行,构建你的第一个PX4控制节点
1. 从零开始理解MAVROS与Offboard模式
第一次接触MAVROS和PX4的Offboard模式时,我完全被各种专业术语搞晕了。经过几个项目的实战,我发现其实理解这套系统并不难。简单来说,MAVROS就像是一个翻译官,把ROS能听懂的语言转换成PX4飞控能理解的MAVLink协议。
Offboard模式是PX4飞控提供的一种特殊飞行模式,它允许外部系统(比如你的ROS节点)完全控制无人机。想象一下,平时我们用遥控器手动控制无人机,而Offboard模式就是把遥控器的控制权交给了你的代码。这个模式下,飞控只会做最基本的稳定性控制,所有导航决策都由外部系统完成。
要进入Offboard模式有几个必要条件:
- 必须保持至少2Hz的控制指令发送频率
- 需要先发送若干次控制指令"预热"
- 必须确保飞控和地面站的通信正常
我在实际项目中遇到过最典型的问题就是忘记持续发送控制指令,导致飞控自动退出Offboard模式。有一次测试时,无人机突然切回悬停模式,就是因为我的控制节点崩溃了,指令流中断导致的。
2. 搭建开发环境与基础配置
2.1 硬件准备与PX4固件烧写
我建议初学者从一套标准的Pixhawk 4套件开始,这是最兼容PX4的硬件平台。首先需要下载QGroundControl地面站软件,用它来给飞控刷写最新的PX4固件。烧写过程很简单:
- 用USB连接飞控和电脑
- 打开QGroundControl会自动检测到飞控
- 在固件页面点击"Flash Firmware"按钮
烧写完成后,建议先进行传感器校准和遥控器设置。这些基础配置在QGroundControl中都有直观的向导界面。特别提醒,一定要先测试手动飞行模式是否正常,这是后续开发的重要基础。
2.2 ROS与MAVROS安装
推荐使用Ubuntu 20.04+ROS Noetic的组合,这是目前最稳定的搭配。安装完基础ROS后,MAVROS可以通过apt直接安装:
sudo apt-get install ros-noetic-mavros ros-noetic-mavros-extras安装完成后需要运行一个安装脚本,它会下载必要的参数文件:
wget https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh chmod +x install_geographiclib_datasets.sh ./install_geographiclib_datasets.sh我遇到过因为网络问题导致参数文件下载失败的情况,这时候可以多试几次,或者手动下载后放到指定目录。
3. 构建第一个Offboard控制节点
3.1 创建ROS包与基础框架
我们先创建一个专门用于无人机控制的ROS工作空间和包:
mkdir -p ~/px4_ws/src cd ~/px4_ws/src catkin_create_pkg px4_control roscpp mavros_msgs geometry_msgs cd .. catkin_make这个基础包依赖了三个关键ROS包:roscpp提供C++支持,mavros_msgs包含所有MAVROS消息定义,geometry_msgs用于处理位置和姿态数据。
3.2 编写核心控制节点
创建一个offboard_node.cpp文件,我们从最基本的框架开始:
#include <ros/ros.h> #include <geometry_msgs/PoseStamped.h> #include <mavros_msgs/CommandBool.h> #include <mavros_msgs/SetMode.h> #include <mavros_msgs/State.h> mavros_msgs::State current_state; void state_cb(const mavros_msgs::State::ConstPtr& msg){ current_state = *msg; } int main(int argc, char **argv) { ros::init(argc, argv, "offboard_node"); ros::NodeHandle nh; // 订阅器、发布器和服务的初始化代码将放在这里 ros::Rate rate(20.0); // 等待飞控连接 while(ros::ok() && !current_state.connected){ ros::spinOnce(); rate.sleep(); } // 主控制循环 while(ros::ok()){ // 控制逻辑将放在这里 ros::spinOnce(); rate.sleep(); } return 0; }这个框架包含了MAVROS控制节点的基本结构:初始化ROS节点、设置通信接口、主循环。state_cb回调函数用于实时更新飞控状态。
4. 实现完整飞行控制逻辑
4.1 初始化通信接口
在主函数中添加以下关键通信接口的初始化代码:
// 状态订阅 ros::Subscriber state_sub = nh.subscribe<mavros_msgs::State> ("mavros/state", 10, state_cb); // 位置指令发布 ros::Publisher local_pos_pub = nh.advertise<geometry_msgs::PoseStamped> ("mavros/setpoint_position/local", 10); // 解锁服务客户端 ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool> ("mavros/cmd/arming"); // 模式设置服务客户端 ros::ServiceClient set_mode_client = nh.serviceClient<mavros_msgs::SetMode> ("mavros/set_mode");这些接口分别用于:
- 获取飞控当前状态
- 发送位置控制指令
- 解锁/锁定无人机
- 切换飞行模式
4.2 实现Offboard模式切换
在主循环前添加Offboard模式初始化代码:
geometry_msgs::PoseStamped pose; pose.pose.position.x = 0; pose.pose.position.y = 0; pose.pose.position.z = 2; // 发送若干位置指令预热 for(int i = 100; ros::ok() && i > 0; --i){ local_pos_pub.publish(pose); ros::spinOnce(); rate.sleep(); } mavros_msgs::SetMode offb_set_mode; offb_set_mode.request.custom_mode = "OFFBOARD"; mavros_msgs::CommandBool arm_cmd; arm_cmd.request.value = true; ros::Time last_request = ros::Time::now();这段代码做了三件事:
- 设置初始目标位置(x=0, y=0, z=2米)
- 发送100次位置指令满足Offboard模式的条件
- 准备模式切换和解锁请求
4.3 主控制循环实现
完整的控制循环代码如下:
while(ros::ok()){ // 尝试切换Offboard模式 if( current_state.mode != "OFFBOARD" && (ros::Time::now() - last_request > ros::Duration(5.0))){ if( set_mode_client.call(offb_set_mode) && offb_set_mode.response.mode_sent){ ROS_INFO("Offboard enabled"); } last_request = ros::Time::now(); } else { // 尝试解锁 if( !current_state.armed && (ros::Time::now() - last_request > ros::Duration(5.0))){ if( arming_client.call(arm_cmd) && arm_cmd.response.success){ ROS_INFO("Vehicle armed"); } last_request = ros::Time::now(); } } // 持续发布目标位置 local_pos_pub.publish(pose); ros::spinOnce(); rate.sleep(); }这个循环实现了:
- 每5秒尝试一次Offboard模式切换
- 成功切换模式后,每5秒尝试一次解锁
- 持续发布目标位置保持控制
5. 测试与调试技巧
5.1 仿真环境测试
在实际飞行前,强烈建议先在仿真环境中测试。PX4提供了完善的Gazebo仿真支持:
roslaunch mavros px4.launch fcu_url:="udp://:14540@127.0.0.1:14557" roslaunch px4 posix_sitl.launch在仿真中测试时,我通常会先用QGroundControl观察飞控状态,确保所有传感器数据正常。然后逐步测试:
- 检查MAVROS连接是否正常
- 测试Offboard模式切换
- 测试解锁功能
- 最后测试位置控制
5.2 常见问题排查
在实际项目中,我遇到过几个典型问题:
Offboard模式无法切换:
- 检查控制指令发送频率是否足够(至少2Hz)
- 确认飞控参数COM_RCL_EXCEPT设置为4(允许Offboard模式)
- 检查飞控和地面站的连接状态
无人机解锁失败:
- 确认遥控器开关位置正确
- 检查飞控安全设置(特别是地理围栏)
- 确保所有传感器校准完成
位置控制不稳定:
- 调整PX4的位置控制参数
- 检查控制指令的时间戳
- 确保没有大的通信延迟
记得在每次飞行前做好安全检查,最好在开阔的场地进行测试,保持高度警惕。我第一次测试自主飞行时过于紧张,手指一直放在遥控器的急停开关上,后来发现这是个好习惯。
