ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于MAVSDK与MQTT的飞控数据采集传输系统设计

基于MAVSDK与MQTT的飞控数据采集传输系统设计 简介本资源是一套面向无人机飞控开发者的C语言跨平台实时数据采集与传输系统适用于嵌入式开发者、飞控算法工程师及物联网通信学习者解决无人机遥测数据低延迟获取、MAVLink协议解析与云端/地面站高效分发的核心问题。压缩包共38个文件含8个CMake构建脚本支撑Linux/Windows/macOS多平台编译、4个C/C源码文件含mqtt_client.cpp与config.h等核心逻辑、5个说明类文本含README.md、说明文件.txt与附赠资源.docx以及日志、缓存、构建中间产物等辅助文件整体仅131KB轻量易集成。已有187人学习下载资源结构清晰顶层为CMake工程框架内含MAVSDK调用接口、MAVLink消息解析模块、Paho MQTT C客户端封装及跨平台适配层配套文档详述架构设计、接口定义与编译流程开发者可直接复用数据采集管道或快速对接自定义MQTT Broker。 做无人机远程监控的项目最麻烦的往往不是飞机能不能飞起来而是飞控产生的数据怎么稳定地送出去。我最近刚把一套基于MAVSDK的飞控数据采集与MQTT实时传输系统跑通整个链路涉及MAVLink协议解析、MAVSDK上层接口调用、Paho MQTT C Client Library集成以及跨平台编译环境配置是个典型的边缘网关数据桥接工程。这里把完整的设计思路和实操过程整理出来尤其是那些踩过的坑给准备做无人机遥测上云、远程巡检或编队监控的朋友一个可以直接参考的底子。这套系统的核心价值其实就一句话把飞控上原本只适合点对点传输的MAVLink数据流转换成适合云端海量设备接入的MQTT消息流。飞控链路距离短、协议固定MQTT的Broker则天然支持大量设备接入、消息持久化和订阅分发两者结合之后地面站、Web端、手机端可以同时拿到飞机状态不用再守着射频链路看数传。项目工程结构是C/C混合的采集端用MAVSDK的C接口读飞控数据传输端用Paho的纯C客户端库作为MQTT发布端中间用cJSON做数据序列化整体在Linux和ARM板子上都能编译运行。这篇博客就按从底层协议到上层应用的顺序把整个系统的实现拆开讲清楚。1. 项目整体思路与架构设计1.1 这套系统到底解决什么问题先说我为什么需要这个东西。当时做的是一个无人机远程巡检的验证项目飞机飞在野外人在办公室飞控链路是标准数传模块距离有限数据只能被地面站接收。如果想让数据回到远程服务器做存储、告警和回放就得在飞控和云端之间加一个“翻译官”和“快递员”。这套系统里的角色划分是这样的飞控端输出MAVLink协议数据常见的如Pixhawk系列飞控通过串口或UDP往外发遥测。采集网关就是一套带处理器的边缘设备通常是一块树莓派或者ARM工控板运行MAVSDK负责连接飞控、接收MAVLink数据。传输链路MQTT协议网关作为客户端把解析出的姿态、GPS、电池等信息发布到Broker。云端消费端任何订阅了对应Topic的Web服务、数据库集群或小程序从Broker拉取数据。所以这里的“系统”本质是一个协议转换与数据桥接的服务程序。它不参与飞控决策也不影响飞行只是被动地读取和转发数据。这也是我后来在架构设计里非常注意的一点任何对飞控数据的下行指令都必须单独设计不能和遥测上报混在同一个Topic里否则容易误触发这是后话。1.2 关键链路与技术选型的取舍这个项目里几个核心组件的选型并不是拍脑袋定的每一项背后都有对比和权衡。先说MAVSDK。其实读MAVLink数据有两条路一是自己按MAVLink帧格式逐字节解析二是用MAVSDK这种封装好的库。MAVSDK底层虽然是C实现的MAVLink协议栈但它对外提供的是非常友好的系统抽象比如Telemetry插件直接给姿态角、四元数、GPS状态不需要自己处理消息ID和字节偏移。它的好处是跨平台、自动重连、接口语义清晰适合做应用层开发。代价是库体量大、依赖多在资源极度紧张的MCU上不合适但跑在Linux边缘网关上是绰绰有余。MQTT的选择就没什么悬念了。市面上IoT消息协议里MQTT是最成熟的一套QoS分级、遗嘱消息、保留消息、断线持久会话这些特性全是针对弱网设备设计的。和裸TCP长连接比MQTT多了一层Broker做缓冲和分发客户端不用管对端在不在线和HTTP轮询比MQTT是推送式的实时性和流量消耗都更好。Paho MQTT C Client Library选纯C版本而不用C版本的考虑是这个库在嵌入式领域用得极广没有C运行时依赖编译出来体积小而且API稳定。另一个重要原因是飞控网关通常不是高性能设备纯C库在交叉编译时省心很多。数据序列化我用了cJSON。这个库单文件、无依赖、嵌套操作方便把飞控结构体转成JSON字符串再发给MQTT云端各语言都能直接解析。下图是系统数据流向我画个文字版飞控(MAVLink) - MAVSDK(C) - 业务逻辑(解析/过滤/序列化) - Paho MQTT C Client(发布) - MQTT Broker - 云端订阅端简单来说采集端MAVSDK负责“听懂”飞控的话业务逻辑负责“整理”成云端友好的格式Paho负责“快递”到Broker。2. MAVLink协议解析与飞控数据读取2.1 MAVLink帧结构与消息格式速览理解MAVLink是后面所有工作的基础。MAVLink是一种轻量级的消息传输协议常见的有v1和v2两个版本。现在新固件基本都默认开v2所以我在工程里固定按v2解析但兼容判断还是保留了因为部分老设备仍是v1。MAVLink v2帧的典型结构如下字段长度(字节)说明STX1帧起始标志v2为0xFDLEN1有效载荷长度INC_FLAGS1不兼容标志如是否需要签名CMP_FLAGS1兼容标志SEQ1消息序号用于丢包检测SYS_ID1系统ID标识飞控COMP_ID1组件ID标识飞控内部模块MSG_ID3消息ID标识消息类型PAYLOAD0~255消息体CRC2校验码其中CRC不仅覆盖PAYLOAD还要覆盖前面的部分字段并且会附加一个消息种子值这很关键。如果你手写解析CRC很容易错因为不同消息的CRC种子不同。在MAVLink的C头文件里有一个MAVLINK_MESSAGE_CRC表专门存放每个消息ID对应的额外CRC种子必须查表才能算对。这个项目里我虽然是基于MAVSDK做的底层帧解析被库消化了但排查问题时必须懂得帧格式本身。比如有一次数据断断续续一看日志里CRC失败率飙升最后定位是串口波特率不匹配而不是信号干扰。2.2 用MAVSDK还是手写解析器这是很多做无人机相关项目的人会纠结的问题。我自己的经验建议是如果跑在Linux级别的主控上无脑选MAVSDK只有当你需要部署到STM32这类单片机或者需要深度定制协议行为时才值得手写。对比一下两条路维度MAVSDK手写MAVLink解析开发效率高Telemetry直接给姿态、GPS等结构化数据低需自己维护消息表、CRC表、结构体依赖较大需要C编译链只需纯C代码内存占用较高极低协议升级适配库升级即可需要自己同步头文件适合场景边缘网关、地面站、仿真MCU、对资源和依赖苛刻的嵌入式场景我用的MAVSDK版本是v2.x它默认支持MAVLink v2通信方式可以自动识别串口和UDP。MAVSDK里面有个关键设计是System和Plugin架构。一个System对象代表一个飞控Telemetry、Action、Mission这些都是挂在System下的插件。采集数据只用到Telemetry但系统初始化的时候可以同时初始化多个插件方便以后扩展航线控制。2.3 实际采集哪些飞控消息飞控遥测消息很多但不是全都要。我按项目需求筛选了五类核心数据HEARTBEATMSG_ID 0飞控心跳用于判断连接状态和飞控类型。ATTITUDEMSG_ID 30姿态角包含roll、pitch、yaw和对应角速度。GPS_RAW_INTMSG_ID 24GPS原始数据经纬度、高度、卫星数、定位类型。BATTERY_STATUSMSG_ID 147电池电压、电流、剩余电量百分比。GLOBAL_POSITION_INTMSG_ID 33融合后的全局位置比位置估计更稳定。用MAVSDK的Telemetry插件订阅这些数据非常简单核心代码大致是#include mavsdk/mavsdk.h #include mavsdk/plugins/telemetry/telemetry.h #include iostream using namespace mavsdk; int main() { Mavsdk mavsdk; ConnectionResult conn_result mavsdk.add_any_connection(udp://:14550); if (conn_result ! ConnectionResult::Success) { std::cerr 连接飞控失败: conn_result std::endl; return -1; } // 等待飞控系统出现 auto system mavsdk.first_system(); if (!system) { std::cerr 未检测到飞控系统 std::endl; return -1; } std::cout 已连接到飞控 System ID: system-get_system_id() std::endl; auto telemetry std::make_sharedTelemetry(system); // 订阅姿态数据 telemetry-subscribe_attitude_quaternion([](Telemetry::Quaternion quat) { std::cout 四元素: w quat.w x quat.x y quat.y z quat.z std::endl; }); // 订阅GPS原始数据 telemetry-subscribe_gps_raw_int([](Telemetry::GpsRawInt gps) { std::cout GPS: lat gps.latitude_deg lon gps.longitude_deg 卫星数 static_castint(gps.satellites_visible) std::endl; }); while (true) { std::this_thread::sleep_for(std::chrono::seconds(1)); } return 0; }这段代码跑起来之后飞控的实时数据就能持续打印。实际业务里我不会在回调里直接做发布操作因为回调线程的调用频率很高直接发MQTT容易造成消息风暴。我的做法是先把数据写入一个环形缓存区再由独立线程按固定频率比如5Hz取出、打包、发送。3. Paho MQTT C Client集成与消息传输3.1 Paho库编译的两种方式Paho MQTT C Client Library的项目名是paho.mqtt.c编译方式比较灵活。我试过两种都在工程里留了脚本。第一种是直接用CMake构建并安装到系统目录git clone https://github.com/eclipse-paho/paho.mqtt.c.git cd paho.mqtt.c cmake -B build -DPAHO_WITH_SSLFALSE -DPAHO_ENABLE_TESTINGFALSE cmake --build build sudo cmake --install build我编译时直接把SSL关了因为我们当前网络环境里Broker和网关在同一内网不需要TLS加密。如果以后要公网传输可以考虑开启SSL但编译时需要额外处理OpenSSL依赖后面跨平台部分会说。第二种是在自己的CMake工程里用FetchContent拉取源码include(FetchContent) FetchContent_Declare( paho_mqtt_c GIT_REPOSITORY https://github.com/eclipse-paho/paho.mqtt.c.git GIT_TAG v1.3.13 ) FetchContent_MakeAvailable(paho_mqtt_c)用FetchContent的好处是版本可控团队里其他人拉下来就能编不需要提前装系统库。3.2 连接Broker和发布消息的关键配置Paho C库提供两套API同步的MQTTClient和异步的MQTTAsync。同步API用起来直观适合发布频率不高的场景异步API则适合需要高吞吐、非阻塞发送的场景。由于我的发布频率峰值能到20Hz我一开始用同步API结果发现发送偶尔会阻塞几百毫秒如果Broker网络抖动会直接拖垮采集线程。后来改成异步API才彻底解决阻塞问题。连接Broker的核心初始化代码如下#include MQTTClient.h #define ADDRESS tcp://127.0.0.1:1883 #define CLIENTID drone_gateway_01 #define TOPIC drones/001/telemetry #define QOS 1 MQTTClient client; MQTTClient_connectOptions conn_opts MQTTClient_connectOptions_initializer; int rc; rc MQTTClient_create(client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); if (rc ! MQTTCLIENT_SUCCESS) { printf(创建客户端失败: %d\n, rc); return -1; } conn_opts.keepAliveInterval 20; conn_opts.cleansession 1; conn_opts.connectTimeout 10; conn_opts.retryInterval 2; conn_opts.automaticReconnect 1; conn_opts.minRetryInterval 1; conn_opts.maxRetryInterval 60; rc MQTTClient_connect(client, conn_opts); if (rc ! MQTTCLIENT_SUCCESS) { printf(连接Broker失败: %d\n, rc); return -1; }几个参数重点说明一下keepAliveInterval心跳间隔。我设置20秒Broker超过约1.5倍时间没收到报文就认为客户端掉线。设太小会频繁产生网络包设太大则断线发现不及时。cleansession 1每次连接都是全新会话不保留离线消息。对于遥测数据这没问题因为飞控数据本来就是“当前值”错过几秒没意义。如果要下发指令建议单独开一个订阅连接并设置cleansession 0。automaticReconnect 1自动重连。这是弱网环境下最重要的开关不用自己写重连逻辑。发布消息我封装了一个函数void publish_json(const char* topic, const char* payload, int qos) { MQTTClient_message pubmsg MQTTClient_message_initializer; pubmsg.payload (void*)payload; pubmsg.payloadlen (int)strlen(payload); pubmsg.qos qos; pubmsg.retained 0; MQTTClient_deliveryToken token; MQTTClient_publishMessage(client, topic, pubmsg, token); // 异步接口下这里不需要等待回调里会收到deliveryComplete }有个容易踩的坑异步API中MQTTClient_publishMessage里的topic参数和msg.payload在函数返回后库内部并不拷贝topic字符串所以不能用临时变量。必须保证这个字符串生命周期足够长最好是静态或动态分配。我最初就是用了栈上的字符串缓冲区导致丢消息排查了半天。3.3 Topic设计与QoS策略MQTT的Topic设计直接影响后续数据消费的复杂度。我建议按设备ID和数据类型分层这样云端订阅时可以灵活过滤。我实际用的Topic结构是drones/{sysid}/telemetry # 所有遥测数据 drones/{sysid}/status # 连接状态、飞行模式变更 drones/{sysid}/event # 告警、超阈值事件遥测Topic里的payload是一个完整的JSON对象包含多种字段{ ts: 1712345678.123, sysid: 1, att: {roll: 0.12, pitch: -0.34, yaw: 2.15}, gps: {lat: 39.9088, lon: 116.3975, alt: 350.2, sats: 15}, bat: {voltage: 11.8, current: 5.2, remaining: 0.78} }QoS策略我这样选择遥测数据QoS 1。因为数据实时性强QoS 2会造成额外确认延迟QoS 0则可能丢帧。QoS 1保证Broker至少收到一次重复消息由云端用时间戳去重。状态类消息QoS 1同时设置retained 1。这样新的云端客户端上线后能立刻知道当前飞控是处于“自动飞行”还是“悬停”状态不用等待下一个状态变化。告警事件QoS 1或2看业务重要性。我这里用了QoS 2因为告警不能丢也不能重复。这里多说一句retained消息。当时我调试Web端时发现只要页面刷新飞控状态就变成“未知”要等好几秒才有新数据刷新出来。后来就是给status Topic开了retained页面一订阅就能拿到最新状态。这个技巧很小但效果立竿见影。4. 跨平台编译与工程组织4.1 整体依赖梳理这个工程的依赖关系大概是这样的依赖库语言用途是否可选MAVSDKC14/17飞控数据采集必选Paho MQTT CC99MQTT发布必选cJSONC99JSON序列化必选OpenSSLCTLS支持Paho/MAVSDK都依赖可选但建议装Libevent/WebSocketsCMAVSDK底层通信MAVSDK依赖的后端AsioCMAVSDK网络IOMAVSDK依赖MAVSDK的底层传输后端有串口、UDP、TCP还支持WebSocket。在Linux和ARM上UDP是最常用的因为大多数数传模块就是走的UDP转发。编译时MAVSDK会自己拉取这些第三方依赖所以不需要手动处理太多。4.2 CMake工程组织示例整个工程我按模块化组织drone_gateway/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ ├── mavlink_reader.h / .cpp │ ├── json_serializer.h / .cpp │ ├── mqtt_bridge.h / .cpp ├── third_party/ │ ├── cJSON.c / cJSON.h └── config/ └── config.json根目录的CMakeLists.txt关键部分是cmake_minimum_required(VERSION 3.16) project(drone_gateway LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_STANDARD 99) # MAVSDK add_subdirectory(third_party/mavsdk) # Paho MQTT C set(PAHO_WITH_SSL ON CACHE BOOL FORCE) set(PAHO_ENABLE_TESTING OFF CACHE BOOL FORCE) add_subdirectory(third_party/paho.mqtt.c) # cJSON 直接编译源码 add_library(cjson third_party/cJSON/cJSON.c) add_executable(drone_gateway src/main.cpp src/mavlink_reader.cpp src/json_serializer.cpp src/mqtt_bridge.cpp ) target_link_libraries(drone_gateway PRIVATE mavsdk mavsdk_telemetry paho-mqtt3as cjson pthread )这里有个细节Paho库编译出来有两个版本paho-mqtt3a是异步APIpaho-mqtt3c是同步APIpaho-mqtt3as是带SSL的异步库。链接时要选对后缀否则编译报未定义引用。4.3 不同平台编译实测记录我实际在三个平台编译过这套工程平台一x86_64 Ubuntu 20.04最顺利直接装依赖就行sudo apt install build-essential cmake libssl-dev mkdir build cd build cmake .. make -j$(nproc)这里的坑是Ubuntu 20.04的默认GCC版本是9.xMAVSDK编译要求C17而Paho库要求C99基本都能满足。平台二树莓派4B (ARM64, Ubuntu Server)编译流程和x86差不多但有两个坑内存不够。树莓派4B如果只有2GB内存make -j4会直接OOM我改成make -j2才编过。默认编译器是32位还是64位要确认。建议直接用64位系统镜像因为32位下MAVSDK的部分第三方依赖会有问题。平台三瑞芯微RK3588 ARM板交叉编译交叉编译相对麻烦我用的是aarch64编译链。核心是给CMake指定工具链文件# aarch64-toolchain.cmake set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g) set(CMAKE_FIND_ROOT_PATH /opt/aarch64/sysroot) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)然后编译mkdir build_arm cd build_arm cmake -DCMAKE_TOOLCHAIN_FILEaarch64-toolchain.cmake .. make -j8交叉编译时最容易出问题的是OpenSSL。因为MAVSDK和Paho编译时如果开了SSL都会去找目标板上的libssl。交叉编译环境下这个库需要事先准备好目标板的rootfs或者直接把SSL关掉。我为了省事在ARM板上直接把PAHO_WITH_SSL关了MAVSDK的底层WebSocket传输也不用只用UDP这样交叉编译就顺利很多。4.4 Windows平台的一点点说明严格说Windows上也能编过但体验比较差。MAVSDK官方支持Windows但依赖的串口和网络库在Windows上编译路径不同还需要装vcpkg来管理第三方依赖。Paho库在Windows上用vcpkg安装最方便vcpkg install paho-mqtt-c但是需要注意Windows版Paho编译默认是DLL方式把它部署到无VC运行库的目标机器上容易跑不起来。如果只是开发调试建议直接用WSL或者Docker里的Linux编译产物放到生产Linux环境。我自己很少在Windows上编这个工程除非只是给客户演示demo。5. 常见问题与排查技巧实录5.1 飞控连接失败报错“没有检测到飞控系统”这个是最常见的。原因我梳理了几个串口设备不存在或权限不足。检查ls /dev/ttyUSB*或/dev/serial*给当前用户加dialout组权限或者用sudo chmod 666 /dev/ttyUSB0临时解决。UDP端口不对。如果数传模块在电脑上开了Mission Planner它正在占着14550端口你再开这个口就会冲突。波特率不对。Pixhawk的TELEM2口默认一般是57600但有些飞控或改装模块是115200一定要先确认固件里参数设置。排查这个问题的通用方法先用QGroundControl或Mission Planner连接飞控确认数传链路正常再用mavlink-inspector之类工具监听看主控端能否收到心跳包。如果地面站能连上而你的程序连不上问题基本出在连接地址和权限上。5.2 数据全是NaN或者明显是0这个情况通常是飞控本身的问题不是采集程序的问题。常见原因飞机没解锁IMU还在初始化状态部分数据可能是NaN。GPS没有完成定位satellites_visible为0经纬度为0。传感器校准丢失飞控内部EKF不健康。排查方式多看MAVSDK提供的健康状态接口最直接的是Telemetry::health_all_ok()。我在程序里加了一行日志非健康状态下会打warning同时把采集频率降到1Hz减少无意义的数据包。5.3 MQTT消息时断时续Broker日志里全是连接中断记录这种现象通常不是程序逻辑错误而是网络或配置问题。我碰到过几种keepalive设置太短。如果Broker和网关之间有几秒延迟keepAliveInterval设成5秒会导致Broker误判掉线。我后来统一设20秒重连稳定很多。Broker地址用了域名但网关的DNS解析不稳定。建议直接换成IP或提前做DNS缓存。网关的4G模块休眠策略。树莓派等设备如果启用省电模式网络会周期性断开导致MQTT被动重连。要在系统层面关闭WiFi/4G模块的省电或者加大keepalive间隔。这里我强烈建议给Paho配置自动重连但要注意自动重连的时间间隔。Paho的initialReconnectDelay和maxReconnectDelay可以控制退避策略我设的是1秒起始、60秒封顶实测在弱网下比较科学。5.4 数据发布频率太高Broker压力大飞控Telemetry消息原始频率很高比如IMU数据能到100Hz甚至更高如果直接把每个回调都发到MQTTBroker很容易被打爆。我的降频策略是筛选关键消息。姿态、GPS这种变化频率中等的消息5~10Hz就足够。在采集端做时间窗口聚合。比如把1秒内的数据合并成一个JSON数组一条MQTT消息里携带多帧数据。用环形缓存加定时器固定间隔发送而不是回调一触发就发。实测下来把10Hz的遥测发布稳定在一个数据包约1KB以内带宽占用很小4G网络完全无压力。5.5 程序长时间运行后内存持续增长这是个经典坑。我排查过两处第一处是Paho的异步发布。使用MQTTClient_publishMessage时如果消息率很高而send缓冲满了消息会堆积在内存里。虽然Paho内部有队列但无限发布会导致内存增长。解决办法是增加频率控制或者改用同步发布并接受偶尔的阻塞。第二处是cJSON对象没有及时删除。cJSON的cJSON_CreateObject()分配的内存必须用cJSON_Delete()释放。我在封装序列化函数时一开始忘记在发送完成后释放对象跑半小时内存就涨了几十MB。正确的发布流程是cJSON* root cJSON_CreateObject(); // ...填充字段... char* payload cJSON_PrintUnformatted(root); // 用payload发布MQTT mqtt_publish(payload); // 释放资源 free(payload); cJSON_Delete(root);不要小看free(payload)这一步cJSON_PrintUnformatted内部也是malloc分配的内存不释放一样泄漏。5.6 遥测数据里时间戳不同步云端如果想按时间线回放姿态数据网关本地时间戳非常关键。我最初是用time(NULL)取的秒级时间后来发现多帧数据在1秒内无法区分顺序只能靠MQTT内的seq字段辅助。改成clock_gettime(CLOCK_REALTIME, ts)取纳秒级时间戳之后云端排序就正常了。另外如果网关和云端的时钟不同步归档的数据会漂移。建议在网关加一个NTP同步并在JSON里同时带设备本地时间和接收时间。这个细节对后续做数据分析和告警别影响很大。6. 我最后想说的几个工程化建议整个系统跑通之后回头总结几个点我认为对要复现这个项目的人很重要。第一个建议模块之间一定要做解耦。采集、序列化、发布拆成三个独立模块用环形缓冲队列通信。这样以后换掉任何一层都不影响其他层。比如想从MAVSDK换成手写MAVLink解析只需要改mavlink_reader模块MQTT部分一行不动。第二个建议开始写代码前先把Topic命名和JSON格式定义清楚。这两个是接口契约一旦定下来云端、网关、数据库多方都要遵守后期改动成本很高。最好是写一个简单的接口文档哪怕只有一页也能避免很多沟通成本。第三个建议日志管理要提前做。这个系统跑在无人值守的网关上出问题只能翻日志。我用了spdlog库按天滚动保留30天日志同时把关键事件起飞、连接断开、数据异常单独输出到syslog。一开始嫌麻烦没做后来一次现场排查花了半天时间才定位到问题就再也不省这个事了。第四个建议做这个项目的边界要清晰数据采集和上报只是整个无人机监控系统的一小块但它是连接飞行器和云端的生命线。数据链路稳定比数据精度更优先先保证心跳不断、消息不积压再谈优化数据内容。所以我在程序启动时会有一个“自检模式”先连续采集30秒检查MAVLink丢包率、MQTT发布成功率全部达标后才进入正常数据流不达标就打印诊断信息这样启动时能第一时间暴露问题。这套基于MAVSDK和MQTT的飞控数据采集传输方案从想法到稳定运行前后折腾了大概两周其中一半时间花在编译和部署上另一半花在排查各种奇奇怪怪的断连问题上。如果你也在做类似的事情希望这篇记录能帮你少走一些弯路。尤其在Paho异步发布、Topic规划、交叉编译这些地方提前想清楚后面会省很多事。本文还有配套的精品资源点击获取
返回列表