无人机PX4飞控 | PX4源码添加自定义uORB消息并保存到日志
PX4源码添加自定义uORB消息并保存到日志
0 前言
PX4的内部通信机制主要依赖于uORB(Micro Object Request Broker),这是一种跨进程的通信机制,一种轻量级的中间件,用于在PX4飞控系统的各个模块之间进行高效的数据交换,它通过发布-订阅(publish/subscribe)模式,实现了不同模块之间的异步通信。

uORB还允许开发者自定义新话题,首先需要创建一个新的.msg文件,将文件名添加到msg/CMakeLists.txt中,之后进行编译,来生成成对应的C++代码及.h头文件,然后在使用该话题的地方包含该头文件即可。
本篇文章介绍添加uORB消息具体方法,并将该消息记录与日志中。
1 添加uORB消息方法
第一步:添加对应的msg文件
PX4原定义好的msg文件都在PX4-Autopilot/msg 文件夹下面,已经有非常多

打开飞机的位置消息文件 vehicle_local_position.msg ,作为参考,可以看到里面有很多的内容,作为总结如下
定义的变量类型 有:
- bool
- char
- float32 / float64
- uint8 / uint16 / uint64
- int8 /int16 /int32
相关的类型定义在 px_generate_uorb_topic_helper.py 文件中

[!NOTE]
也可以定义对应类型的向量,例如: float32[3]
msg文件最后两行还可以定义本msg的ID
例如vehicle_local_position.msg的 设置ID如下

[!NOTE]
一个uORB消息类型可以定义多个不同名字的msg ID ,但是不同的uORB消息类型不可以定义相同名字的msg ID。
第二步:将msg文件名添加到CMakeLists.txt 文件中
在编写好 **.msg 文件后,需要将该文件的名字添加到PX4-Autopilot/msg/CMakeLists.txt 文件中
这样系统就将**.msg文件
自动编译生成对应的**.h文件了
添加到39行那个set函数里,一般加到最下面一个

第三步:引用头文件
在需要引用的头文件中加入uORB相关的头文件
通常一般需要引用的有下面几个
#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionCallback.hpp>
然后就是头文件引用对应msg生成的头文件 ,前面的路径一般是uORB/topics/ 。例如:
#include <uORB/topics/**.h>
至此添加一个uORB消息类型即完成了!下面则是使用uORB消息的方法。
第四步:uORB消息的订阅
订阅的声明举个例子 如下:
uORB::Subscription _vehicle_land_detected_sub{ORB_ID(vehicle_land_detected)};
- uORB::Subscription 就是声明一个uORB订阅类型
- _vehicle_land_detected_sub 订阅变量的名字
- ORB_ID(vehicle_land_detected) 订阅的uORB的ID,如果在msg文件中没有定义ID,那么msg文件的名字就是ID,也可以通过#TOPICS 来设置对应的ID ,一个msg可以设置多个不同的ID
获取最新的已订阅的uORB消息,伪代码如下:
vehicle_land_detected_s 变量名a
if(_vehicle_land_detected_sub.update(&变量名a))
{具体操作
}
第五步:uORB消息的发布
发布的声明举个例子 如下:
uORB::PublicationData<takeoff_status_s> _takeoff_status_pub{ORB_ID(takeoff_status)};
- uORB::PublicationData ——声明一个uORB发布类型
- <takeoff_status_s> ——发布消息的结构体,一般结构体的名字就是msg文件的名字
- _takeoff_status_pub ——uORB发布类型的变量名称
- ORB_ID(takeoff_status) ——发布的订阅的uORB的ID
发布指定的uORB消息,伪代码如下:
takeoff_status_s 变量名a
变量名a 各成员变量赋值
_takeoff_status_pub.publish(变量名a);
第六步:将uORB消息记录在日志中
如果希望将该消息记录在日志中
那么需要打开 PX4-Autopilot/src/modules/logger/logged_topics.cpp 文件
文件中的 void LoggedTopics::add_default_topics() 函数就是 添加记录日志的topic的
可以看到原本的有这样几个功能函数:

它们用于控制日志记录中的主题的功能区别是:
- add_topic —— 函数用于将指定的uORB主题添加到日志记录中。这意味着每当该主题的数据更新时,都会被记录到日志文件中。带间隔参数:
add_topic(topic_name, interval_ms),其中interval_ms指定记录间隔(毫秒),例如,add_topic("demo_uorb", 100)表示每100毫秒记录一次该主题的数据; - add_optional_topic——函数用于添加一个可选的主题。与
add_topic()不同,该函数允许用户选择是否启用该主题的日志记录。用户可以根据需要手动开启或关闭该主题的日志记录。 - add_optional_topic_multi ——与
add_optional_topic()类似,但允许同时添加多个主题。这使得可以一次性配置多个可选主题的日志记录。
2 实践
2.1 代码实现
PX4-Autopilot/msg 文件夹下面,新建一个文件,文件命名为:jone_demo.msg
在 jone_demo.msg 文件中定义四个参数:
uint64 timestamp # time since system start (microseconds)bool enable
float32 acc_norm
float32[3] acc
编写好jone_demo.msg文件后,
将 jone_demo.msg 文件的名字添加到PX4-Autopilot/msg/CMakeLists.txt 文件中,这样系统就将jone_demo.msg文件自动编译生成对应的jone_demo.h文件了
添加到39行那个set函数里,一般加到最下面一个

先编译一下
make px4_sitl_default
这样就生成了对应的jone_demo.h ,路径是:build/px4_sitil_default/uORB/topics

在之前添加的模块jone_demo中的JoneDemo.hpp 头文件中加入uORB相关的头文件
通常一般需要引用的有下面几个
#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionCallback.hpp>
jone_demo.msg 生成的头文件为:jone_demo.h
#include <uORB/topics/jone_demo.h>
下面订阅sensor_combined的uORB消息,获取其中的三轴加速度信息
在JoneDemo.hpp 中类的私有变量区加入
uORB::Subscription _sensor_combined_sub{ORB_ID(sensor_combined)};
去订阅传感器信息的uORB消息,所以前面要加上该消息的引用
#include <uORB/topics/sensor_combined.h>
在JoneDemo.hpp 中类的私有变量区加入
uORB::PublicationData<jone_demo_s> _jone_demo_pub{ORB_ID(jone_demo)};
可以打开jone_demo.h文件,看下jone_demo_s 结构体的定义

下面在cpp文件中进行具体的uORB消息订阅与发布操作
在JoneDemo.cpp 的Run()函数中加入
sensor_combined_s imu;if(_sensor_combined_sub.update(&imu)){jone_demo_s jone;jone.timestamp = hrt_absolute_time();//获得系统的绝对时间jone.enable = true;jone.acc[0] = accelerometer_m_s2[0];jone.acc[1] = accelerometer_m_s2[1];jone.acc[2] = accelerometer_m_s2[2];jone.acc_norm = sqrtf(jone.acc[0]*jone.acc[0]+jone.acc[1]*jone.acc[1]+jone.acc[2]*jone.acc[2]);_jone_demo_pub.publish(jone);}
通过上面的代码,在检测到sensor_combined_s消息更新时,那么就会在jone_demo_s 变量中 赋值加速度三轴的值,并且计算模长,然后发布jone_demo_s变量的uORB消息。
将jone_demo消息添加在日志记录中
打开 PX4-Autopilot/src/modules/logger/logged_topics.cpp 文件
文件中的 void LoggedTopics::add_default_topics() 函数就是 添加记录日志的topic的
在add_default_topics() 函数里加入:
add_topic("jone_demo");
2.2 测试
编译下看有没有问题
make px4 default_sitl_default
没问题则可以运行下
make px4 default_sitl_default gazebo
控制飞机起飞,飞一小段时间
下载日志
点QGC的这个图标

在弹窗选择分析工具

选择日志下载界面

一开始没有日志,需要点击刷新

找到对应的日期日志,点击下载即可

完成后,则在对应的选择的路径下面,生成了需要的日志文件

log_5说明下载的ID 5 的日志,然后是时间
下面通过plotjudge数据分析工具,来看日志里记录的uORB消息
在里面找到我们记录的对应的uORB消息的ID:jone_demo
点开是我们声明的对应的消息体

对应的数据曲线

相关文章:
无人机PX4飞控 | PX4源码添加自定义uORB消息并保存到日志
PX4源码添加自定义uORB消息并保存到日志 0 前言 PX4的内部通信机制主要依赖于uORB(Micro Object Request Broker),这是一种跨进程的通信机制,一种轻量级的中间件,用于在PX4飞控系统的各个模块之间进行高效的数据交换…...
HTMLCSS :下雪了
这段代码创建了一个动态的雪花飘落加载动画,通过 CSS 技术实现了雪花的下落和消失效果,为页面添加了视觉吸引力和动态感。 大家复制代码时,可能会因格式转换出现错乱,导致样式失效。建议先少量复制代码进行测试,若未能…...
如何处理 Typecho Joe 主题被抄袭或盗版的问题
在开源社区中,版权保护是一个非常重要的话题。如果你发现自己的主题(如 Joe 主题)被其他主题(如子比主题)抄袭或盗版,你可以采取以下措施来维护自己的权益。 一、确认侵权行为 在采取任何行动之前…...
利用Vue和javascript分别编写一个“Hello World”的定时更新
目录 一、利用Vue编写一个“Hello World”的定时更新(1)vue编码在Html文件中(2)vue编码在js文件中 二、利用javascript编写一个“Hello World”的定时更新 一、利用Vue编写一个“Hello World”的定时更新 (1ÿ…...
volatile变量需要减少读取次数吗
问题说明 本人在前期读Netty源码时看到这样一段源码和注释: private boolean invokeHandler() {// Store in local variable to reduce volatile reads.int handlerState this.handlerState;return handlerState ADD_COMPLETE || (!ordered && handlerS…...
bootstrap.yml文件未自动加载问题解决方案
在添加bootstrap.yml文件后,程序未自动扫描到,即图标是这样的: 查了一些资料,是缺少bootstrap相关依赖,虽然已经添加了spring-cloud-context依赖,但是这个依赖并未引入bootstrap依赖,可能是版本问题,需要手动引入 <dependency><groupId>org.springframework.cloud&…...
编程AI深度实战:AI编程工具哪个好? Copilot vs Cursor vs Cody vs Supermaven vs Aider
系列文章: 编程AI深度实战:私有模型deep seek r1,必会ollama-CSDN博客 编程AI深度实战:自己的AI,必会LangChain-CSDN博客 编程AI深度实战:给vim装上AI-CSDN博客 编程AI深度实战:火的编程AI,都在用语法树(AST)-CSDN博客 编程AI深度实战:让verilog不再是 AI …...
前端知识速记--CSS篇:display
前端知识速记–CSS篇:display 一、什么是 display 属性? display 属性用于指定一个元素如何被显示在网页上。它不仅影响元素的显示形式,还对元素的布局、结构以及与其他元素之间的关系产生重要影响。 二、常用 display 属性值 1. block …...
51单片机 01 LED
一、点亮一个LED 在STC-ISP中单片机型号选择 STC89C52RC/LE52RC;如果没有找到hex文件(在objects文件夹下),在keil中options for target-output- 勾选 create hex file。 如果要修改编程 :重新编译-下载/编程-单片机重…...
WPF进阶 | WPF 动画特效揭秘:实现炫酷的界面交互效果
WPF进阶 | WPF 动画特效揭秘:实现炫酷的界面交互效果 前言一、WPF 动画基础概念1.1 什么是 WPF 动画1.2 动画的基本类型1.3 动画的核心元素 二、线性动画详解2.1 DoubleAnimation 的使用2.2 ColorAnimation 实现颜色渐变 三、关键帧动画深入3.1 DoubleAnimationUsin…...
分页按钮功能
前言 在前端开发中,分页功能是一个常见的需求,特别是当需要展示大量数据时,它能有效提升用户体验。该文章结合运用了HTML,CSS,JS实现网页的分页按钮功能,并且可以选择每页显示的条数试试更新总页数及显示当…...
数据分析系列--⑦RapidMiner模型评价(基于泰坦尼克号案例含数据集)
一、前提 二、模型评估 1.改造⑥ 2.Cross Validation算子说明 2.1Cross Validation 的作用 2.1.1 模型评估 2.1.2 减少过拟合 2.1.3 数据利用 2.2 Cross Validation 的工作原理 2.2.1 数据分割 2.2.2 迭代训练与测试 2.2.3 结果汇总 …...
集合通讯概览
集合通信概览 (1)通信的算法 是根据通讯的链路组成的 (2)因为通信链路 跟硬件强相关,所以每个CCL的库都不一样 芯片与芯片、不同U之间是怎么通信的 多卡训练:多维并行(xxx并行在上一期已经讲述…...
【FreeRTOS 教程 八】直达任务通知
目录 一、FreeRTOS 直达任务通知: (1)直达任务通知基本介绍: (2)更新目标通知的值: (3)性能优势和使用限制: 二、直达任务通知 API: &#…...
Ubuntu 18.04安装Emacs 26.2问题解决
个人博客地址:Ubuntu 18.04安装Emacs 26.2问题解决 | 一张假钞的真实世界 no X development libraries were found checking for X... no checking for X... true configure: error: You seem to be running X, but no X development libraries were found. You …...
nodejs:js-mdict 的下载、安装、测试、build
js-mdict 项目的目录结构:js-mdict 项目教程 js-mdict 下载地址: js-mdict-master.zip 先解压到 D:\Source\ js-mdict 6.0.2 用了 ts (TypeScript) 和 Jest,增加了应用开发的难度,因为先要了解 ts 和 Jest。 参阅:测试与开发&a…...
CSS关系选择器详解
CSS关系选择器详解 学习前提什么是关系选择器?后代选择器(Descendant Combinator)语法示例注意事项 子代选择器(Child Combinator)语法示例注意事项 邻接兄弟选择器(Adjacent Sibling Combinator࿰…...
Python在线编辑器
from flask import Flask, render_template, request, jsonify import sys from io import StringIO import contextlib import subprocess import importlib import threading import time import ast import reapp Flask(__name__)RESTRICTED_PACKAGES {tkinter: 抱歉&…...
蓝桥杯备考:高精度算法之除法
我们除法的高精度其实也不完全是高精度,而是一个高精度作被除数除以一个低精度 模拟我们的小学除法 由于题目中我们的除数最大是1e9,当它真正是1e9的时候,t是有可能超过1e9的,所以要用long long...
笔试-业务逻辑4
应用 小明在玩一个数字加减游戏,输入4个正整数:s、t、a、b,其中s>1,b<105,a!b。只使用加法或者减法,使得st。 每回合,小明用当前的数字,加上或减去一个数字;目前有…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...
Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...
路由基础-路由表
本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中,往往存在多个不同的IP网段,数据在不同的IP网段之间交互是需要借助三层设备的,这些设备具备路由能力,能够实现数据的跨网段转发。 路由是数据通信网络中最基…...
