Pixhawk-信息流浅解析

     根深方能叶茂 在等待的日子里,刻苦读书,谦卑做人,养得深根,日后才能枝叶茂盛。 --Better(根爷)


前我们已经谈到系统框架,之前谈到了定制自己功能的两部:添加模块和修改信息流。


鉴于信息流的重要性,我们在这里重新复习整理一下:看完之后你应该做到三点:

1、掌握uorb基本函数的使用

2、能够添加自己的uorb

3、尝试去探究一下uorb和mavlink



    下面开始先复习第一部分,uorb的基本函数:


    uORB(Micro Object Request Broker,微对象请求代理器)是PX4/Pixhawk系统中非常重要且关键的一个模块,它肩负了整个系统的数据传输任务,所有的传感器数据、GPS、PPM信号等都要从芯片获取后通过uORB进行传输到各个模块进行计算处理。实际上uORB是一套跨「进程」 的IPC通讯模块。在Pixhawk中, 所有的功能被独立以进程模块为单位进行实现并工作。而进程间的数据交互就由为重要,必须要能够符合实时、有序的特点。 
  Pixhawk使用的是NuttX实时ARM系统,uORB实际上是多个进程打开同一个设备文件,进程间通过此文件节点进行数据交互和共享。进程通过命名的「总线」交换的消息称之为「主题」(topic),在Pixhawk 中,一个主题仅包含一种消息类型,通俗点就是数据类型。每个进程可以「订阅」或者「发布」主题,可以存在多个发布者,或者一个进程可以订阅多个主题,但是一条总线上始终只有一条消息。(注意一条总线上始终只有一条消息,后来的信息总会覆盖掉前面的消息

Pixhawk-信息流浅解析_第1张图片

应用层中操作基础飞行的应用之间都是隔离的,这样提供了一种安保模式,以确保基础操作独立的高级别系统状态的稳定性。而沟通它们的就是uORB。


    下面是一些常用函数:

int orb_subscribe(const struct orb_metadata *meta)
功能:订阅主题(topic);
说明:即使订阅的主题没有被公告,但是也能订阅成功;但是在这种情况下,却得不到数据,直到主题被公告;
这就是为什么发布数据之前需要先公告,公告相当于注册吧。在消息主题中,句柄用的很多,都是对句柄直接操作的。句柄的初始化是放在进程的初始化部分的。

参数:
meta:uORB元对象,可以认为是主题id;
返回值:
正确返回一个句柄,句柄是你自己定义的,初始化为-1,如int my_topic_sub=-1;

int my_topic_sub = orb_subscribe(ORB_ID(my_topic));

注意:订阅的句柄常常起名为_sub指的就是subscribe,看到不要以为是sub副的意思;而发布的主题,后缀常常是_pub是publish的意思。


int orb_set_interval(int handle, unsigned interval)
功能:设置订阅的最小时间间隔;
说明:如果设置了,则在这间隔内发布的数据将订阅不到;需要注意的是,设置后,第一次的数据订阅还是由起初设置的频率来获取。handle句柄,订阅主题返回的句柄,interval间隔时间,系统常设置的是33ms,就是30hz的更新频率。

    订阅了消息主题,如何检查数据更新了吗?下面就是两种方式,区别自己比较吧,之前我提到过。

int poll(struct pollfd fds[], nfds_t nfds, int timeout)

功能:监控文件描述符(多个);
说明:timeout就是最大阻塞这么长时间等待你的数据,因为我不可能一直等你,那样岂不是什么也干不了,所以限制一个时间,就等这么常时间。返回为0那就是时间都用完了也没等到数据,>0就是时间内拿到了数据,<0那就是出错了,看到没有返回的是拿到你数据时我还剩多少阻塞时间。

输入: 

fds:struct pollfd结构类型的数组,进程可以同时等待很多个主题数据,当有数据更新时,判断一下是谁
nfds:用于标记数组fds中的结构体元素的总数量;
timeout:是poll函数调用阻塞的时间,单位:毫秒;
返回值:
>0:阻塞时间内拿到了数据;
==0:抱歉时间都用完了,也没能拿到数据;
-1:poll函数调用失败;


int orb_check(int handle, bool *updated)
功能:检查一个主题数据有没有更新,更新了updated会被设置为true。但一旦调用ob_copy来接收、处理过后,updated会被自动设置为false,所以这种方式数据只能被第一个人检测到,后面人再检测到时updated已经是fals。


    两种方式检查到数据已经更新了,怎么取出,怎么使用?

int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
功能:从订阅的主题中获取数据并将数据保存到buffer中。meta消息的ID,handle句柄,哪个句柄,你订阅时返回的句柄,从消息中拷贝数据放到buffer中。buffer是自己消息的数据结构类型自己定义的。例:sensor_combined_s raw ;orb_copy(ORB_ID(sensor_combined), sensor_sub_fd, &raw);


    前面说的都是订阅,那么怎么发布?

orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)
功能:先公告主题,相当于注册,只要一次就行了。meta公告的消息ID,data公告的原始数据。
说明:在发布主题之前是必须的;否则订阅者虽然能订阅,但是得不到数据;

int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
功能:公告之后就可以发布主题数据。meta公告的消息ID,handle公告返回的句柄,这个句柄初始化为null,data发布的数据,要发布什么数据,自己填充。


      至于使用例程自己去官网看吧,例程很多。



2、能够添加自己的uorb

   下面讲第二个问题,如何添加自己的主题。

1)在msg/下仿照其他文件,写自己的主题内容,msg的名字就是你消息主题的名字

2)在cmakelist中添加你的msg文件名

之后再编译,就会在build/src/moudle/uorb/topic中有你自定义的主题.h文件。看看里面的内容是不是和你自定义的msg内容一样,还给你生成了主题的数据结构。当使用这个主题时,#include你的主题就可以使用它了。



3、探究一下uorb和mavlink


   Mavlink是目前最常见的无人机飞控协议之一。PX4对Mavlink协议提供了良好的原生支持。该协议既可以用于地面站(GCS)对无人机(UAV)的控制,也可用于UAV对GCS的信息反馈。其飞控场景一般是这样的:
a) 手工飞控:GCS -> (MavLink) -> UAV
b) 信息采集:GCS <- (Mavlink) <- UAV
c) 自治飞控:User App -> (MavLink) -> UAV


   也就是说,如果你想实现地面站控制飞行,那么由你的地面站使用Mavlink协议,通过射频信道(或 wifi etc.)给无人机发送控制指令就可以了。如果你想实现无人机自主飞行,那么就由你自己写的应用(运行在无人机系统上)使用Mavlink协议给无人机发送本地的控制指令就可以了。

    然而,为实现飞控架构的灵活性,避免对底层实现细节的依赖,在PX4中,并不鼓励开发者在自定义飞控程序中直接使用Mavlink,而是鼓励开发者使用一种名为uORB((Micro Object Request Broker,微对象请求代理)的消息机制。其实uORB在概念上等同于posix里面的命名管道(named pipe),它本质上是一种进程间通信机制。由于PX4实际使用的是NuttX实时ARM系统,因此uORB实际上相当于是多个进程(驱动级模块)打开同一个设备文件,多个进程(驱动级模块)通过此文件节点进行数据交互和共享。

    在uORB机制中,交换的消息被称之为topic,一个topic仅包含一种message类型(即数据结构)。每个进程(或驱动模块)均可“订阅”或“发布”多个topic,一个topic可以存在多个发布者,而且一个订阅者可也订阅多个topic。而正因为有了uORB机制的存在,上述飞控场景变成了:

a) 手工飞控:GCS -> (MavLink) -> (uORB topic) -> UAV
b) 信息采集:GCS <- (Mavlink) <- (uORB topic) <- UAV
c) 自治飞控:User App -> (uORB topic) -> (MavLink) -> UAV

    有了以上背景基础,便可以自写飞控逻辑了,仅需在PX4源码中,添加一个自定义module,然后使用uORB订阅相关信息(如传感器消息等),并发布相关控制信息(如飞行模式控制消息等)即可。

    最后值得一提的是,在PX4系统中,还提供了一个名为mavlink的专用module,源码在firmware的src/modules/mavlink中,这货与linux的控制台命令工具集相当相似,其既可以作为ntt控制台下的命令使用,又可作为系统模块加载后台运行。其所实现的功能包括:1)uORB消息解析,将uORB消息实际翻译为具体的Mavlink底层指令,或反之。2)通过serial/射频通信接口获取或发送Mavlink消息,既考虑到了用户自写程序的开发模式,也适用于类似linux的脚本工具链开发模式,使用起来很灵活。


4、还可以通过mavlink修改信息流,地面站就是走这个,这个有时间再整理。


你可能感兴趣的:(Pixahwk)