无人机 | MAVROS安装与基础知识梳理(附ROS C++仿真案例)
本文全面梳理无人机MAVROS从安装到应用的基础知识,并提供简单的基于MAVROS无人机控制的案例
1 MAVROS简介
MAVROS 是无人机开发中连接机器人操作系统(ROS)与飞控系统的关键中间件,通过标准化通信协议实现ROS节点与无人机的交互。它基于MAVLink(Micro Air Vehicle Link) 轻量级通信协议,为ROS生态提供了与飞控(如Pixhawk、ArduPilot、PX4等)通信的统一接口,使开发者无需深入理解底层飞控协议,即可直接调用ROS的丰富工具链(如RViz可视化、Gazebo仿真、导航栈)快速搭建无人机任务,推动了无人机应用的灵活开发与高效迭代
MAVROS的核心功能包括双向数据传输:一方面,它订阅飞控的传感器数据(如IMU、GPS、电池状态)并发布至ROS话题,供导航、感知等模块使用;另一方面,它接收ROS服务或动作指令(如起飞、降落、位姿控制),转换为MAVLink消息发送至飞控执行。此外,MAVROS支持多种通信接口(串口、UDP、TCP),适配不同硬件场景,并提供参数配置服务,允许动态读写飞控参数(如PID调参、飞行模式切换)。

2 MAVROS安装
通过以下命令安装MAVROS
sudo apt-get install ros-noetic-mavros
sudo apt install ros-noetic-mavros-extras
GeographicLib是一个开源的地理计算库,专门用于处理地球表面的高精度地理坐标计算,例如:
- 经纬度与局部坐标系(如北东地坐标系,ENU)的转换
- 地理坐标系之间的转换(如 WGS84 到 UTM)
- 地球椭球模型下的距离、方位角、高程计算
- 大地水准面(Geoid)的高度校正
MAVROS在处理无人机导航和地理空间数据时需要依赖GeographicLib提供的高精度地理计算功能,因此GeographicLib
wget https://raw.githubusercontent.com/mavlink/mavros/master/mavros/scripts/install_geographiclib_datasets.sh
sudo chmod +x ./install_geographiclib_datasets.sh
sudo ./install_geographiclib_datasets.sh
3 MAVROS基础知识
3.1 MAVROS坐标系
MAVROS中涉及到以下坐标系:
global系:一般由GPS定义,例如经纬高坐标系(WGS84)local系:- ROS端:采用
ENU坐标系,一般是由MAVROS发布的map坐标系,其坐标原点是MAVROS收到里程计信息时飞控所在的位置,并规定x轴朝东、y轴朝北、z轴朝天,此时机体方向朝东; - 飞控端:PX4/ArduPilot等内部使用,采用
NED坐标系;
- ROS端:采用
body系:- ROS端:采用
FLU坐标系,即前左上,一般是由MAVROS发布的base_link坐标系 - 飞控端:采用
FRD坐标系,即前右下
- ROS端:采用
具体关系如下图所示
以下面的场景为实例,map系和Gazebo里的坐标系方向一致。机身前方定义为东,即map系的x轴正方向,机身前进方向同时为base_link系的x轴正方向。所以从方向来看,ROS端的map系和base_link系一致

3.2 MAVROS常用话题
3.2.1 /mavros/state
- 功能:订阅MAVROS的状态数据,如连接状态、是否解锁、当前无人机模式等
- 数据类型:
mavros_msgs/Statestd_msgs/Header header uint32 seq time stamp string frame_id bool connected bool armed bool guided bool manual_input string mode uint8 system_status - 参数说明:
connected: 检测无人机与地面站的物理连接状态armed:监控无人机电机是否解锁,只有armed=true时表示电机已解锁,无人机可飞行mode:常用模式有:MANUAL:完全手动模式POSCTL:位置控制模式ALTCTL:高度控制模式OFFBOARD:板外模式,ROS主机控制无人机需要切换到这个模式MISSION:自动任务模式LOITER:自动悬停模式RTL:自动返航模式LAND:自动降落模式TAKEOFF:自动起飞模式
manual_input:检测是否有人工遥控器输入system_status:无人机整体系统状态,分为未初始化、系统启动中、待机模式、任务执行中和紧急状态
3.2.2 /mavros/setpoint_position/local
- 功能:定点飞行
- 数据类型:
geometry_msgs/PoseStampedstd_msgs/Header header uint32 seq time stamp string frame_id geometry_msgs/Pose pose geometry_msgs/Point position float64 x float64 y float64 z geometry_msgs/Quaternion orientation float64 x float64 y float64 z float64 w - 参数说明:只有
position生效,不控制姿态orientation。position是相对于ROS端local坐标系的坐标
3.2.3 /mavros/local_position/odom
- 功能:提供无人机在ROS端坐标系的位姿和速度里程计信息
- 数据类型:
nav_msgs/Odometrystd_msgs/Header header uint32 seq time stamp string frame_id string child_frame_id geometry_msgs/PoseWithCovariance pose geometry_msgs/Pose pose geometry_msgs/Point position float64 x float64 y float64 z geometry_msgs/Quaternion orientation float64 x float64 y float64 z float64 w float64[36] covariance geometry_msgs/TwistWithCovariance twist geometry_msgs/Twist twist geometry_msgs/Vector3 linear float64 x float64 y float64 z geometry_msgs/Vector3 angular float64 x float64 y float64 z float64[36] covariance - 参数说明:位姿信息是相对于ROS端
local坐标系的坐标,速度信息是是相对于ROS端body坐标系的坐标
3.2.4 /mavros/setpoint_raw/local
- 功能:主要用于设置无人机各轴的加速度或推力
- 数据类型:
mavros_msgs::PositionTargetstd_msgs/Header header uint8 coordinate_frame uint8 FRAME_LOCAL_NED = 1 uint8 FRAME_LOCAL_OFFSET_NED = 7 uint8 FRAME_BODY_NED = 8 uint8 FRAME_BODY_OFFSET_NED = 9 uint16 type_mask uint16 IGNORE_PX = 1 # Position ignore flags uint16 IGNORE_PY = 2 uint16 IGNORE_PZ = 4 uint16 IGNORE_VX = 8 # Velocity vector ignore flags uint16 IGNORE_VY = 16 uint16 IGNORE_VZ = 32 uint16 IGNORE_AFX = 64 # Acceleration/Force vector ignore flags uint16 IGNORE_AFY = 128 uint16 IGNORE_AFZ = 256 uint16 FORCE = 512 # Force in af vector flag uint16 IGNORE_YAW = 1024 uint16 IGNORE_YAW_RATE = 2048 geometry_msgs/Point position geometry_msgs/Vector3 velocity geometry_msgs/Vector3 acceleration_or_force float32 yaw float32 yaw_rate - 参数说明:
coordinate_frame:飞控端采用的坐标系,一般设置为FRAME_LOCAL_NED,但是该话题数据都是在ROS端坐标系下,MAVROS会自动进行一次坐标变换type_mask:类型掩码,例如只控制加速度需要将位置、速度、角速度等标志为置为忽略
3.2.5 /mavros/setpoint_raw/attitude
- 功能:用于设置无人机的姿态、推力和各轴角速度
- 数据类型:
mavros_msgs::AttitudeTargetstd_msgs/Header header uint8 type_mask uint8 IGNORE_ROLL_RATE = 1 # body_rate.x uint8 IGNORE_PITCH_RATE = 2 # body_rate.y uint8 IGNORE_YAW_RATE = 4 # body_rate.z uint8 IGNORE_THRUST = 64 uint8 IGNORE_ATTITUDE = 128 # orientation field geometry_msgs/Quaternion orientation geometry_msgs/Vector3 body_rate float32 thrust
3.3 MAVROS常用服务
3.3.1 /mavros/cmd/arming
- 功能:用于设置无人机的上锁或解锁状态
- 数据类型:
mavros_msgs/CommandBoolbool value // true解锁,false上锁 --- bool success uint8 result
3.3.2 /mavros/set_mode
- 功能:用于设置无人机飞控的飞行模式
- 数据类型:
mavros_msgs/SetModestring custom_mode uint8 base_mode uint8 MAV_MODE_PREFLIGHT=0 uint8 MAV_MODE_STABILIZE_DISARMED=80 uint8 MAV_MODE_STABILIZE_ARMED=208 uint8 MAV_MODE_MANUAL_DISARMED=64 uint8 MAV_MODE_MANUAL_ARMED=192 uint8 MAV_MODE_GUIDED_DISARMED=88 uint8 MAV_MODE_GUIDED_ARMED=216 uint8 MAV_MODE_AUTO_DISARMED=92 uint8 MAV_MODE_AUTO_ARMED=220 uint8 MAV_MODE_TEST_DISARMED=66 uint8 MAV_MODE_TEST_ARMED=194 --- bool mode_sent - 参数说明:ROS端控制要切换到
OFFBOARD模式
4 仿真案例
4.1 案例一:设置无人机板外模式并解锁
this->arm_client_ = this->nh_.serviceClient<mavros_msgs::CommandBool>("mavros/cmd/arming");
this->set_mode_client_ = this->nh_.serviceClient<mavros_msgs::SetMode>("mavros/set_mode");
mavros_msgs::SetMode offboardMode;
offboardMode.request.custom_mode = "OFFBOARD";
mavros_msgs::CommandBool armCmd;
armCmd.request.value = true;
ros::Time lastRequest = ros::Time::now();
while (ros::ok())
{
if (this->mavros_state_.mode != "OFFBOARD" && (ros::Time::now() - lastRequest > ros::Duration(5.0)))
{
if (this->set_mode_client_.call(offboardMode) && offboardMode.response.mode_sent)
{
cout << "Offboard mode enabled." << endl;
}
lastRequest = ros::Time::now();
}
else
{
if (!this->mavros_state_.armed && (ros::Time::now() - lastRequest > ros::Duration(5.0)))
{
if (this->arm_client_.call(armCmd) && armCmd.response.success)
{
cout << "Vehicle armed." << endl;
}
lastRequest = ros::Time::now();
}
}
r.sleep();
}
4.2 案例二:无人机起飞到指定高度
假设要飞到1m的高度
this->position_pub_ = this->nh_.advertise<geometry_msgs::PoseStamped>("/mavros/setpoint_position/local", 1000);
geometry_msgs::PoseStamped ps;
ps.header.frame_id = "map";
ps.header.stamp = ros::Time::now();
ps.pose.position.x = this->odom_.pose.pose.position.x;
ps.pose.position.y = this->odom_.pose.pose.position.y;
ps.pose.position.z = 1.0;
ps.pose.orientation = this->odom_.pose.pose.orientation;
this->position_pub_.publish(ps);
4.3 获取无人机位姿并更新状态
this->odom_sub_ = this->nh_.subscribe<nav_msgs::Odometry>("/mavros/local_position/odom", 1000, &flightBase::odomCB, this);
void flightBase::odomCB(const nav_msgs::Odometry::ConstPtr &odom)
{
this->odom_ = *odom;
this->curr_position_(0) = this->odom_.pose.pose.position.x;
this->curr_position_(1) = this->odom_.pose.pose.position.y;
this->curr_position_(2) = this->odom_.pose.pose.position.z;
Eigen::Vector3d curr_vel_body(this->odom_.twist.twist.linear.x, this->odom_.twist.twist.linear.y, this->odom_.twist.twist.linear.z);
Eigen::Vector4d orientation_quat(this->odom_.pose.pose.orientation.w, this->odom_.pose.pose.orientation.x, this->odom_.pose.pose.orientation.y, this->odom_.pose.pose.orientation.z);
Eigen::Matrix3d orientation_rot = quat2RotMatrix(orientation_quat);
this->curr_vel_ = orientation_rot * curr_vel_body;
}
完整工程代码请联系下方博主名片获取
🔥 更多精彩专栏:
「智能机器人开发者大赛」官方平台,致力于为开发者和参赛选手提供赛事技术指导、行业标准解读及团队实战案例解析;聚焦智能机器人开发全栈技术闭环,助力开发者攻克技术瓶颈,促进软硬件集成、场景应用及商业化落地的深度研讨。 加入智能机器人开发者社区iRobot Developer,与全球极客并肩突破技术边界,定义机器人开发的未来范式!
更多推荐



所有评论(0)