| |
|
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
| -> 嵌入式 -> PX4-3-uORB -> 正文阅读 |
|
|
[嵌入式]PX4-3-uORB |
|
uORB(Micro Object Request ?Broker,微对象请求代理器)是PX4中非常重要且关键的一个模块,用于各个模块之间的数据交互。实际上uORB是一套跨「 uORB多个进程通过共享内存的方式,进行数据交互和共享。进程通过命名的「 由于PX4代码更新很快,uORB模块在各个版本中可能有所不同,如最新发布的1.12版本就有比较大的变化,将uORB模块由modules中移动到了plorforms/common中,uORB的定位有所改变,上升到了系统基础组件,不过这里还是以1.11.3版本这个去年发布的稳定版本为例讲解。 这一篇的内容比较长,需要花一些时间阅读,建议可以先大致阅读,如果对uORB的机制感兴趣可以收藏一下,后面结合实际代码阅读。 接口uORB的外部接口提供了C和C++两种接口,应用程序可以使用C编写也可以使用C++ C接口C接口定义在 src/modules/uORB/uORB.h // 向消息网络公告一个发布者,它初始化这个topic公告,在/obj目录下创建一个topic节点(如果需要)并发布初始数据 orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data, unsigned int queue_size = 1) // 向消息网络公告一个发布者,它初始化这个topic公告,在/obj目录下创建一个topic节点(如果需要)并发布初始数据,multi可用于创建同一topic的多个独立实例(每个实例都有自己的缓冲区)。这对于发布同一topic的多个发布者非常有用。订阅人然后订阅所有实例并选择要使用的源。 orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, ORB_PRIO priority,unsigned int queue_size = 1); // 取消 int orb_unadvertise(orb_advert_t handle); // 向topic发布一个新数据 int ?orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data); // 订阅一个topic int ?orb_subscribe(const struct orb_metadata *meta); // 一个topic存在多个发布者时,订阅指定实例 int ?orb_subscribe_multi(const struct orb_metadata *meta, unsigned instance); // 取消订阅一个topic int ?orb_unsubscribe(int handle); // 检测一个topic是否有数据更新 int ?orb_check(int handle, bool *updated); // 检查一个topic是否存在并且有数据发布 int ?orb_exists(const struct orb_metadata *meta, int instance); // 返回topic的优先级 int ?orb_priority(int handle, enum ORB_PRIO *priority); // 设置订阅topic更新的最小间隔,可用于防止订阅者过快的更新数据 int ?orb_set_interval(int handle, unsigned interval); // 获取订阅topic更新的最小间隔 int orb_get_interval(int handle, unsigned *interval); C++接口C++的接口就简单很多,只需要new 对应的类就可以了 // 定义消息发布者
uORB::Publication<xxx_topic_s> xxx_topic_pub{ORB_ID(xxx_topic)};
// 定义消息订阅者
uORB::Subscription xxx_topic_sub{ORB_ID(xxx_topic)};
// 消息发布
xxx_topic_pub..publish(data);
// 消息订阅
if (xxx_topic_sub.updated()) {
xxx_topic_sub.copy(&data);
}
添加新的消息添加消息非常简单,在/msg目录下创建一个新的msg文件,然后在msg/CMakeLists.txt文件中添加新增加的文件即可 内部机制自动生成代码PX4使用了大量自动代码生成方法,减少用户的重复性代码编辑,比如Mavlink、uavcan、param的消息创建以及部分gazebo模型文件的生成。 uORB的代码生成脚本位于 msg/tools,使用python进行代码生成。 生成的文件在 build/xxx/msg/tmp目录下可以找到,包括一个头文件目录和一个cpp文件目录,阅读创建的文件内容可以大概了解主要创建了什么内容。以airspeed文件为例,airspeed.h文件中 //定义了消息的结构体
#ifdef __cplusplus
struct __EXPORT airspeed_s {
#else
struct airspeed_s {
#endif
uint64_t timestamp;
float indicated_airspeed_m_s;
float true_airspeed_m_s;
float air_temperature_celsius;
float confidence;
#ifdef __cplusplus
#endif
};
// 申明消息的uORB元数据,用于uORB通过ORB_ID(_name)定位消息
ORB_DECLARE(airspeed);
airspeed.cpp文件中 constexpr char __orb_airspeed_fields[] = "uint64_t timestamp;float indicated_airspeed_m_s;float true_airspeed_m_s;float air_temperature_celsius;float confidence;"; // 定义消息的uORB元数据,对应头文件中的ORB_DECLARE(airspeed); ORB_DEFINE(airspeed, struct airspeed_s, 24, __orb_airspeed_fields, static_cast<uint8_t>(ORB_ID::airspeed)); ? 消息公告机制消息是如何发布到uORB的呢,我们来看看消息advertise都做了哪些事情 // 消息公告的c接口
orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)
// ->
// 调用uORB::Manager类的消息公告函数
uORB::Manager::get_instance()->orb_advertise(meta, data);
// ->
// 多消息实例公告函数的复用接口
orb_advert_t uORB::Manager::orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance,ORB_PRIO priority, unsigned int queue_size)
// ->
? ?// open消息节点
? ?int fd = node_open(meta, true, instance, priority);
?
? ? ? ?// ->
? ? ? ?// 调用消息节点管理类uORB::DeviceMaster的消息公告接口
? ? ? ?ret = _device_master->advertise(meta, advertiser, instance, priority);
?
? ? ? ? ? ?// ->
? ? ? ? ? ?// 创建消息节点,这个节点类定义了消息的主要读写方法
? uORB::DeviceNode *node = new uORB::DeviceNode(meta, group_tries, devpath, priority);
?
? ?// 设置消息buffer的大小
? ?int result = px4_ioctl(fd, ORBIOCSETQUEUESIZE, (unsigned long)queue_size);
?
? ?// 发布消息以初始化消息对象
? ?result = orb_publish(meta, advertiser, data);
?
? ? ? ?// ->
? ? ? ?// 调用消息节点类的消息发布接口
? ? ? ?uORB::DeviceNode::publish(meta, handle, data);
?
? ? ? ? ? ?// ->
? ? ? ? ? ?// 调用消息写入接口
? ? ? ? ? ?ret = devnode->write(nullptr, (const char *)data, meta->o_size);
?
? ? ? ? ? ? ? ?// ->
? ? ? ? ? ? ? ?// 申请消息对象内存
? if (nullptr == _data) {
? _data = new uint8_t[_meta->o_size * _queue_size];
? }
? ? ? ? ? ? ?
我们将消息公告接口的主要调用过程整理了一下,梳理了一下类的调用关系,消息公告主要完成:
类的调用层级为 uORB::Manager ? -> uORB::DeviceMaster ? ? ? -> uORB::DeviceNode ? ? ? ? ? -> cdev::CDev 消息发布和订阅的机制梳理了消息公告的过程,uORB的内部机制就有一个雏形了,其他的接口也都封装在这几个类中 消息的主要操作方法主要封装在uORB::DeviceNode类中,主要就是消息的读写接口 这里不过多展开,大家可以结合源码分析几个接口函数 消息回调函数的机制消息订阅有两种机制,异步订阅和消息回调
我们看看这个消息回调类都做了哪些事情 类的调用层级为 SubscriptionCallbackWorkItem
-> SubscriptionCallback
-> SubscriptionInterval
在registerCallback函数中,任务类将回调函数注册到消息节点中,在消息发生更新时会调用这个callback方法 而调用的方法为 // src/modules/uORB/SubscriptionCallback.hpp
// SubscriptionCallbackWorkItem
void call() override
{
// schedule immediately if updated (queue depth or subscription interval)
if ((_required_updates == 0)
|| (_subscription.get_node()->published_message_count() >= (_subscription.get_last_generation() + _required_updates))) {
if (updated()) {
_work_item->ScheduleNow();
}
}
}
通过 _work_item->ScheduleNow() 方法进行任务的重调度 这里涉及 px4::WorkItem 类,PX4是如何通过ScheduleNow方法调度 VtolAttitudeControl::Run()这个run函数的呢 这个我们在下一个分享 PX4的任务调度 中分析。 往期分享: PX4-2-系统架构浅析_AcmeUav的博客-CSDN博客 工欲善其事-3-整理技术笔记(gitbook)_AcmeUav的博客-CSDN博客 使用3D地面站(AcmeGCS)的编队飞行_AcmeUav的博客-CSDN博客 这个博客转载自我个人的微信公众号,这里会不定期更新一些我整理的无人机相关知识和个人设计,欢迎添加关注。
? ? |
|
|
| 嵌入式 最新文章 |
| 基于高精度单片机开发红外测温仪方案 |
| 89C51单片机与DAC0832 |
| 基于51单片机宠物自动投料喂食器控制系统仿 |
| 《痞子衡嵌入式半月刊》 第 68 期 |
| 多思计组实验实验七 简单模型机实验 |
| CSC7720 |
| 启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
| STM32初探 |
| STM32 总结 |
| 【STM32】CubeMX例程四---定时器中断(附工 |
|
|
| 上一篇文章 下一篇文章 查看所有文章 |
|
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
| 360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年10日历 | -2025/10/22 16:01:25- |
|
| 网站联系: qq:121756557 email:121756557@qq.com IT数码 |