注:这是看过好多文章总结出来的,转载了较多人的博客,希望有知道原出处的人把地址留下,我贴上来。在此谢谢各位前辈的总结。(我会在后续笔记中贴出在我自己的程序中对于uorb的使用)

进程与应用程序(传感器应用程序发送传感器数据到姿态过滤应用程序)之间的通讯是pixhawk软件架构的重要组成部分,进程(即所谓的节点)通过命名的总线交换消息称之为“主题”,在pixhawk中,一个主题仅包含一种消息类型,例如:vehicle_attitude主题传输包含姿态结构(翻滚,俯仰和偏航估算)。节点可以在总线,主题上发布一跳消息或者订阅总线,主题。通讯双方之间并不知道在与谁通讯,可以存在多个发布或一条消息有多个订阅者。这种设计模式可以防止锁定的问题。

pixhawk的发布订阅机制是通过“微对象请求代理”(uORB)来实现的。

快速入门:

在深入细节之前,以下是一对简单,完整的发布/订阅模型。发布者发布一条名为“random——integer”的主题并用随机整数更新该主题。订阅者检查并打印这些更新。

[cpp] view plain copy print?
  1. topic.h
  2. /* declare the topic */
  3. ORB_DECLARE(random_integer);/* define the data structure that will be published where subscribers can see it */
  4. struct random_integer_data {int r;};
  5. publisher.c
  6. #include <topic.h>/* create topic metadata */
  7. ORB_DEFINE(random_integer);/* file handle that will be used for publishing */
  8. static int topic_handle;
  9. int init(){/* generate the initial data for first publication */
  10. struct random_integer_data rd = { .r = random(), };/* advertise the topic and make the initial publication */
  11. topic_handle = orb_advertise(ORB_ID(random_integer), &rd);
  12. }
  13. int update_topic(){/* generate a new random number for publication */
  14. struct random_integer_data rd = { .r = random(), };/* publish the new data structure */
  15. orb_publish(ORB_ID(random_integer), topic_handle, &rd);
  16. }
  17. subscriber.c
  18. #include <topic.h>/* file handle that will be used for subscribing */
  19. static int topic_handle;
  20. int init(){/* subscribe to the topic */
  21. topic_handle = orb_subscribe(ORB_ID(random_integer));
  22. }
  23. void check_topic(){
  24. bool updated;struct random_integer_data rd;/* check to see whether the topic has updated since the last time we read it */
  25. orb_check(topic_handle, &updated);
  26. if (updated) {/* make a local copy of the updated data structure */
  27. orb_copy(ORB_ID(random_integer), topic_handle, &rd);
  28. printf("Random integer is now %d\n", rd.r);
  29. }
  30. }
topic.h
/* declare the topic */
ORB_DECLARE(random_integer);/* define the data structure that will be published where subscribers can see it */
struct random_integer_data {int r;};publisher.c
#include <topic.h>/* create topic metadata */
ORB_DEFINE(random_integer);/* file handle that will be used for publishing */
static int topic_handle;
int init(){/* generate the initial data for first publication */struct random_integer_data rd = { .r = random(), };/* advertise the topic and make the initial publication */topic_handle = orb_advertise(ORB_ID(random_integer), &rd);
}
int update_topic(){/* generate a new random number for publication */struct random_integer_data rd = { .r = random(), };/* publish the new data structure */orb_publish(ORB_ID(random_integer), topic_handle, &rd);
}subscriber.c
#include <topic.h>/* file handle that will be used for subscribing */
static int topic_handle;
int init(){/* subscribe to the topic */topic_handle = orb_subscribe(ORB_ID(random_integer));
}
void check_topic(){bool updated;struct random_integer_data rd;/* check to see whether the topic has updated since the last time we read it */orb_check(topic_handle, &updated);if (updated) {/* make a local copy of the updated data structure */orb_copy(ORB_ID(random_integer), topic_handle, &rd);printf("Random integer is now %d\n", rd.r);}
}

发布:

发布分为三个独立但又相关的行为;确定主题,公告主题和发布主题更新。

确定主题:

pixhawk系统为提供部件之前的通用接口定义了许多标准主题,如果发布者想使用标准主题和相关的数据结构不需要做额外的工作。

自定义主题

要定义一个自定义主题,发布者需要提供给订阅者一个头文件(参考上面的topic.h),在这个头文件中必须有:

1.用主题的名称做作为参数调用ORB_DECLARE()宏来定义一个实例

2.定义一个结构体,用来描述将要用来发布的数据结构

主题的名称应该要具有描述性,pixhawk的管理使用下划线来分割主题名称为独立的部分并且首选更通用的术语表示元件的名称。

例如:raw sensor data发布在sensors_raw主题

除了头文件,发布者必须要具有使用ORB_DEFINE()宏在源码中定义一个实例,当固件被构建时,他将被编译并且链接到固件。

可选主题:

如果一个主题通过一个软件组件来发布,那么它属于可选主题,并且可能不会存在于发布后的固件,这种情况下,头文件也可以改用ORB_DECLARE_OPTIONAL()宏来替代,以这种方式声明主题,发布者不需要专门来处理什么。但在下面讨论的也有额外要处理的情况,当处理可选主题时订阅者必须要注意。

公告主题:

在数据被发布到一个主题前,它必须被公告,发布者可以使用下面的API来公告一个新的主题。

[cpp] view plain copy print?
  1. extern int orb_advertise(const struct orb_metadata *meta, const void *data);
    extern int orb_advertise(const struct orb_metadata *meta, const void *data);

公告也可以发布初始化数据到主题,meta参数是传递给API的一个指针,指向由ORB_DEFINE()宏定义好的数据,通常使用ORB_ID()宏来根据主题名称获取该指针。请注意,虽然主题更新可以从中断处理函数发布,公告主题必须在常规的线程上下文中执行。

多个发布:

只有一个发布者可以具有发布一次一个主题,但是该主题手柄可以被关闭,因为是文件描述符,可以通过close()函数关闭。

发布更新:

一旦公告了一个主题,公告主题后返回的句柄可使用下面的API来发布主题更新。

[cpp] view plain copy print?
  1. extern int orb_publish(const struct orb_metadata *meta, int handle, const void *data);
    extern int orb_publish(const struct orb_metadata *meta, int handle, const void *data);

U ORB不换冲多个更新,当用户检查一个主题,他们将只能看到最新的更新。

订阅者:

订阅主题的要求如下:

1.调用ORB_DEFINE()或ORB_DEFINE_OPTIONAL()宏(在订阅者的头文件中包含他们)

2.发布到主题的数据结构定义(通常与发布者使用同一头文件)

如果满足上面的条件后,订阅者可以使用下面的api来订阅一个主题:

[cpp] view plain copy print?
  1. extern int orb_subscribe(const struct orb_metadata *meta);
    extern int orb_subscribe(const struct orb_metadata *meta);

如果可选主题不存在于固件之中,订阅到可选的主题将会失败,但其他主题即便发布者没有进行公告也会订阅成功,这样可大大降低系统对启动顺序的安排。

这里没有专门来限制一个任务的最大订阅数。

要取消订阅一个主题,可以用下面的API:

[cpp] view plain copy print?
  1. extern int orb_unsubscribe(int handle);
    extern int orb_unsubscribe(int handle);

拷贝数据到主题:

订阅者不能引用ORB中存储的数据或其他订阅共享的数据,而是在订阅者请求时从ORB拷贝数据到订阅者的临时缓冲区。副本拷贝的方式可以避免锁定ORB的问题,并保持两者之间(发布者,订阅者)的API接口简单。它也允许订阅者在必要的时候直接修改拷贝副本的数据供自己使用。

当订阅者想要把主题中的最新数据拷贝一份全新的副本,可以使用:

[cpp] view plain copy print?
  1. extern int orb_copy(const struct orb_metadata *meta, int handle, void *buffer);
    extern int orb_copy(const struct orb_metadata *meta, int handle, void *buffer);  

拷贝是以原子操作进行的,所以可以保证获取到发布者最新的数据。

检查更新:

订阅者可以使用下面的API来检查一个主题在发布者最后更新后,有没有人调用过orb_copy来接收,处理:

[cpp] view plain copy print?
  1. extern int orb_check(int handle, bool *updated);
    extern int orb_check(int handle, bool *updated);      

如果主题在被公告前就有人订阅,那么这个API将返回“not-updated”直到主题被公告。

发布时间戳:

订阅者可以使用下面的API来检查一个主题最后发布的时间。

[cpp] view plain copy print?
  1. extern int orb_stat(int handle, uint64_t *time);
    extern int orb_stat(int handle, uint64_t *time);

需要注意的是,要小心的使用这个调用,因为不能保证再调用返回后不久主题就不会被发布(调用返回后不久,主题可能马上又被发布,导致最后更新时间错误)

uORB的管理罗辑是通过创建线程后台运行方式实现。

uORB深入探索

uORB是pixhawk系统中非常重要的一个模块,它肩负了整个系统的数据传输任务,所有的传感器数据,GPS,ppm信号等都要从芯片获取后通过uORB进行传输到各个模块进行计算处理。

1.uORB的架构简述:

uORB是一套跨进程的IPC通讯模块。在pixhawk中,所有的功能被独立以进程模块为单位进行实现并工作。而进城间的数据交互尤为重要,必须要能够符号实时,有序的特点。

pixhawk使用nuttx实时ARM系统,而uORB对于nuttx而言,它仅仅是一个普通的文件设备对象,这个设备支持open,close,read,write,ioctl以及poll机制。通过这些接口的实现,uORB提供了一套“点对多”的跨进程广播通讯机制。“点”指的是通讯消息的“源”,“多”指的是一个源可以有多个用户来接受,处理。而源和用户的关系在于,源不需要去考虑用户是否课余i收到某条被广播的消息或什么时候收到这条消息。它只是需要单纯的把要广播的数据推送到uORB的消息总线上,对于用户而言,源推送了多少次的小心也不重要,重要的是取回最新的这条消息。

2.uORB的实现位于固件源码的src/modules/uORB/uORB.cpp文件,它通过重载CDev基类来组织一个uORB的设备实例。并且完成Read/Write等功能的重载。uORB的入口点是uorb_main函数,在这里它检查uORB的启动参数来完成对应的功能,uORB支持start/test/status这3条启动参数,在pixhawk的rcS启动脚本中,使用start参数来进行初始化,其他2个参数分别用来进行uORB功能的自检和列出uORB的当前状态。

在rcS中使用start参数启动后,uORB会创建并初始化它的设备实例,其中的实现大部分都在CDev基类完成。这个过程类似于Linux设备驱动中的Probe函数,通过init调用完成设备的创建,节点注册以及派遣例程的设置等。

源码解读:(最新版本的uORB)

uORB文件夹说明

1.uORB文件夹结构

2.文件/目录说明

objects_common.cpp:通用接口标准主题定义集合,如添加新主题就在这里定义。

uORBMap.hpp:对象请求节点链表管理(驱动节点)

uORBSet.hpp:对象请求节点链表管理(非驱动节点)

Publication.cpp/ Publication.hpp:在不同的发布中遍历使用

Subscription.cpp/ Subscription.hpp:在不同的发布中遍历使用

uORB.cpp:uORB的实现

uORB.h:uORB的头文件

uORBCommon.hpp:uORB公共部分变量定义实现

uORBCommunicator.hpp:远程订阅的接口实现,实现了对不同的通信通道管理,如添加、移除订阅者,可以基于TCP/IP或者fastRPC;传递给通信链路的实现,以提供在信道上接收信息的回调。

uORBDevices_nuttx.cpp:节点操作,close,open,read,write等

uORbMain.cpp:uORB入口

uORBManager.hpp:uORB功能函数实现的头文件

uORBManager_nuttx.cpp:uORB功能函数的实现(Nuttx)

uORBManager_posix.cpp:uORB功能函数的实现(Posix)

uORBTest_UnitTest.cpp:uORB测试

uORBTest_UnitTest.hpp:uORB测试头文件,包括主题定义和声明等

pixhawk自学笔记之uorb学习总结相关推荐

  1. David Silver强化学习公开课自学笔记——Lec1强化学习简介

    本笔记摘自知乎博主旺财的搬砖历险记和叶强,仅用于自学 1.背景介绍 (1)背景 强化学习是多学科多领域交叉的产物,本质是解决决策问题,即学会自动决策,在各个领域体现不同,但都归结为人类如何且为什么能做 ...

  2. pixhawk自学笔记之px4程序启动顺序

    在了解px4启动之前我们需要了解一下bootloader.Bootloader是在操作系统内核运行之前运行,可以初始化硬件设备,建立内存空间映射图等,整个系统的加载启动任务就是完全由Bootloade ...

  3. OpenMV自学笔记

    OpenMV自学笔记1 目的 学习OpenMV是为了准备农业机器人大赛,也是为了后续课题中使用图像处理.主要目的是:使用OpenMV识别到物体(色块),并将色块信息(位置.大小等)输出到arduino ...

  4. 什么是Android逆向?如何学习安卓逆向?Android逆向自学笔记入门到实战

    简单地来说,安卓逆向是对已经打包好的APP进行反编译.源码分析了解APP实现逻辑的一门技术.我们可以把安卓安装时用到的APK文件看作一个加密后的压缩包,逆向就是要最大程序地还原出APK打包之前的源码. ...

  5. 自然语言处理自学笔记-02 Word2vec——基于神经网络学习单词表示

    自然语言处理自学笔记-02 Word2vec--基于神经网络学习单词表示 Word2vec 定义损失函数 skip-gram算法 从原始文本到结构化数据 制定实际的损失函数 近似损失函数 连续词带模型 ...

  6. 基于 Java 机器学习自学笔记 (第63-65天:集成学习之AdaBoost)

    注意:本篇为50天后的Java自学笔记扩充,内容不再是基础数据结构内容而是机器学习中的各种经典算法.这部分博客更侧重于笔记以方便自己的理解,自我知识的输出明显减少,若有错误欢迎指正! 目录 一.关于集 ...

  7. Python自学笔记——视频课程来自小甲鱼零基础入门学习python

    Python自学笔记 细枝末节 / 浮点除 // 地板除 字符串 apitalize() 把字符串的第一个字符改为大写 casefold() 把整个字符串的所有字符改为小写 center(width) ...

  8. 字节跳动大佬的Python自学笔记.pdf

    1. 字节跳动大佬的Python自学笔记 这是我的一个朋友自学资料包,通过这个资料包自学拿到了字节跳动的Offer, 下面是他之前入门学习Python时候的学习资料,非常全面,从Python基础.到w ...

  9. 怎么用vc采集ni卡数据_SystemLink自学笔记(6):SystemLink架构和数据服务

    1. SystemLink架构和数据服务 1.1. 架构和特点 现在在对SystemLink的功能有了一个大概的了解后,可以进一步从它的整体架构学习这门新技术了.NI官网给出了白皮书,原文是英文资料, ...

最新文章

  1. 运用类CL_SALV_TABLE实现alv
  2. [EDA]Quartus II 实验简答题
  3. oracle 细粒审核,oracle10g 细粒审计
  4. MySQL基础篇(03):系统和自定义函数总结,触发器使用详解
  5. Jdb命令 The Java Debugger
  6. python的基础_python基础知识,python必背内容,一、python的基
  7. 6.6使用环境变量配置外部环境
  8. deepin系统安装成功了之后重启电脑没有deepin启动选项的简单解决办法
  9. 深入浅出MFC:动态创建控件
  10. STM32串口接收以及发送大全
  11. 批处理系统、分时操作系统、实时操作系统
  12. Python绘制太阳花
  13. vue 调用 js 获取的今天日期、本周、本月、本年起始和结束日期
  14. KVM(多电脑切换器)
  15. python数据分析经典书籍有哪些_数据分析有哪些好书值得推荐?
  16. 关于智能家居、360wifi、wifi开关,以及wifi芯片的选择
  17. 【实操】python opencv将图片合成视频,并插入音频
  18. php去掉字符串带逗号前面的字符,php 怎么去掉字符串最后一个逗号
  19. LEETCODE 136.Singel Number
  20. 流行的rpc框架性能测试对比

热门文章

  1. N-Gram的数据结构
  2. spring AOP解析之xml方式详解
  3. Ubuntu mysql连接错误10060/10061的方法
  4. SQL*Plus中替换变量与定义变量
  5. Apache添加mod_rewrite模块
  6. 程序员转实施工程师_只有程序员才能看得懂?程序员:算了,不看了,我得写代码了...
  7. word2vec中文相似词计算和聚类的使用说明及c语言源码
  8. Python之将彩色图片批量转化为黑白图片
  9. 2020\Simulation_1\2.约数个数
  10. 并发编程——进程——Process对象的属性和方法