高翔《自动驾驶中的slam技术》第3章代码-run_imu_integration.cc
·
//
// Created by xiang on 2021/11/5.
//
#include <glog/logging.h>
#include <iomanip>
#include "ch3/imu_integration.h"
#include "common/io_utils.h"
#include "tools/ui/pangolin_window.h"
DEFINE_string(imu_txt_path, "./data/ch3/10.txt", "数据文件路径");
DEFINE_bool(with_ui, true, "是否显示图形界面");
/// 本程序演示如何对IMU进行直接积分
/// 该程序需要输入data/ch3/下的文本文件,同时它将状态输出到data/ch3/state.txt中,在UI中也可以观察到车辆运动
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
FLAGS_stderrthreshold = google::INFO;
FLAGS_colorlogtostderr = true;
google::ParseCommandLineFlags(&argc, &argv, true);
if (FLAGS_imu_txt_path.empty()) {
return -1;
}
sad::TxtIO io(FLAGS_imu_txt_path);
// 该实验中,我们假设零偏已知
Vec3d gravity(0, 0, -9.8); // 重力方向
Vec3d init_bg(00.000224886, -7.61038e-05, -0.000742259);
Vec3d init_ba(-0.165205, 0.0926887, 0.0058049);
//IMU积分类初始化(使用重力加速度,陀螺仪零偏,加速度计零偏)
sad::IMUIntegration imu_integ(gravity, init_bg, init_ba);
//初始化界面
std::shared_ptr<sad::ui::PangolinWindow> ui = nullptr;
if (FLAGS_with_ui) {
ui = std::make_shared<sad::ui::PangolinWindow>();
ui->Init();
}
/// 记录结果
//使用正则表达式输出保存结果
auto save_result = [](std::ofstream& fout, double timestamp, const Sophus::SO3d& R, const Vec3d& v,
const Vec3d& p) {
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() << " ";
};
fout << std::setprecision(18) << timestamp << " " << std::setprecision(9);
save_vec3(fout, p);
save_quat(fout, R.unit_quaternion());
save_vec3(fout, v);
fout << std::endl;
};
//读取数据
std::ofstream fout("./data/ch3/state.txt");
//传入参数为函数类型参数,用正则表达式初始化,然后io调用Go函数运行
io.SetIMUProcessFunc([&imu_integ, &save_result, &fout, &ui](const sad::IMU& imu) {
//这里面最重要的是IMU如何积分
imu_integ.AddIMU(imu);
save_result(fout, imu.timestamp_, imu_integ.GetR(), imu_integ.GetV(), imu_integ.GetP());
if (ui) {
//积分完进行更新
ui->UpdateNavState(imu_integ.GetNavState());
usleep(1e2);
}
}).Go();
// 打开了可视化的话,等待界面退出
while (ui && !ui->ShouldQuit()) {
usleep(1e4);
}
if (ui) {
ui->Quit();
}
return 0;
}
// 增加imu读数
// 【注意这里】重力的方向不会受到物体的旋转影响,但是自身加速矢量会受到本身旋转的影响。
void AddIMU(const IMU& imu) {
double dt = imu.timestamp_ - timestamp_;
if (dt > 0 && dt < 0.1) {
// 假设IMU时间间隔在0至0.1以内
//假设模型为匀加速直线运动
//p_ 初始位姿
//v_ * dt 匀速直线运动部分
//0.5 * gravity_ * dt * dt 重力加速部分(固定值)
//0.5 * (R_ * (imu.acce_ - ba_)) * dt * dt //受旋转影响的直线加速部分
p_ = p_ + v_ * dt + 0.5 * gravity_ * dt * dt + 0.5 * (R_ * (imu.acce_ - ba_)) * dt * dt;
// v_ 初始速度
// R_ * (imu.acce_ - ba_) * dt 受旋转影响的加速部分
// gravity_ * dt 受重力影响的加速部分
v_ = v_ + R_ * (imu.acce_ - ba_) * dt + gravity_ * dt;
//R_ 初始旋转姿态
//Sophus::SO3d::exp((imu.gyro_ - bg_) * dt) //变换的旋转姿态
//cartographer还用到了IMU的线速度,慢速情况下IMU的线速度其实是对重力的测量,cartographer其实是背包模型,一般情况下都是慢速。
//这里没有用到imu的线速度,应该是更准确一些的
R_ = R_ * Sophus::SO3d::exp((imu.gyro_ - bg_) * dt);
}
// 更新时间
timestamp_ = imu.timestamp_;
}
其他:
cartographer使用pose_extrapolator来融合IMU、odom、激光数据来推断位姿
关于cartographer使用IMU的注释
// Keeps track of the orientation using angular velocities and linear
// accelerations from an IMU. Because averaged linear acceleration (assuming
// slow movement) is a direct measurement of gravity, roll/pitch does not drift,
// though yaw does.
更多推荐
所有评论(0)