Mavlink生成和收发通讯

  • 1. 演示效果
  • 2. Mavlink 生成
    • 2.1 安装python3
    • 2.2 Mavlink下载和运行
    • 2.3 xml文件修改
    • 2.4 自定义Mavlink生成
  • 3. 业务逻辑实现
    • 3.1 QML前端显示
      • 3.1.1 发送部分
      • 3.1.2 接收显示
    • 3.2 C++后端
      • 3.2.1 QGC发送
      • 3.2.2 MockLink接收
      • 3.2.3 MockLink发送
      • 3.2.4 QGC接收

所有的热爱都要不遗余力,真正喜欢它便给它更高的优先级,和更多的时间吧!

关于QGC地面站其它文章请点击这里:     QGC地面站

本文源码地址:     QGC_CCH地面站

我建了个QGC学习交流群,感兴趣的小伙伴们可以扫码加入哦,失效了,可以加我微信拉进群


1. 演示效果


测试的时候如下,连接MockLink中的PX4:

QGC发送数据: 需要手动点击发送,MockLink中会打印接收到的两个字节
MockLink发送数据: 1HZ的定时器发送

2. Mavlink 生成

主要流程参考官网:

Installing MAVLink

Generating MAVLink Libraries

2.1 安装python3

安装教程可以参考这个,Python3.7.3安装(Win10),现在已经是3.9.5版本了。安装完后测试下看是否装成功了

然后安装 pip3,直接打开cmd命令

pip3 install future

如果报这个:

可以升级一下,不升级应该也行吧~

python -m pip install --upgrade pip

然后查看版本:

pip show pip

2.2 Mavlink下载和运行

需要递归下载

git clone https://github.com/mavlink/mavlink.git --recursive

下载不完全会导致运行不了Mavlink生成器,需要安装包,关注后评论留邮箱私发

进入下载的Mavlink的根文件夹,执行

python mavgenerate.py

如下,弹出了Mavlink生成器:

2.3 xml文件修改

打开 ~\libs\mavlink\include\mavlink\v2.0\message_definitions\ardupilotmega.xml

仿原有的格式,自定义236号ID,并添加在226号后,如下:

<message id="226" name="RPM"><description>RPM sensor output.</description><field type="float" name="rpm1">RPM Sensor1.</field><field type="float" name="rpm2">RPM Sensor2.</field>
</message>
<message id="236" name="CSDN_TEST"><description>CSDN TEST.</description><field type="uint8_t" name="byte1">FRIST BYTE.</field><field type="uint8_t" name="byte2">SECOND BYTE.</field>
</message>

定义了byte1、byte1两个字节的数据,此处就是你需要与无人机通讯的数据。

PX4中定义的话最好在 common.xml 中添加。

2.4 自定义Mavlink生成

如下:

XML~\libs\mavlink\include\mavlink\v2.0\message_definitions\ardupilotmega.xml
Out: 可以新建个文件作为输出,也可以直接覆盖QGC中的mavlink库(不太推荐,但是此次测试就是直接覆盖的,覆盖的话记得先备份下原本的mavlink库)

这就是生成的mavlink库:

复制 ardupilotmega 下的 mavlink_msg_csdn_test.h到 qgc的mavlink对应位置下( 如果全选OUT下的文夹复制到qgc mavlink库中可跳过这些步骤)

覆盖 qgc的mavlink的ardupilotmega.h ,注意看其实就改了几处:

① 修改 #define MAVLINK_MESSAGE_CRCS 校验处,增加了236号ID的校验

② include mavlink_msg_csdn_test.h 头文件

③ 修改 MAVLINK_MESSAGE_INFO

④ 修改 MAVLINK_MESSAGE_NAMES

注意: 其中最重要的是第一处的 MAVLINK_MESSAGE_CRCS 校验,如果在Mocklink中能通讯,实际的飞控无法通讯多半是检验位没通过,就是此处有问题,可以分别检查下 ardupilotmega.h、common.h、standard中的MAVLINK_MESSAGE_CRCS,甚至可以都加上新增的校验ID

3. 业务逻辑实现

3.1 QML前端显示


添加在 FlightDisplayView.qml (有些版本是FlyView.qml)后:

3.1.1 发送部分

发送的关键就是 activeVehicle.testSendToVehicle(protectTextField1.text, protectTextField2.text) ,把两个用户输入数据的文本框发送给MockLink

//FlightDisplayView.qml (有些版本是FlyView.qml) 最后Rectangle {id:                         sendRectanchors.top:                parent.topanchors.topMargin:          20anchors.horizontalCenter:   parent.horizontalCenterheight:                     col.height * 1.1width:                      col.width * 1.1radius:                     2color:                      "black"Column {id:                     colspacing:                4anchors.centerIn:       parentQGCLabel {anchors.horizontalCenter:   parent.horizontalCentertext:                       "Mavlink 发送测试!"font.pointSize:             12font.bold:                  truecolor:                      "red"}Row {anchors.left:       parent.leftanchors.right:      parent.rightQGCLabel {id:                         tipsLabelanchors.verticalCenter:     protectTextField1.verticalCentertext:                       qsTr("第一个字节:")font.pointSize:             11font.bold:                  truecolor:                      "#B7FF4A"}QGCTextField {id:                         protectTextField1width:                      parent.width - parent.spacing - tipsLabel.widthheight:                     tipsLabel.implicitHeight * 1.5text:                       "1"inputMethodHints:           Qt.ImhFormattedNumbersOnlyfocus:                      trueonEditingFinished: {if(text > 256) {text = 256mainWindow.showMessageDialog(qsTr("警告"), qsTr("输入必须小于等于256"))}else if(text < 0) {text = 0mainWindow.showMessageDialog(qsTr("警告"), qsTr("输入必须大于等于0"))}}}}Row {anchors.left:       parent.leftanchors.right:      parent.rightQGCLabel {id:                         tipsLabel2anchors.verticalCenter:     protectTextField2.verticalCentertext:                       qsTr("第二个字节:")font.pointSize:             11font.bold:                  truecolor:                      "#B7FF4A"}//保护距离的输入QGCTextField {id:                         protectTextField2width:                      parent.width - parent.spacing - tipsLabel2.widthheight:                     tipsLabel2.implicitHeight * 1.5text:                       "1"inputMethodHints:           Qt.ImhFormattedNumbersOnlyfocus:                      trueonEditingFinished: {if(text > 256) {text = 256mainWindow.showMessageDialog(qsTr("警告"), qsTr("输入必须小于等于256"))}else if(text < 0) {text = 0mainWindow.showMessageDialog(qsTr("警告"), qsTr("输入必须大于等于0"))}}}}QGCButton {id:                             mavTestButtonbackRadius:                     height/2text:                           qsTr("MAVLINK消息发送测试")enabled:                        activeVehicleonClicked: {if(activeVehicle)activeVehicle.testSendToVehicle(protectTextField1.text, protectTextField2.text)}}}}

3.1.2 接收显示

接收的关键就是:activeVehicle.rcvByte1 和 activeVehicle.rcvByte2,后续C++中还会提及。

//FlightDisplayView.qml (有些版本是FlyView.qml) 最后Rectangle {anchors.top:                sendRect.bottomanchors.topMargin:          20anchors.horizontalCenter:   parent.horizontalCenterheight:                     colSendRect.height * 1.2width:                      colSendRect.width * 1.2radius:                     2color:                      "black"Column {id:                     colSendRectspacing:                4anchors.centerIn:       parentQGCLabel {anchors.horizontalCenter:   parent.horizontalCentertext:                       "Mavlink 接收测试!"font.pointSize:             12font.bold:                  truecolor:                      "red"}Row {id:                 row1anchors.horizontalCenter: parent.horizontalCenterheight:                       label1.heightQGCLabel {id:                       label1anchors.verticalCenter:   parent.verticalCentertext:                       qsTr("接收的第一个字节:")font.pointSize:             11font.bold:                  truecolor:                      "#B7FF4A"}QGCLabel {anchors.verticalCenter:     parent.verticalCentertext:                       activeVehicle ? activeVehicle.rcvByte1 : ""font.pointSize:             11font.bold:                  truecolor:                      "#B7FF4A"}}Row {anchors.left:                   row1.leftheight:                         label2.heightQGCLabel {id:                         label2anchors.verticalCenter:     parent.verticalCentertext:                       qsTr("接收的第二个字节:")font.pointSize:             11font.bold:                  truecolor:                      "#B7FF4A"}QGCLabel {anchors.verticalCenter:     parent.verticalCentertext:                       activeVehicle ? activeVehicle.rcvByte2 : ""font.pointSize:             11font.bold:                  truecolor:                      "#B7FF4A"}}}}

3.2 C++后端

使用QGC与MockLink的通讯可以模拟QGC地面站与PX4/APM飞控的通讯,来验证QGC地面站是否编写有问题,再与飞控对接这样能确保地面站是没问题的。再提醒下,MockLink和QGC本身用的是同一套mavlink,所以检验位肯定正确,如不正确,请看前文的分析。

以下代码配合 QGC_CCH地面站 饮用更佳

3.2.1 QGC发送

上述QML中发送的核心就是:

activeVehicle.testSendToVehicle(protectTextField1.text, protectTextField2.text)

protectTextField1.text, protectTextField2.text 为两个文本框中数据

QGC中发送函数:

//Vehicle.cc
void Vehicle::testSendToVehicle(quint8 byte1, quint8 byte2)
{mavlink_message_t       msg;mavlink_csdn_test_t     csdn_test_t;//用户数据填充到结构体中csdn_test_t.byte1 = byte1;csdn_test_t.byte2 = byte2;qDebug() << "csdn_test_t.byte1" << csdn_test_t.byte1;  //QGC send cmd to xxxqDebug() << "csdn_test_t.byte2" << csdn_test_t.byte2;  //QGC send cmd to xxxmavlink_msg_csdn_test_encode_chan(_mavlink->getSystemId(),_mavlink->getComponentId(),priorityLink()->mavlinkChannel(),&msg,&csdn_test_t);sendMessageOnLink(priorityLink(), msg);//有些版本可用以下方式发送//sendMessageOnLinkThreadSafe(priorityLink(), msg);
}

Vehicle.h中声明:

public:
...
Q_INVOKABLE void testSendToVehicle(quint8 byte1, quint8 byte2);

3.2.2 MockLink接收

MockLink接收函数:

//MockLink.cc
void MockLink::_handleCSDNTest(const mavlink_message_t& msg)
{mavlink_csdn_test_t csdn_test_t;mavlink_msg_csdn_test_decode(&msg, &csdn_test_t);qDebug() << "[MockLink] Rcv byte1: " << csdn_test_t.byte1;qDebug() << "[MockLink] Rcv byte2: " << csdn_test_t.byte2;
}

调用MockLink接收函数:

//MockLink.cc
void MockLink::_handleIncomingMavlinkBytes(const uint8_t* bytes, int cBytes)
{//最后加入:case MAVLINK_MSG_ID_CSDN_TEST:_handleCSDNTest(msg);break;
}

接收函数声明:

//MockLink.h
class MockLink : public LinkInterface {...
private:
...void _handleCSDNTest(const mavlink_message_t& msg);
}

3.2.3 MockLink发送

发送两个字节数据的声明:

//MockLink.h
class MockLink : public LinkInterface {...
private:
...void _sendCSDNTest(void);//发送的两个数据uint8_t  _testByte1;uint8_t  _testByte2;}

数据初始化:

//MockLink.cc
MockLink::MockLink(SharedLinkConfigurationPointer& config) {...//初始化列表最后添加, _testByte1                            (0), _testByte2                            (0)
}

发送函数:

void MockLink::_sendCSDNTest(void)
{mavlink_message_t   msg;//发送的两个数据一个加,一个减_testByte1++;_testByte2--;mavlink_msg_csdn_test_pack_chan(_vehicleSystemId,_vehicleComponentId,_mavlinkChannel,&msg,_testByte1,        // MAV_TYPE_testByte2      // MAV_AUTOPILOT);respondWithMavlinkMessage(msg);
}

模拟发送需要借助定时器,以下为1HZ发送的:

// MockLink.cc
void MockLink::_run1HzTasks(void)
{..._sendVibration();_sendSysStatus();_sendADSBVehicles();//[修改]_sendCSDNTest();...
}

3.2.4 QGC接收

QGC中接收函数:

void Vehicle::_handleCSDNTestRcv(mavlink_message_t& message)
{mavlink_csdn_test_t csdn_test_t;mavlink_msg_csdn_test_decode(&message, &csdn_test_t);//赋值_rcvByte1 = csdn_test_t.byte1;_rcvByte2 = csdn_test_t.byte2;//触发信号,QML前端中接收,可搜 activeVehicle.rcvByte1emit rcvByte1Changed(_rcvByte1);emit rcvByte2Changed(_rcvByte2);//    qDebug() << "[Vehicle] Rcv RcvByte1:" << _rcvByte1;
//    qDebug() << "[Vehicle] Rcv RcvByte2:" << _rcvByte2;
}

调用接收函数:

void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message) {...case MAVLINK_MSG_ID_WIND:_handleWind(message);break;//[修改]case MAVLINK_MSG_ID_CSDN_TEST:_handleCSDNTestRcv(message);break;}

变量初始化:

Vehicle::Vehicle(...): FactGroup(_vehicleUIUpdateRateMSecs, ":/json/Vehicle/VehicleFact.json")..., _gitHash(versionNotSetValue), _uid(0)//[修改], _rcvByte1(0), _rcvByte2(0)
{}

变量和函数声明:

class Vehicle : public FactGroup
{Q_OBJECT
public:...Q_PROPERTY(quint8  rcvByte1                  READ rcvByte1                      NOTIFY rcvByte1Changed)Q_PROPERTY(quint8  rcvByte2                  READ rcvByte2                      NOTIFY rcvByte2Changed)...quint8     rcvByte1              () { return _rcvByte1; }quint8     rcvByte2              () { return _rcvByte2; }signals:...void rcvByte1Changed              (quint8 rcvByte1);void rcvByte2Changed              (quint8 rcvByte2);...
private:void _handleCSDNTestRcv(mavlink_message_t& message);...quint8            _rcvByte1;quint8            _rcvByte2;...
}

看都看完了,如果对你有任何帮助,请不要吝啬你的一键三连哦,感谢各位~


关于QGC地面站其它文章请点击这里:     QGC地面站

本文源码地址:     QGC_CCH地面站

QGC地面站Mavlink生成和MockLink模拟收发通讯相关推荐

  1. QGC地面站二次开发(二)QGC 界面自定义和修改

    目录 1.QGC 地面站的显示机制 1.1.C++类注册为 qml 可访问类型 1.2.注册属性或者方法 1.1.1. 属性声明 1.1.2.方法声明 2.QGC 地面站界面初步修改 3.QGC 地面 ...

  2. QGC地面站中视频流配置及gstreamer安装

    QGC地面站中视频流配置及gstreamer安装 1. QGC地面站各版本视频流测试 2. 安装gstreamer 3. 修改路径 4. 地面站配置 5. Android版本安装 关于QGC地面站其它 ...

  3. QGC地面站二次开发(一)地面站介绍以及软件框架(1)地面站使用介绍和接口介绍

    目录 QGC界面显示框架 页面介绍 飞行页面 Application Setting页面 General Offline map 连接 Mock Link Vehicle Setup页面 Plan页面 ...

  4. apm软件仿真+QGC地面站 环境搭建

    本教程使用场景:apm软件仿真运行于虚拟机 ubuntu环境.qgc地面站位于windows 系统.两个环境在同一台电脑上. 一.apm仿真环境搭建 1.安装vm虚拟机及ubuntu 18. 2.ub ...

  5. QGC地面站小白安装与简单实用

    QGC二次开发 电脑:联想拯救者Lenovo R720,在电脑上安装虚拟机-->在虚拟机中安装UBuntu系统-->在Ubuntu中安装QGC以及Qt编译器. 1 安装VMware Wor ...

  6. PX4 QGC地面站自定义参数

    QGC地面站自定义参数(新手操作)v1.8.2 QGC以往版本下载地址 htps://github.com/mavlink/qgroundcontrol/tags 最终的添加结果如下: 具体步骤如下: ...

  7. 【测试】QGC地面站开发课程完结篇--一站多机控制测试说明

    阿木实验室去年推出的QGC地面站开发实战课程,随着地面站控制多架飞机的测试的成功,课程全部完结,以下是我们户外测试最终版地面站的测试视频: 视频地址: https://v.qq.com/x/page/ ...

  8. Ubuntu18.04下px4+MAVROSM+QGC地面站安装教程及避坑指南

    下面安装建立在已经安装好了ROS的基础,未安装ROS的请先按照下面教程安装ROSROS 安装教程 目录 一.安装px4_toolchain 二.编译PX4固件 三.mavros and mavlink ...

  9. 树莓派ubuntu mate系统连接PX4并通过UDP连接至QGC地面站

    前提条件: 树莓派安装了ubuntu mate 20.04系统 ubuntu mate已经安装好ros(这里是noetic版本)系统,Mavros 安装好QGC地面站的PC USB数据线(确定能传输数 ...

最新文章

  1. Oracle数据库日常维护知识总结
  2. PHP5 VC9、VC6、Thread Safe、Non Thread Safe各个版本区别
  3. easymock快速入门
  4. golang经典书籍--Go语言圣经
  5. javascript自定义事件原理
  6. android开发微博搜索,一款帮助用户自动提取微博热搜、知乎热榜、百度实时热点条目中与特定领域...
  7. flink中datastream和dataset各自print()的异同
  8. python asyncio 并发编程_asyncio并发编程
  9. django-命名空间与反向解析-模板反向解析-视图反向解析
  10. 【IT】关于Code打卡机时遇到的问题及解决
  11. 手机分辨率大小自适应功能
  12. 背阔肌(04):杠铃俯身划船
  13. linux键盘控制鼠标软件下载,手机控制电脑软件(Mouse Server)
  14. 前端面试题总结(js、html、小程序、React、算法、vue 、全栈热门视频资源)
  15. Android应用权限大全(Manifest.permission)
  16. IDEA如何简单的设置中文
  17. caffe安装详细完整过程(Ubuntu16.04、Ubuntu18.04系统)
  18. sqrt函数,对数进行开根号
  19. linux pam mysql,Linux-PAM PAM-MySQL的总结
  20. 求根节点到叶节点数字之和(C语言)

热门文章

  1. 外链自动转内链html,一个简单的HTML实现外链转内链
  2. 【EDA设计笔记】EDA-USB_SPI_FLASH-设计与实现
  3. oracle crs 4639,处理CRS-4639和CRS-4000错误
  4. httpclient4.5 结合 讯代理 实现IP代理
  5. 智能电表专用DC-DC芯片
  6. 华语乐坛到底姓什么?------酷狗篇
  7. java 中有几种类型的流?JDK 为每种类型的流提供了一些抽象类以供继承, 请说出他们分别是哪些类?
  8. 将cooledit作为一个音频信号发生器(http://www.zsjys.net/JYJY/ShowArticle.asp?ArticleID=64)
  9. python缩写月份单词_Python替换月份为英文缩写的实现方法
  10. 旗杆的安装方法和流程