Mavlink开发笔记【一】

写在前头

本系列主要介绍,本人在开发 iOS App 时,用 Mavlink 协议和 CocoaAsyncSocket 与无人设备进行通信;包括接收数据、发送指令、自动执行任务等功能。

本系列的主要内容是介绍 Mavlink消息、Mavlink 指令、参考地面站发送指令逻辑并移植到App中等等;只涉及到 Mavlink 的应用。

而不是告诉你 什么是 Mavlink,Mavlink 是如何工作的等等。

这些内容官网介绍的非常非常非常的详细,很多博客也会介绍相关 Mavlink 是什么的巴拉巴拉。

但是本人在实际开发过程中,很多时候遇到使用某些指令产生了问题,需要了解这个问题的原因、具体的解决方法等等,但可能是搜索资料能力不行吧,反正全网搜索半天都搜不到相关资料。

同时地面站(GCS)的源码是C和C++的。如果你能看懂地面站源代码。那么这个系列可能对于你太过于肤浅

地面站是一个非常全面且功能强大的;如果在某些指令逻辑处理时,或者对某条指令参数不确定时;地面站源码是最佳的老师。

就比我们的飞控测试工程师对我说:如果你的 App 操作有BUG,但是地面站对应的操作没有问题,那么你就不要甩锅给无人设备的硬件、飞控代码、遥控器代码上,肯定是你的代码问题

地面站开源代码:github.com/mavlink/qgr…

用户手册:docs.qgroundcontrol.com/master/en/i…

开发手册:mavlink.io/zh/

一、获取 iOS 的开源工具库

iOS的开源库分为两种,C语言和Swift语言,可以通过官网的生成器生成对应代码的 Mavlink 库。
mavlink.io/zh/getting_…

本系列使用 Objective-C的主要语言,使用C语言的 Mavlink 库

image.png

文件名后面的 _rover 是后续加入的,实际获取的 Mavlink 库是没有的

二、请求接收数据流(无人机/无人船/无人车)

在描述 Mavlink相关协议 前,需要了解的是,Mavlink 接收和发送指令都是有格式的。
如果不按照格式进行;则会出现,发消息没反应,收消息解析不对。

工具类封装了一个发送消息的方法,接收 mavlink_message_t对象,根据 Mavlink 协议封装内容并send
image.png

在连接无人设备成功后,会在连接成功过的代理方法中向无人设备发送一条 REQUEST_DATA_STREAM 指令。
这个指令作用是用于向无人设备请求数据流。
image.png

虽然官网标记该指令已被弃用和代替,但是实际还是能够使用。

image.png

mavlink_message_t:消息载体(结构体),基本上发送指令的消息都是通过他
mavlink_msg_request_data_stream_pack:#66 的封装消息函数,将相应参数封装至mavlink_message_t
FSYSTEMID, FCOMID:固定参数,分别是255和190;componentId指的是主系统中的子系统;190 MAV_COMP_ID_MISSIONPLANNER的枚举值。我当前项目实际上没有用到。
MAV_DATA_STREAM_ALL:所有数据流,实际可根据数据内容选择相应枚举

如图所示,发送指令的方式实际上非常简单,但是也比较难。难点主要是这些参数的选择。

对于刚接触 Mavlink 的小伙伴,可能都不清楚这些参数的含义;不过一般情况下不用担心,因为如果涉及到无人设备的项目,通常会有一个资深?飞控工程师.对于参数方面的选择,一般不需要前端人员进行选择。

当该指令发送成功后;- (void)socket:didReadData:withTag:就会源源不断收到无人设备的各种状态数据。

三、Mavlink 消息处理

Socket接收到的 data 数据需要处理,通过固定模板转换后根据msgid来判断接收到的消息的tag值

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    mavlink_message_t msg;
    mavlink_status_t  status;
    char *bytes = (char *)[data bytes];
    for (NSInteger i = 0; i < [data length]; ++i) {
        if (mavlink_parse_char(MAVLINK_COMM_0, bytes[i], &msg, &status)) {
            // do something
            switch(msg.msgid) {
            
            }
        }
      }
}
复制代码

四、msgid 指定消息tag值查找手册

无论是刚入门或者是入门一段时候后,都会存在对消息的某一个tag值不了解的情况,

因为在msg.msgid中存在大量tag值,而且每个tag值使用不同的c函数解析
如果对消息中参数定义不清楚,可以使用官方开发手册找到对应枚举表,查看每个参数的定义。
以心跳包MAVLINK_MSG_ID_HEARTBEAT了解参数内容进行举例:

1、使用 Xcode 定义跳转能够得到枚举的具体值

image.png

2、官网查找对应枚举表

command指导表:mavlink.io/zh/messages…

3、页面全局搜索

搜索#0关键字,0 是对应的枚举值,可根据实际情况查找

image.png

五、Mavlink 消息不同Tag的处理

还是以MAVLINK_MSG_ID_HEARTBEAT举例

1、先使用对应文件中结构体:mavlink_heartbeat_t作为处理结果的对象载体

2、再使用mavlink_msg_heartbeat_decode(const mavlink_message_t* msg, mavlink_heartbeat_t* heartbeat)msg解析成mavlink_heartbeat_t

这样就能使用接收从无人设备传过来的具体参数值,具体代码块:

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    mavlink_message_t msg;
    mavlink_status_t  status;
    char *bytes = (char *)[data bytes];
    for (NSInteger i = 0; i < [data length]; ++i) {
        if (mavlink_parse_char(MAVLINK_COMM_0, bytes[i], &msg, &status)) {
            // do something
            switch(msg.msgid) {
                case MAVLINK_MSG_ID_HEARTBEAT: {
                //  code: 0
                mavlink_heartbeat_t heartbeat;
                mavlink_msg_heartbeat_decode(&msg, &heartbeat);
                NSLog(@"%d",heartbeat.custom_mode);
                break;
            }
        }
      }
}
复制代码

基本上消息的处理就是这几步就能完成。

本次的 Mavlink 开发笔记先到此为止。下次的内容主要是介绍当前项目中,常用的消息Tag值,以及对应tag值的解析

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享