cartographer 处理IMU(激光,里程计等)流程

2023-10-27

1、cartographer_ros
入口文件:node_main.cc
入口函数main,如下图:

  ::ros::init(argc, argv, "cartographer_node");
  ::ros::start();

  cartographer_ros::ScopedRosLogSink ros_log_sink;
  cartographer_ros::Run();

2、void Run()   启动轨迹处

  if (FLAGS_start_trajectory_with_default_topics) {
    node.StartTrajectoryWithDefaultTopics(trajectory_options);
  }

3、文件node.cc

  AddTrajectory(options, DefaultSensorTopics());  函数   

LaunchSubscribers(options, topics, trajectory_id);   订阅有关话题

4、LaunchSubscribers  

{SubscribeWithHandler<sensor_msgs::Imu>(&Node::HandleImuMessage,
                                        trajectory_id, topic,
                                       &node_handle_, this),

5、HandleImuMessage兵分两路  一路用于位姿推算   一路用于后面的计算

  if (imu_data_ptr != nullptr) {
    extrapolators_.at(trajectory_id).AddImuData(*imu_data_ptr);
  }
  sensor_bridge_ptr->HandleImuMessage(sensor_id, msg);

6、位姿推算这儿

文件:cartographer/mapping/nternal/pose_extrapolator.cc

void PoseExtrapolator::AddImuData(const sensor::ImuData& imu_data) {
  CHECK(timed_pose_queue_.empty() ||
        imu_data.time >= timed_pose_queue_.back().time);
  imu_data_.push_back(imu_data);
  TrimImuData();
}

7、后面的IMU运算到了  sensor_bridge.cc

void SensorBridge::HandleImuMessage(const std::string& sensor_id,
                                    const sensor_msgs::Imu::ConstPtr& msg) {
  std::unique_ptr<carto::sensor::ImuData> imu_data = ToImuData(msg);
  if (imu_data != nullptr) {
    trajectory_builder_->AddSensorData(
        sensor_id,
        carto::sensor::ImuData{imu_data->time, imu_data->linear_acceleration,
                               imu_data->angular_velocity});
  }
}

8、在添加轨迹中定义了变量 CollatedTrajectoryBuilder 继承TrajectoryBuilderInterface(虚函数,接口)

  void AddSensorData(const std::string& sensor_id,
                     const sensor::ImuData& imu_data) override {
    AddData(sensor::MakeDispatchable(sensor_id, imu_data));
  }

9、而 sensor_collator_->AddSensorData中,  sensor::Collator sensor_collator_;在map_builder.h中定义了。继而找到在collator.cc中找到了实现

void Collator::AddSensorData(const int trajectory_id,
                             std::unique_ptr<Data> data) {
  QueueKey queue_key{trajectory_id, data->GetSensorId()};
  queue_.Add(std::move(queue_key), std::move(data));
}

10、这里就会把IMU数据加入队列啦。std::unique_ptr是标准库的智能指针,与auto_ptr真的非常类似,auto_ptr可以说可以随便赋值,但赋值完后原来的对象就不知不觉报废,而unique_ptr不让你随便赋值,只能move内存转移。

11、注意到在collator.h中一个函数: ( sensor/internal/collator.cc)

void Collator::AddTrajectory(
    const int trajectory_id,
    const std::unordered_set<std::string>& expected_sensor_ids,
    const Callback& callback) {
  for (const auto& sensor_id : expected_sensor_ids) {
    const auto queue_key = QueueKey{trajectory_id, sensor_id};
    queue_.AddQueue(queue_key,
                    [callback, sensor_id](std::unique_ptr<Data> data) {
                      callback(sensor_id, std::move(data));
                    });
    queue_keys_[trajectory_id].push_back(queue_key);
  }
}

在 CollatedTrajectoryBuilder的构造函数中回调了  HandleCollatedSensorData

CollatedTrajectoryBuilder::CollatedTrajectoryBuilder( //整理的轨迹生成器
    const proto::TrajectoryBuilderOptions& trajectory_options,
    sensor::CollatorInterface* const sensor_collator, const int trajectory_id,
    const std::set<SensorId>& expected_sensor_ids,
    std::unique_ptr<TrajectoryBuilderInterface> wrapped_trajectory_builder)
    : sensor_collator_(sensor_collator),
      collate_landmarks_(trajectory_options.collate_landmarks()),
      collate_fixed_frame_(trajectory_options.collate_fixed_frame()),
      trajectory_id_(trajectory_id),
      wrapped_trajectory_builder_(std::move(wrapped_trajectory_builder)),
      last_logging_time_(std::chrono::steady_clock::now()) {
  std::unordered_set<std::string> expected_sensor_id_strings;
  for (const auto& sensor_id : expected_sensor_ids) {
    if (sensor_id.type == SensorId::SensorType::LANDMARK &&
        !collate_landmarks_) {
      continue;
    }
    if (sensor_id.type == SensorId::SensorType::FIXED_FRAME_POSE &&
        !collate_fixed_frame_) {
      continue;
    }
    expected_sensor_id_strings.insert(sensor_id.id);
  }
  sensor_collator_->AddTrajectory(
      trajectory_id, expected_sensor_id_strings,
      [this](const std::string& sensor_id, std::unique_ptr<sensor::Data> data) {
        HandleCollatedSensorData(sensor_id, std::move(data));
      });
}

 

12、它在CollatedTrajectoryBuilder的构造函数中调用了,传入的回调函数名为HandleCollatedSensorData,处理整理后的传感器数据,到这里就开始进入关键正题啦!

void CollatedTrajectoryBuilder::HandleCollatedSensorData(
    const std::string& sensor_id, std::unique_ptr<sensor::Data> data) {
  auto it = rate_timers_.find(sensor_id);
  if (it == rate_timers_.end()) {
    it = rate_timers_
             .emplace(
                 std::piecewise_construct, std::forward_as_tuple(sensor_id),
                 std::forward_as_tuple(
                     common::FromSeconds(kSensorDataRatesLoggingPeriodSeconds)))
             .first;
  }
  it->second.Pulse(data->GetTime());

  if (std::chrono::steady_clock::now() - last_logging_time_ >
      common::FromSeconds(kSensorDataRatesLoggingPeriodSeconds)) {
    for (const auto& pair : rate_timers_) {
      LOG(INFO) << pair.first << " rate: " << pair.second.DebugString();
    }
    last_logging_time_ = std::chrono::steady_clock::now();
  }

  data->AddToTrajectoryBuilder(wrapped_trajectory_builder_.get());
}

13、在头文件cartographer/mapping_2d/global_trajectory_builder.cc中,知道GlobalTrajectoryBuilder类继承了GlobalTrajectoryBuilderInterface类,如图:

template <typename LocalTrajectoryBuilder, typename PoseGraph>
class GlobalTrajectoryBuilder : public mapping::TrajectoryBuilderInterface {
 public:

14、自然就能找到GlobalTrajectoryBuilder::AddImuData的具体实现了

  void AddSensorData(const std::string& sensor_id,
                     const sensor::ImuData& imu_data) override {
    if (local_trajectory_builder_) {
      local_trajectory_builder_->AddImuData(imu_data);
    }
    pose_graph_->AddImuData(trajectory_id_, imu_data);
  }

15、pose_graph是PoseGraph2D的父类,虚函数,多态  

void PoseGraph2D::AddImuData(const int trajectory_id,
                             const sensor::ImuData& imu_data) {
  AddWorkItem([=]() EXCLUDES(mutex_) {
    common::MutexLocker locker(&mutex_);
    if (CanAddWorkItemModifying(trajectory_id)) {
      optimization_problem_->AddImuData(trajectory_id, imu_data);
    }
    return WorkItem::Result::kDoNotRunOptimization;
  });
}

16、OptimizationProblem类

void OptimizationProblem2D::AddImuData(const int trajectory_id,
                                       const sensor::ImuData& imu_data) {
  imu_data_.Append(trajectory_id, imu_data);
}

17、map_by_time.h  将数据附加到'trajectory_id',根据需要创建轨迹。

  void Append(const int trajectory_id, const DataType& data) {
    CHECK_GE(trajectory_id, 0);
    auto& trajectory = data_[trajectory_id];
    if (!trajectory.empty()) {
      CHECK_GT(data.time, std::prev(trajectory.end())->first);
    }
    trajectory.emplace(data.time, data);
  }

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cartographer 处理IMU(激光,里程计等)流程 的相关文章

  • ROS消息sensor_msgs::Imu数据格式

    ubuntu下打开终端输入 rosmsg show sensor msgs Imu 查看sensor msgs Imu的数据格式 std msgs Header header uint32 seq time stamp 时间戳 string
  • ROS2+cartographer+激光雷达+IMU里程计数据融合(robot_locazation) 建图

    目录 写在前面总体流程分块解释IMU数据接收和发布车轮编码器数据接收和发布数据融合 robot localization概括使用 cartographer订阅 效果 写在前面 之前写了一篇ROS2 43 cartorgrapher 43 激
  • Mavros读取PixHawk硬件的IMU数据

    Ubuntu18 04 读取PixHawk硬件的IMU数据 实现方式 使用mavros话题读取到Pixhawk飞控的IMU数据 实现步骤 安装ros 检查是否安装cmake xff08 未安装根据提示安装 xff09 cmake span
  • 在PX4下更换pixhawk的IMU

    写在前面 出于一些原因 xff0c 这篇文章不给出具体的源码 xff0c 因此博主试着将这篇写成了一篇科普性质的文章 xff0c 如果你认真读的话 xff0c 应该会有收获的 为什么要更换pixhawk的传感器 xff1f 大多数的玩家拿到
  • VINS(七)estimator_node 数据对齐 imu预积分 vision

    首先通过vins estimator mode监听几个Topic xff08 频率2000Hz xff09 xff0c 将imu数据 xff0c feature数据 xff0c raw image数据 xff08 用于回环检测 xff09
  • ros rviz显示rosbag中的图像和imu数据

    一 rosbag相关的指令 1 rostopic list 列举出系统中正在发布的ros 话题 2 rosbag record a 录制系统中所有正在发布的ros 话题 3 rosbag record topic1 topic2 o bag
  • 利用Kalibr标定双目相机与IMU

    本文介绍如何利用Kalibr标定工具进行双目相机与IMU的联合标定 主要过程包括以下四步 xff1a 生成标定板标定双目相机标定IMU联合标定 1 生成标定板 使用AprilTag rosrun kalibr kalibr create t
  • 飞控IMU数据进阶处理(FFT,滤波器)

    前面的文章 xff08 知乎专栏 https zhuanlan zhihu com c 60591778 xff09 曾简单讲过IMU数据 xff08 陀螺仪 加速度数据 xff09 的校准以及一阶低通滤波 本文在此基础上更进一步讲一下数据
  • 再谈IMU数据处理(滤波器)

    本文开始前 xff0c 先回答一个问题 上一篇文章最后提到了卡尔曼滤波器用来做一维数据的数字滤波处理 xff0c 最终的实验结果说 xff1a 该模型下的卡尔曼滤波处理与二阶IIR低通滤波处理效果几乎一致 有网友指出是错误的 xff0c 卡
  • RealSenseD345I —— imu + camera标定

    目录 1 标定目的 2 标定准备 3 标定步骤 nbsp nbsp nbsp nbsp 1 IMU标定 nbsp nbsp nbsp
  • Xsens Mti-g-710 IMU driver在Ubuntu18.04 ROS melodic中的安装使用

    Ubuntu18 04下安装的ROS melodic 如何使用Xsens Mti g 710 IMU driver xff1f 这里给出一个详细步骤说明 这里的IMU是USB接口 1安装 首先插入IMU的USB口 命令行运行 gt lsus
  • 49、OAK测试官方的IMU模块和SpatialLocationCalculator节点

    基本思想 xff1a 不太懂IMU是干嘛的 xff0c 不像图像那么容易可视化 xff0c 参考官方demo的 xff0c 记录一下 xff0c 后续这篇需要补充 xff0c 参考的IMU的介绍 xff0c 原理不懂 xff0c 先占个坑
  • 优化IMU数据避免突变的建议

    影响IMU数据变化的主要因素是应力 温度和电气干扰 xff1b xff11 温度的的骤升 xff0c 比如芯片的位置附件有相关器件几秒钟工作一次 xff0c 此时温度骤升 xff0c 可能会引起数据也发生突变 xff0c 周围有变化的热源和
  • 利用IMU数据来计算位移

    目标 xff1a 利用IMU测得的加速度信息来计算位移 xff0c 很简单假设是匀加速运动或是匀速运动都可以 xff0c 主要是看问题的背景来具体去确定运动模型 xff0c 这里我就取个简单的匀加速运动模型 学习过程 xff1a 1 了解I
  • 一文了解IMU原理、误差模型、标定、惯性传感器选型以及IMU产品调研(含IMU、AHRS、VRU和INS区别)

    在此记录一下测试IMU过程中的其它文章 xff0c 便于以后查看 xff1a IMU的误差标定以及姿态解算ROS下通过USB端口读取摄像头数据 包括笔记本自带摄像头 激光 摄像头 IMU等传感器数据同步方法 message filters
  • Kalibr进行相机-IMU联合标定踩坑记录RuntimeError: Optimization failed!

    1 具体标定步骤 xff0c 跟网上别的一模一样 xff0c 此处就不列举 2 记录踩坑过程 xff1a RuntimeError Optimization failed 当执行到开始联合标定时 xff0c 也就是如下指令 xff1a ka
  • IMU-Allan方差分析

    使用Allan方差来确定MEMS陀螺仪的噪声参数 陀螺仪测量模型为 使用长时间静止的陀螺仪数据对陀螺仪噪声参数进行分析 上式中 三个噪声参数N 角度随机游走 K 速率随机游走 和B 偏差不稳定性 背景 Allan方差最初由David W A
  • IMU背包对动物行为影响测试

    动物行为是一种可观察和可测量的指标 轻量化和低成本的传感器技术的先进发展为研究人员提供了以最小干预来跨越空间和时间跟踪动物的机会 特别是对于家禽业来说 已经从传统的笼养系统转变为无笼养系统 许多技术可用于检测大群鸡的行为 活动和位置 为了有
  • PID算法(没办法完全理解的东西)

    快速 P 准确 I 稳定 D P Proportion 比例 就是输入偏差乘以一个常数 I Integral 积分 就是对输入偏差进行积分运算 D Derivative 微分 对输入偏差进行微分运算 输入偏差 读出的被控制对象的值 设定值
  • IMU用于上肢功能评估

    来自日本团队牵头研究揭示了利用九轴运动传感器评估上肢Fugl Meyer FMA 的潜力 该探索侧重于将惯性测量单元 IMU 集成到 FMA 的方法中 并探究是否可以出现标准化和更客观的测量 从而解决动态运动评估中的一个紧迫问题 九轴 IM

随机推荐

  • 探究软件测试人员的进阶之路

    一谈到进阶 大部分文章 包括前面一些文章也会写到职级如何从初级 中级 高级 一直进阶到专家级 然后写上每个级别所需要的知识技能 然而 我们掌握了这些所谓初 中 高的知识和技能 真的就能成为测试专家了吗 对于这个问题 大部分人应该都带着疑惑或
  • qt导入html css样式表,第45篇 进阶(五)Qt样式表

    第45篇 进阶 五 Qt样式表 导语 一个完善的应用程序不仅应该有实用的功能 还要有一个漂亮的外观 这样才能使应用程序更加友善 更加吸引用户 作为一个跨平台的UI开发框架 Qt提供了强大而灵活的界面外观设计机制 Qt样式表是一个可以自定义部
  • 分数阶导数的意义_导数的意义

    分数阶导数的意义 钙衍生物 CALCULUS DERIVATIVES After derivative theory posts we will start to see some of the applications that make
  • 私人用的红帽linux,红帽宣布为个人开发者提供16个RHEL免费许可 支持在生产环境中使用...

    自从红帽宣布结束CentOS操作系统后就引起很多争议 按红帽计划CentOS 8将是最后的版本并且会在年底停更 这使得很多依赖该操作系统的个人和企业无比愤怒 因为这突如其来的变更将会导致大量生产环境需要更换系统 现在红帽为平息用户愤怒正在扩
  • 双极性SPWM波生成

    本篇文章主要介绍用于逆变电路的双极性SPWM波生成 SPWM波就是脉冲宽度按正弦规律变化和正弦波等效的PWM波形 用于控制逆变电路中开关器件的通断 使其输出的脉冲电压的面积与所希望输出的正弦波在相应区间内的面积相等 经滤波后可以得到正弦波输
  • @Transactional事务中发送MQ消息,事务还未完成但是消息已经发送

    Transactional事务中发送MQ消息 事务还未完成但是消息已经发送 这种情况会导致一些问题 1 事务还未提交 但是消息已经发送 这个时候消息中的一些信息提供给别人调用 但是别人调用并没有在数据库找到该记录 因为事务还未提交 2 事务
  • 多线程面试题

    目录 1 僵尸进程和孤儿进程 1 1 孤儿进程定义 1 2 僵尸进程定义 1 2 怎样来清除僵尸进程 1 kill杀死元凶父进程 一般不用 2 父进程用wait或waitpid去回收资源 方案不好 3 通过信号机制 在处理函数中调用wait
  • 8种方案,保证缓存和数据库的最终一致性

    订阅专栏 前言 我们通常使用缓存机制来提升系统的性能 缓存系统下的读写操作 一般都需要操作数据库与缓存 对于读操作 一般是先查询缓存 查询不到再查询数据库 最后回写进缓存 而对于写操作 究竟是先删除 更新 缓存 再更新数据库 还是先更新数据
  • open build service打包deb,并浅谈一点

    详细打包步骤注意 https zh opensuse org openSUSE Build Service Debian builds 认识 浅谈如何认识open build service的 最近在研究软件打包分发和发布的相关知识 发现了
  • CSS 预处理工具 Less 的介绍及使用 步骤

    文章目录 Less是什么 Less的使用方法 Less 中的注释 Less 中的变量 Less 中的嵌套 Less 中的混合 Mixin Less 中的运算 Less 中的转译 Less 中的作用域 Less 中的导入 Less实用实例 文
  • zipkin接入mysql【windows】

    java jar zipkin jar 这种方式启动数据是保存在内存中的 下面我们配置一下将数据保存到mysql中 创建数据库 CREATE DATABASE zipkin 创建表结构 表结构内容参考以下连接 https github co
  • STM32CubeIDE设置Flash烧录地址和大小(告别Keil魔术棒)

    STM32CubeIDE中设置Flash烧写地址和范围 在由Keil平台转到STM32CubeIDE平台过程中 我们熟悉的点开魔术棒进行相关烧录配置的方式已经不适用了 在STM32CubeIDE平台中我们需要通过修改文件的方式来实现 稍显麻
  • sublime text3 python 代码提示_Sublime Text3+Anaconda插件实现智能提示python IDE

    导读 前言上期给你们介绍装Sublime Text3和Python环境 可以编写简单的python类库sublime text3 python 可是却不能像其它IDE一样智能提醒 这样用这个意义也就不大了 今天就给你们推荐python智能提
  • jeecg boot笔记(一)-使用模糊查询

    1 引入 JInput import JInput from components jeecg JInput vue 2 使用
  • NOIP2004 火星人(全排列)

    题目来源 http acm wust edu cn problem php id 1074 soj 0 题目描述 火星人共有N个手指 每个手指分别代表着1 N共N个数 可以通过改变这个这N个手指的顺序来改变值的大小 但是人类想要和火星人交流
  • docker安装 镜像检索、本地下载上传、重命名

    安装docker wget https mirrors aliyun com docker ce linux centos docker ce repo O etc yum repos d docker ce repo yum y inst
  • 基于GPRS的无线视频监控系统

    1 引言 目前 远程视频监控系统已经广泛应用于工矿企业生产现场监控 电信机房监控 城市交通管理等领域 常见的远程视频监控系统大多是通过架设专用的有线媒介 或者租用电信运营商的通信线路传输视频信号 前者工程工期长 前期投入比较大 传输距离有限
  • 学生成绩管理系统

    一个年级 相当链表A 该年级5个班 每个班5个人 相当于链表B1 B5 做一个学生成绩管理系统 include
  • C/C++操作文件

    1 C 给字符数组内文件名排序 假设我们获得到的文件名列表是一个二维字符数组 给这样的数据排序首先要获得排序所需的关键字 如下 void getNum char dstChar int num 首先要知道字符串长啥样 用字符串中的哪几个位置
  • cartographer 处理IMU(激光,里程计等)流程

    1 cartographer ros 入口文件 node main cc 入口函数main 如下图 ros init argc argv cartographer node ros start cartographer ros Scoped