无人机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飞控系统的各个模块之间进行高效的数据交换…...
【IocDI】_存储Bean的五大类注解及getBean的使用
目录 1. Bean的存储 1.1 类注解 1.1.1 Controller:控制器存储 1.1.2 Service:服务存储 1.1.3 Repository:仓库存储 1.1.4 Component:组件存储 1.1.5 Configuration:配置存储 1.2 五大类注解之间的关系 2. get…...
VLAN 基础 | 不同 VLAN 间通信实验
注:本文为 “ Vlan 间通信” 相关文章合辑。 英文引文,机翻未校。 图片清晰度限于原文图源状态。 未整理去重。 How to Establish Communications between VLANs? 如何在 VLAN 之间建立通信? Posted on November 20, 2015 by RouterSwi…...
GRE阅读双线阅读 --青山学堂GRE全程班 包括 阅读、数学、写作、填空、背单词
新版GRE考试整体结构 section题量时间写作1篇issue30min语文S112道题(7道填空5道阅读)18min数学S112道题21min语文S215道题(7道填空8道阅读)23min数学S215道题26min Tips: 写作结束后,语文和数学的顺序不固定,2中可能: issue -> V ->…...
算法总结-二分查找
文章目录 1.搜索插入位置1.答案2.思路 2.搜索二维矩阵1.答案2.思路 3.寻找峰值1.答案2.思路 4.搜索旋转排序数组1.答案2.思路 5.在排序数组中查找元素的第一个和最后一个位置1.答案2.思路 6.寻找旋转排序数组中的最小值1.答案2.思路 1.搜索插入位置 1.答案 package com.sunxi…...
litemall,又一个小商场系统
litemall Spring Boot后端 Vue管理员前端 微信小程序用户前端 Vue用户移动端 代码地址:litemall: 又一个小商城。 litemall Spring Boot后端 Vue管理员前端 微信小程序用户前端 Vue用户移动端...
5.5.1 面向对象的基本概念
文章目录 基本概念面向对象的5个原则 基本概念 面向对象的方法,特点时其分析与设计无明显界限。虽然在软件开发过程中,用户的需求会经常变化,但客观世界对象间的关系是相对稳定的。对象是基本的运行实体,由数据、操作、对象名组成…...
Java_类加载器
小程一言类加载器的基础双亲委派模型核心思想优势 各类加载器的职责 类加载器的工作流程举例:如何在Java中使用类加载器启动类加载器、扩展类加载器与系统类加载器输出解释自定义类加载器 类加载器与类冲突总结 小程一言 本专栏是对Java知识点的总结。在学习Java的过…...
开源音乐管理软件Melody
本文软件由网友 heqiusheng 推荐。不过好像已经是一年前了 😂 简介 什么是 Melody ? Melody 是你的音乐精灵,旨在帮助你更好地管理音乐。目前的主要能力是帮助你将喜欢的歌曲或者音频上传到音乐平台的云盘。 主要功能包括: 歌曲…...
一、TensorFlow的建模流程
1. 数据准备与预处理: 加载数据:使用内置数据集或自定义数据。 预处理:归一化、调整维度、数据增强。 划分数据集:训练集、验证集、测试集。 转换为Dataset对象:利用tf.data优化数据流水线。 import tensorflow a…...
Vue.js组件开发-实现左侧浮动菜单跟随页面滚动
使用 Vue 实现左侧浮动菜单跟随页面滚动 实现步骤 创建 Vue 项目:使用 Vue CLI 创建一个新的 Vue 项目。设计 HTML 结构:包含一个左侧浮动菜单和一个主要内容区域。编写 CSS 样式:设置菜单的初始样式和滚动时的样式。使用 Vue 的生命周期钩…...
分析哲学:从 语言解剖到 思想澄清的哲学探险
分析哲学:从 语言解剖 到 思想澄清 的哲学探险 第一节:分析哲学的基本概念与公式解释 【通俗讲解,打比方来讲解!】 分析哲学,就像一位 “语言侦探”,专注于 “解剖语言”,揭示我们日常使用的语…...
MySQL 插入数据指南
MySQL 插入数据指南 引言 MySQL 是一款广泛使用的开源关系数据库管理系统,被广泛应用于各种规模的组织中。在数据库管理中,数据的插入是基础操作之一。本文将详细介绍如何在 MySQL 中插入数据,包括插入单条记录和多条记录,以及一…...
寒假刷题Day20
一、80. 删除有序数组中的重复项 II class Solution { public:int removeDuplicates(vector<int>& nums) {int n nums.size();int stackSize 2;for(int i 2; i < n; i){if(nums[i] ! nums[stackSize - 2]){nums[stackSize] nums[i];}}return min(stackSize, …...
鸿蒙物流项目之基础结构
目录: 1、项目结构2、三种包的区别和使用场景3、静态资源的导入4、颜色样式设置5、修改项目名称和图标6、静态包基础目录7、组件的抽离8、在功能模块包里面引用静态资源包的组件 1、项目结构 2、三种包的区别和使用场景 3、静态资源的导入 放在har包中,那…...
[漏洞篇]SQL注入漏洞详解
[漏洞篇]SQL注入漏洞详解 介绍 把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。通过构造恶意的输入,使数据库执行恶意命令,造成数据泄露或者修改内容等,以达到攻击的目的。…...
【最后203篇系列】006 -使用ollama运行deepseek-r1前后端搭建
说明 这块已经不算新内容了,年前搭完了后端(ollama),本来想早点分享的,但是当时的openwebui有点不给力,有些地方不适配,然后配置项找不到。所以前端没搭好,也就不完整:只能通过命令…...
CSS Module 常用笔记
Date: January 30, 2025 CSS 先介绍下普通 CSS,再简明介绍下 css module 的使用 普通 CSS 内联 style 定义: 内联 style 是通过在元素的 style 属性中直接设置 CSS 样式。这种方式允许我们直接在 JSX 中为组件或元素添加样式。 写法: &…...
JDK-1.8.0_432安装(CentOS7)
目录 1、卸载系统自带JDK 2、下载安装包并解压 3、赋予可执行权限 4、设置环境变量 5、刷新环境变量 6、查看JDK版本 1、卸载系统自带JDK # 查询出自带的jdk rpm -qa | grep jdk rpm -qa | grep java # 将上述命令列出的包依次删除 rpm -e --nodeps xxxxxxx 2、下载…...
【Linux】24.进程信号(1)
文章目录 1. 信号入门1.1 进程与信号的相关知识1.2 技术应用角度的信号1.3 注意1.4 信号概念1.5 信号处理常见方式概览 2. 产生信号2.1 通过终端按键产生信号2.2 调用系统函数向进程发信号2.3 由软件条件产生信号2.4 硬件异常产生信号2.5 信号保存 3. 阻塞信号3.1 信号其他相关…...
C++ 字面量深度解析:从基础到实战进阶
在 C 开发中,字面量(Literal)不仅是基础语法的一部分,更是提升代码可读性、安全性和性能的关键工具。本文将深入探讨 C 字面量的高级特性、最新标准支持(C11/14/17/20)以及实际开发中的应用技巧,…...
股票入门知识
股票入门(更适合中国宝宝体制) 股市基础知识 本文介绍了股票的基础知识,股票的分类,各板块发行上市条件,股票代码,交易时间,交易规则,炒股术语,影响股价的因素…...
用Python实现K均值聚类算法
在数据挖掘和机器学习领域,聚类是一种常见的无监督学习方法,用于将数据点划分为不同的组或簇。K均值聚类算法是其中一种简单而有效的聚类算法。今天,我将通过一个具体的Python代码示例,向大家展示如何实现K均值聚类算法࿰…...
Flask代码审计实战
文章目录 Flask代码审计SQL注入命令/代码执行反序列化文件操作XXESSRFXSS其他 审计实战后记reference Flask代码审计 SQL注入 1、正确的使用直白一点就是:使用”逗号”,而不是”百分号” stmt "SELECT * FROM table WHERE id?" connectio…...
Unity 2D实战小游戏开发跳跳鸟 - 跳跳鸟碰撞障碍物逻辑
在有了之前创建的可移动障碍物之后,就可以开始进行跳跳鸟碰撞到障碍物后死亡的逻辑,死亡后会产生一个对应的效果。 跳跳鸟碰撞逻辑 创建Obstacle Tag 首先跳跳鸟在碰撞到障碍物时,我们需要判定碰撞到的是障碍物,可以给障碍物的Prefab预制体添加一个Tag为Obstacle,添加步…...
【玩转 Postman 接口测试与开发2_015】第12章:模拟服务器(Mock servers)在 Postman 中的创建与用法(含完整实测效果图)
《API Testing and Development with Postman》最新第二版封面 文章目录 第十二章 模拟服务器(Mock servers)在 Postman 中的创建与用法1 模拟服务器的概念2 模拟服务器的创建2.1 开启侧边栏2.2 模拟服务器的两种创建方式2.3 私有模拟器的 API 秘钥的用法…...
mysql操作语句与事务
数据库设计范式 数据库设计的三大范式 第一范式(1NF):要求数据库表的每一列都是不可分割的原子数据项,即列中的每个值都应该是单一的、不可分割的实体。例如,如果一个表中的“地址”列包含了省、市、区等多个信息…...
android Camera 的进化
引言 Android 的camera 发展经历了3个阶段 : camera1 -》camera2 -》cameraX。 正文 Camera1 Camera1 的开发中,打开相机,设置参数的过程是同步的,就跟用户实际使用camera的操作步骤一样。但是如果有耗时情况发生时,会…...
ASP.NET Core Filter
目录 什么是Filter? Exception Filter 实现 注意 ActionFilter 注意 案例:自动启用事务的筛选器 事务的使用 TransactionScopeFilter的使用 什么是Filter? 切面编程机制,在ASP.NET Core特定的位置执行我们自定义的代码。…...
Git 的起源与发展
序章:版本控制的前世今生 在软件开发的漫长旅程中,版本控制犹如一位忠诚的伙伴,始终陪伴着开发者们。它的存在,解决了软件开发过程中代码管理的诸多难题,让团队协作更加高效,代码的演进更加有序。 简单来…...
