ArduPilot开源代码之NavEKF3

1. 源由

NavEKF3 类用于无人机系统中的导航和状态估计。它是扩展卡尔曼滤波器(EKF)实现的一部分,用于根据传感器数据估计移动物体的状态。

  • 自主设备: 用于无人机、车、船等,利用传感器数据保持稳定飞行/导航。
  • 传感器融合: 整合来自不同来源的数据(IMU、GPS、光流)以提高准确性。
  • 错误处理: 许多方法返回布尔值以指示成功,表明有稳健的错误检查。
  • 实时处理: 设计为在高频率调用时处理新数据(例如 IMU 更新)。

如果需要具体方法或概念的进一步细节,请随时询问!

2. 框架设计

2.1 友元类

  • NavEKF3_core 是一个友元类,可以访问 NavEKF3 的私有成员。

注:详见ArduPilot开源代码之NavEKF3_core

2.2 禁止复制

  • CLASS_NO_COPY(NavEKF3); 防止类实例被复制。

2.3 参数和配置

  • 静态结构 var_infovar_info2 可能用于存储配置参数。

注:定义和初始化,详见AP_NavEKF3.cpp/h文件。

2.4 核心功能

  • 初始化: InitialiseFilter() 设置滤波器。
  • 更新: UpdateFilter() 在有新的 IMU 数据时调用。
  • 健康检查: 像 healthy()pre_arm_check() 确保系统完整性。

2.4.1 InitialiseFilter

EKF3算法核心初始化过程,主要进行内存分配和变量初始化

// 初始化滤波器
bool NavEKF3::InitialiseFilter(void)
{
   
   
    // 如果禁用或IMU掩码为0,则返回false
    if (_enable == 0 || _imuMask == 0) {
   
   
        return false;
    }
    const auto &ins = AP::dal().ins();

    AP::dal().start_frame(AP_DAL::FrameType::InitialiseFilterEKF3);

    // 获取当前IMU采样时间
    imuSampleTime_us = AP::dal().micros64();

    // 计算预期的帧时间
    const float loop_rate = ins.get_loop_rate_hz();
    if (!is_positive(loop_rate)) {
   
   
        return false;
    }
    _frameTimeUsec = 1e6 / loop_rate;

    // 预测时每次预期的IMU帧数
    _framesPerPrediction = uint8_t((EKF_TARGET_DT / (_frameTimeUsec * 1.0e-6) + 0.5));

#if !APM_BUILD_TYPE(APM_BUILD_AP_DAL_Standalone)
    // 如有必要,转换参数
    convert_parameters();
#endif

#if APM_BUILD_TYPE(APM_BUILD_Replay)
    // 如果没有加速度计,返回false
    if (ins.get_accel_count() == 0) {
   
   
        return false;
    }
#endif

    // 如果核心为空,则代表第一次调用,属于初始化阶段,需要进行core的内存分配
    if (core == nullptr) {
   
   

        // 对于一个IMU,不运行多个滤波器
        uint8_t mask = (1U<<ins.get_accel_count())-1;
        _imuMask.set_and_default(_imuMask.get() & mask);
        
        // 初始化设置变量
        for (uint8_t i=0; i<MAX_EKF_CORES; i++) {
   
   
            coreSetupRequired[i] = false;
            coreImuIndex[i] = 0;
        }
        num_cores = 0;

        // 从掩码计数IMU
        for (uint8_t i=0; i<INS_MAX_INSTANCES; i++) {
   
   
            if (_imuMask & (1U<<i)) {
   
   
                coreSetupRequired[num_cores] = true;
                coreImuIndex[num_cores] = i;
                num_cores++;
            }
        }

        // 检查是否有足够的内存创建EKF核心
        if (AP::dal().available_memory() < sizeof(NavEKF3_core)*num_cores + 4096) {
   
   
            GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "EKF3内存不足");
            _enable.set(0);
            num_cores = 0;
            return false;
        }

        // 尝试从CCM RAM分配,如果不可用或已满则回退到普通RAM
        core = (NavEKF3_core*)AP::dal().malloc_type(sizeof(NavEKF3_core)*num_cores, AP::dal().MEM_FAST);
        if (core == nullptr) {
   
   
            _enable.set(0);
            num_cores = 0;
            GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "EKF3分配失败");
            return false;
        }

        // 对所有核心调用构造函数
        for (uint8_t i = 0; i < num_cores; i++) {
   
   
            new (&core[i]) NavEKF3_core(this);
        }
    }

    // 设置已创建的核心
    // 指定使用的IMU并创建数据缓冲区
    // 如果无法设置核心,返回false并下次调用函数时再试
    bool core_setup_success = true;
    for (uint8_t core_index=0; core_index<num_cores; core_index++) {
   
   
        if (coreSetupRequired[core_index]) {
   
   
            coreSetupRequired[core_index] = !core[core_index].setup_core(coreImuIndex[core_index], core_index);
            if (coreSetupRequired[core_index]) {
   
   
                core_setup_success = false;
            }
        }
    }
    // 如果任何核心无法设置,则失败退出
    if (!core_setup_success) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值