PX4-Autopilot/msg/
这个目录下定义了所有uORB消息的格式
用于PX4各模块间传递消息
px4开发文档给出的uORB消息的参考资料
https://docs.px4.io/master/en/middleware/uorb.html
如何新增一个uORB消息
1.在PX4-Autopilot/msg/文件夹下新增一个*.msg文件,写法参考其他msg文件
通过在.msg文件中添加类似于以下内容的行,可以将单个消息定义用于多个独立的主题:
# TOPICS mission offboard_mission onboard_mission
然后在代码中,把它们作为主题ID: ORB_ID(offboard_mission)
。
2. PX4-Autopilot/msg/文件夹中,打开cmakelists.txt文件,加入对应的*.msg,这样才会编译这个消息,如下:
set(msg_files
actuator_armed.msg
actuator_controls.msg
actuator_outputs.msg
adc_report.msg
airspeed.msg
airspeed_validated.msg
battery_status.msg
camera_capture.msg
camera_trigger.msg
cellular_status.msg
collision_constraints.msg
..
//[查看全部](https://github.com/PX4/PX4-Autopilot/blob/master/msg/CMakeLists.txt)
)
编译后会自动生成一个对应的头文件。
3.只要在一个模块中引用这个叫uORB消息的头文件,便可进行使用了,如:
#include <uORB/topics/sensor_combined.h>
..
int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined));
该sensor_sub_fd是一个主题手柄,可用于非常有效地进行封锁来等待新的数据。当前线程进入睡眠状态,一旦有新数据可用,调度程序会自动将其唤醒,而在等待时不会占用任何CPU周期。
为此,我们使用poll()
添加poll()到订阅中看起来像:
#include <poll.h>
#include <uORB/topics/sensor_combined.h>
..
int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined));
/* 可以使用此技术等待多个主题,仅在此处使用一次 */
px4_pollfd_struct_t fds[] = {
{ .fd = sensor_sub_fd, .events = POLLIN },
};
while (true) {
/* 等待1个文件描述符的传感器更新1000毫秒(1秒) */
int poll_ret = px4_poll(fds, 1, 1000);
..
if (fds[0].revents & POLLIN) {
/* 获得的第一个文件描述符的数据 */
struct sensor_combined_s raw;
/* 将传感器原始数据复制到本地缓冲区 */
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]);
}
}
发布uORB消息
例如:初始化struct要发布的主题并发布主题
#include <uORB/topics/vehicle_attitude.h>
..
/* 广播姿态主题 */
struct vehicle_attitude_s att;
memset(&att, 0, sizeof(att));
orb_advert_t att_pub_fd = orb_advertise(ORB_ID(vehicle_attitude), &att);
在主循环中,随时准备发布信息:
orb_publish(ORB_ID(vehicle_attitude), att_pub_fd, &att);
完整的示例代码
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/tasks.h>
#include <px4_platform_common/posix.h>
#include <unistd.h>
#include <stdio.h>
#include <poll.h>
#include <string.h>
#include <math.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[])
{
PX4_INFO("Hello Sky!");
/* 订阅传感器组合主题 */
int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined));
/* 限制更新速度5hz */
orb_set_interval(sensor_sub_fd, 200);
/* 广播姿态主题 */
struct vehicle_attitude_s att;
memset(&att, 0, sizeof(att));
orb_advert_t att_pub = orb_advertise(ORB_ID(vehicle_attitude), &att);
/* 可以使用此技术等待多个主题,仅在此处使用一个 */
px4_pollfd_struct_t fds[] = {
{ .fd = sensor_sub_fd, .events = POLLIN },
/* 可有多个订阅,如: * { .fd = other_sub_fd, .events = POLLIN }, */
};
int error_counter = 0;
for (int i = 0; i < 5; i++) {
/* 等待1个文件描述符的传感器更新1000毫秒(1秒) */
int poll_ret = px4_poll(fds, 1, 1000);
/* 处理poll结果 */
if (poll_ret == 0) {
/* 这意味着我们的订阅没有向我们提供数据 */
PX4_ERR("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) {
/* 使用计数器来防止过饱和(并使我们减速) */
PX4_ERR("ERROR return value from poll(): %d", poll_ret);
}
error_counter++;
} else {
if (fds[0].revents & POLLIN) {
/* 获得的第一个文件描述符的数据 */
struct sensor_combined_s raw;
/* 将传感器原始数据复制到本地缓冲区 */
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]);
/* 设置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);
}
/* 这里可有更多的文件描述符,格式如下: * if (fds[1..n].revents & POLLIN) {} */
}
}
PX4_INFO("exiting");
return 0;
}