PX4代码解析(2)
前言
在大致了解PX4代码架构后,我们需要了解PX4的通信机制。在PX4代码架构中,每通信总线主要分为两个部分,一是内部通信总线uORB,即PX4内部进程通信采用的协议,例如PX4内部姿态控制需要获取飞行器姿态,而飞行器姿态是由姿态解算产生,它们之间便是由uorb通信
二是外部通信总线Mavlink,它主要负责飞控端与地面站系统的通信协议,后续会详细讲解,本章主要先了解uorb。本章分为三个部分,先介绍uorb基础,然后结合源码讲解怎么使用uorb,最后实际操作练手
一、uorb基础
关于这一部分,CSDN上有很多大佬对uorb进行了详细的讲解,我写的不一定有他们好,就不献丑了,推荐阅读
1、http://shequ.dimianzhan.com/articles/315
2、https://blog.csdn.net/freeape/article/details/46880637
看完之后,你就会对uorb有一定的了解,说简单点,在uorb中,发送者只管发送消息到消息池中,不管谁去调用,接收者只管去消息池中获得需要的消息,不管消息是谁发布的,示意图如下
在了解uorb后 ,下面以官方例程开始讲解怎么使用uorb
二、uorb代码讲解
在官方提供的px4代码中,有一个历程就是讲解uorb使用的,首先进入PX4目录下src/example目录,找到px4_simple_app,如下图所示
在px4_simple_app下有一个c文件,直接打开
//需要使用的头文件
#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[])
{//在控制台输出Hello SkyPX4_INFO("Hello Sky!");//定义句柄接收名为sensor_combined的消息int sensor_sub_fd = orb_subscribe(ORB_ID(sensor_combined));//定义更新频率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);/* 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) *///检查1s内是否有数据更新//int poll_ret = px4_poll(fds, 1, 1000);/* handle the poll result *///返回值为0,证明1s内数据没有更新if (poll_ret == 0) {/* this means none of our providers is giving us data */PX4_ERR("Got no data within a second");} else if (poll_ret < 0) {//返回值为-1,证明出错/* 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("ERROR return value from poll(): %d", poll_ret);}error_counter++;} else {//返回值大于0,说明得到数据后还剩poll_ret时间if (fds[0].revents & POLLIN) {/* obtained data for the first file descriptor *///定义sensor_combined的结构体,接收sensor_combined的消息struct sensor_combined_s raw;/* copy sensors raw data into local 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]);/* set att and publish this information for other appsthe following does not have any meaning, it's just an example*///填充到之前公告要发布的话题中att.q[0] = raw.accelerometer_m_s2[0];att.q[1] = raw.accelerometer_m_s2[1];att.q[2] = raw.accelerometer_m_s2[2];//发布vehicle_attitude消息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.在代码中我们看到了vehicle_attitude_s,sensor_combined_s的结构体,有人会好奇这些结构体怎么产生的。实际上,这些结构体是由我们之前定义好的msg编译产生,即系统根据你之前定义的消息自动生成。打开PX4目录,进入其中msg文件夹,你会看到许多以.msg结尾的文件,如下图
我们可以在其中找到sensor_combined.msg文件,打开文件
uint64 timestamp # time since system start (microseconds)int32 RELATIVE_TIMESTAMP_INVALID = 2147483647 # (0x7fffffff) If one of the relative timestamps is set to this value, it means the associated sensor values are invalid# gyro timstamp is equal to the timestamp of the message
float32[3] gyro_rad # average angular rate measured in the XYZ body frame in rad/s over the last gyro sampling period
uint32 gyro_integral_dt # gyro measurement sampling period in usint32 accelerometer_timestamp_relative # timestamp + accelerometer_timestamp_relative = Accelerometer timestamp
float32[3] accelerometer_m_s2 # average value acceleration measured in the XYZ body frame in m/s/s over the last accelerometer sampling period
uint32 accelerometer_integral_dt # accelerometer measurement sampling period in usuint8 CLIPPING_X = 1
uint8 CLIPPING_Y = 2
uint8 CLIPPING_Z = 4
uint8 accelerometer_clipping # bitfield indicating if there was any accelerometer clipping (per axis) during the sampling period
我们可以看到其中定义的消息,结合之前的代码,可以看到px4_simple_app这个例子实际上是取出sensor_combined的加速度数据,并把它以vehicle_attitude话题发布出去,不过这些消息都是系统定义好的,后面会介绍怎么定义和使用自己的消息。
2.代码讲解完毕,但该代码一般情况下不会运行,因为飞控板上的资源非常少,一般是不编译的。控制是否编译的文件在board/px4中(若是V1.11之前的版本可能在cmake文件中),如下
这些不同文件夹是针对不同硬件的编译配置,打开以fmu开头的文件夹或者sitl,你会发现以.cmake结尾的文件,例如sitl,该文件夹主要主管仿真的相关配置
在这些以.cmake结尾的文件中,我们常用default.cmake,打开文件
px4_add_board(PLATFORM posixVENDOR px4MODEL sitlLABEL defaultTESTINGDRIVERS#barometer # all available barometer drivers#batt_smbuscamera_capturecamera_trigger#differential_pressure # all available differential pressure drivers#distance_sensor # all available distance sensor driversgps#imu # all available imu drivers#magnetometer # all available magnetometer driverspwm_out_sim#telemetry # all available telemetry driverstone_alarm#uavcanMODULESairspeed_selectorattitude_estimator_qcamera_feedbackcommanderdatamanekf2eventsfw_att_controlfw_pos_control_l1land_detectorlanding_target_estimator#load_monlocal_position_estimatorloggermavlinkmc_att_controlmc_hover_thrust_estimatormc_pos_controlmc_rate_controlnavigatorrc_updatereplayrover_pos_controlsensors#sihsimulatortemperature_compensationvmountvtol_att_controluuv_att_controlSYSTEMCMDS#config#dumpfiledynesc_calibled_controlmixermotor_rampmotor_test#mtd#nshtermparamperfpwmrebootsd_benchshutdowntests # tests and test runner#toptopic_listenertune_controlverwork_queueEXAMPLESdyn_hello # dynamically loading modules examplefixedwing_control # Tutorial code from https://px4.io/dev/example_fixedwing_controlhellomy_demoapp#hwtest # Hardware test#matlab_csv_serialpx4_mavlink_debug # Tutorial code from http://dev.px4.io/en/debug/debug_values.htmlpx4_simple_app # Tutorial code from http://dev.px4.io/en/apps/hello_sky.htmlrover_steering_control # Rover example appuuv_example_appwork_item)set(config_sitl_viewer jmavsim CACHE STRING "viewer for sitl")
set_property(CACHE config_sitl_viewer PROPERTY STRINGS "jmavsim;none")set(config_sitl_debugger disable CACHE STRING "debugger for sitl")
set_property(CACHE config_sitl_debugger PROPERTY STRINGS "disable;gdb;lldb")# If the environment variable 'replay' is defined, we are building with replay
# support. In this case, we enable the orb publisher rules.
set(REPLAY_FILE "$ENV{replay}")
if(REPLAY_FILE)message(STATUS "Building with uorb publisher rules support")add_definitions(-DORB_USE_PUBLISHER_RULES)message(STATUS "Building without lockstep for replay")set(ENABLE_LOCKSTEP_SCHEDULER no)
else()set(ENABLE_LOCKSTEP_SCHEDULER yes)
endif()
你会看到一些比较熟悉的字母,例如DRIVERS,MODULES等,这正是我们src目录下的文件,而跟在这些文件夹之后的正是目录下的源代码,其实这份编译文件我已经修改过,在EXAMPLES下有px4_simple_app
三、px4_simple_app代码结果展示
验证代码结果,你可以将代码下载到支持PX4的硬件中,也可以采用jMavSim,gazebo等仿真软件进行半物理仿真,操作步骤如下
1.按上一章的讲解找到boards/px4/sitl文件夹,修改default.camke文件,在EXAMPLES下添加px4_simple_app
2.保存,在PX4目录下输入代码make px4_sitl_default jmavsim,等待编译成功
3.当出现下面界面就说明编译成功
4.这时返回终端窗口,输入help,你会看到可以运行的代码,你会在其中找到px4_simple_app
5.在终端输入px4_simple_app,会有以下结果
下章介绍如何在msg中添加自己的消息,并在PX4源码中添加自己的程序
PX4代码解析(2)相关推荐
- PX4代码解析(5)
一.前言 我所讨论的PX4代码是基于v1.11版本,该版本与之前的版本有不少不同,其中一个比较大的区别在于新版本大部分用到了C++中模板,使得代码没有以前那么容易理解,因此我在后面介绍PX4的姿态估计 ...
- PX4代码解析(6)
一.前言 上一节介绍了PX4姿态估计调用函数的流程,这一节分享一下我对PX4姿态解算的解读.首先,要理解PX4姿态解算的程序,要先从传感器的特性入手,这里主要介绍的传感器有加速度计,磁力计,陀螺仪. ...
- px4代码解析(3)
前言 在使用PX4飞控时,我们难免要对其进行二次开发,例如修改控制算法,添加新的传感器,这时需要在代码中定义属于自己的消息.本节主要分享一下如何在PX4代码中添加自己的消息 一.消息添加与配置 从代码 ...
- PX4代码解析(1)
前言 做pixhawk飞控有一段时间了,但在学习过程中遇到许多困难,目前网上找不到比较完整的PX4学习笔记,我打算结合自己理解,写写自己对PX4源码的理解,不一定对,只是希望与各位大佬交流交流,同时梳 ...
- PX4代码解析(4)
一.引言 PX4程序是基于实时操作系统(Real-time operating system, RTOS)的上层应用程序,PX4飞控程序的很多重要模块都是在Nuttx操作系统的调度下运行的.因此,想要 ...
- PX4代码解析:振动分析
本篇文章首发于公众号:无人机系统技术.更多无人机技术相关文章请关注此公众号 一.前言 前面的文章主要都是一些理论知识为主,很多读者朋友看了之后可能会有点枯燥,里面很多公式看起来也比较晦涩,今天起给大家 ...
- px4代码jlink调试
之前看了许多介绍px4环境搭建的文章有介绍windows下eclipse和ubuntu下eclipse阅读px4源码的文章,但是没有看到对px4进行代码调试的文章,后来查看px官网发现可以通过visu ...
- PX4代码学习系列博客(6)——offboard模式位置控制代码分析(之前转载过,这是第二次转载了)
我刚刚发现这篇文章去年八月份的时候转载过一次了 https://blog.csdn.net/sinat_16643223/article/details/107874349 转载自:https://b ...
- matrix_multiply代码解析
matrix_multiply代码解析 关于matrix_multiply 程序执行代码里两个矩阵的乘法,并将相乘结果打印在屏幕上. 示例的主要目的是展现怎么实现一个自定义CPU计算任务. 参考:ht ...
最新文章
- pandas数据转换时遇到不能转换的数据转为NaN的参数设置errors='coerce'
- js 的 math 函数
- matlab宏参赛,MATLAB杯无人机大赛 | 决赛通知!
- Web笔记-使用jsonp解决跨域请求(CROS)问题
- 深度学习自学(三十七):基于用户自定义要求3D房间自动设计研究
- java实现数据的Excel导出(合并单元格、样式等)
- Hyper-V 2016 系列教程40 使用 PowerShell 实现虚拟机自动化和管理虚拟机
- 探讨如何在有着1000万条数据的MS SQL SERVER数据库中实现快速的数据提取和数据分页...
- Windows-Server-2012-如何实现多个用户远程桌面登陆
- Navicat Premium 15 工具自动被杀毒防护软件删除解决方法
- 怎么获取jquery版本_获取jQuery版本
- Java生成csv文件设置文本格式
- 计算机科学导论二分法实验报告,二分法上机实验报告.doc
- NYOJ 62 笨小熊
- 磨金石教育学剪辑是正规的教育机构吗?小白学剪辑怎么样?有什么学习方法?
- caj打印PDF提示打印超范围应该怎么办?
- 【HAN】代码逐句理解三
- 抑制细胞代谢紊乱的抑制剂
- 大数据(052)Oozie【Oozie介绍 CDH安装Oozie】
- 改善Unity编辑器对Lua文件的支持