PX4+Gazebo仿真:从键盘指令到无人机轨迹的Offboard控制实践

张开发
2026/4/9 17:00:36 15 分钟阅读

分享文章

PX4+Gazebo仿真:从键盘指令到无人机轨迹的Offboard控制实践
1. 环境搭建与基础配置在开始PX4Gazebo仿真之前我们需要先搭建好开发环境。我推荐使用Ubuntu 20.04 LTS系统这是目前最稳定的ROS Noetic支持版本。记得第一次配置环境时我花了整整一天时间解决各种依赖问题现在把这些经验都总结给你。首先安装PX4固件。建议直接从PX4官方GitHub仓库克隆最新稳定版git clone https://github.com/PX4/PX4-Autopilot.git --recursive cd PX4-Autopilot make px4_sitl gazebo接下来安装MAVROS这是连接ROS和PX4的桥梁。使用apt安装最方便sudo apt 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 sudo ./install_geographiclib_datasets.shQGroundControl地面站可以直接从官网下载AppImage文件。记得给文件添加可执行权限chmod x QGroundControl.AppImage ./QGroundControl.AppImage环境配置中最容易出问题的是串口权限和ROS工作空间设置。建议将用户加入dialout组sudo usermod -a -G dialout $USER2. 键盘控制的核心原理键盘控制无人机的本质是将离散的按键事件转换为连续的空间坐标。想象一下玩游戏时的角色移动WASD按键对应前后左右移动PL控制高度升降。但在无人机控制中我们需要考虑更多因素。核心思路是通过ROS话题传递按键信息。我创建了两个节点一个监听键盘输入另一个处理飞控指令。键盘节点使用termios库实现非阻塞读取这样就不会卡住整个程序termios new_settings initial_settings_; new_settings.c_lflag ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, new_settings); fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);在飞控节点中我定义了目标位置变量target_position。每次收到按键消息时就根据按键类型修改这个变量if (msg-data w) { target_position Eigen::Vector3d(0.5, 0, 0); // 向前移动0.5米 } else if (msg-data s) { target_position Eigen::Vector3d(-0.5, 0, 0); // 向后移动0.5米 }这里有个重要细节我设置了position_updated标志位。只有收到有效按键时才发布新位置避免无效消息刷屏。实测下来这种设计能显著降低CPU占用率。3. Offboard模式的安全使用Offboard模式是PX4中最高级别的控制模式使用不当可能导致无人机失控。我强烈建议新手先在仿真环境中充分测试再考虑真机实验。安全使用Offboard模式有几个关键点必须保持2Hz以上的位置消息发送频率否则PX4会自动切换回Hold模式建议先用QGC手动切到Offboard模式而不是在代码中硬切换始终设置合理的飞行高度限制我的经验是仿真环境中不超过5米在代码实现上我设置了20Hz的发布频率远高于最低要求ros::Rate rate(20.0); // 20Hz发布频率 while (ros::ok()) { local_pos_pub.publish(pose); ros::spinOnce(); rate.sleep(); }第一次实验时我犯了个错误没有先发送若干位置消息就直接切Offboard模式结果PX4拒绝切换。后来发现PX4要求必须先收到连续的位置指令才能切模式这是安全设计。4. 轨迹平滑处理技巧原始方案中直接加减固定值的做法会导致无人机运动不够平滑。我后来改进了算法加入了加速度限制和轨迹规划。改进后的位置更新算法Eigen::Vector3d velocity(0.1, 0.1, 0.05); // 定义各轴最大速度 if (msg-data w) { target_position velocity.cwiseProduct(Eigen::Vector3d(1,0,0)); }还可以加入二阶低通滤波器平滑运动filtered_position 0.2 * target_position 0.8 * filtered_position; pose.pose.position.x filtered_position[0];对于更复杂的轨迹我推荐使用ROS的trajectory_msgs。可以预先计算好整条路径的点位然后按时间序列发布trajectory_msgs::MultiDOFJointTrajectory trajectory; trajectory.points.resize(3); trajectory.points[0].transforms[0].translation.x 1.0; trajectory.points[1].transforms[0].translation.y 2.0; trajectory.points[2].transforms[0].translation.z 3.0;5. 调试技巧与常见问题调试无人机仿真时我习惯用rqt_graph查看节点连接情况。这张图能直观显示话题的订阅发布关系rosrun rqt_graph rqt_graph常见问题1Gazebo启动后无人机模型掉地上了 解决方法检查PX4启动参数是否正确确认使用了正确的世界文件make px4_sitl gazebo_iris常见问题2MAVROS连接失败 检查步骤确认PX4和MAVROS使用相同的UDP端口查看mavros/state话题是否显示connected检查防火墙设置是否阻止了UDP通信我习惯用rostopic echo查看关键话题数据rostopic echo /mavros/local_position/pose rostopic echo /keyboard_input当遇到控制失灵时首先检查QGC中的飞行模式指示。仿真环境中可以随时重启但真机操作前务必确保有完善的保护措施。6. 进阶开发方向基础键盘控制实现后可以考虑以下几个进阶方向加入速度控制模式修改mavros/setpoint_velocity话题geometry_msgs/TwistStamped velocity_msg; velocity_msg.twist.linear.x 0.5; // 0.5m/s前进速度实现航点飞行读取预定义的航点文件自动顺序飞行waypoints [[0,0,1], [2,0,1], [2,2,1]] for wp in waypoints: send_position(wp) while distance 0.1: sleep(0.1)添加避障功能订阅激光雷达数据动态调整路径void lidarCallback(const sensor_msgs::LaserScan scan) { // 处理扫描数据 if (obstacle_detected) { adjustTrajectory(); } }集成计算机视觉使用OpenCV处理摄像头数据实现目标跟踪我在实际项目中发现将控制逻辑封装为状态机最可靠。比如定义起飞、巡航、降落等状态每个状态有明确的进入条件和退出条件。这样代码更易维护也更容易处理异常情况。

更多文章