ArduPilot开源飞控之AP_Baro_DroneCAN
ArduPilot开源飞控之AP_Baro_DroneCAN
- 1. 源由
- 2. back-end抽象类
- 3. 方法实现
- 3.1 probe
- 3.2 update
- 3.3 subscribe_msgs
- 3.4 handle_pressure/handle_temperature
- 3.5 CAN port
- 4. 参考资料
1. 源由
鉴于ArduPilot开源飞控之AP_Baro中涉及Sensor Driver有以下总线类型:
- I2C
- Serial UART
- CAN
- SITL //模拟传感器(暂时并列放在这里)
ArduPilot之开源代码Sensor Drivers设计的front-end / back-end分层设计思路,AP_Baro主要描述的是front-end。
为了更好的从整体理解气压计这个传感器的嵌入式应用,这里深入到back-end驱动层,针对基于CAN协议的气压计设备,进行一个研读和理解。
2. back-end抽象类
AP_Baro_Backend驱动层需实现方法:
- void update()
- static AP_Baro_Backend *probe(AP_Baro &baro, AP_HAL::OwnPtr<AP_HAL::Device> dev)
注:通常来说使用ChibiOS的都有定时器,如果没有定时器,可以使用void accumulate(void)来实现传感器的数据定时获取。
class AP_Baro_Backend
{
public:AP_Baro_Backend(AP_Baro &baro);virtual ~AP_Baro_Backend(void) {};// each driver must provide an update method to copy accumulated// data to the frontendvirtual void update() = 0;// accumulate function. This is used for backends that don't use a// timer, and need to be called regularly by the main code to// trigger them to read the sensorvirtual void accumulate(void) {}void backend_update(uint8_t instance);// Check that the baro valid by using a mean filter.// If the value further that filtrer_range from mean value, it is rejected.bool pressure_ok(float press);uint32_t get_error_count() const { return _error_count; }#if AP_BARO_MSP_ENABLEDvirtual void handle_msp(const MSP::msp_baro_data_message_t &pkt) {}
#endif#if AP_BARO_EXTERNALAHRS_ENABLEDvirtual void handle_external(const AP_ExternalAHRS::baro_data_message_t &pkt) {}
#endif/*device driver IDs. These are used to fill in the devtype fieldof the device ID, which shows up as BARO_DEVID* parameters tousers.*/enum DevTypes {DEVTYPE_BARO_SITL = 0x01,DEVTYPE_BARO_BMP085 = 0x02,DEVTYPE_BARO_BMP280 = 0x03,DEVTYPE_BARO_BMP388 = 0x04,DEVTYPE_BARO_DPS280 = 0x05,DEVTYPE_BARO_DPS310 = 0x06,DEVTYPE_BARO_FBM320 = 0x07,DEVTYPE_BARO_ICM20789 = 0x08,DEVTYPE_BARO_KELLERLD = 0x09,DEVTYPE_BARO_LPS2XH = 0x0A,DEVTYPE_BARO_MS5611 = 0x0B,DEVTYPE_BARO_SPL06 = 0x0C,DEVTYPE_BARO_UAVCAN = 0x0D,DEVTYPE_BARO_MSP = 0x0E,DEVTYPE_BARO_ICP101XX = 0x0F,DEVTYPE_BARO_ICP201XX = 0x10,DEVTYPE_BARO_MS5607 = 0x11,DEVTYPE_BARO_MS5837 = 0x12,DEVTYPE_BARO_MS5637 = 0x13,DEVTYPE_BARO_BMP390 = 0x14,};protected:// reference to frontend objectAP_Baro &_frontend;void _copy_to_frontend(uint8_t instance, float pressure, float temperature);// semaphore for access to shared frontend dataHAL_Semaphore _sem;virtual void update_healthy_flag(uint8_t instance);// mean pressure for range filterfloat _mean_pressure; // number of dropped samples. Not used for now, but can be usable to choose more reliable sensoruint32_t _error_count;// set bus ID of this instance, for BARO_DEVID parametersvoid set_bus_id(uint8_t instance, uint32_t id) {_frontend.sensors[instance].bus_id.set(int32_t(id));}
};
3. 方法实现
由于气压数据来自CAN总线,因此,其逻辑与MSP协议类似,相对简单,没有校准等复杂物理公式。
3.1 probe
实例初始化。
AP_Baro_DroneCAN::probe├──> WITH_SEMAPHORE(_sem_registry);├──> AP_Baro_DroneCAN* backend = nullptr;│├──> <for (uint8_t i = 0; i < BARO_MAX_DRIVERS; i++)>│ └──> <_detected_modules[i].driver == nullptr && _detected_modules[i].ap_dronecan != nullptr>│ ││ │ /********************************************************************************│ │ * Registered DroneCAN Baro Node *│ │ ********************************************************************************/│ ├──> backend = new AP_Baro_DroneCAN(baro);│ ├──> <backend == nullptr>│ │ └──> AP::can().log_text(AP_CANManager::LOG_ERROR,LOG_TAG,│ │ "Failed register DroneCAN Baro Node %d on Bus %d\n",│ │ _detected_modules[i].node_id,│ │ _detected_modules[i].ap_dronecan->get_driver_index());│ ├──> <else>│ │ ├──> _detected_modules[i].driver = backend;│ │ ├──> backend->_pressure = 0;│ │ ├──> backend->_pressure_count = 0;│ │ ├──> backend->_ap_dronecan = _detected_modules[i].ap_dronecan;│ │ ├──> backend->_node_id = _detected_modules[i].node_id;│ │ ├──> backend->_instance = backend->_frontend.register_sensor();│ │ ├──> backend->set_bus_id(backend->_instance, AP_HAL::Device::make_bus_id(AP_HAL::Device::BUS_TYPE_UAVCAN,│ │ │ _detected_modules[i].ap_dronecan->get_driver_index(),│ │ │ backend->_node_id, 0));│ │ └──> AP::can().log_text(AP_CANManager::LOG_INFO,LOG_TAG,│ │ "Registered DroneCAN Baro Node %d on Bus %d\n",│ │ _detected_modules[i].node_id,│ │ _detected_modules[i].ap_dronecan->get_driver_index());│ └──> break;└──> return backend;
3.2 update
front-end / back-end数据更新。
AP_Baro_DroneCAN::update├──> float pressure = 0;├──> WITH_SEMAPHORE(_sem_baro);└──> <new_pressure>├──> <_pressure_count != 0>│ ├──> pressure = _pressure / _pressure_count;│ ├──>_pressure_count = 0;│ └──>_pressure = 0;├──> _copy_to_frontend(_instance, pressure, _temperature);├──> _frontend.set_external_temperature(_temperature);└──> new_pressure = false;
3.3 subscribe_msgs
CAN协议消息处理钩子。
AP_Baro_DroneCAN::subscribe_msgs├──> ap_dronecan == nullptr>│ └──> return;├──> <Canard::allocate_sub_arg_callback(ap_dronecan, &handle_pressure, ap_dronecan->get_driver_index()) == nullptr>│ └──> AP_BoardConfig::allocation_error("pressure_sub");└──> <Canard::allocate_sub_arg_callback(ap_dronecan, &handle_temperature, ap_dronecan->get_driver_index()) == nullptr>└──> AP_BoardConfig::allocation_error("temperature_sub");
3.4 handle_pressure/handle_temperature
处理CAN协议中气压数据。
AP_Baro_DroneCAN::handle_pressure├──> WITH_SEMAPHORE(_sem_registry);├──> driver = get_dronecan_backend(ap_dronecan, transfer.source_node_id, true);├──> <driver == nullptr>│ └──> return;└──> WITH_SEMAPHORE(driver->_sem_baro);├──> _update_and_wrap_accumulator(&driver->_pressure, msg.static_pressure, &driver->_pressure_count, 32);└──> driver->new_pressure = true;
处理CAN协议中温度数据。
AP_Baro_DroneCAN::handle_temperature├──> WITH_SEMAPHORE(_sem_registry);├──> driver = get_dronecan_backend(ap_dronecan, transfer.source_node_id, false);├──> <driver == nullptr>│ └──> return;└──> WITH_SEMAPHORE(driver->_sem_baro);└──> driver->_temperature = KELVIN_TO_C(msg.static_temperature);
3.5 CAN port
目前的官方文档有不一致的问题,希望后续能有完善和更新。
- 【1】Inconsistent CAN startup documentation
- 【2】Inconsistent CAN startup documentation #5475
init_ardupilot└──> AP_CANManager::init└──> AP_DroneCAN::init└──> AP_Baro_DroneCAN::subscribe_msgs
4. 参考资料
【1】ArduPilot开源飞控系统之简单介绍
【2】ArduPilot之开源代码Task介绍
【3】ArduPilot飞控启动&运行过程简介
【4】ArduPilot之开源代码Library&Sketches设计
【5】ArduPilot之开源代码Sensor Drivers设计
相关文章:
ArduPilot开源飞控之AP_Baro_DroneCAN
ArduPilot开源飞控之AP_Baro_DroneCAN 1. 源由2. back-end抽象类3. 方法实现3.1 probe3.2 update3.3 subscribe_msgs3.4 handle_pressure/handle_temperature3.5 CAN port 4. 参考资料 1. 源由 鉴于ArduPilot开源飞控之AP_Baro中涉及Sensor Driver有以下总线类型: …...
Supervised Contrastive Pre-training for Mammographic Triage Screening Model
方法 品红色箭头表示将生成的孪生编码器分别迁移到单视角学习模块和双视角学习模块...
JVM技术文档--JVM优化思路以及问题定位--JVM可调整参数汇总
阿丹: 一个优秀的程序员,是因为在线上的排查以及遇到的线上、生产事故较多所以定位问题以及解决问题会比普通程序员快很多,所以一个优秀的程序员要逐渐形成自己的方法论,来完善和解决问题。 我们是如何发现问题的呢? …...
Oracle10g数据库迁移方案
试验了很多次Oracle数据库迁移才成功,贴出来给大家参考一下,我看到有的地方写迁移之后还需要重新建立temp表空间,这个还没有研究。另外说一点的是两个数据库的版本一定要一致,之前失败过一次,就是因为两个数据库的版本…...
备忘录模式:对象状态的保存与恢复
欢迎来到设计模式系列的第十八篇文章,本篇将介绍备忘录模式。备忘录模式是一种行为型设计模式,它允许在不破坏封装性的前提下捕获一个对象的内部状态,并在之后恢复该状态。这种模式通常用于需要提供撤销操作的情况。 什么是备忘录模式&#…...
C# InvokeRequired线程安全
C# InvokeRequired线程安全 为了保证新家的线程可能要对主界面的控件元素的属性发生一些改变,此时防止此操作对于主线程的影响,就提出了 InvokeRequired方法,保证主线程的安全,同时新加的线程也可以改变主页面中元素的值。 定义…...
pdf怎么转成jpg图片格式
pdf怎么转成jpg图片格式?对于大家平时在工作或者生活中的图片使用习惯,经常需要将各种格式的文件转换成易于浏览和使用的JPG格式图片以便保存。如今,因为pdf文件具有更强的稳定性和设备兼容性,PDF文件在平时的电脑使用过程中可以说…...
React +ts + babel+webpack
babel babel/preset-typescript 专门处理ts "babel/cli": "^7.17.6", "babel/core": "^7.17.8", "babel/preset-env": "^7.16.11", "babel/preset-react": "^7.16.7", "babel/preset…...
红队专题-REVERSE二进制逆向反编译
红队专题 招募六边形战士队员IDA pro安装python2加入环境变量py2安装pip安装IDA 7.0 proIDAPython: importing "site" failed. 招募六边形战士队员 一起学习 代码审计、安全开发、web攻防、逆向等。。。 私信联系 IDA pro 安装python2 python-2.7.3.msi 加入环…...
Spring技术原理之Bean生命周期原理解析
Spring技术原理之Bean生命周期原理解析 Spring作为Java领域中的优秀框架,其核心功能之一是依赖注入和生命周期管理。其中,Bean的生命周期管理是Spring框架中一个重要的概念。在本篇文章中,我们将深入探讨Spring技术原理中的Bean生命周期原理…...
Unity实现设计模式——模板方法模式
Unity实现设计模式——模板方法模式 模板模式(Template Pattern), 指在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 简单说, 模板方法模式定义一个操作中的算法的骨架&…...
C++实现高性能内存池(二)
文章目录 一、设计内存池二、实现MemoryPool::construct() 实现MemoryPool::deallocate() 实现MemoryPool::~MemoryPool() 实现MemoryPool::allocate() 实现三、与 std::vector 的性能对比一、设计内存池 在上节中,我们在模板链表栈中使用了默认构造器来管理栈操作中的元素内…...
沪深300期权一个点多少钱?
经中国证监会批准,深圳证券交易所于2019年12月23日上市嘉实沪深300ETF期权合约品种。该产品是以沪深300为标的物的嘉实沪深300ETF交易型指数基金为标的衍生的标准化合约,下文介绍沪深300期权一个点多少钱?本文来自:期权酱 一、沪深300期权涨…...
怎么防止重要文件夹丢失?文件夹安全如何保护?
我们在使用电脑的过程中,会将重要数据放在文件夹中,那么,我们该怎么防止重要文件夹丢失呢?下面我们就一起来了解一下。 EFS加密 EFS加密可以对于NTFS卷上的文件夹进行加密,加密后的文件夹将只允许加密时登录系统的用户…...
用于物体识别和跟踪的下游任务自监督学习-1-引言
一:引言: 图像和视频理解是计算机视觉应用中的基本问题,旨在使机器能够像人类一样解释和理解视觉数据。这些问题涉及识别图像和视频中的对象、人物、动作、事件和场景。如图1.1-(a)所示的图像识别任务包括对象检测[1]…...
式子表达ds类——多用位置/值域表示未知数+区间覆盖转区间加:CF407E
https://www.luogu.com.cn/problem/CF407E 多用位置/值域表示未知数 推出的式子中 n n n 表示长度,应该直接换成 r − l 1 r-l1 r−l1 区间覆盖转区间加 推出的式子有 m x , m n mx,mn mx,mn,朴素思路是用单调队列区间覆盖维护 那样就不能很方便…...
Python 实现秒表功能(比较好玩的题目)
以下实例使用 time 模块来实现秒表功能: import time print(按下回车开始计时,按下ctrlc停止计时) while True:input("")starttimetime.time()print(开始)try:while True:print(计时:,round(time.time()-starttime,0),秒)time.sle…...
DALL-E 3调参教程;百度新出的AI写小说神器;通义听悟看播客也太爽了;系列博文带你理解生成式AI | ShowMeAI日报
👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🔥 2023年诺贝尔奖全部揭晓,一文看完6类奖项花落谁家 https://www.nobelprize.org/prizes 随着最后一项「经济学奖」的揭秘&a…...
设计模式-享元模式
概念 共享内存(主要考虑内存,而非效率)相同的数据,共享使用(JS中未找到经典应用场景) 演示 <!-- 无限下拉列表,将事件代理到高层节点上 --> <!-- 如果都绑定到<a>标签&#x…...
中秋时节赏明月,五子棋戏月饼趣 — Flutter中秋限定版五子棋
前言 当中秋时节来临,我们都期待着与亲人朋友共度这个美好的节日。这个时候,除了传统的赏月和品尝美味的月饼,我还有一个特别的建议——尝试一款有趣的Flutter五子棋游戏!这款五子棋游戏以中秋为主题,游戏的棋子也可爱…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...
