ArduSub程序学习(11)--EKF实现逻辑①

1.read_AHRS()

进入EKF,路径ArduSub.cpp里面的fast_loop()里面的read_AHRS();

//从 AHRS(姿态与航向参考系统)中读取并更新与飞行器姿态有关的信息
void Sub::read_AHRS()
{// Perform IMU calculations and get attitude info//-----------------------------------------------// <true> tells AHRS to skip INS update as we have already done it in fast_loop()//告诉 AHRS 跳过惯性导航系统(INS)的更新,因为 INS 的更新已经在主循环的快速循环(fast_loop())中完成了。ahrs.update(true);ahrs_view.update(true);
}

2.update(ture)

负责更新AHRS的各个组件,并管理不同类型的扩展卡尔曼滤波器(EKF)

//通过EKF,读取姿态信息
void AP_AHRS_NavEKF::update(bool skip_ins_update)
{// support locked access functions to AHRS data//信号量锁定WITH_SEMAPHORE(_rsem);// drop back to normal priority if we were boosted by the INS// calling delay_microseconds_boost()//在完成传感器更新后,恢复调度器的正常优先级,之前可能使用过临时提升。hal.scheduler->boost_end();//更新DCMupdate_DCM(skip_ins_update);//针对SITL的条件编译
#if CONFIG_HAL_BOARD == HAL_BOARD_SITLupdate_SITL();
#endif//如果外部AHRS启用,则调用外部更新函数。
#if HAL_EXTERNAL_AHRS_ENABLEDupdate_external();
#endif//hal.console->printf("Current EKF Type: %d\n", static_cast<int>(_ekf_type.get()));//EKF选择和执行if (_ekf_type == 2) {// if EK2 is primary then run EKF2 first to give it CPU// priority
#if HAL_NAVEKF2_AVAILABLEupdate_EKF2();
#endif
#if HAL_NAVEKF3_AVAILABLEupdate_EKF3();
#endif} else {// otherwise run EKF3 first
#if HAL_NAVEKF3_AVAILABLEupdate_EKF3();
#endif
#if HAL_NAVEKF2_AVAILABLEupdate_EKF2();
#endif}#if AP_MODULE_SUPPORTED// call AHRS_update hook if any//如果支持任何模块,调用钩子以允许它们执行与AHRS相关的附加更新。AP_Module::call_hook_AHRS_update(*this);
#endif// push gyros if optical flow present//如果光流传感器可用,获取陀螺仪漂移(偏差)并用此信息更新光流系统。if (hal.opticalflow) {const Vector3f &exported_gyro_bias = get_gyro_drift();hal.opticalflow->push_gyro_bias(exported_gyro_bias.x, exported_gyro_bias.y);}if (_view != nullptr) {// update optional alternative attitude view//如果存在可选的替代视图,则更新该视图的姿态。_view->update(skip_ins_update);}#if !HAL_MINIMIZE_FEATURES && AP_AHRS_NAVEKF_AVAILABLE// update NMEA output//如果未最小化功能且EKF可用,更新NMEA输出,这是用于海洋导航的标准。update_nmea_out();
#endif//检查当前活动EKF类型是否自上次更新以来发生变化EKFType active = active_EKF_type();//如果发生变化,则向地面控制站(GCS)发送关于当前活动EKF类型的消息。if (active != last_active_ekf_type) {last_active_ekf_type = active;const char *shortname = "???";switch ((EKFType)active) {case EKFType::NONE:shortname = "DCM";break;
#if CONFIG_HAL_BOARD == HAL_BOARD_SITLcase EKFType::SITL:shortname = "SITL";break;
#endif
#if HAL_EXTERNAL_AHRS_ENABLEDcase EKFType::EXTERNAL:shortname = "External";break;
#endif
#if HAL_NAVEKF3_AVAILABLEcase EKFType::THREE:shortname = "EKF3";break;
#endif
#if HAL_NAVEKF2_AVAILABLEcase EKFType::TWO:shortname = "EKF2";break;
#endif}GCS_SEND_TEXT(MAV_SEVERITY_INFO, "AHRS: %s active", shortname);}
}

 2.1update_DCM(bool skip_ins_update)

        更新DCM(方向余弦矩阵,Direction Cosine Matrix)的作用是保持和更新飞行器或自主车辆的姿态信息,使得其在三维空间中的朝向能够持续精确地被估计和修正。

        陀螺仪在长时间运行时会产生漂移误差。更新DCM时,可以利用传感器(如加速度计、磁力计等)的测量值,计算与当前DCM表示的姿态之间的误差,并据此调整陀螺仪读数。通过这种方式,DCM能够起到校正漂移的作用,确保姿态估计的准确性。

//更新姿态和航向参考系统(AHRS)中的方向余弦矩阵(DCM)。DCM是一种用来表示三维空间中物体姿态的数学模型。
void AP_AHRS_NavEKF::update_DCM(bool skip_ins_update)
{// we need to restore the old DCM attitude values as these are// used internally in DCM to calculate error values for gyro drift// correction//恢复旧的DCM姿态值:roll = _dcm_attitude.x;pitch = _dcm_attitude.y;yaw = _dcm_attitude.z;//更新DCM的内部数据,确保当前姿态和其他相关值同步。update_cd_values();AP_AHRS_DCM::update(skip_ins_update);// keep DCM attitude available for get_secondary_attitude()//将更新后的 roll、pitch 和 yaw 值重新赋值回 _dcm_attitude_dcm_attitude = {roll, pitch, yaw};
}

        ★★在使用EKF进行姿态估计的系统中,DCM通常作为备用机制存在。当EKF失效或者不稳定时,系统可以回退到DCM来提供可靠的姿态估计。通过不断更新DCM,系统可以确保即使在EKF不可用的情况下,仍然有一个稳定的姿态估计可用。 

if (_ekf_type == 2) {update_EKF2();update_EKF3();
} else {update_EKF3();update_EKF2();
}
update_DCM(skip_ins_update);
  • EKF2和EKF3 是不同的卡尔曼滤波器版本,它们可能分别处理不同的数据源或者计算策略。系统根据具体情况优先更新某个EKF,并依次更新另一个EKF。
  • DCM的更新 则在EKF更新后进行,确保即便EKF更新失败或不稳定,系统仍能通过DCM获得姿态数据。

        在一些导航系统中,DCM可能作为EKF的初始估计工具。由于DCM计算效率高,姿态估计在短期内较为准确,EKF可以使用DCM的估计值作为其初始状态,逐渐根据传感器数据和预测模型进行更复杂的修正。

        如果EKF在某些情况下出现问题(如传感器数据丢失、不可靠的传感器输入等),系统可以回退到DCM,继续保持姿态估计的基本功能。因此,DCM作为EKF的一种补充或者冗余备份,能够增强系统的鲁棒性。

2.2update_EKF2();

 这段代码实现了AP_AHRS_NavEKF::update_EKF2()函数,用于更新飞行器导航系统中使用的扩展卡尔曼滤波器2(EKF2)的状态。该函数主要负责初始化EKF2滤波器并在之后的每个周期内更新滤波器状态,获取姿态估计、陀螺仪漂移修正、加速度计数据等。

//更新飞行器导航系统中使用的扩展卡尔曼滤波器2(EKF2)的状态
void AP_AHRS_NavEKF::update_EKF2(void)
{//hal.console->printf("_ekf2_started=%d\r\n",_ekf2_started);if (!_ekf2_started) {// wait 1 second for DCM to output a valid tilt error estimate//hal.console->printf("AAAAAA1\r\n");//等待1秒以便DCM输出有效的倾斜误差估计if (start_time_ms == 0) {start_time_ms = AP_HAL::millis();}// if we're doing Replay logging then don't allow any data// into the EKF yet.  Don't allow it to block us for long.// 检查看门狗是否重置并确保不长时间阻塞数据if (!hal.util->was_watchdog_reset()) {if (AP_HAL::millis() - start_time_ms < 5000) {//hal.console->printf("AAAAAA2\r\n");if (!AP::logger().allow_start_ekf()) {return;}}}等待预设的启动延迟时间,然后初始化EKF2if (AP_HAL::millis() - start_time_ms > startup_delay_ms) {_ekf2_started = EKF2.InitialiseFilter();}}if (_ekf2_started) {//hal.console->printf("BBBBB1\r\n");//EKF2更新,融合传感器数据来更新姿态、速度和位置估计。EKF2.UpdateFilter();//hal.console->printf("BBBBB2\r\n");if (active_EKF_type() == EKFType::TWO) {//hal.console->printf("CCCCC1\r\n");Vector3f eulers;//矩阵更新EKF2.getRotationBodyToNED(_dcm_matrix);//姿态获取EKF2.getEulerAngles(-1,eulers);roll  = eulers.x;pitch = eulers.y;yaw   = eulers.z;update_cd_values();update_trig();// Use the primary EKF to select the primary gyro//陀螺仪漂移修正const int8_t primary_imu = EKF2.getPrimaryCoreIMUIndex();const AP_InertialSensor &_ins = AP::ins();// get gyro bias for primary EKF and change sign to give gyro drift// Note sign convention used by EKF is bias = measurement - truth//计算修正后的陀螺仪数据_gyro_drift.zero();EKF2.getGyroBias(-1,_gyro_drift);_gyro_drift = -_gyro_drift;// calculate corrected gyro estimate for get_gyro()_gyro_estimate.zero();if (primary_imu == -1 || !_ins.get_gyro_health(primary_imu)) {// the primary IMU is undefined so use an uncorrected default value from the INS library_gyro_estimate = _ins.get_gyro();} else {// use the same IMU as the primary EKF and correct for gyro drift_gyro_estimate = _ins.get_gyro(primary_imu) + _gyro_drift;}// get z accel bias estimate from active EKF (this is usually for the primary IMU)// 加速度计数据的处理与校正float abias = 0;EKF2.getAccelZBias(-1,abias);// This EKF is currently using primary_imu, and abias applies to only that IMUfor (uint8_t i=0; i<_ins.get_accel_count(); i++) {Vector3f accel = _ins.get_accel(i);if (i == primary_imu) {accel.z -= abias;}if (_ins.get_accel_health(i)) {_accel_ef_ekf[i] = _dcm_matrix * get_rotation_autopilot_body_to_vehicle_body() * accel;}}_accel_ef_ekf_blended = _accel_ef_ekf[primary_imu>=0?primary_imu:_ins.get_primary_accel()];//滤波器状态更新nav_filter_status filt_state;EKF2.getFilterStatus(-1,filt_state);AP_Notify::flags.gps_fusion = filt_state.flags.using_gps; // Drives AP_Notify flag for usable GPS.AP_Notify::flags.gps_glitching = filt_state.flags.gps_glitching;AP_Notify::flags.have_pos_abs = filt_state.flags.horiz_pos_abs;}}
}

 

  • 初始化EKF2:函数首先检查EKF2是否启动,并在适当时机进行初始化。
  • 姿态和传感器数据更新:在EKF2成功启动后,获取姿态数据并修正陀螺仪和加速度计的漂移,确保姿态估计准确。
  • 滤波器状态和融合:不断更新EKF2的状态,结合传感器数据(如GPS)进行位置和姿态融合,确保系统导航的可靠性。

2.3 update_EKF3();

AP_AHRS_NavEKF::update_EKF3() 函数实现了扩展卡尔曼滤波器3(EKF3)的更新流程。它与 update_EKF2() 类似,但专门用于 EKF3 的处理。主要功能包括初始化滤波器、更新姿态数据、陀螺仪漂移修正、加速度计偏置校正等。

未完待续~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/53786.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优化iOS日志管理:构建高效的日志体系

引言 在现代应用程序开发中&#xff0c;日志记录不仅仅是调试工具&#xff0c;它也是性能监控和安全审计的关键组成部分。有效的日志管理能够帮助开发者快速识别和理解问题&#xff0c;同时提供系统运行状态的深刻洞察。在这篇博客中&#xff0c;我们将深入讨论日志的重要性&a…

C++模拟实现list:list、list类的初始化和尾插、list的迭代器的基本实现、list的完整实现、测试、整个list类等的介绍

文章目录 前言一、list二、list类的初始化和尾插三、list的迭代器的基本实现四、list的完整实现五、测试六、整个list类总结 前言 C模拟实现list&#xff1a;list、list类的初始化和尾插、list的迭代器的基本实现、list的完整实现、测试、整个list类等的介绍 一、list list本…

影响6个时序Baselines模型的代码Bug

前言 我是从去年年底开始入门时间序列研究&#xff0c;但直到最近我读FITS这篇文章的代码时&#xff0c;才发现从去年12月25号就有人发现了数个时间序列Baseline的代码Bug。如果你已经知道这个Bug了&#xff0c;那可以忽略本文&#xff5e; 这个错误最初在Informer&#xff0…

web入门

什么是spring 特点&#xff1a;配置繁琐&#xff0c;入门难度大&#xff0c;提出了springboot 1.springbootweb入门例子 2.http协议 2.1概述 2.2请求协议 由三部分组成&#xff1a;请求行、请求头、请求体 2.3响应协议 2.4协议解析

云桌面+数字人:开启直播新纪元

随着科技的飞速发展&#xff0c;直播行业也在不断变革。云桌面和数字人直播作为新兴力量&#xff0c;正逐渐崭露头角&#xff0c;受到了广泛关注。 云桌面技术的出现&#xff0c;为直播带来了全新的可能性。它不再依赖传统的本地硬件设备&#xff0c;而是通过云计算提供弹性可…

我与Linux的爱恋:命令行参数|环境变量

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;Linux的学习 文章目录 一.命令行参数二.环境变量1.环境变量的基本概念2.查看环境变量的方法3.环境变量相关命令4.环境变量的组织方式以及获取环境变量的三种方法 环境变量具有全局属性 一…

C++map与set

文章目录 前言一、map和set基础知识二、set与map使用示例1.set去重操作2.map字典统计 总结 前言 本章主要介绍map和set的基本知识与用法。 一、map和set基础知识 map与set属于STL的一部分&#xff0c;他们底层都是是同红黑树来实现的。 ①set常见用途是去重 &#xff0c;set不…

数据技术进化史:从数据仓库到数据中台再到数据飞轮的旅程

随着大数据时代的到来&#xff0c;数据已经成为企业的核心资产之一。在过去几十年间&#xff0c;数据技术也随之不断演进&#xff0c;从早期的数据仓库到近年来热门的数据中台&#xff0c;再到正在快速发展的数据飞轮概念&#xff0c;每一步都是技术革新的体现。 一、数据仓库&…

电商跨境电商商城系统/网上商城接口/电商数据接口详情

电商API接口背景&#xff1a;电商运营中&#xff0c;数据分析这项工作越来越重要&#xff0c;许多品牌方也越来越热衷去做电商数据分析。不过&#xff0c;全面的数据该如何获取呢&#xff0c;此时&#xff0c;电商数据接口的重要性便凸显出来了。 电商API数据接口主要有以下特…

外包干了两年,收获真不少...

有一种打工人的羡慕&#xff0c;叫做“大厂”。 真是年少不知大厂香&#xff0c;错把青春插稻秧。 但是&#xff0c;在深圳有一群比大厂员工更庞大的群体&#xff0c;他们顶着大厂的“名”&#xff0c;做着大厂的工作&#xff0c;还可以享受大厂的伙食&#xff0c;却没有大厂…

深度伪造语音检测(Deepfake Speech Detection, DSD)全面概述

近期&#xff0c;深度学习技术和神经网络在生成型人工智能领域已取得重大突破。如今&#xff0c;关键的通信媒介&#xff0c;如音频、图像、视频和文本&#xff0c;均能实现自动生成&#xff0c;并广泛应用于诸多领域&#xff0c;包括聊天机器人系统&#xff08;如ChatGPT&…

Kettle9连接mysql8.0.36失败处理

一、问题描述 kettle作为数据转换同步的工具&#xff0c;使用java开发&#xff0c;连接数据库使用jar的驱动包&#xff0c;比如oracle连接使用ojdbc8.jar&#xff0c;mysql连接使用mysql-connect-java-8.0.*,但是截止目前mysql8.0.33到8.0.36在官网是没有mysql驱动包的&#x…

IPD如何解决产品开发的典型问题

IPD&#xff08;Integrated Product Development&#xff0c;集成产品开发&#xff09;是一种领先的、成熟的产品开发的管理思想和管理模式。它是根据大量成功的产品开发管理实践总结出来的&#xff0c;并被大量实践证明的高效的产品开发模式。从汉捷咨询二十多年来为五百多家企…

18724 二叉树的遍历运算

### 思路 1. **递归构建树**&#xff1a; - 先序遍历的第一个节点是根节点。 - 在中序遍历中找到根节点的位置&#xff0c;左边部分是左子树&#xff0c;右边部分是右子树。 - 递归构建左子树和右子树。 2. **递归生成后序遍历**&#xff1a; - 递归生成左子树的…

飞睿智能实时雷达活体探测传感器模块,智能家居静止检测实时感知人员有无

随着科技的飞速发展&#xff0c;我们的生活正在经历着未有的创新。在这个创新的浪潮中&#xff0c;实时雷达活体探测传感器模块的技术正逐渐崭露头角&#xff0c;以其独特的优势为我们的生活带来安全与便捷。今天&#xff0c;我们就来详细探讨一下这项技术&#xff0c;看看它是…

【DP解密多重背包问题】:优化策略与实现

文章目录 什么是多重背包问题&#xff1f;多重背包问题的数学模型 例题多重背包问题Ⅰ多重背包问题Ⅱ 总结 什么是多重背包问题&#xff1f; 多重背包问题是一个经典的组合优化问题。与标准背包问题不同&#xff0c;在多重背包问题中&#xff0c;每种物品可以选择多个&#xf…

蓝桥杯15届C/C++B组省赛题目

问题描述 小蓝组织了一场算法交流会议&#xff0c;总共有 5050 人参加了本次会议。在会议上&#xff0c;大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手 (且仅有一次)。但有 77 个人&#xff0c;这 77 人彼此之间没有进行握手 (但这 77 人与…

langchain v0.3更新了什么?

版本改动 这是具体改动的链接 官方blog首先说明了&#xff1a; 所有软件包已在内部从 Pydantic 1 升级到 Pydantic 2。 所有软件包都完全支持在用户代码中使用 Pydantic 2&#xff0c;而无需使用 langchain_core.pydantic_v1 或 pydantic.v1 等桥接程序。 由于 Pydantic 1 已…

【HTTP】请求“报头”(Host、Content-Length/Content-Type、User-Agent(简称 UA))

Host 表示服务器主机的地址和端口号 URL 里面不是已经有 Host 了吗&#xff0c;为什么还要写一次&#xff1f; 这里的 Host 和 URL 中的 IP 地址、端口什么的&#xff0c;绝大部分情况下是一样的&#xff0c;少数情况下可能不同当前我们经过某个代理进行转发。过程中&#xf…

2024年项目经理不能错过的开源项目管理系统大盘点:全面指南

在2024年&#xff0c;随着项目管理领域的不断发展&#xff0c;开源项目管理系统成为了项目经理们提升工作效率的利器。本文将全面盘点几款备受推荐的开源项目管理系统&#xff0c;帮助项目经理们找到最佳选择&#xff0c;不容错过。 在项目管理日益复杂的今天&#xff0c;开源项…