PX4代码学习系列博客(4)——uORB相关

来源:互联网 发布:工业设计需要软件 编辑:程序博客网 时间:2024/06/08 01:55

uORB简介

px4使用的是NuttX实时操作系统,而这个操作系统没有在应用程序间通信的功能。为了满足飞控消息传递的实时性,uORB才被开发出来。

uORB(Micro Object Request Broker,微对象请求代理器)是px4系统中特殊的一个模块(应用程序),它负责在不同的模块(应用程序)之间传递数据。从传感器采集到的数据,从地面站发送的控制指令,位置和姿态的解算结果等,都是通过uORB来传递的。

在px4中,各个模块通过命名的“总线”交换的消息称之为“主题”(topic),一个主题仅包含一种消息类型,通俗点就是数据类型。每个进程可以“订阅”(subscribe)或者“发布”(publish)主题,可以存在多个发布者,或者一个进程可以订阅多个主题,但是一条总线上始终只有一条消息。

uORB目录结构

在目录Firmware\src\modules\uORB下:

这里写图片描述

图中的“topics”文件夹在Firmware\build_px4fmu-v2_default\src\modules\uORB中。这个文件夹需要在程序编译后才有。topics文件夹下是px4飞控内部uORB上传输的所有消息。

文件功能介绍

topics文件夹: 系统通用接口定义的标准主题,比如电池电量转态、GPS的位置参数等
uORB_tests文件夹: uORB测试
CMakeLists.txt: uORB模块makefile文件
ORBMap.hpp : 对象请求器节点链表管理(驱动节点)
ORBSet.hpp : 对象请求器节点管理(非驱动节点)
Publication.cpp和Publication.hpp : 在不同的发布中遍历使用。
Subscription.cpp和Subscription.hpp: 在不同的订阅中遍历使用。
uORB.cpp和uORB.h : uORB的c语言实现,其实它是调用了c++中类的方法。这样简化了编程接口。
uORBCommon.hpp : uORB公共部分变量定义实现。
uORBCommunicator.hpp : 远程订阅的接口实现,实现了对不同的通信通道管理,如添加/移除订阅者,可以基于TCP/IP或fastRPC;传递给通信链路的实现,以提供在信道上接收消息的回调。
uORBDevices.cpp和uORBDevices.hpp : 节点操作,close,open,read,write
uORBMain.cpp : uORB应用程序的定义。
uORBManager.cpp和uORBManager.hpp : uORB函数实现,被uORB.cpp和uORB.h调用,一般在其他模块调用的函数具体实现都在这个文件。
uORBTopics.h:两个函数的外部申明。
uORBUtiles.cpp和uORBUtiles.hpp: 好像没有被调用到。

uORBManager.cpp中函数解析

orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data, unsigned int queue_size = 1);//申明orb消息并发送初始数据。返回用来发布消息的句柄
int orb_unadvertise(orb_advert_t handle);//与上一条功能相反
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data);//发布一条消息,第二个参数是orb_advertise的返回值
int orb_subscribe(const struct orb_metadata *meta);//订阅一条消息
int orb_unsubscribe(int handle);//取消订阅一条消息
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer);//从主题中获取数据,在调用之前一般会调用orb_check来检查主题是否被更新
int orb_check(int handle, bool *updated);//检查主题是否被更新
int orb_stat(int handle, uint64_t *time);//返回主题最近被更新的时间
int orb_priority(int handle, int32_t *priority);//返回一个主题的优先级
int orb_set_interval(int handle, unsigned interval);//设置为订阅者更新数据的最小时间间隔
int orb_get_interval(int handle, unsigned *interval);//获得为订阅者更新数据的最小时间间隔

一个简单的订阅流程

(以attitude_estimator_q模块为例)

_sensors_sub = orb_subscribe(ORB_ID(sensor_combined));px4_pollfd_struct_t fds[1] = {};fds[0].fd = _sensors_sub;fds[0].events = POLLIN;while(px4_poll(fds, 1, 1000)<=0);//直到收到订阅的主题。sensor_combined_s sensors;orb_copy(ORB_ID(sensor_combined), _sensors_sub, &sensors)//此时数据已经保存到结构体sensors中。

一个简单的发布流程

(以attitude_estimator_q模块为例)

struct control_state_s ctrl_state = {};//准备ctrl_state中的数据。orb_advert_t    _ctrl_state_pub = nullptr;int ctrl_inst;//该变量没有被用到。if (_ctrl_state_pub == nullptr) {    //如果没有申明过要发布control_state,那么需要调用orb_advertise_multi    _ctrl_state_pub = orb_advertise_multi(ORB_ID(control_state), &ctrl_state, &ctrl_inst, ORB_PRIO_HIGH);    if (_ctrl_state_pub!= nullptr)     {        return 0;    }} else {    //否则,可以直接发送申明过的主题。    return orb_publish(ORB_ID(control_state), _ctrl_state_pub, &ctrl_state);}
原创粉丝点击