原文地址:http://blog.csdn.net/oqqENvY12/article/details/61615609
PX4 对Mavlink 协议提供了良好的原生支持。该协议既可以用于地面站(Ground ControlStation, GCS) 对无人机(UAV) 的控制,也可用于对地面站的信息反馈。其飞控场景一般是这样的:
也就是说,如果你想要实现地面站控制飞行,那么由你的地面站使用Mavlink 协议,通过射频信道(或wifi 等)给无人机发送控制指令就可以了。如果你想实现无人机自主飞行,那么就由你自己写的应用(运行在无人机系统上)使用Mavlink 协议给无人机发送本地的控制指令就可以了。
在PX4 中,并不鼓励开发者在自定义飞控程序中直接使用Mavlink ,而是鼓励开发者使用uORB微对象请求代理器消息机制。
在uORB 机制中,交换的消息被称之为主题(topic) ,一个主题仅包含一种消息类型(即数据结构)。每个进程(或驱动模块)均可“订阅”或“发布”多个主题,一个主题可以存在多个发布者,而且一个订阅者可也订阅多个主题。
Mavlink传输时的基本单位是消息帧。
协议设计的目标是传输速度和安全性。它允许消息内容检查、消息丢失检测,每个数据包需要6 字节报头。
每次发完一个消息,SEQ的内容会加1,加到255后会从0重新开始。这个序号用于mavlink消息帧接收端计算消息丢失比例用的,相当于是信号强度。
COMP是例如相机、舵机0-13,IMU123之类的
在mavlink消息帧里最重要的两个东西,一个是msgid;一个是payload,前者是payload中内容的编号,后者则存放了消息。
消息有许多种类型,在官网的网页中中以蓝色的“#”加数字的方式来表示消息的编号如 “#0”(这样的表示方法应该是为了方便在网页中查找相应编号消息的定义)。
在官网介绍网页里往下拉,大概拉到二分之一的位置处,开始出现“MAVLink Messages”的介绍,往下看是各种消息的数据组成说明。
先以 #0 消息为例,这个消息叫心跳包(heartbeat)。
它一般用来表明发出该消息的设备是活跃的,飞行器和地面站都会发出这个信号(一般以1Hz发送),地面站和飞行器会根据是否及时收到了心跳包来判断是否和飞行器或地面站失去了联系。
MAVLINK的一包数据由FE开头的,一包数据由FE开头到下一个FE出现为截止。
FE为包开头 09为数据包长度(LEN) MavLink的长度是固定的
94消息序号 01硬件系统序号 01设备号(Pixhawk刷PX4固件默认都是01)
第五位是消息类型序号 括号里面是有效数据载荷(长度为9)
最后两位是数据校验位。
我们通过消息类型序号可以看到这是0号消息,0号消息是心跳包消息。
并不是所有的MAVLink消息都是在向外发送消息的,左边是直接从QGC地面站观察得到的当前活动的MAVLink消息
右边是使用串口调试助手记录的mavlink数据
Firmware1.5之前的版本,都是采用拔掉SD卡进NSH的方式进行调试
新版固件无论是否存在SD卡,MAVLink都在不停的往外吐数,十分影响调试
可以通过修改rcS启动脚本解决问题。
模式是8 个状态开关的各种组合方式。各个标识之间,可以使用“或逻辑”组合起来,共同表示飞控/飞行器的当前状态。
以多轴为例。它分为主模式(main mode)和子模式(sub mode),两种模式组合在一起成为最终的模式,主模式分为3种,手动(manual),辅助assist),自动(auto)。在辅助模式中,又分为高度控制模式(altctl)和位置控制模式(posctl)两个子模式。。自动模式里又分为3个子模式,任务模式(mission),留待模式(loiter),返航模式(return),任务模式就是执行设定好的航点任务,留待模式就是gps悬停模式,返航模式就是直线返回home点并自动降落。
以上是心跳包的分析,还有很多其他的数据包的分析类似,请自行翻阅官方指导文件。
因为我们在使用基于这套飞控开发的过程中,会有很多自定义的数据要求,比如我们添加一个新的传感器(在飞控中添加一个自定义传感器),我们会把新的传感器数据发送回来和地面站交互,这时候就会涉及到自定义一个MAVLINK的消息包,自定义消息包的数据,发送给地面站来解析显示。
对于MAVLINK这套系统,有对应的工具,来自动生成MAVLINK的库函数,只要约定好消息包的结构体,我们就可以用相应的MAVLINK工具,来生成MAVLINK库的头文件和功能接口函数。
APM,amtrixpilot这类文件夹里是各个飞控自己定义的mavlink消息类型,
原始的mavlink消息放在common文件夹里(大部分消息都在common文件夹中)。
Checksum.h中存放的是计算校验码的代码。
Mavlink_helper.h里面是将各个消息包补充完整(调用checksum.h中的函数计算检验码并补上消息帧的头,比如sysid和compid等)成为mavlink消息帧再发送。以及逐字解包函数。最主要的功能集中在这两个文件中。
Mavlink_conversions.h里面是dcm,欧拉角,四元数三种姿态表示方法之间的转换代码
MAVLink消息以XML格式定义,然后转换为C / C ++,C#或Python代码(存在多个生成器)。
生成自定义的消息包
重要的就是两个消息发送和消息编码函数,在具体的调用函数里面就是调用这个消息发送函数把mavlink的消息发送出去,这些都是,mavlink函数自动生成的函数,我们在用的时候调用即可。
Send函数的功能是将传入的各个参数按照对应的格式放到xxx对应的消息包中(即打包),此时还未形成mavlink包。
还需要_mav_finalize_message_chan_send用于更新消息帧的编号(seq每发送一帧加1),并将消息帧的头和计算校验码,使得成为一个完整的mavlink消息帧。
最后调用串口发送函数进行消息帧的发送
mavlink_main.cpp是mavlink的主函数
mavlink_messages.cpp是所有的mavlink消息的消息类,比如心跳包消息类,系统数据消息类,姿态数据消息类等等,如果我们要自定义自己的消息并且通过mavlink协议发送出去,我们就要添加自己自定义的消息类,然后把这个消息类实例化,就可以使用了。
mavlink_receiver.cpp这个是飞控接收,地面站发来的消息指令用的。分析这个函数,就可以实现通过地面站来控制飞控。
最终我们要追加一个我们自定义的mavlink 数据流类到StreamListItem 数据流链表里面,这个数据流链表在MAVLINK_messages.cpp 里面,在MAVLINK 模块的主函数中会不断轮询这个StreamListItem 数据流链表,并且执行链表里面的数据发送函数来实现MAVLINK 消息的不断发送,我们添加了自己定义的函数,那么我们就要把我们自己定义的类也添加到这个链表里面。
按道理我们自定义好的MAVLINK 消息,就可以在地面站里面显示了,前提是地面站的mavlink包能够解析这个你自定义的数据,一般来讲通过MAVLINK generator 生成器生成的mavlink 库,和地面站的mavlink 库是同一套库,就没问题可以保证解析到。
比较偷懒的做法是把自己要发生的消息,通过mavlink 原有的包发送出去,地面站解析这个原有的包即可。比如用debug MAVLINk 消息包。