Ardupilot — EKF3使用光流室内定位代码梳理
文章目录
前言
1 Copter.cpp
1.1 void IRAM_ATTR Copter::fast_loop()
1.2 void Copter::read_AHRS(void)
1.3 对象ahrs说明
2.3 对象EKF3说明
3.2 对象core说明
前言
故事的开始,要从参数 EK3_FLOW_USE 说起。
注意:该参数适用于高级用户。
控制是否将光流数据融合到 24 状态导航估算器或 1 状态地形高度估算器中。
| RebootRequired | Values | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| True |
|
本文主要梳理一下,在旋翼中 EKF3 的整个运行流程,以及在哪一步融合光流数据进行室内定位飞行。
前置参数:
1、AHRS_EKF_TYPE = 3;
使用 EKF3 卡尔曼滤波器进行姿态和位置估算。
2、EK3_GPS_TYPE = 3;
禁止使用 GPS - 当在 GPS 质量较差、多径误差较大的环境中使用光流量传感器飞行时,这一点非常有用。
1 Copter.cpp
1.1 void IRAM_ATTR Copter::fast_loop()
Ardupilot 代码中,需求资源多,运算频率高的任务,一般在 fast_loop() 函数中。这里我们只展示和 EKF3 运行相关的代码段。
运行 EKF 状态估算器(耗资巨大)。
// Main loop - 400hz
void IRAM_ATTR Copter::fast_loop()
{...// run EKF state estimator (expensive)// --------------------read_AHRS();...
}
1.2 void Copter::read_AHRS(void)
读取姿态航向参考系统信息的入口函数。
我们告诉 AHRS 跳过 INS 更新,因为我们已经在 fast_loop() 中进行了更新。
void Copter::read_AHRS(void)
{// Perform IMU calculations and get attitude info//-----------------------------------------------
#if HIL_MODE != HIL_MODE_DISABLED// update hil before ahrs updategcs().update_receive();gcs().update_send();
#endif// we tell AHRS to skip INS update as we have already done it in fast_loop()ahrs.update(true);
}
1.3 对象ahrs说明
在 Copter.h 中,我们用 AP_AHRS_NavEKF 类定义了 ahrs 对象。
AP_AHRS_NavEKF ahrs{EKF2, EKF3, AP_AHRS_NavEKF::FLAG_ALWAYS_USE_EKF};
2 AP_AHRS_NavEKF.cpp
2.1 void AP_AHRS_NavEKF::update(bool skip_ins_update)
所以,我们在跳转 update() 这个成员函数的时候,跳转到 AP_AHRS_NavEKF 类的 update() 函数。
根据 AHRS_EKF_TYPE = 3,我们运行 update_EKF3()。
void AP_AHRS_NavEKF::update(bool skip_ins_update)
{...if (_ekf_type == 2) {// if EK2 is primary then run EKF2 first to give it CPU// priorityupdate_EKF2();update_EKF3();} else {// otherwise run EKF3 firstupdate_EKF3();update_EKF2();}...
}
2.2 void AP_AHRS_NavEKF::update_EKF3(void)
更新 EKF3。
void AP_AHRS_NavEKF::update_EKF3(void)
{...if (_ekf3_started) {EKF3.UpdateFilter();...}
}
2.3 对象EKF3说明
在 AP_AHRS_NavEKF.h 中,我们用 NavEKF3 类定义了 EKF3 对象。
NavEKF3 &EKF3;
3 AP_NavEKF3.cpp
3.1 void IRAM_ATTR NavEKF3::UpdateFilter(void)
所以,我们在跳转 UpdateFilter() 这个成员函数的时候,跳转到 NavEKF3 类的 UpdateFilter() 函数。
更新滤波器状态 - 只要有新的 IMU 数据,就应调用该函数。
// Update Filter States - this should be called whenever new IMU data is available
void IRAM_ATTR NavEKF3::UpdateFilter(void)
{if (!core) {return;}imuSampleTime_us = AP_HAL::micros64();const AP_InertialSensor &ins = AP::ins();bool statePredictEnabled[num_cores];for (uint8_t i=0; i<num_cores; i++) {// if we have not overrun by more than 3 IMU frames, and we// have already used more than 1/3 of the CPU budget for this// loop then suppress the prediction step. This allows// multiple EKF instances to cooperate on schedulingif (core[i].getFramesSincePredict() < (_framesPerPrediction+3) &&(AP_HAL::micros() - ins.get_last_update_usec()) > _frameTimeUsec/3) {statePredictEnabled[i] = false;} else {statePredictEnabled[i] = true;}core[i].UpdateFilter(statePredictEnabled[i]);}...
}
3.2 对象core说明
在 AP_NavEKF3.h 中,我们用 NavEKF3_core 类定义了 core 对象。
NavEKF3_core *core = nullptr;
4 AP_NavEKF3_core.cpp
4.1 void IRAM_ATTR NavEKF3_core::UpdateFilter(bool predict)
所以,我们在跳转 UpdateFilter() 这个成员函数的时候,跳转到 NavEKF3_core 类的 UpdateFilter() 函数。
如果缓冲区中有新的 IMU 数据,则运行 EKF 方程,在融合时间跨度上进行估算。
/********************************************************
* UPDATE FUNCTIONS *
********************************************************/
// Update Filter States - this should be called whenever new IMU data is available
void IRAM_ATTR NavEKF3_core::UpdateFilter(bool predict)
{...// Check arm status and perform required checks and mode changescontrolFilterModes();...// Run the EKF equations to estimate at the fusion time horizon if new IMU data is available in the bufferif (runUpdates) {// Predict states using IMU data from the delayed time horizonUpdateStrapdownEquationsNED();// Predict the covariance growthCovariancePrediction();// Update states using magnetometer or external yaw sensor dataSelectMagFusion();// Update states using GPS and altimeter dataSelectVelPosFusion();// Update states using range beacon dataSelectRngBcnFusion();// Update states using optical flow dataSelectFlowFusion();// Update states using body frame odometry dataSelectBodyOdomFusion();// Update states using airspeed dataSelectTasFusion();// Update states using sideslip constraint assumption for fly-forward vehiclesSelectBetaFusion();// Update the filter statusupdateFilterStatus();}...
}
这里有两个函数和 EKF3 使用光流传感器有关:controlFilterModes(),SelectFlowFusion()。
5 AP_NavEKF3_Control.cpp
5.1 void NavEKF3_core::controlFilterModes()
控制滤波器模式转换。
// Control filter mode transitions
void NavEKF3_core::controlFilterModes()
{...// Set the type of inertial navigation aiding usedsetAidingMode();...
}
5.2 void NavEKF3_core::setAidingMode()
设置所使用的惯性导航辅助类型。
我们把飞控连接 QGC,小喇叭会不断的弹出“...stopped aiding”和“...started relative aiding”消息。
根据 AidingMode 的枚举定义,分为三种情况。
1、AID_ABSOLUTE = 0;正在使用 GPS 或其他形式的绝对位置参考辅助(也可同时使用光流),因此位置估算是绝对的。
2、AID_NONE = 1;不使用辅助,因此只有姿态和高度估计值。必须使用 constVelMode 或 constPosMode 来限制倾斜漂移。
3、AID_RELATIVE = 2;只使用光流辅助,因此位置估算值将是相对的。
这里,如果光流传感器数据良好,我们运行 AID_RELATIVE;如果光流数据较差或没有,我们运行 AID_NONE。
// Set inertial navigation aiding mode
void NavEKF3_core::setAidingMode()
{...// 检查我们是否开始或停止援助,并根据需要设置状态和模式// check to see if we are starting or stopping aiding and set states and modes as requiredif (PV_AidingMode != PV_AidingModePrev) {// set various usage modes based on the condition when we start aiding. These are then held until aiding is stopped.switch (PV_AidingMode) {case AID_NONE:// We have ceased aidinggcs().send_text(MAV_SEVERITY_WARNING, "EKF3 IMU%u stopped aiding",(unsigned)imu_index);// When not aiding, estimate orientation & height fusing synthetic constant position and zero velocity measurement to constrain tilt errors// 无辅助时,利用合成恒定位置和零速度测量来估计方位和高度,以限制倾斜误差...case AID_RELATIVE:// We are doing relative position navigation where velocity errors are constrained, but position drift will occur// 我们正在进行相对位置导航,速度误差受到限制,但位置漂移会发生gcs().send_text(MAV_SEVERITY_INFO, "EKF3 IMU%u started relative aiding",(unsigned)imu_index);...
}
6 AP_NavEKF3_OptFlowFusion.cpp
6.1 void NavEKF3_core::SelectFlowFusion()
选择性融合光学流量传感器的测量。
// select fusion of optical flow measurements
void NavEKF3_core::SelectFlowFusion()
{...// 将光流数据融合到主滤波器中// Fuse optical flow data into the main filterif (flowDataToFuse && tiltOK) {if (frontend->_flowUse == FLOW_USE_NAV) {// Set the flow noise used by the fusion processesR_LOS = sq(MAX(frontend->_flowNoise, 0.05f));// Fuse the optical flow X and Y axis data into the main filter sequentiallyFuseOptFlow();}// reset flag to indicate that no new flow data is available for fusionflowDataToFuse = false;}...
}
6.2 void NavEKF3_core::FuseOptFlow()
依次将光流 X 轴和 Y 轴数据融合到主滤波器中。
首次融合光流传感器数据,会提示:"EKF3 IMU%u fusing optical flow"。
void NavEKF3_core::FuseOptFlow()
{...// notify first time onlyif (!flowFusionActive) {flowFusionActive = true;gcs().send_text(MAV_SEVERITY_INFO, "EKF3 IMU%u fusing optical flow",(unsigned)imu_index);}...
}相关文章:
Ardupilot — EKF3使用光流室内定位代码梳理
文章目录 前言 1 Copter.cpp 1.1 void IRAM_ATTR Copter::fast_loop() 1.2 void Copter::read_AHRS(void) 1.3 对象ahrs说明 2 AP_AHRS_NavEKF.cpp 2.1 void AP_AHRS_NavEKF::update(bool skip_ins_update) 2.2 void AP_AHRS_NavEKF::update_EKF3(void) 2.3 对象EKF3说…...
【Linux】自动化构建工具 —— make/makefileLinux第一个小程序 - 进度条
📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:Linux 🎯长路漫漫浩浩,万事皆有期待 上一篇博客:Linux编译…...
tensorflow的unet模型
import tensorflow as tf from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Dropout, UpSampling2D, concatenate# 定义 U-Net 模型 def unet(input_size(256, 256, 3)):inputs Input(input_size)# 编码器部分conv1 Conv2D(64, 3, activationrelu, padding…...
(2023 最新版)IntelliJ IDEA 下载安装及配置教程
IntelliJ IDEA下载安装教程(图解) IntelliJ IDEA 简称 IDEA,由 JetBrains 公司开发,是 Java 编程语言开发的集成环境,具有美观,高效等众多特点。在智能代码助手、代码自动提示、重构、J2EE 支持、各类版本…...
react 实现拖动元素
demo使用create-react-app脚手架创建 删除一些文件,创建一些文件后 结构目录如下截图com/index import Movable from ./move import { useMove } from ./move.hook import * as Operations from ./move.opMovable.useMove useMove Movable.Operations Operationse…...
【EI会议】第二届声学,流体力学与工程国际学术会议(AFME 2023)
第二届声学,流体力学与工程国际学术会议 2023 2nd International Conference on Acoustics, Fluid Mechanics and Engineering(AFME 2023) 声学、流体力学两个古老的学科发展至今,无时无刻都在影响着我们的生活。小到日常使用的耳…...
Android StringFog 字符串自动加密
一、StringFog 作用 一款自动对dex/aar/jar文件中的字符串进行加密Android插件工具,正如名字所言,给字符串加上一层雾霭,使人难以窥视其真面目。可以用于增加反编译难度,防止字符串代码重复。 支持java/kotlin。支持app打包生成…...
上四休三,未来的期许
近日“少上一天班,究竟香不香”引发关注,英国媒体2月21日报道,一项全世界目前为止参加人数最多的“四天工作制”试验,不久前在英国取得了成功。很多人表示上过四天班之后,给多少钱也回不去五天班的时代了。 来百度APP畅…...
怎么防止360安全卫士修改默认浏览器?
默认的浏览器 原先选项是360极速浏览器(如果有安装的话),我这里改成了Chrome。 先解锁 才能修改。...
调整参数提高mysql读写速度
要提升MySQL的写入速度,您可以采取一些参数调整和优化措施,这些措施可以根据您的具体应用和环境进行调整。以下是一些常见的参数和优化建议: InnoDB存储引擎: 如果您使用的是InnoDB存储引擎,确保以下参数被设置得合理: innodb_buffer_pool_size:增加内存池大小,以便更多…...
Go expvar包
介绍与使用 expvar 是 exposed variable的简写 expvar包[1]是 Golang 官方为暴露Go应用内部指标数据所提供的标准对外接口,可以辅助获取和调试全局变量。 其通过init函数将内置的expvarHandler(一个标准http HandlerFunc)注册到http包ListenAndServe创建的默认Serve…...
Yolo v8代码逐行解读
train.py文件 1.FILE Path(__file__).resolve() __file__代表的是train.py文件,Path(__file__).resolve()结果是train.py文件的绝对路径。 2.ROOT FILE.parents[0] 获得train.py父目录的绝对路径 3.sys.path 是一个列表list,里面包含了已经添加到系…...
9.18号作业
完善登录框 点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容“账号密码不匹配,是否重新登录”,给定两个按钮…...
Spring源码阅读(spring-framework-5.2.24)
spring-aop spring-aspects spring-beans spring-context 等等 第一步: Tags spring-projects/spring-framework GitHub 找到相应的release版本 第二步: 下载相应版本的gardle,如何看版本 spring-framework/gradle/wrapper /gradl…...
【SpringMVC】文件上传与下载、JREBEL使用
目录 一、引言 二、文件的上传 1、单文件上传 1.1、数据表准备 1.2、添加依赖 1.3、配置文件 1.4、编写表单 1.5、编写controller层 2、多文件上传 2.1、编写form表单 2.2、编写controller层 2.3、测试 三、文件下载 四、JREBEL使用 1、下载注册 2、离线设置 一…...
数据结构 第二章作业 线性表 西安石油大学
在顺序表中插入和删除一个结点需平均移动多少个结点?具体的移动次数取决于 哪两个因素? 在顺序表中插入和删除一个结点时,平均移动的结点数量取决于两个因素:插入/删除位置和当前顺序表的长度。 插入/删除位置:如果要…...
vue.mixin全局混合选项
在Vue.js中,Vue.mixin 是一个用来全局混合(mixin)选项的方法。它允许你在多个组件中共享相同的选项,例如数据、方法、生命周期钩子等。这可以用来在组件之间重复使用一些逻辑或共享一些通用的功能 Vue.mixin({// 在这里定义混合的选项data() {return {s…...
VMware Fusion 13+Ubuntu ARM Server 22.04.3在M2芯片的Mac上共享文件夹
因为Server版没有桌面,VMware Tools不能直接装,导致没办法共享文件。 Ubuntu中的包如果需要更新,先执行下面的步骤 sudo apt update 再执行 sudo apt upgrade 不需要更新的话,直接执行下面的步骤 先把open-vm-tools卸载了 …...
PostgreSQL serial类型
serial类型和序列 postgresql序列号(SERIAL)类型包括 smallserial(smallint,short),serial(int)bigserial(bigint,long long int) 不管是smallserial,serial还是bigserial,其范围都是(1,9223372036854775807)&#…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
