- 嵌入式
- 物联网
- 机器人
- 自动驾驶
- 智能硬件
【免费下载链接】PX4-Autopilot
PX4 Autopilot Software
本篇技术指南以 PX4-Autopilot 仓库中 docs/en/msg_docs/MavlinkLog.md 所定义的MavlinkLoguORB 消息为核心,完整剖析其字段定义、日志级别语义与队列设计,并深入源码讲解"发布端(mavlink_log_xxx()系列宏)→ uORB 主题 → STATUSTEXT 流 → MAVLink 地面站"的端到端数据链路。读完本文,你将掌握如何在自己的模块中安全、规范地发布机载日志文本,理解其如何被转换为 MAVLinkSTATUSTEXT消息送达 QGroundControl 等地面站,并清楚它与 MAVLinkLOG_*(ULog 文件传输)协议的本质区别。
消息定义:三个字段承载一条日志
MavlinkLog是 PX4 用于在飞行控制器内部传递"面向地面站的文本日志"的 uORB 主题,其唯一 TOPIC 名为mavlink_log。该主题的原始定义位于 msg/MavlinkLog.msg,全文如下:
uint64 timestamp # time since system start (microseconds) char[127] text uint8 severity # log level (same as in the linux kernel, starting with 0) uint8 ORB_QUEUE_LENGTH = 8对应生成的 C 结构体类型为mavlink_log_s(见 uORB/topics/mavlink_log.h 生成头 的引用)。消息共三个字段:
| 字段 | 类型 | 单位 | 说明 |
|---|---|---|---|
timestamp | uint64 | 微秒 | 系统启动以来的时间(microseconds),由hrt_absolute_time()填充 |
text | char[127] | — | 日志文本内容,最多 127 字节(含结尾\0),UTF-8 文本 |
severity | uint8 | — | 日志级别,与 Linux 内核日志级别语义一致,从 0 开始(0 为最高紧急度) |
需要注意:
char[127]是 uORB 消息定义中的存储容量上限,并不代表推荐的使用长度。实际发送文本建议控制在MAVLINK_LOG_MAXLEN(50 字节)以内,原因见下文"STATUSTEXT 流"一节。
severity 字段:与 Linux 内核对齐的 8 级日志体系
文档明确指出severity采用与 Linux 内核相同的日志级别(starting with 0)。在 src/lib/systemlib/mavlink_log.h 中,PX4 用宏将 0~7 的数值语义一一对应:
| 宏 | 数值 | 语义(对应 Linux 内核) |
|---|---|---|
_MSG_PRIO_EMERGENCY | 0 | 系统不可用(KERN_EMERG) |
_MSG_PRIO_ALERT | 1 | 必须立即处理(KERN_ALERT) |
_MSG_PRIO_CRITICAL | 2 | 严重错误(KERN_CRIT) |
_MSG_PRIO_ERROR | 3 | 错误(KERN_ERR) |
_MSG_PRIO_WARNING | 4 | 警告(KERN_WARNING) |
_MSG_PRIO_NOTICE | 5 | 正常但值得注意(KERN_NOTICE) |
_MSG_PRIO_INFO | 6 | 信息(KERN_INFO) |
_MSG_PRIO_DEBUG | 7 | 调试信息(KERN_DEBUG) |
数值越小越紧急,这与 MAVLinkSTATUSTEXT消息的severity字段(MAV_SEVERITY枚举)取值一致,因此该字段可被地面站直接用于告警颜色分级与弹窗提示。
队列设计:ORB_QUEUE_LENGTH = 8
ORB_QUEUE_LENGTH = 8意味着该主题使用容量为 8 的 uORB 队列(queue),而非单槽 topic。这一设计的直接价值在于:
- 允许短暂突发:当短时间内连续发布多条日志(如启动阶段密集的初始化告警)时,队列可缓存最多 8 条未消费消息,避免消息丢失;
- 容忍消费延迟:STATUSTEXT 流按"拉取"节奏消费(仅在 GCS 连接且有剩余发送带宽时读取),队列为这种异步节奏提供了缓冲。
从源码结构看,消费端 STATUSTEXT.hpp 使用while (_mavlink_log_sub.updated() && ...)循环排空队列,并通过get_last_generation()检测是否发生队列溢出丢弃(若 generation 跳变则通过 perf counter"STATUSTEXT missed messages"计数并打印channel %d has missed ...调试信息)。因此,超过 8 条/轮的突发日志仍可能被丢弃,发布方不应依赖该队列做可靠传输。
发布端:mavlink_log_xxx() 宏与 mavlink_vasprintf 实现
所有机载模块通过 src/lib/systemlib/mavlink_log.h 提供的四个便捷宏发布日志,每个宏同时完成两件事:发布 uORB 消息 + 打印到机载控制台:
#define mavlink_log_info(_pub, _text, ...) \ do { \ mavlink_vasprintf(_MSG_PRIO_INFO, _pub, _text, ##__VA_ARGS__); \ PX4_INFO(_text, ##__VA_ARGS__); \ } while(0); #define mavlink_log_warning(_pub, _text, ...) // _MSG_PRIO_WARNING + PX4_WARN #define mavlink_log_emergency(_pub, _text, ...) // _MSG_PRIO_EMERGENCY + PX4_ERR #define mavlink_log_critical(_pub, _text, ...) // _MSG_PRIO_CRITICAL + PX4_WARN底层核心函数mavlink_vasprintf()定义于 src/lib/systemlib/mavlink_log.cpp:
__EXPORT void mavlink_vasprintf(int severity, orb_advert_t *mavlink_log_pub, const char *fmt, ...) { if (!fmt || mavlink_log_pub == nullptr) { return; } mavlink_log_s log_msg; log_msg.severity = severity; log_msg.timestamp = hrt_absolute_time(); va_list ap; va_start(ap, fmt); vsnprintf((char *)log_msg.text, sizeof(log_msg.text), fmt, ap); va_end(ap); if (*mavlink_log_pub != nullptr) { orb_publish(ORB_ID(mavlink_log), *mavlink_log_pub, &log_msg); } else { *mavlink_log_pub = orb_advertise(ORB_ID(mavlink_log), &log_msg); } }实现要点:
- 字段填充:
severity直接来自宏传入的优先级常量;timestamp使用hrt_absolute_time()(硬件实时时钟,微秒级);text经vsnprintf格式化并受sizeof(log_msg.text)(127 字节)硬性截断,杜绝缓冲区溢出; - 惰性发布(lazy advertising):首次调用时
orb_advertise()创建主题,后续复用同一个orb_advert_t *指针调用orb_publish()——这正是所有调用方(如 mavlink_mission.cpp、mavlink_parameters.cpp、CollisionPrevention.cpp 等)都需要在类中保存orb_advert_t _mavlink_log_pub{nullptr}成员的原因。
实践示例:在模块中发布日志
参考 mavlink_main.cpp 的用法,任何模块中可按如下模式发布:
#include <lib/systemlib/mavlink_log.h> // 成员变量:orb_advert_t _mavlink_log_pub{nullptr}; mavlink_log_info(&_mavlink_log_pub, "Enable transmitting with IRIDIUM mavlink on device %s\t", _device_name); mavlink_log_critical(&_mavlink_log_pub, "SET_POSITION_TARGET_LOCAL_NED coordinate frame %" PRIu8 " unsupported\t", ...);注意三个细节:
- 宏是可变参数风格,用法与
printf一致,%s、%d、PRIu8等格式符均可使用; - 文本尾部惯用
\t结尾,这是 PX4 日志约定的分隔符,便于地面站/控制台解析; - 宏同时输出到控制台(
PX4_INFO/PX4_WARN/PX4_ERR),因此不要重复调用printf以免日志重复。
消费端:STATUSTEXT 流将 uORB 消息桥接为 MAVLink 消息
机载侧的mavlink_log主题最终由 MAVLink 模块的STATUSTEXT 流(src/modules/mavlink/streams/STATUSTEXT.hpp)消费并转换为 MAVLinkSTATUSTEXT消息发送至地面站。关键逻辑:
- 仅向 GCS 发送:
send()首先检查_mavlink->is_gcs_connected(),未连接地面站时直接跳过,避免浪费遥测带宽(见 STATUSTEXT.hpp); - 陈旧消息过滤:通过
hrt_elapsed_time(&mavlink_log.timestamp) < 5_s丢弃超过 5 秒的积压消息,防止把过期状态发给地面站(STATUSTEXT.hpp); - 文本分片(chunking):MAVLink
STATUSTEXT的text字段仅 50 字节,而 uORB 消息text最大 127 字节,因此发送时按max_chunk_size = sizeof(msg.text)(即 50 字节)循环切分,并通过chunk_seq序号标识分片、msg.id标识同一条日志,接收端可据此重组(STATUSTEXT.hpp); - 字段映射:
msg.severity = mavlink_log.severity直接透传,保证地面站能按紧急程度分级显示。
这也是MAVLINK_LOG_MAXLEN(50 字节)这一建议上限的由来:超过 50 字节的文本会被切成多片 STATUSTEXT 消息发送,虽然 PX4 与主流地面站均支持重组,但短消息可减少分片、降低误码风险。
重要区分:mavlink_log 主题 ≠ MAVLink LOG_* 文件传输协议
MavlinkLog(uORB 主题mavlink_log)负责文本日志的实时上行(机载 → 地面站显示),而仓库中 src/modules/mavlink/mavlink_log_handler.h 与 mavlink_log_handler.cpp 中的MavlinkLogHandler类处理的是另一套东西——MAVLinkLOG_REQUEST_LIST/LOG_REQUEST_DATA/LOG_REQUEST_END/LOG_ERASE协议,即地面站下载 ULog 日志文件的流程(对应 mavlink_receiver.cpp 的handle_message()与 mavlink_receiver.cpp 的send()调用)。
两者虽然都含"Log"字样且同属 MAVLink 模块,但定位完全不同:
| 维度 | MavlinkLog(uORB 主题) | MavlinkLogHandler(LOG_* 协议) |
|---|---|---|
| 传输对象 | 短文本日志(≤127 字节) | 飞行日志文件(ULog) |
| 方向 | 机载 → 地面站(实时) | 地面站请求 → 机载(文件块下载) |
| 对应 MAVLink 消息 | STATUSTEXT | LOG_ENTRY/LOG_DATA/LOG_REQUEST_* |
| 底层载体 | uORB 主题mavlink_log | 状态机(Idle/Listing/SendingData)直接读写 SD 卡文件 |
阅读源码时切勿混淆:修改日志文本格式应关注MavlinkLog.msg与 mavlink_log.cpp,而涉及"通过地面站导出日志文件"则需查看mavlink_log_handler.cpp的create_log_list_file()、log_entry_from_id()等实现。
总结
MavlinkLog消息以极简的三字段结构(时间戳 + 文本 + 级别)构成了 PX4 机载文本日志的公共总线:任何模块通过mavlink_log_info/warning/critical/emergency宏即可发布(src/lib/systemlib/mavlink_log.h),消息进入容量为 8 的 uORB 队列,由 STATUSTEXT 流在 GCS 连接时取出、过滤陈旧项、按 50 字节分片后以 MAVLinkSTATUSTEXT送达地面站(src/modules/mavlink/streams/STATUSTEXT.hpp)。理解这一链路,无论是对自定义模块输出诊断信息,还是排查地面站日志缺失(队列溢出、陈旧丢弃、GCS 未连接),都能精准定位到对应环节。
- 嵌入式
- 物联网
- 机器人
- 自动驾驶
- 智能硬件
【免费下载链接】PX4-Autopilot
PX4 Autopilot Software
相关推荐
Sherlock 用户名搜索完整入门指南:5 分钟查遍 400+ 社交平台
Sherlock 用户名搜索完整入门指南:5 分钟查遍 400+ 社交平台 Sherlock 是一款开源的用户名搜索工具:输入一个用户名,它会自动在 GitHu
嵌入式物联网机器人自动驾驶智能硬件PX4 CameraCapture uORB 消息解析:从相机触发反馈到地理标记的完整数据链路
PX4 CameraCapture uORB 消息解析:从相机触发反馈到地理标记的完整数据链路 CameraCapture 是 PX4 飞行控制栈中用于描述"一
嵌入式物联网机器人自动驾驶智能硬件Mac 菜单栏管理工具 Ice:隐藏排序菜单图标与自定义外观的完整指南
Mac 菜单栏管理工具 Ice:隐藏排序菜单图标与自定义外观的完整指南 你的 Mac 顶栏挤满了各种图标,找电池或网络状态要在十几个小图标里逐个辨认。Ice 是
嵌入式物联网机器人自动驾驶智能硬件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考