高翔《自动驾驶中的slam技术》第3章代码-run_eskf_gins.cc

文章介绍了ESKF(扩展卡尔曼滤波)在视觉SLAM中的应用,作者推荐了高博的《视觉SLAM14讲》作为学习资源。作者认为很多复杂的数学概念如协方差、滤波等可以更直观地表述,并分享了对ESKF的理解,它是KF和EKF的拓展,用于处理非线性问题。文中还给出了C++代码示例,展示如何结合RTK和IMU数据进行组合导航的实现。
摘要由CSDN通过智能技术生成

eskf 不太懂的看看高博的《视觉SLAM14讲》和和高博的简明ESKF
说实话,我看了4-5遍了,只能浅浅领悟,我感觉很多东西被公式化了,不要看到一大堆公式就被吓倒,这些公式一一简化就是+ - * /。
其实如果能有一本数学的科普书,或者视频教程就好了。把一些什么协方差,滤波,偏导,指数,反对称矩阵,旋转矩阵,扰动,旋转向量,四元数,以直观的形式表达。
所以到现在我还是只能浅浅理解。阶段性记录,与君共享。

ESKF与KF 、EKF有什么不同?一个是过滤当前值
过滤 你可以理解成平均,1号评委打分9.7,2号评委打分9.5,那选手的得分过滤后是9.6=(9.7+9.5)/ 2,这里可以理解为KF和EKF的方式
ESKF与KF、EKF有什么不同呢?还是用评委打分的方式,1号评委打分为9.7(基础得分9.6+印象分0.1),2号评委打分为9.5(基础得分9.6+印象分-0.1),那使用ESKF如何计算选手的最终得分呢?
最终的分:9.6+(0.1+ (-0.1))/2 = 9.6
有的同学说如果2个评委的基础得分不一样怎么办?那9.6是不是也要平均一下?
这个就是算法,你想怎么处理都可以,公式是死的,人是活的,也许人家的公式也要优化与改进。
ESKF只是一个数据融合的方式,可能比KF、EKF稳定一些吧。

//
// Created by xiang on 2021/11/11.
//

#include "ch3/eskf.hpp"
#include "ch3/static_imu_init.h"
#include "common/io_utils.h"
#include "tools/ui/pangolin_window.h"
#include "utm_convert.h"

#include <gflags/gflags.h>
#include <glog/logging.h>
#include <fstream>
#include <iomanip>

DEFINE_string(txt_path, "/home/peak/slam_in_autonomous_driving-master/data/ch3/10.txt", "数据文件路径");
DEFINE_double(antenna_angle, 12.06, "RTK天线安装偏角(角度)");
DEFINE_double(antenna_pox_x, -0.17, "RTK天线安装偏移X");
DEFINE_double(antenna_pox_y, -0.20, "RTK天线安装偏移Y");
DEFINE_bool(with_ui, true, "是否显示图形界面");
DEFINE_bool(with_odom, false, "是否加入轮速计信息");

/**
 * 本程序演示使用RTK+IMU进行组合导航
 */
int main(int argc, char** argv) {
    //谷歌的日志库
    google::InitGoogleLogging(argv[0]);
    FLAGS_stderrthreshold = google::INFO;
    FLAGS_colorlogtostderr = true;
    google::ParseCommandLineFlags(&argc, &argv, true);

    if (fLS::FLAGS_txt_path.empty()) {
        return -1;
    }

    // 初始化器
    sad::StaticIMUInit imu_init;  // 使用默认配置
    //eskf类
    sad::ESKFD eskf;

    sad::TxtIO io(FLAGS_txt_path);
    //GPS显示的位置
    Vec2d antenna_pos(FLAGS_antenna_pox_x, FLAGS_antenna_pox_y);
    //这是一个函数,用来保存数据,怎么用?看下面,
    //【】是什么意思,说实话我又忘记了,还有【=】【&】,
    // 如果真的不习惯这种用法,把他当成函数指针。【】【=】【&】不去管他(换汤不换药,也许以后用多了就习惯了,)
    auto save_vec3 = [](std::ofstream& fout, const Vec3d& v) { fout << v[0] << " " << v[1] << " " << v[2] << " "; };
    auto save_quat = [](std::ofstream& fout, const Quatd& q) {
        fout << q.w() << " " << q.x() << " " << q.y() << " " << q.z() << " ";
    };

    auto save_result = [&save_vec3, &save_quat](std::ofstream& fout, const sad::NavStated& save_state) {
        fout << std::setprecision(18) << save_state.timestamp_ << " " << std::setprecision(9);
        save_vec3(fout, save_state.p_);
        save_quat(fout, save_state.R_.unit_quaternion());
        save_vec3(fout, save_state.v_);
        save_vec3(fout, save_state.bg_);
        save_vec3(fout, save_state.ba_);
        fout << std::endl;
    };

    std::ofstream fout("./data/ch3/gins.txt");
    bool imu_inited = false, gnss_inited = false;

    //共享指针,C++要自己回收内存的诞生产品,感觉做的还有漏洞,所以又诞生了另一个指针类型weak_ptr;把它当成一个指针就好了。
    std::shared_ptr<sad::ui::PangolinWindow> ui = nullptr;
    if (FLAGS_with_ui) {
        ui = std::make_shared<sad::ui::PangolinWindow>();
        ui->Init();
    }

    /// 设置各类回调函数
    bool first_gnss_set = false;
    Vec3d origin = Vec3d::Zero();

    //这个代码不要懵,换汤不换药,相当于分步执行以下4步。
    //  io.SetIMUProcessFunc();
    //  io.SetGNSSProcessFunc();
    //  io.SetOdomProcessFunc();
    //  io.Go();
    // 为什么要这样写?你看不懂是我最大的愿望,哈哈,我的理解(有学过javaweb的同学就能很好的理解了,IDEA可以方便生成一个类的Get和Set,其实就是给客户开放了便捷的操作接口)
    // 那高博连起来写是作什么?他其实就是想让你看不懂,没有什么其他,哈哈!原理同stdout的 << 符号。
    io.SetIMUProcessFunc([&](const sad::IMU& imu) {
          /// IMU 处理函数
          if (!imu_init.InitSuccess()) {
              imu_init.AddIMU(imu);
              return;
          }

          /// 需要IMU初始化
          if (!imu_inited) {
              // 读取初始零偏,设置ESKF
              sad::ESKFD::Options options;
              // 噪声由初始化器估计
              options.gyro_var_ = sqrt(imu_init.GetCovGyro()[0]);
              options.acce_var_ = sqrt(imu_init.GetCovAcce()[0]);
              eskf.SetInitialConditions(options, imu_init.GetInitBg(), imu_init.GetInitBa(), imu_init.GetGravity());
              imu_inited = true;
              return;
          }

          if (!gnss_inited) {
              /// 等待有效的RTK数据
              return;
          }

          /// GNSS 也接收到之后,再开始进行预测
          eskf.Predict(imu);

          /// predict就会更新ESKF,所以此时就可以发送数据
          auto state = eskf.GetNominalState();
          if(ui){
              ui->UpdateNavState(state);
          }

          /// 记录数据以供绘图
          save_result(fout, state);

          usleep(1e3);
      })
        .SetGNSSProcessFunc([&](const sad::GNSS& gnss) {
            /// GNSS 处理函数
            if (!imu_inited) {
                return;
            }

            sad::GNSS gnss_convert = gnss;
            if (!sad::ConvertGps2UTM(gnss_convert, antenna_pos, FLAGS_antenna_angle) || !gnss_convert.heading_valid_) {
                return;
            }

            /// 去掉原点
            if (!first_gnss_set) {
                origin = gnss_convert.utm_pose_.translation();
                first_gnss_set = true;
            }
            gnss_convert.utm_pose_.translation() -= origin;

            // 要求RTK heading有效,才能合入ESKF
            eskf.ObserveGps(gnss_convert);

            auto state = eskf.GetNominalState();
            if (ui) {
                ui->UpdateNavState(state);
            }
            save_result(fout, state);

            gnss_inited = true;
        })
        .SetOdomProcessFunc([&](const sad::Odom& odom) {
            /// Odom 处理函数,本章Odom只给初始化使用
            imu_init.AddOdom(odom);
            if (FLAGS_with_odom && imu_inited && gnss_inited) {
                eskf.ObserveWheelSpeed(odom);
            }
        })
        .Go();

    while (ui && !ui->ShouldQuit()) {
        usleep(1e5);
    }
    if (ui) {
        ui->Quit();
    }
    return 0;
}

关于ESKF部分,后面再详细分解。
https://zhuanlan.zhihu.com/p/441182819

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SLAM(同时定位与地图构建)技术自动驾驶具有重要的应用和解决难点。SLAM是指通过感知和计算来同时完成车辆在未知环境的定位以及地图构建的过程。 在自动驾驶SLAM可以帮助车辆实时地感知周围环境,通过激光雷达、摄像头等传感器获取环境的信息,并利用这些信息来构建地图。随后,车辆根据地图进行定位,以便更准确地进行路径规划和导航。 SLAM自动驾驶面临的主要难点包括传感器数据的融合、实时性要求和环境复杂性等。首先,传感器数据融合是指将来自多个传感器的数据进行整合,以准确获取车辆周围环境的信息。这需要对不同传感器的数据进行校准和融合算法的设计,以提高地图的精确性和定位的准确性。 其次,自动驾驶对实时性的要求非常高,快速准确地感知和定位是保证安全行驶的关键。因此,SLAM系统需要在高速行驶时迅速更新地图和定位结果,同时处理大量的传感器数据和进行高效的计算。 此外,自动驾驶车辆通常面临复杂多变的交通环境,包括车道线、交通标志、其他车辆等各种要素。SLAM系统需要能够准确感知并识别这些要素,并进行高精度地图构建和定位。同样,环境的动态物体和障碍物对SLAM技术也提出了挑战,需要通过运动估计和更新机制来及时更新地图和定位信息。 总而言之,SLAM技术自动驾驶的应用非常重要,可以为自动驾驶车辆提供准确的地图和定位信息。然而,传感器数据的融合、实时性要求和环境复杂性是SLAM技术自动驾驶的主要难点,需要通过算法优化和工程实践来解决。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可峰科技

生活不易

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值