当前位置: 首页 > java >正文

【NextPilot日志移植】logged_topics.cpp解析

📘 PX4 Logger 模块注册 uORB 主题、实际订阅与数据采集流程

🧭 目的与背景

在 PX4 飞控中,日志记录模块 logger 需要记录多个 uORB 主题的数据(如 IMU、GPS、姿态等)。为了系统统一管理这些记录需求,logger 提供了 add_topic() 接口用于“登记想记录的 uORB 主题”,实现模块内部集中管理与订阅。


🧩 logger::add_topic() 的本质作用

topics.logger::add_topic("sensor_accel", 100, TopicSubscriber::IntervalMeasureMode::Exact, 0);
✅ 实际作用
  • 向 logger 模块登记想要记录的 uORB 主题;
  • 记录这些主题的名称、记录频率、测量模式等信息;
  • 后续由 logger 内部统一处理订阅与记录。
❌ 不包括的操作
  • 不等同于调用 orb_subscribe(),不会立即订阅;
  • 不等同于调用 orb_advertise(),不会注册/创建新主题;
  • 主题必须已经存在于系统中并由其他模块发布。

🗂️ 参数详解

参数含义说明
nameuORB 主题名(如 "sensor_accel"
interval_ms记录频率,单位 ms(如 100 表示每 100 ms 记录一次)
measure_mode测量模式,如 Exact 表示严格按周期记录
instance主题实例号(用于处理多个 IMU 等多实例情况)

🧱 logger 模块的内部结构

  1. 调用 add_topic()
    把主题信息写入 TopicSubscriber 对象的队列或映射表中。

  2. 启动 logger 时统一订阅
    logger 在初始化或任务启动时遍历所有已登记主题,调用 orb_subscribe() 实际订阅。

  3. 定时记录数据
    logger 根据每个主题的 interval_ms 周期读取数据并写入日志文件(通常是 ulog 格式)。


🧮 简要流程图(逻辑)

代码中 add_topic()↓
记录待订阅主题信息↓
logger 启动时统一 orb_subscribe()↓
定时读取并写入日志文件

🧾 示例:logger_main.cpp 中注册主题

// 典型注册方式
topics.logger::add_topic("vehicle_attitude", 50); // 每 50 ms 记录一次姿态
topics.logger::add_topic("sensor_gyro", 100);     // 每 100 ms 记录一次陀螺仪

🧠 延伸理解:为什么不直接订阅?

如果每个地方都调用 orb_subscribe()

  • 会造成重复订阅、资源浪费;
  • 不好统一管理日志频率;
  • 无法自动匹配多实例等情况。

logger 统一订阅后可:

  • 动态调整频率;
  • 控制记录启停;
  • 集中写入磁盘。

🧩 回顾:add_topic() 只是登记

调用 logger::add_topic("topic_name", ...) 后,主题信息被保存在 logger 的内部容器中(如 TopicSubscriber 列表),此时并未真正执行订阅与数据读取操作。


🚀 真正订阅:在 logger::initialize_topics() 中统一完成

✅ 发生时机

logger 启动后,在主循环启动前调用:

bool Logger::initialize_topics()
✅ 核心代码流程
for (TopicSubscriber &sub : _subscriptions) {sub.subscribe();  // 真正调用 orb_subscribe()
}

这里 TopicSubscriber 是对每个 add_topic() 的封装对象,subscribe() 方法内部包含:

_orb_sub_fd = orb_subscribe_multi(_topic_name, _instance);

✅ 此时才真正使用 orb_subscribe 完成对每个 uORB 主题的订阅!


📦 数据采集:在 logger 主循环中周期读取(调用 orb_copy()

核心代码位置

文件路径:

src/modules/logger/logger.cpp

函数位置:

void Logger::run()
主循环中采集逻辑:
while (!should_exit()) {for (TopicSubscriber &sub : _subscriptions) {if (sub.should_copy()) {sub.copy();}}
}

🧠 详细解释:sub.copy() 内部做了什么?

bool TopicSubscriber::copy()
{orb_copy(_topic_id, _orb_sub_fd, &_data);  // 读取最新数据_log_writer.write(_data);                  // 写入日志缓冲区return true;
}

✅ 每次循环判断是否到了记录周期(通过 should_copy()),如果到了,就执行 orb_copy() 把数据读出来,并调用 ulog_stream 写入磁盘日志文件中。


🗂️ 总结:logger 记录数据的完整生命周期

add_topic()             → 只是登记主题信息
initialize_topics()     → 统一 orb_subscribe() 实际订阅
Logger::run()           → 周期判断是否采样
TopicSubscriber::copy() → orb_copy() + 写入日志

🧪 补充调试建议

可通过日志或断点验证以下内容:

  • logger::initialize_topics() 中的订阅是否成功(检查 _orb_sub_fd 是否有效);
  • logger::run() 中是否触发 copy()
  • orb_copy() 返回是否正常;
  • ulog 日志中是否能看到该主题。
http://www.xdnf.cn/news/4913.html

相关文章:

  • 动态规划之背包问题:组合优化中的经典NP挑战
  • CCDO|企业数字化转型:机制革新与人才培育的双重引擎
  • 在 Ubuntu 上安装并运行 ddns-go 教程
  • 量化交易策略的运行
  • StreamRL:弹性、可扩展、异构的RLHF架构
  • Rust中记录日志:fast_log
  • 第一天——贪心算法——分饼干
  • 【软件设计师:软件】20.软件设计概述
  • Oracle链接服务器导致SQL Server异常终止
  • PHP会话技术
  • 机器学习与深度学习的区别与联系:多角度详细分析
  • Java 模板引擎 Thymeleaf JSP FreeMarker
  • 【物联网】基于树莓派的物联网开发【1】——初识树莓派
  • 塔能工业互联节能方案:数据驱动工业制造绿色转型
  • 遗传算法(GA)
  • MiM: Mask in Mask Self-SupervisedPre-Training for 3D Medical Image Analysis
  • 基于公共卫生大数据收集与智能整合AI平台构建测试:从概念到实践
  • 【C++进阶】第2课—多态
  • 数据统计的意义:钱包余额变动
  • C++八股 —— map/unordered_map
  • 发那科机器人5(异常事件和程序备份加载+ROBOGUIDE离线仿真)
  • 服务器多客户端连接核心要点(1)
  • 计算机视觉】OpenCV项目实战:eye_mouse_movement:基于opencv实战眼睛控制鼠标
  • 【Python】Pycharm中安装库可靠的方法
  • 从AI到新能源:猎板PCB的HDI技术如何定义高端制造新标准?
  • Java设计模式之单例模式:从入门到精通
  • 大数据狙击金融欺诈——技术如何守护交易安全?
  • c++:双向链表容器(std::list)
  • C语言—指针3
  • 集群/微服务/分布式