无人机 | MAVROS安装与基础知识梳理(附ROS C++仿真案例)

无人机 | MAVROS安装与基础知识梳理(附ROS C++仿真案例)

目录

1 MAVROS简介

MAVROS是无人机开发中连接机器人操作系统(ROS)与飞控系统的关键中间件,通过标准化通信协议实现ROS节点与无人机的交互。它基于MAVLink(Micro Air Vehicle Link)轻量级通信协议,为ROS生态提供了与飞控(如PixhawkArduPilotPX4等)通信的统一接口,使开发者无需深入理解底层飞控协议,即可直接调用ROS的丰富工具链(如RViz可视化、Gazebo仿真、导航栈)快速搭建无人机任务,推动了无人机应用的灵活开发与高效迭代

MAVROS的核心功能包括双向数据传输:一方面,它订阅飞控的传感器数据(如IMUGPS、电池状态)并发布至ROS话题,供导航、感知等模块使用;另一方面,它接收ROS服务或动作指令(如起飞、降落、位姿控制),转换为MAVLink消息发送至飞控执行。此外,MAVROS支持多种通信接口(串口、UDPTCP),适配不同硬件场景,并提供参数配置服务,允许动态读写飞控参数(如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坐标系;
  • body系:
    • ROS端:采用FLU坐标系,即前左上,一般是由MAVROS发布的base_link坐标系
    • 飞控端:采用FRD坐标系,即前右下

具体关系如下图所示

在这里插入图片描述

以下面的场景为实例,map系和Gazebo里的坐标系方向一致。机身前方定义为东,即map系的x轴正方向,机身前进方向同时为base_link系的x轴正方向。所以从方向来看,ROS端的map系和base_link系一致

在这里插入图片描述

3.2 MAVROS常用话题

3.2.1 /mavros/state

  • 功能:订阅MAVROS的状态数据,如连接状态、是否解锁、当前无人机模式等
  • 参数说明
    • connected: 检测无人机与地面站的物理连接状态
    • armed:监控无人机电机是否解锁,只有armed=true时表示电机已解锁,无人机可飞行
    • mode:常用模式有:
      • MANUAL:完全手动模式
      • POSCTL:位置控制模式
      • ALTCTL:高度控制模式
      • OFFBOARD:板外模式,ROS主机控制无人机需要切换到这个模式
      • MISSION:自动任务模式
      • LOITER:自动悬停模式
      • RTL:自动返航模式
      • LAND:自动降落模式
      • TAKEOFF:自动起飞模式
    • manual_input:检测是否有人工遥控器输入
    • system_status:无人机整体系统状态,分为未初始化、系统启动中、待机模式、任务执行中和紧急状态

数据类型mavros_msgs/State

std_msgs/Header header uint32 seq time stamp string frame_id bool connected bool armed bool guided bool manual_input string mode uint8 system_status 

3.2.2 /mavros/setpoint_position/local

  • 功能:定点飞行
  • 参数说明:只有position生效,不控制姿态orientationposition是相对于ROS端local坐标系的坐标

数据类型geometry_msgs/PoseStamped

std_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 

3.2.3 /mavros/local_position/odom

  • 功能:提供无人机在ROS端坐标系的位姿和速度里程计信息
  • 参数说明:位姿信息是相对于ROS端local坐标系的坐标,速度信息是是相对于ROS端body坐标系的坐标

数据类型nav_msgs/Odometry

std_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 

3.2.4 /mavros/setpoint_raw/local

  • 功能:主要用于设置无人机各轴的加速度或推力
  • 参数说明
    • coordinate_frame:飞控端采用的坐标系,一般设置为FRAME_LOCAL_NED,但是该话题数据都是在ROS端坐标系下,MAVROS会自动进行一次坐标变换
    • type_mask:类型掩码,例如只控制加速度需要将位置、速度、角速度等标志为置为忽略

数据类型mavros_msgs::PositionTarget

std_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 

3.2.5 /mavros/setpoint_raw/attitude

  • 功能:用于设置无人机的姿态、推力和各轴角速度

数据类型mavros_msgs::AttitudeTarget

std_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/CommandBool

bool value // true解锁,false上锁 --- bool success uint8 result 

3.3.2 /mavros/set_mode

  • 功能:用于设置无人机飞控的飞行模式
  • 参数说明:ROS端控制要切换到OFFBOARD模式

数据类型mavros_msgs/SetMode

string 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 

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;}

完整工程代码请联系下方博主名片获取


🔥 更多精彩专栏

👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

Read more

API 设计的 7 个致命错误:为什么你的接口让前端想打人

API 设计的 7 个致命错误:为什么你的接口让前端想打人

凌晨一点,前端在群里 @了你 “后端大哥,为什么删除用户的接口是 POST?” “为什么获取用户列表要传 20 个参数?” “为什么同一个错误,有时返回 200,有时返回 500?” “能不能别再改接口了?这是这个月第三次了!” 你看着手机,心里一万头草泥马奔腾而过。 明明功能都实现了,为什么前端还是不满意? 因为你的 API 设计,可能犯了这 7 个致命错误。 今天,我们就来聊聊那些让前端抓狂、让自己背锅、让项目延期的 API 设计问题。 错误 1:把数据库表结构直接暴露成 API 灾难现场 // ❌ 直接暴露数据库结构GET/api/user_account_info?user_id=123// 返回{"user_id"

从Web到AI:Skills市场与共享经济实战指南

从Web到AI:Skills市场与共享经济实战指南

图片来源网络,侵权联系删。 Skills生态系统相关系列文章 从Web到AI:构建行业专属Skills生态系统的实战指南与未来展望 从Web到AI:金融/医疗/教育行业专属Skills生态系统设计实战 从Web到AI:Skills市场与共享经济实战指南 文章目录 * 1. 当NPM遇见AI技能市场 * 2. Web生态与Skills市场的基因同源性 * 2.1 核心概念映射表(Web→AI) * 2.2 企业级Skills市场架构 * 3. 用共享经济思维重构Skills交易 * 3.1 交易模型设计(类比Stripe支付) * 3.2 技能质量门禁(类比NPM质量评分) * 4. 三端协同Skills市场系统 企业级实战 * 4.1 项目结构(Spring Cloud + Vue3 + 小程序) * 4.2 核心功能代码实现 * 5. Web开发者转型Skills市场的痛点解决方案 * 5.

ChatTTS WebUI界面定制化:修改主题、添加快捷键、导出配置模板

ChatTTS WebUI界面定制化:修改主题、添加快捷键、导出配置模板 1. 为什么需要定制你的ChatTTS WebUI? 你刚打开ChatTTS WebUI,被它自然到让人起鸡皮疙瘩的语音惊艳到了——但几轮试用后,可能开始觉得: * 默认的浅色界面看久了眼睛累; * 每次都要鼠标点“生成”按钮,手速跟不上脑速; * 找到一个完美音色后,下次想复用却要翻日志、手动输Seed,一不小心就忘了; * 团队协作时,想把“语速5+固定Seed 11451+带笑声停顿”的整套设置一键分享给同事,却只能截图或口述。 这些问题,都不是模型能力的问题,而是界面体验的缺口。 ChatTTS本身是开源的,它的WebUI基于Gradio构建——而Gradio天生支持深度定制:改颜色、加键盘操作、存/载配置、甚至嵌入自定义CSS。 本文不讲模型原理,不跑训练,只聚焦一件事:让你的ChatTTS WebUI真正长成你想要的样子。 全程无需改模型代码,所有操作在WebUI启动前或启动时完成,小白可照着做,5分钟生效。

【二十】前端现代化:从传统到现代的前端技术演进

【二十】前端现代化:从传统到现代的前端技术演进 核心观点 前端技术的发展是一场革命,它从简单的静态页面,演变为复杂的单页应用,再到如今的微前端架构。前端现代化不仅仅是技术的更新,更是开发思维和开发方式的转变。这是我在过去十年前端开发生涯中最深刻的体会。 我的前端开发故事 从jQuery到现代框架:前端开发的蜕变 毕业后不久,我开始了我的前端开发生涯。那时候,前端开发的主要工具是HTML、CSS和jQuery。我记得我的第一个项目是一个企业官网,我用jQuery实现了图片轮播、表单验证、导航菜单等功能。虽然代码有点混乱,但看到页面能够正常运行,我还是很有成就感的。 随着项目的复杂度增加,我开始感受到jQuery的局限性。2014年,我参与了一个电商项目,需要实现购物车、商品详情、订单流程等复杂功能。我用jQuery编写了大量的代码,结果发现: * 代码混乱:HTML、CSS和JavaScript混合在一起,难以维护 * 事件处理复杂:大量的事件绑定和回调函数,导致代码嵌套层级很深 * 状态管理困难:购物车的状态需要在多个页面之间共享,实现起来很复杂 * 性能问题