22. /* subscribe to sensor_combined topic */
23. int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined)); 24.
25. /* one could wait for multiple topics with this technique, just us
ing one here */
26. struct pollfd fds[] = {
27. { .fd = sensor_sub_fd, .events = POLLIN },
28. /* there could be more file descriptors here, in the for
m like:
29. * { .fd = other_sub_fd, .events = POLLIN }, 30. */ 31. }; 32.
33. int error_counter = 0; 34.
35. while (true) {
36. /* wait for sensor update of 1 file descriptor for 1000
ms (1 second) */
37. int poll_ret = poll(fds, 1, 1000); 38.
39. /* handle the poll result */ 40. if (poll_ret == 0) {
41. /* this means none of our providers is giving
us data */
42. printf(\
second\\n\);
43. } else if (poll_ret < 0) {
44. /* this is seriously bad - should be an emerg
ency */
45. if (error_counter < 10 || error_counter % 50
== 0) {
46. /* use a counter to prevent floodin
g (and slowing us down) */
47. printf(\
rn value from poll(): %d\\n\
48. , poll_ret); 49. }
50. error_counter++; 51. } else { 52.
53. if (fds[0].revents & POLLIN) {
54. /* obtained data for the first file
descriptor */
55. struct sensor_combined_s raw;
56. /* copy sensors raw data into local
buffer */
57. orb_copy(ORB_ID(sensor_combined), s
ensor_sub_fd, &raw);
58. printf(\
ter:\\t%8.4f\\t%8.4f\\t%8.4f\\n\,
59. (double)raw.accelerometer
_m_s2[0],
60. (double)raw.accelerometer
_m_s2[1],
61. (double)raw.accelerometer
_m_s2[2]);
62. }
63. /* there could be more file descriptors here,
in the form like:
64. * if (fds[1..n].revents & POLLIN) {} 65. */ 66. } 67. } 68.
69. return 0; 70. }
编译app,通过下面的指令:
1.
make
测试uORB订阅
运行更新后的程序。UORB app 可能已经在运行,但是重新运行一次也没关系,所以执行:
1.
uorb start
目标请求中间人已经被激活,可以启动传感器:
1.
sh /etc/init.d/rc.sensors
最后一步是启动应用,但是为什么语法不同?
1.
px4_simple_app &
不同是,uorb和传感器应用作为后台程序运行Daemon(computing)。 这就允许在不失去对NuttShell控制的情况下,启动/停止其。假如忘了在行末输入& ,应用将会将现在传感器的值铺满显示屏:
1. 2. 3. 4. 5. 6.
[px4_simple_app] Accelerometer: 0.0483 0.0821 0.0332 [px4_simple_app] Accelerometer: 0.0486 0.0820 0.0336 [px4_simple_app] Accelerometer: 0.0487 0.0819 0.0327 [px4_simple_app] Accelerometer: 0.0482 0.0818 0.0323 [px4_simple_app] Accelerometer: 0.0482 0.0827 0.0331 [px4_simple_app] Accelerometer: 0.0489 0.0804 0.0328
由于不是后台程序,没有办法将其停止,只能让其运行,或者通过发起下面的命令重启自驾仪:
1.
reboot
或者按压PX4FMU上的reset button.如何将应用变为后台程序可以参考this tutorial 。
Step 6: 速率受限的订阅
上一步最后一步是屏幕上铺满传感器数据。通常并不需要数据以最高速率刷新,试图保持最高速率,通常会使整个系统变慢。 API接口非常简单:
1.
orb_set_interval(int handle, unsigned interval);
限制topic到1 Hz, 只需添加:
1.
orb_set_interval(sensor_sub_fd, 1000);
到示例代码这行的下面(在line 55附近):
1. 2.
/* subscribe to sensor_combined topic */
int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined));
屏幕将会以1Hz的速率方便的打印传感器数据。
Step 7: 发布数据
为了使用计算得到的输出,下一步是发布结果。假如我们使用了一个topic,mavlink app通过该topic转发到地面站,我们甚至可以查看结果。出于这个目的,来拦截姿态 topic。 接口非常简单,初始化topic结构,并通告(advertise)topic。
1. 2. 3. 4. 5. 6.
#include
/* advertise attitude topic */ struct vehicle_attitude_s att; memset(&att, 0, sizeof(att));
orb_advert_t att_pub_fd = orb_advertise(ORB_ID(vehicle_attitude), &att);
在主循环中,当其准备好后,发布信息:
1.
orb_publish(ORB_ID(vehicle_attitude), att_pub_fd, &att);
修改后的完整示例代码为:
1. /**
2. * @file px4_simple_app.c
3. * Minimal application example for PX4 autopilot 4. */ 5.
6. #include
11. #include
12. #include
15. __EXPORT int px4_simple_app_main(int argc, char *argv[]); 16.
17. int px4_simple_app_main(int argc, char *argv[]) 18. {
19. printf(\); 20.
21. /* subscribe to sensor_combined topic */
22. int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined)); 23. orb_set_interval(sensor_sub_fd, 1000); 24.
25. /* advertise attitude topic */ 26. struct vehicle_attitude_s att;
27. memset(&att, 0, sizeof(att));
28. int att_pub_fd = orb_advertise(ORB_ID(vehicle_attitude), &att); 29.
30. /* one could wait for multiple topics with this technique, just usi
ng one here */
31. struct pollfd fds[] = {
32. { .fd = sensor_sub_fd, .events = POLLIN },
33. /* there could be more file descriptors here, in the form l
ike:
34. * { .fd = other_sub_fd, .events = POLLIN }, 35. */ 36. }; 37.
38. int error_counter = 0; 39.
40. while (true) {
41. /* wait for sensor update of 1 file descriptor for 1000 ms
(1 second) */
42. int poll_ret = poll(fds, 1, 1000); 43.
44. /* handle the poll result */ 45. if (poll_ret == 0) {
46. /* this means none of our providers is giving us d
ata */
47. printf(\
nd\\n\);
48. } else if (poll_ret < 0) {
49. /* this is seriously bad - should be an emergency
*/
50. if (error_counter < 10 || error_counter % 50 == 0)
{
51. /* use a counter to prevent flooding (and
slowing us down) */
52. printf(\
ue from poll(): %d\\n\
53. , poll_ret); 54. }
55. error_counter++; 56. } else { 57.
58. if (fds[0].revents & POLLIN) {
59. /* obtained data for the first file descr
iptor */
60. struct sensor_combined_s raw;