UORB模块研读
uORB函数解析:
uORB模块(Micro Object Request Broker,微对象请求代理器)
uORB是Pixhawk系统中关键的一个模块,肩负了数据传输任务。所有传感器,数据传输任务,GPS,PPM信号从芯片获取后通过uORB进行传输,到各个模块计算处理。(可以理解为数据中心仓库)
uORB是跨进程的IPC通信模块。实际多个进程打开同一设备文件,通过此文件节点进行数据交互和共享。
进程间通过命名(总线)交换消息成为topic
一个topic包含一种消息类型/数据类型。
每个进程可以订阅/发布topic,一个进程可以订阅多个主题,但一条总线始终只能有一条消息。
公告topic
extern int orb_advertise(const struct orb_metadata *meta,const void *data)
meta:uORB元对象,可以看topic的ID,通过ORB_ID赋值。
data:指向一个被初始化,发布者要发布的数据存储变量指针。
发布更新
extern int orb_publish(const struct orb_metadata *meta, int handle, const void *data)
handle:orb_advertise函数返回的句柄
data:指向发布数据的制作
订阅topic
要求的满足条件:
- 调用ORB_DEFINE()或ORB_DEFINE_OPTIONAL()宏(在订阅头文件中包含他们)
- 发布到主题的数据结构定义
extern int orb_subscribe(const struct orb_metadata *meta)
取消订阅
extern int orb_unsubscribe(int handle)
拷贝数据
订阅者不能引用从ORB中存储数据或其他订阅共享的数据,只能拷贝到临界缓冲区
extern int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
检查更新
extern int orb_check(int handle, bool *updataed)
发布时间戳
extern int orb_stat(int handle,uint64_t *time)
Note:
- 必须要先orb_advertise()+orb_subscribe()后,才能使用orb_copy()
- 所有主题在Firmware/Build_px4fmu-v2_default/Src_Modules/uORB/Topics
- 也可以到Firmware/Msg下找到
uORB原理解析:
实现方式:
- 首先模块入口是uORBMain.cpp,这里会创建唯一的MasterNode实例,负责内部的设备节点的控制
- MasterNode简洁:继承自CDev,是一个字符设备,linux中设备都是文件,所以会在对应路径下生成文件,主要对Cdev的ioctl函数进行多态实现,类内部维护一个Nodemap的数据结构(后面有详细简绍),所有的DeviceNode都会加入其中管理。
- 当外部调用uORB的方法时候,实际间接调用了uORB::Manger类的方法,也可以理解做Manger是外部函数的管理入口,MasterNode是内部节点的管理器。
- 外部函数调用uORB时候都会通过uORB::Manger::get_instance()这个函数获取Manger的实例指针。这个函数是静态函数,根据判断命名空间中_Instance指针是否为空,确保全nameespace中只有这么一个Manger实例。
- 实际节点,DeviceNode,继承自CDev,每一个字符设备都会生成对应的文件。这个类重载了open,close,read,wirte,ioctl,还有其他一些函数。
- 当外部调用orb_advertise时,Manger会做如下的事情:
- 以发布者的身份调用node_open函数,最后返回对应文件的文件描述符fd。先确认一下是否这个主题对应实例的序号已经被发布过,如果是,会重新发布一下,否则(对应文件不存在,也就是这个主题对应ID的DeviceNode不存在),会调用node_adve