pixhawk uORB初步分析

2023-05-16

再次编辑,因为发现大神的解析,添加在最后,若一般人我不告诉他闭嘴

根据自己理解画的流程图:(2016.05.29加)


由于上节分析GPS涉及到AP_GPS_PX4::read函数,

// update internal state if new GPS information is available
bool
AP_GPS_PX4::read(void)
{
    bool updated = false;
    orb_check(_gps_sub, &updated);    

    if (updated) {
        if (OK == orb_copy(ORB_ID(vehicle_gps_position), _gps_sub, &_gps_pos)) {
            state.last_gps_time_ms = AP_HAL::millis();
            state.status  = (AP_GPS::GPS_Status) (_gps_pos.fix_type | AP_GPS::NO_FIX);
            state.num_sats = _gps_pos.satellites_used;
            state.hdop = uint16_t(_gps_pos.eph*100.0f + .5f);

            if (_gps_pos.fix_type >= 2) {
                state.location.lat = _gps_pos.lat;
                state.location.lng = _gps_pos.lon;
                state.location.alt = _gps_pos.alt/10;

                state.ground_speed = _gps_pos.vel_m_s;
                state.ground_course_cd = wrap_360_cd(degrees(_gps_pos.cog_rad)*100);
                state.hdop = _gps_pos.eph*100;

                // convert epoch timestamp back to gps epoch - evil hack until we get the genuine
                // raw week information (or APM switches to Posix epoch ;-) )
                uint64_t epoch_ms = uint64_t(_gps_pos.time_utc_usec/1000.+.5);
                uint64_t gps_ms = epoch_ms - DELTA_POSIX_GPS_EPOCH + LEAP_MS_GPS_2014;
                state.time_week = uint16_t(gps_ms / uint64_t(MS_PER_WEEK));
                state.time_week_ms = uint32_t(gps_ms - uint64_t(state.time_week)*MS_PER_WEEK);

                if (_gps_pos.time_utc_usec == 0) {
                  // This is a work-around for https://github.com/PX4/Firmware/issues/1474
                  // reject position reports with invalid time, as APM adjusts it's clock after the first lock has been aquired
                  state.status = AP_GPS::NO_FIX;
                }
            }
            if (_gps_pos.fix_type >= 3) {
                state.have_vertical_velocity = _gps_pos.vel_ned_valid;
                state.velocity.x = _gps_pos.vel_n_m_s;
                state.velocity.y = _gps_pos.vel_e_m_s;
                state.velocity.z = _gps_pos.vel_d_m_s;
                state.speed_accuracy = _gps_pos.s_variance_m_s;
                state.have_speed_accuracy = true;
            }
            else {
                state.have_vertical_velocity = false;
            }
        }
    }

    return updated;
}
其中包含 orb_check(_gps_sub, &updated); if (OK == orb_copy(ORB_ID(vehicle_gps_position), _gps_sub, &_gps_pos))。故在此节做一个初步分析。

假如我需要添加一个新的数据源进行进程间的通信,比如GPS,其逻辑应该是这样的:

首先创建文件ardupilot/modules/PX4Firmware/src/modules/uORB/topics/vehicle_gps_position.

里面的内容包含2方面,一个是数据结构,一个是ORB_DECLARE(vehicle_gps_position);

数据结构如下

ardupilot/modules/PX4Firmware/src/modules/uORB/topics/vehicle_gps_position.h
#ifdef __cplusplus
struct __EXPORT vehicle_gps_position_s {
#else
struct vehicle_gps_position_s {
#endif
	uint64_t timestamp_position;
	int32_t lat;
	int32_t lon;
	int32_t alt;
	int32_t alt_ellipsoid;
	uint64_t timestamp_variance;
	float s_variance_m_s;
	float c_variance_rad;
	uint8_t fix_type;
	float eph;
	float epv;
	float hdop;
	float vdop;
	int32_t noise_per_ms;
	int32_t jamming_indicator;
	uint64_t timestamp_velocity;
	float vel_m_s;
	float vel_n_m_s;
	float vel_e_m_s;
	float vel_d_m_s;
	float cog_rad;
	bool vel_ned_valid;
	uint64_t timestamp_time;
	uint64_t time_utc_usec;
	uint8_t satellites_used;
#ifdef __cplusplus
#endif
};

然后在ardupilot/modules/PX4Firmware/src/modules/uORB/objects_common.cpp

#include "topics/vehicle_gps_position.h"
ORB_DEFINE(vehicle_gps_position, struct vehicle_gps_position_s);
/**
 * Define (instantiate) the uORB metadata for a topic.
 *
 * The uORB metadata is used to help ensure that updates and
 * copies are accessing the right data.
 *
 * Note that there must be no more than one instance of this macro
 * for each topic.
 *
 * @param _name		The name of the topic.
 * @param _struct	The structure the topic provides.
 */
#define ORB_DEFINE(_name, _struct)			\
	const struct orb_metadata __orb_##_name = {	\
		#_name,					\
		sizeof(_struct)				\
	}; struct hack

__BEGIN_DECLS
这样就把vehicle_gps_position和结构体vehicle_gps_position_s对应起来了

ORB_DECLARE(vehicle_gps_position);

ardupilot/modules/PX4Firmware/src/modules/uORB/uOrb.h

/**
 * ORB_DECLARE的宏定义,实际上就是让外界可以使用_name这个所表示的结构体数据
 */
#if defined(__cplusplus)
# define ORB_DECLARE(_name)     extern "C" const structorb_metadata __orb_##_name __EXPORT
# defineORB_DECLARE_OPTIONAL(_name)    extern "C"const struct orb_metadata __orb_##_name __EXPORT
#else
# define ORB_DECLARE(_name)     extern const struct orb_metadata__orb_##_name __EXPORT
# defineORB_DECLARE_OPTIONAL(_name)    externconst struct orb_metadata __orb_##_name __EXPORT
#endif
接着通过ORB_ID(vehicle_gps_position)   产生一个指针指向结构体vehicle_gps_position_s

#define ORB_ID(_name)	&__orb_##_name
至此将数据结构体定义与函数的输入联系起来了
接下来就是分析以下函数的使用过程

ardupilot/libraries/AP_GPS/AP_GPS_PX4.cpp

orb_check(_gps_sub, &updated);

orb_copy(ORB_ID(vehicle_gps_position), _gps_sub, &_gps_pos);

_gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position));

ardupilot/modules/PX4Firmware/src/drives/gps/gps.cpp

orb_publish(ORB_ID(vehicle_gps_position), _report_gps_pos_pub, &_report_gps_pos);

orb_advert_t _report_gps_pos_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report_gps_pos);

1.发送方

首先按以上方式建立好数据结构vehicle_gps_position_svehicle_gps_position_s(用于进程间通讯)

然后通过读取传感器得到具体的数据,存入结构体中

对发布主题进行公告,同时获取公告主题的句柄

orb_advert_t _report_gps_pos_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report_gps_pos);

最后用orb_publish(ORB_ID(vehicle_gps_position), _report_gps_pos_pub, &_report_gps_pos); 结合之前获得的主题ID和句柄以及结构体完成数据发布。

至此,数据发布完毕。为了满足编译的条件,我们要添加ardupilot/modules/PX4Firmware/src/drives/gps/module.mk

MODULE_COMMAND	= gps

SRCS		= gps.cpp \
		  gps_helper.cpp \
		  mtk.cpp \
		  ashtech.cpp \
		  ubx.cpp

MODULE_STACKSIZE = 1200

MAXOPTIMIZATION	 = -Os
2.接收方

首先用_gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position));进行订阅

有的其它数据需要设置订阅的查询时间间隔(GPS暂时没看到需要设置)比如

ardupilot/modules/PX4Firmware/src/drives/px4fmu/fmu.cpp

for (unsigned i = 0; i < actuator_controls_s::NUM_ACTUATOR_CONTROL_GROUPS; i++) {
			if (_control_subs[i] > 0) {
				orb_set_interval(_control_subs[i], update_rate_in_ms);
			}
		}
建立pollfd结构体,用于查询设备状态
/* This is the Nuttx variant of the standard pollfd structure. */

struct pollfd
{
  int         fd;       /* The descriptor being polled */
  sem_t      *sem;      /* Pointer to semaphore used to post output event */
  pollevent_t events;   /* The input event flags */
  pollevent_t revents;  /* The output event flags */
  FAR void   *priv;     /* For use by drivers */
};
ardupilot/modules/PX4Firmware/src/drives/gps/gps_helper.cpp

int
GPS_Helper::poll_or_read(int fd, uint8_t *buf, size_t buf_length, uint64_t timeout)
{

#ifndef __PX4_QURT

	/* For non QURT, use the usual polling. */

	pollfd fds[1];//建立pollfd结构体,用于查询设备状态
	fds[0].fd = fd;//赋值
	fds[0].events = POLLIN;//赋值


	/* Poll for new data,  */
	int ret = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout);//阻塞timeout秒,返回值:0表示未跟新数据,<0表示数据跟新错误,其它表示主题状态发生改变

	if (ret > 0) {
		/* if we have new data from GPS, go handle it */
		if (fds[0].revents & POLLIN) {       //判断主题产生了跟新
			/*
			 * We are here because poll says there is some data, so this
			 * won't block even on a blocking device. But don't read immediately
			 * by 1-2 bytes, wait for some more data to save expensive read() calls.
			 * If more bytes are available, we'll go back to poll() again.
			 */
			usleep(GPS_WAIT_BEFORE_READ * 1000);
			return ::read(fd, buf, buf_length);

		} else {
			return -1;
		}

	} else {
		return ret;
	}

#else
	/* For QURT, just use read for now, since this doesn't block, we need to slow it down
	 * just a bit. */
	usleep(10000);
	return ::read(fd, buf, buf_length);
#endif
}

到此为设置订阅的查询时间间隔

接下来是

利用_gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position));订阅主题,并获取相应的句柄_gps_sub

利用orb_check(_gps_sub, &updated);检查主题是否跟新,其中bool updated = false;

利用orb_copy(ORB_ID(vehicle_gps_position), _gps_sub, &_gps_pos);接收跟新的主题

最后在ardupilot/mk/PX4/px4_common.mk中添加

#MODULES	+= drivers/gps
至于以下函数具体细节暂不探讨,知道是这样用

ardupilot/libraries/AP_GPS/AP_GPS_PX4.cpp

orb_check(_gps_sub, &updated);

orb_copy(ORB_ID(vehicle_gps_position), _gps_sub, &_gps_pos);

_gps_sub = orb_subscribe(ORB_ID(vehicle_gps_position));

ardupilot/modules/PX4Firmware/src/drives/gps/gps.cpp

orb_publish(ORB_ID(vehicle_gps_position), _report_gps_pos_pub, &_report_gps_pos);

orb_advert_t _report_gps_pos_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_report_gps_pos);


抛砖引玉:一定要戳我,神来之笔


如果您觉得此文对您的发展有用,请随意打赏。 
您的鼓励将是笔者书写高质量文章的最大动力^_^!!


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pixhawk uORB初步分析 的相关文章

随机推荐

  • Linux环境下下载pydicom

    Linux中只要使用命令即可 sudo pip install pydicom 如果出现sudo xff1a pip xff1a command not found 把sudo去掉 xff0c 再操作一次 因为在执行Linux命令时 xff
  • C语言编程实现汉诺塔问题

    C语言编程实现汉诺塔问题 1 首先解释一下 xff0c 汉诺塔问题 xff1a 古代梵塔内有A B C3个座 xff0c 开始时A座上面有64个盘子 xff0c 盘子大小不等 xff0c 大的在下 xff0c 小的在上 一个老和尚想把64个
  • ORA-28000: the account is locked

    原因 xff1a Oracle账户多次以错误密码登录 xff0c 导致数据库服务器宕机 xff0c 账户被锁定 以系统账户sys 登录Oracle xff0c 查看sql SELECT FROM DBA PROFILES WHERE RES
  • Docker镜像编译方式

    1 普通Dockerfile的缺点 我们通常情况下要编译Spring Boot的Docker镜像 xff0c 一般会写一个下面这样的Dockerfile FROM openjdk span class token operator span
  • Python入门第一章笔记 从安装到编写hello world

    1 下载Python安装包 xff1b 可以到官网下载 xff1a https www python org 但是如果没有翻墙的话 xff0c 下载会很慢 25M安装包 xff0c 需要1个小时以上 如果没有耐心等可以在csdn进行下载 x
  • 养老产业政策链接

    江西省养老政策文件 xff1a 江西省养老服务条例 http mzw ganzhou gov cn gzsmzjy c103172 202201 d238525b35bb47b49b3de312c9b63a60 shtml 南昌市养老服务体
  • 我多变的2013

    我多变的2013 第一篇 xff1a 回顾 回顾工作 首先简单的做个自我介绍吧 xff0c 我是87年的 xff0c 北漂已经是第5个年头了 xff0c 一直都从事java开发工作 前后只换过一家公司 xff0c 第一家待了近两年 xff0
  • 我花1200大洋所学的“元学习课”究竟学了些什么?

    我花1200大洋所学的 元学习课 究竟学了些什么 xff1f 讲课的是台湾的一位大牛名叫Xdite xff0c 以及亿万富豪李笑来 能够跟牛人学习怎么学习我想应该不会有错吧 xff0c 对我来说这次做的应该是一次正确的决定 xff0c 所谓
  • 成长记录-开启我的新生 (2016-12-06)

    真的是很惊险 xff0c 我差一点就错过了 获得新生 的机会 xff0c 我在蜻蜓音频中听到了逻辑思维 xff0c 从逻辑思维中了解到了 得到 xff0c 从 得到 中订阅了吴军博士的 硅谷来信 xff0c 却在过去的好几个月里 xff0c
  • 最新Java电子书

    最新Java电子书 JAVA参考大全 J2SE 5EDITION 世界级程序设计大师作品 Thinking in Java第三版 43 第四版 xff08 中文版 43 习题答案 xff09 Java数据库高级编程宝典 Java核心技术第八
  • ELK-ElasticSearch权威指南笔记

    ELK ElasticSearch笔记 文章目录 ELK ElasticSearch笔记 前言测试工具 语法索引 xff0c 文档和类型文档元数据检索索引里文档数据查看当前节点的所有 Index查看所有index的mapping 映射 查看
  • 关于JAVA中内存溢出的解决办法

    关于JAVA中内存溢出的解决办法 J2ee应用系统是运行在J2EE应用服务器上的 xff0c 而j2ee应用服务器又是运行在JVM上的 xff0c 生成环境中JVM参数的优化和设置对于J2EE应用系统性能有着决定性的作用 要优化系统 xff
  • ireport的使用总结

    ireport的使用总结 截图居然都没显示出来 xff0c 如有需要可以到 xff08 http download csdn net detail czp0608 4140640 xff09 下载 相信很多java程序员们 xff0c 在开
  • 卡尔曼滤波C代码分析

    文章下载地址 xff1a http wenku baidu com view 3c42b7733186bceb18e8bb29
  • 作为一个新人,怎样学习嵌入式Linux?

    作为一个新人 xff0c 怎样学习嵌入式Linux xff1f 被问过太多次 xff0c 特写这篇文章来回答一下 在学习嵌入式Linux之前 xff0c 肯定要有C语言基础 汇编基础有没有无所谓 就那么几条汇编指令 xff0c 用到了一看就
  • pixhawk启动脚本分析

    Nuttx系统启动是由ardupilot mk PX4 ROMFS init d里的rcS和rc APM完成的 笔者阅读了rcS和rc APM xff0c 该脚本类似C语言 xff0c 并做了相关注释 主要是一些设备自检 xff0c 启动各
  • pixhawk ArduPilot_main启动与运行分析

    上节分析 2 个系统启动脚本 xff0c 一个是 ardupilot mk PX4 ROMFS init d 里的 rcS xff0c 另一个是 rc APM xff0c 这个脚本在 rcS 里得到了调用 xff0c 也就是说 xff0c
  • pixhawk make文件分析

    由于笔者没学过Linux等系统 xff0c 对make文件所知甚少 xff0c 本节分析可能有大量错误 xff0c 只提供参考 xff0c 随着技术积累 xff0c 以后会回过头改正错误的地方 xff0c 也非常欢迎提出指导意见 其中分析大
  • pixhawk 从main开始分析传感器数据如何流动起来,以GPS为例

    void Copter loop scheduler run time available gt MAIN LOOP MICROS 0u time available 本文以GPS数据为代表 xff0c 分析数据如何从硬件驱动层慢慢的流到主
  • pixhawk uORB初步分析

    再次编辑 xff0c 因为发现大神的解析 xff0c 添加在最后 xff0c 若一般人我不告诉他 根据自己理解画的流程图 xff1a xff08 2016 05 29加 xff09 由于上节分析GPS涉及到AP GPS PX4 read函数