PX4:【uORB通讯机制】

uORB: (Micro Object Request Broker )

[PX4进程间的通讯机制:多对多的信息发布与订阅方式]

在这里插入图片描述

发布消息:

1. 公告 advertise:

相当于初始化,在发布消息之前需要对主题(topic)进行公告,一个topic只公告一次
创建一个主题(uORB上创建一个消息源)
驱动程序通过以下接口公告一个主题:

orb_advert_t  orb_advertise( const struct orb_metadata *meta, const void *data )
meta:为发布数据的ID
data:为发布数据的初始内容

2. 发布 publish:

当消息源产生一个新数据时,可通过已公告的主题向uORB发布消息

消息源通过以下接口发布消息:

int  orb_publish(const struct orb_metadata * meta, orb_advert_t handle,  const void *data)
{ return uORB::Manager::get_instance()->orb_publish(meta, handle, deta ); }
meta:为发布数据的ID
handle:为发布数据的句柄(文件描述符),初始化为null
data:为发布数据的内容

订阅消息:

1. 订阅 2. 检查更新 3. 拷贝数据

1.订阅 subscribe:
订阅主题,当主题发生更新后,会收到来自uORB的通知
应用程序可通过以下接口来订阅主题:

 int orb_subscribe(const struct orb_metadata *meta)
{ return uORB::Manager::get_instance()->orb_subscribe(meta);  }
meta:订阅发布数据的ID
返回一个int型的句柄

2. 1检查更新:方式一【非关键数据】
每隔一段时间,检测主题数据是否更新

 int orb_check(int handle, bool *updated)
{   return uORB::Manager::get_instance()->orb_check(handle, updated);  }
检测handle句柄是否更新,若更新,updated会被设置为true。
一旦调用orb_copy来接受处理后,update会被自动设置为false,因此该方式下数据仅能被一个用户检测到。

2.2 检查更新:方式二【数据很重要】
阻塞等待数据更新,设置等待时间上限,等待数据更新。

 int poll( struct pollfd *fds,  nfds_t nfds,  int timeout);
fds:已经订阅的主题数据
timeout:最大阻塞时间 ms
返回值: >0[ 阻塞时间内拿到了数据 ]
         -1[  函数调用失败]
        ==0[ 时间用完还没拿到数据 ]

3. 拷贝数据
通过以上方式检测到数据更新之后,将数据拷贝到buffer中

int  orb_copy(const struct orb_metadata *meta, int handle, void *buffer);
meta:要拷贝数据的ID
handle:要拷贝数据数据的句柄
buffer:储存位置

如何订阅一个数据

/* 1. 订阅 */  
         int  sensor_sub_fd = orb_subscribe( ORB_ID( sensor_combine )) ; 
        //订阅一个sensor_combine 的主题
                                                                                                             //返回 int 型句柄  sensor_sub_fd 
         orb_set_interval(sensor_sub_fd, 200);    //设置更新频率 5Hz
        //sensor_combine 的msg数据类型中:包含了 陀螺仪和加速度计的各项数据
         struct fds[ ] = {  {.fd = sensor_sub_fd,  .event = POLLIN }};
                   // fd 与 event 是结构体中的成员,此处只等待一个主题,也可以等待多个主题
                   // 句柄:sensor_sub_fd  
/* 2. 检测  */
        if( 循环条件 ){
             int poll_ret = poll ( fds, 1 ,1000 );  //阻塞等待: 消息的句柄,等待消息的个数,最大等待时间(ms)
             //处理poll返回的结果
             if( poll_ret == 0)  //表示:时间溢出,最大等待时间时间内还没拿到数据
                     PX4_ERR("Got no data within a second");
             else if ( poll_ret < 0 )   //表示:调用发生错误,记录错误发生的次数
             {   
                  if (error_counter < 10 || error_counter % 50 == 0)  
                  { 
			          /* use a counter to prevent flooding (and slowing us down) */
				      PX4_ERR("ERROR return value from poll(): %d", poll_ret);     
				   } 
                  error_counter++;
                  
              } else {  
               //  poll_ret > 0 的情况,表示:最大等待时间内拿到了订阅的数据,可以开始进行下一步骤
/* 3. 拷贝订阅数据  */
                    //判断一下,是哪个数据发生了更新
                     if ( fds[0].revents & POLLIN ) { //fds[0].revents:文件描述符的flag
                           struct sensor_combined_s  raw;  
                          //拷贝数据(数据id,数据句柄,拷贝到buffer)
			              orb_copy(ORB_ID(sensor_combined), sensor_sub_fd, &raw); 
			              PX4_INFO("Accelerometer:\t%8.4f\t%8.4f\t%8.4f", 
					      (double)raw.accelerometer_m_s2[0],
					      (double)raw.accelerometer_m_s2[1],
					      (double)raw.accelerometer_m_s2[2]);
                     }
                       //若订阅多个topic,可以继续   if ( fds[1....n].revents & POLLIN ) { ...  }
               } 
            } //循环结束

如何发布一个数据

    /*1. advertise attitude topic 主题发布前需要进行初始化公告 ,公告attitude 主题,仅一次 */

	struct vehicle_attitude_s att;
	memset(&att, 0, sizeof(att));
	orb_advert_t att_pub = orb_advertise(ORB_ID(vehicle_attitude), &att);

    /*2. 将得到的数据赋值给att,并发布数据,提供给其他的应用 */

     att.q[0] = raw.accelerometer_m_s2[0]; 
	 att.q[1] = raw.accelerometer_m_s2[1]; 
	 att.q[2] = raw.accelerometer_m_s2[2];

	 orb_publish(ORB_ID(vehicle_attitude), att_pub, &att);

       //ORB_ID(vehicle_attitude) 为发布数据的ID
       //att_pub :为发布数据的句柄(文件描述符)
       // &att:为发布数据的内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值