关于px4中uorb以及px4_simple_app的终极理解

时间:2021-05-12 16:07:00

先允许我卖个萌:

—。—-


看了一下午关于px4中的uorb的分析,终于有所感悟了。信息量有点大,先让我缓缓,理理思绪。
先说说我之前的疑惑吧:
**

疑惑1

.** 在一开始学习px4的时候,就在网上看到很多人说uorb是一个很难理解的东西。看看概念,谁都知道他是一种通信机制,但我需要一种更加通俗易懂的解释。那就看看我的解释。

什么是uorb

在PX4中,应用程序间发送信息的独立通道叫做“topics”,在px4中很重要的一个东西就是传感器的数据信息,于是我们就需要“多传感器间的uORB消息机制”(sensor_combinedtopic)。这种消息机制使得整个系统能够同步实时传感器数据。另外我需要提的是,传感器将他的数据信息只发布(上传)到这个通道,至于传给谁他不管,而接受方订阅一个信息也是从这个通道,而不是从某个传感器,也就是接收方不管信息从哪里来。然后就可以推广到一些非传感器的器件。除此外,我们也需要这个通道去发布我们自己的信息,比如飞机的姿态,他是无法从传感器直接读出来得,是需要我们人为通过算法去解算,然后我们就将解算出来的信息在发布出去,至于谁要用这个数据,看你咯0.0


疑惑2

:我之前以为如果我们需要去实时显示某一传感器的信息,先要去写传感器的发布数据程序,然后写我们的订阅数据的程序。但后面我错了,因为我在看源码(/src/Firmware/src/modules/sensors)下的sensors.cpp时,意外发现了了不得的东西,就是publish,上图:

关于px4中uorb以及px4_simple_app的终极理解

这段程序的前面部分是对传感器接受的数据进行处理,比如滤波,降噪等,然后选出最好的(vote机制),然后publish。

也就是说,传感器发布数据是自动的,不需要我们去写发布程序。(惊不惊喜,意不意外 0.0)


疑惑三

如何理解这个orb-id,我后来的理解是帮助你辨识和记忆这个发布或订阅的东西是啥。比如

orb_subscribe(ORB_ID(sensor_combined));

让我们知道这是订阅传感器的数据。

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

让我们知道发布的数据是关于飞机姿态的。


px4_simple_app

#include <px4_config.h> 
#include <px4_tasks.h> 
#include <px4_posix.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <poll.h> 
#include <string.h> 

#include <uORB/uORB.h> 
#include <uORB/topics/sensor_combined.h> 
#include <uORB/topics/vehicle_attitude.h> 

__EXPORT int px4_simple_app_main(int argc, char *argv[]);  

int px4_simple_app_main(int argc, char *argv[])  
{  

    int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined));// 订阅 
    orb_set_interval(sensor_sub_fd, 1000); //设置订阅时间间隔 



    /* 一个应用可以等待多个主题,在这里只等待一个主题 */  
    px4_pollfd_struct_t fds[] = {  
        { .fd = sensor_sub_fd,   .events = POLLIN },  
        /* there could be more file descriptors here, in the form like: * { .fd = other_sub_fd, .events = POLLIN }, */  
    };  

    int error_counter = 0;  

    for (int i = 0; i < 5; i++) {  
        /* wait for sensor update of 1 file descriptor for 1000 ms (1 second) */  
        int poll_ret = px4_poll(fds, 1, 1000);  

        /* handle the poll result */  
        if (poll_ret == 0) {  
            /* this means none of our providers is giving us data */  
            PX4_ERR("[px4_simple_app] Got no data within a second");  

        } else if (poll_ret < 0) {  
            /* this is seriously bad - should be an emergency */  
            if (error_counter < 10 || error_counter % 50 == 0) {  
                /* use a counter to prevent flooding (and slowing us down) */  
                PX4_ERR("[px4_simple_app] ERROR return value from poll(): %d"  
                    , poll_ret);  
            }  

            error_counter++;  

        } else {  

            if (fds[0].revents & POLLIN) {  
                /* obtained data for the first file descriptor */  

                struct sensor_combined_s raw;//sensor_combined_s是在头文件中定义的,里面有传感器发布的数据,也可以用来储存copy来的数据 

                /* copy sensors raw data into local buffer */  
                orb_copy(ORB_ID(sensor_combined), sensor_sub_fd, &raw);//copy前必须要有subscribe,因为需要他的句柄。 
                PX4_WARN("[px4_simple_app] 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]);  

            }  

        }  
    }  
        PX4_INFO("exiting");  
    return 0;  
} 

说明:
1. sensor_combined.h,系统自带的,他就是传感器发布信息的去处。我们也是从里面订阅信息的。
sensor_combined.h里面有:
关于px4中uorb以及px4_simple_app的终极理解

2.vehicle_attitude.h是系统写好的用来放我们自己要发布数据,当然我们也可以自己写一个topic来发布我们的数据,比如以后要加入的超声波传感器就需要我们自己去写。
vehicle_attitude.h里面有:

关于px4中uorb以及px4_simple_app的终极理解


px4_simple_app改进版

#include <px4_config.h> 
#include <px4_tasks.h> 
#include <px4_posix.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <poll.h> 
#include <string.h> 

#include <uORB/uORB.h> 
#include <uORB/topics/sensor_combined.h> 
#include <uORB/topics/vehicle_attitude.h> 

__EXPORT int px4_simple_app_main(int argc, char *argv[]);  

int px4_simple_app_main(int argc, char *argv[])  
{  
    /* subscribe to sensor_combined topic */  
    int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined));  
    orb_set_interval(sensor_sub_fd, 1000);  

    /* advertise attitude topic */  
    struct vehicle_attitude_s att;  
    memset(&att, 0, sizeof(att));  
    orb_advert_t att_pub = orb_advertise(ORB_ID(vehicle_attitude), &att);  

    /* one could wait for multiple topics with this technique, just using one here */  
    px4_pollfd_struct_t fds[] = {  
        { .fd = sensor_sub_fd,   .events = POLLIN },  
        /* there could be more file descriptors here, in the form like: * { .fd = other_sub_fd, .events = POLLIN }, */  
    };  

    int error_counter = 0;  

    for (int i = 0; i < 5; i++) {  
        /* wait for sensor update of 1 file descriptor for 1000 ms (1 second) */  
        int poll_ret = px4_poll(fds, 1, 1000);  

        /* handle the poll result */  
        if (poll_ret == 0) {  
            /* this means none of our providers is giving us data */  
            PX4_ERR("[px4_simple_app] Got no data within a second");  

        } else if (poll_ret < 0) {  
            /* this is seriously bad - should be an emergency */  
            if (error_counter < 10 || error_counter % 50 == 0) {  
                /* use a counter to prevent flooding (and slowing us down) */  
                PX4_ERR("[px4_simple_app] ERROR return value from poll(): %d"  
                    , poll_ret);  
            }  

            error_counter++;  

        } else {  

            if (fds[0].revents & POLLIN) {  
                /* obtained data for the first file descriptor */  
                struct sensor_combined_s raw;  
                /* copy sensors raw data into local buffer */  
                orb_copy(ORB_ID(sensor_combined), sensor_sub_fd, &raw);  
                PX4_WARN("[px4_simple_app] 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]);  

                /* set att and publish this information for other apps */  
                att.rollspeed = raw.accelerometer_m_s2[0];  
                att.pitchspeed = raw.accelerometer_m_s2[1];  
                att.yawspeed = raw.accelerometer_m_s2[2];  
                orb_publish(ORB_ID(vehicle_attitude), att_pub, &att);  
            }  

            /* there could be more file descriptors here, in the form like: * if (fds[1..n].revents & POLLIN) {} */  
        }  
    }  

    PX4_INFO("exiting");  

    return 0;  
} 

分析:
1.在改进版中加入了发布的过程,即我们将订阅的传感器信息变为姿态信息后发布出去了。
2.很多topic就是既要有输入也要有输出。输入就是订阅的,输出就是发布的。
3.发布前必须要有公告,因为你需要公告的句柄。

 (后面我在想起什么在补充)