ArduPilot开源飞控之AP_Baro_SITL
ArduPilot开源飞控之AP_Baro_SITL
- 1. 源由
- 2. back-end抽象类
- 3. 方法实现
- 3.1 AP_Baro_SITL
- 3.2 _timer
- 3.3 temperature_adjustment
- 3.4 wind_pressure_correction
- 3.5 update
- 4. 参考资料
1. 源由
鉴于ArduPilot开源飞控之AP_Baro中涉及Sensor Driver有以下总线类型:
- I2C
- Serial UART
- CAN
- SITL //模拟传感器(暂时并列放在这里)
ArduPilot之开源代码Sensor Drivers设计的front-end / back-end分层设计思路,AP_Baro主要描述的是front-end。
为了AP_Baro代码研读的完整性,就继续简单的整理下下针对AP_Baro_SITL研读和理解。
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. 方法实现
AP_Baro_SITL是一个模拟器件,其气压数据来源于模拟系统,对于模拟系统这里不展开,其传递参量的主要方式是全局变量_sitl->state.altitude。
3.1 AP_Baro_SITL
实例初始化,注册一个定时回调函数。
AP_Baro_SITL::AP_Baro_SITL└──> <_sitl != nullptr>├──> _instance = _frontend.register_sensor();├──> <APM_BUILD_TYPE(APM_BUILD_ArduSub)>│ └──> _frontend.set_type(_instance, AP_Baro::BARO_TYPE_WATER);├──> set_bus_id(_instance, AP_HAL::Device::make_bus_id(AP_HAL::Device::BUS_TYPE_SITL, 0, _instance, DEVTYPE_BARO_SITL));││ /********************************************************************************│ * start periodic call back *│ ********************************************************************************/└──> hal.scheduler->register_timer_process(FUNCTOR_BIND(this, &AP_Baro_SITL::_timer, void));
3.2 _timer
定时模拟高度数据(这里不涉及温度的校准,但是做了一些模拟的噪音,比如:baro glitch/drift/noise/temperature/wind)。
AP_Baro_SITL::_timer│ /********************************************************************************│ * 100Hz *│ ********************************************************************************/├──> const uint32_t now = AP_HAL::millis();├──> <(now - _last_sample_time) < 10>│ └──> return;│├──> _last_sample_time = now;├──> float sim_alt = _sitl->state.altitude;├──> <_sitl->baro[_instance].disable>│ └──> return; // barometer is disabled││ /********************************************************************************│ * Update simulated altitude *│ ********************************************************************************/│ // Noise for simulated altitude├──> sim_alt += _sitl->baro[_instance].drift * now * 0.001f;├──> sim_alt += _sitl->baro[_instance].noise * rand_float();││ // add baro glitch├──> sim_alt += _sitl->baro[_instance].glitch;││ // add delay├──> uint32_t best_time_delta = 200; // initialise large time representing buffer entry closest to current time - delay.├──> uint8_t best_index = 0; // initialise number representing the index of the entry in buffer closest to delay.││ // storing data from sensor to buffer├──> <now - _last_store_time >= 10> // store data every 10 ms.│ ├──> _last_store_time = now;│ ├──> <_store_index > _buffer_length - 1> │ │ └──> _store_index = 0; // reset buffer index if index greater than size of buffer│ ││ │ // if freezed barometer, report altitude to last recorded altitude│ ├──> <_sitl->baro[_instance].freeze == 1>│ │ └──> sim_alt = _last_altitude;│ ├──> < else >│ │ └──> _last_altitude = sim_alt;│ ││ ├──> _buffer[_store_index].data = sim_alt; // add data to current index│ ├──> _buffer[_store_index].time = _last_store_time; // add time_stamp to current index│ └──> _store_index = _store_index + 1; // increment index││ // return delayed measurement├──> const uint32_t delayed_time = now - _sitl->baro[_instance].delay; // get time corresponding to delay││ // find data corresponding to delayed time in buffer├──> <for (uint8_t i = 0; i <= _buffer_length - 1; i++)>│ │ // find difference between delayed time and time stamp in buffer│ ├──> uint32_t time_delta = abs((int32_t)(delayed_time - _buffer[i].time));│ │ // if this difference is smaller than last delta, store this time│ └──> <time_delta < best_time_delta>│ ├──> best_index = i;│ └──> best_time_delta = time_delta;│├──> <best_time_delta < 200> // only output stored state if < 200 msec retrieval error│ └──> sim_alt = _buffer[best_index].data;││ /********************************************************************************│ * Temperature adjust *│ ********************************************************************************/├──> <!APM_BUILD_TYPE(APM_BUILD_ArduSub)>│ ├──> float sigma, delta, theta;│ ├──> AP_Baro::SimpleAtmosphere(sim_alt * 0.001f, sigma, delta, theta);│ ├──> float p = SSL_AIR_PRESSURE * delta;│ ├──> float T = KELVIN_TO_C(SSL_AIR_TEMPERATURE * theta);│ └──> temperature_adjustment(p, T);├──> <else>│ ├──> float rho, delta, theta;│ ├──> AP_Baro::SimpleUnderWaterAtmosphere(-sim_alt * 0.001f, rho, delta, theta);│ ├──> float p = SSL_AIR_PRESSURE * delta;│ └──> float T = KELVIN_TO_C(SSL_AIR_TEMPERATURE * theta);││ /********************************************************************************│ * add in correction for wind effects *│ ********************************************************************************/├──> p += wind_pressure_correction(_instance);│├──> _recent_press = p;├──> _recent_temp = T;└──> _has_sample = true;
3.3 temperature_adjustment
温度模拟修正。
AP_Baro_SITL::temperature_adjustment├──> const float tsec = AP_HAL::millis() * 0.001f;├──> const float T_sensor = T + AP::sitl()->temp_board_offset;├──> const float tconst = AP::sitl()->temp_tconst;├──> <tsec < 23 * tconst> // time which past the equation below equals T_sensor within approx. 1E-9│ ├──> const float T0 = AP::sitl()->temp_start;│ └──> T = T_sensor - (T_sensor - T0) * expf(-tsec / tconst);├──> < else >│ └──> T = T_sensor;├──> const float baro_factor = AP::sitl()->temp_baro_factor;├──> const float Tzero = 30.0f; // start baro adjustment at 30C└──> <is_positive(baro_factor)>│ // this produces a pressure change with temperature that│ // closely matches what has been observed with a ICM-20789│ // barometer. A typical factor is 1.2.└──> p -= powf(MAX(T - Tzero, 0), baro_factor);
3.4 wind_pressure_correction
风力压强修正。
AP_Baro_SITL::wind_pressure_correction├──> const auto &bp = AP::sitl()->baro[instance];││ // correct for static pressure position errors├──> const Vector3f &airspeed_vec_bf = AP::sitl()->state.velocity_air_bf;│├──> float error = 0.0;├──> const float sqx = sq(airspeed_vec_bf.x);├──> const float sqy = sq(airspeed_vec_bf.y);├──> const float sqz = sq(airspeed_vec_bf.z);││ // error for x├──> <is_positive(airspeed_vec_bf.x)>│ └──> error += bp.wcof_xp * sqx;├──> < else >│ └──> error += bp.wcof_xn * sqx;││ // error for y├──> <is_positive(airspeed_vec_bf.y)>│ └──> error += bp.wcof_yp * sqy;├──> < else >│ └──> error += bp.wcof_yn * sqy;││ // error for z├──> <is_positive(airspeed_vec_bf.z)>│ └──> error += bp.wcof_zp * sqz;├──> < else >│ └──> error += bp.wcof_zn * sqz;│└──> return error * 0.5 * SSL_AIR_DENSITY * AP::baro().get_air_density_ratio();
3.5 update
front-end / back-end数据更新。
AP_Baro_SITL::update├──> <!_has_sample>│ └──> return;├──> WITH_SEMAPHORE(_sem);├──> _copy_to_frontend(_instance, _recent_press, _recent_temp);└──> _has_sample = false;
4. 参考资料
【1】ArduPilot开源飞控系统之简单介绍
【2】ArduPilot之开源代码Task介绍
【3】ArduPilot飞控启动&运行过程简介
【4】ArduPilot之开源代码Library&Sketches设计
【5】ArduPilot之开源代码Sensor Drivers设计
相关文章:
ArduPilot开源飞控之AP_Baro_SITL
ArduPilot开源飞控之AP_Baro_SITL 1. 源由2. back-end抽象类3. 方法实现3.1 AP_Baro_SITL3.2 _timer3.3 temperature_adjustment3.4 wind_pressure_correction3.5 update 4. 参考资料 1. 源由 鉴于ArduPilot开源飞控之AP_Baro中涉及Sensor Driver有以下总线类型: …...
基于Java的病人跟踪治疗管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…...
RCD吸收电路的工作原理及参数计算方法详解
在电子电力技术和自动化控制领域内,RCD吸收电路非常重要,它的作用是吸收瞬间过电压和过电路免受电压波动的影响,因此被广泛应用在各种设备及系统中,今天凡亿将带领小伙伴们来了解下RCD吸收电路的工作原理及计算方法。 1、RCD吸收电…...
leetcode做题笔记169. 多数元素
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入:nums [3,2,3] 输出:3 示例 …...
FATFS f_printf 如何支持写入浮点数据。
参考原子和网上的移植最新的fatfs系统后,挂载打开文件始终返回13错误代码,在自己的项目中移植最新的fatfs0.15版本解决问题,使用f_printf能成功进行浮点数据写入了 参考的文章如下: https://zhuanlan.zhihu.com/p/444427537 问题描述 在使用fatfs的f_printf向文件.csv中写入…...
postman忘记密码提交没响应
现象:通过客户端进到账户页面一直无响应,可copy the url 到浏览器进入页面,使用浏览器提交几次还是没响应。 实测有用方法: 1、通过手机进入官网 https://www.getpostman.com ,找到忘记密码入口。 2、多提交几次后&…...
初学vue,想自己找个中长期小型项目练练手,应该做什么?
前言 可以试着做一两个完整的后台管理项目后再去做其他的,下面推荐一些github上的vue后台管理的项目,可以自己选择性的练一下手 Vue2 1、iview-admin Star: 16.4k 基于 iview组件库开发的一款后台管理系统框架,提供了一系列的强大组件和基…...
【牛客面试必刷TOP101】Day11.BM63 跳台阶和 BM67 不同路径的数目(一)
作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:牛客面试必刷TOP101 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!!&…...
[NOIP 2022] 建造军营 题解
题目 P1 边双缩点 观察样例二,可以发现边双内的边可选可不选。由此考虑边双缩点,Tarjan 找桥即可,缩点后变成一棵树。 P2 设计状态 用最终合法答案形态截这颗树,设计 f u f_u fu 表示 u u u 子树内非空,且子树…...
射频识别技术(RFID)在智能制造模具管理中的应用
背景介绍 模具是工业生产的核心装备,被誉为“工业之母”,广泛应用于机械、汽车、轻工、电子、化工、冶金、建材等各个行业,是制造加工企业的重要资产,然而,传统的人工纸质记录方式已无法满足模具管理的需求࿰…...
奖品定制经营商城小程序的作用是什么
奖品是激励人员团体很好的方式,也是荣誉象征,奖牌、奖杯、高端礼盒等,同时市场中团体非常多,其需求也是很多,尤其定制方面,就更是不用说。 对奖品定制企业来说,除了线下门店获客经营外…...
深度学习常用脚本总结
👨💻个人简介: 深度学习图像领域工作者 🎉工作总结链接:https://blog.csdn.net/qq_28949847/article/details/128552785 链接中主要是个人工作的总结,每个链接都是一些常用demo,…...
hive数据表创建
目录 分隔符 分区表 二级分区 分桶表 外部表 分隔符 CREATE TABLE emp( userid bigint, emp_name array<string>, emp_date map<string,date>, other_info struct<deptname:string, gender:string>) ROW FORMAT DELIMITED FIELDS TERMINATED BY \t COL…...
查看本机Arp缓存,以及清除arp缓存
查看Arp缓存目录 Windows 系统使用 winR,输入cmd 在命令窗口输入 arp -a 删除Arp缓存目录 在命令窗口输入 arp -d * 查看主机路由表...
Unity MRTK Hololens2眼动交互
/** ** UnityVersion : 2021.3.6f1* Description : 眼部交互基类* Author: * CreateTime : 2023-10-11 09:43:20* Version : V1.0.0* * */using System.Collections.Generic; using Microsoft.MixedReality.Toolkit.Input; using UnityEngine;namespace MRTKExtend.EyeTrackin…...
接口自动化测试 —— 协议、请求流程
一、架构 CRM客户关系管理系统 SAAS Software As A Service 软件即服务 PAAS Platform AS A Service 平台即服务 快速交付→ 快:自己去干、有结果、事事有回音、持续改进 单体架构——》垂直架构——》面向服务架构——》微服务架构(分布式…...
JDK安装详细教程
JDK安装详细教程 国内大多数使用的是1.8的版本,对于初学者来说这个版本很友善,不过由于我安装过了1.8,所以我这里演示JDK21 的安装,过程并无区别,只在下载时注意选择1.8版本。1.8就是JDK8. 文章目录 JDK安装详细教程一…...
vulnhub_Fowsniff靶机渗透测试
Fowsniff靶机 靶机地址:https://www.vulnhub.com/entry/fowsniff-1,262/ 文章目录 Fowsniff靶机信息收集web渗透密码碰撞POP3邮件服务器渗透获取权限权限提升靶机总结 信息收集 通过nmap扫描,靶机开放22 80 110 143端口,110是pop3邮件服务…...
FPGA面试题(3)
一.FPGA和CPLD区别 FPGA:现场可编程门阵列CPLD:复杂可编程逻辑器件 二.多位异步信号如何同步 单比特异步信号 慢时钟域->快时钟域:同步打拍快时钟域->慢时钟域:先拓展位宽再同步打拍 多比特异步信号 1.异步FIFO2.保持…...
Avalonia常用小控件Menu
1.项目下载地址:https://gitee.com/confusedkitten/avalonia-demo 2.UI库Semi.Avalonia,项目地址 https://github.com/irihitech/Semi.Avalonia 样式预览: axaml代码 : <UserControl xmlns"https://github.com/avalo…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
