BLAM源码解析(五)—— 回环检测

2023-05-16

上一节介绍了BLAM的帧间匹配和帧图匹配,代码简洁明了。

本节介绍BLAM的回环检测模块。具体代码块如下:

 // Check for new loop closures.
  bool new_keyframe;
  if (HandleLoopClosures(msg_filtered, &new_keyframe)) {
    // We found one - regenerate the 3D map.
    PointCloud::Ptr regenerated_map(new PointCloud);
    loop_closure_.GetMaximumLikelihoodPoints(regenerated_map.get());

    mapper_.Reset();
    PointCloud::Ptr unused(new PointCloud);
    mapper_.InsertPoints(regenerated_map, unused.get());

    // Also reset the robot's estimated position.
    localization_.SetIntegratedEstimate(loop_closure_.GetLastPose());
  } else {
    // No new loop closures - but was there a new key frame? If so, add new
    // points to the map.
    if (new_keyframe) {
      localization_.MotionUpdate(gu::Transform3::Identity());
      localization_.TransformPointsToFixedFrame(*msg_filtered, msg_fixed.get());
      PointCloud::Ptr unused(new PointCloud);
      mapper_.InsertPoints(msg_fixed, unused.get());
    }
  }

  // Visualize the pose graph and current loop closure radius.
  loop_closure_.PublishPoseGraph();

我们知道视觉SLAM一般通过词袋模型进行回环,激光SLAM中的佼佼者Cartographer通过分支定界+栅格匹配进行回环,等等。BLAM由于构建的是点云地图,不涉及栅格更新,因此通过最简单的ICP进行回环。接下来逐行解析:

首先使用HandleLoopClosures,向位姿图中加入新位姿节点:

  if (!loop_closure_.AddBetweenFactor(localization_.GetIncrementalEstimate(),  // MJY
                                      covariance, &pose_key)) {

接下来使用AddKeyScanPair,向回环检测模块加入关键帧。

  if (!loop_closure_.AddKeyScanPair(pose_key, scan)) {

然后最重要的:在可回环范围内寻找回环,可回环范围由第一节介绍的几个参数决定。

  if (!loop_closure_.FindLoopClosures(pose_key, &closure_keys)) {

寻找回环的过程中将回环边加入位姿图。

让我们回到BlamSlam.cc,继续HandleLoopClosures以下的内容,使用了如下函数将历史关键帧的点云转换到全局坐标系,合并到一起,加入到回环检测模块的mapper_中:

    loop_closure_.GetMaximumLikelihoodPoints(regenerated_map.get());

注意,这个点云是经过回环校正的点云,因此是经过回环检测优化的map

然后用回环校正的位姿,更新定位模块localization_中的位姿,即:

void PointCloudLocalization::SetIntegratedEstimate(
    const gu::Transform3& integrated_estimate) {
  integrated_estimate_ = integrated_estimate;

  // Publish transform between fixed frame and localization frame.
  geometry_msgs::TransformStamped tf;
  tf.transform = gr::ToRosTransform(integrated_estimate_);
  tf.header.stamp = stamp_;
  tf.header.frame_id = fixed_frame_id_;
  tf.child_frame_id = base_frame_id_;
  tfbr_.sendTransform(tf);
}

最终发布位姿图。没有订阅者是不发布的。

  loop_closure_.PublishPoseGraph();

至此,BLAM源码介绍完毕,接下来尽情调参,实现你自己特定场景的SLAM吧!!!!

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

BLAM源码解析(五)—— 回环检测 的相关文章

  • 第十四篇,STM32的CAN总线通信

    1 CAN总线的概念 CAN指的是控制器局域网网络 Controller Area Network xff0c 由德国博世汽车电子厂商开发出来 CAN使用差分信号 xff0c 具有较强的抗干扰能力和传输稳定性 CAN属于多主通信 xff0c
  • OpenCV图像处理学习十九,像素重映射cv::remap

    一 像素重映射概念 重映射就是把输入图像中各个像素按照制定的规则顺序映射到另外一张图像的对应位置上去 xff0c 形成一张新的图像 二 像素映射API函数接口 cv remap xff08 InputArray src 输入图像 Outpu
  • OpenCV图像处理学习二十一,直方图比较方法

    一 直方图比较 直方图比较是对输入的两张图像进行计算得到直方图H1与H2 xff0c 归一化到相同的尺度空间 xff0c 然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度 xff08 每张图像都有唯一的直方图与之对应 xff0
  • 嵌入式FreeRTOS学习八,xTaskCreate创建任务的细节以及恢复中断任务实现

    一 创建任务函数xTaskCreate 任务也不是很复杂的东西 xff0c 任务也就是一个函数xTaskCreate 简单得说 xff0c 创建一个任务 xff0c 你得提供它的执行函数 xff0c 你得提供它的栈的大小 xff0c 函数的
  • 嵌入式FreeRTOS学习一,FreeRTOS概述和代码结构

    一 FreeRTOS是什么 FreeRTOS 是由 Real Time Engineers Ltd 出品 xff0c 是一款市场领先的 RTOS 现在已经支持几十种 处理器架构 Free即免费的 xff0c RTOS全称是 Real Tim
  • 嵌入式FreeRTOS学习二,FreeRTOS任务的创建和删除

    一 任务的创建和删除 1 1 函数xTaskCreate 此函数用来创建一个任务 xff0c 任务需要RAM来保存与任务有关的状态信息 任务控制块 xff0c 任务也需要一定的RAM 来作为任务堆栈 如果使用函数xTaskCreate 来创
  • 嵌入式FreeRTOS学习五,FreeRTOS任务调度器

    四 调度器 FreeRTOS 操作系统支持三种调度方式 xff1a 抢占式调度 xff0c 时间片调度和合作式调度 实际应用主要是抢占式调度和时间片调度 xff0c 合作式调度用到的很少 启动调度器的API函数vTaskStartSched
  • 嵌入式FreeRTOS学习九,任务链表的构成,TICK时间中断和任务状态切换调度

    一 tskTaskControlBlock 函数结构体 在tskTaskControlBlock 任务控制块结构体中 xff0c 其中有任务状态链表和事件链表两个链表成员 xff0c 首先介绍任务状态链表这个结构 xff0c 这个链表通常用
  • 嵌入式FreeRTOS学习十,任务调度和任务就绪链表任务调度过程

    一 main函数里面的栈是哪里分配的 main函数里面用到的栈 xff0c 假设为msp 是汇编代码里面设定的 xff0c 对于STM32F103 在汇编代码里的向量表设置了一个栈 initial sp 那这个栈是给谁用的呢 xff1f 可
  • ovn 通过网关虚拟路由器连接外部网络

    本文实验如何通过ovn的网关逻辑路由器将ovn网络连接到外部网络 前面讲过ovn的逻辑路由器是分布式的 xff0c 这意味着它没有绑定到某个节点上 xff0c 而是存在于所有节点上的 xff0c 同时它是通过每个节点的openflow流表来
  • 嵌入式FreeRTOS学习十一,深入理解任务调度机制

    一 任务调度机制 可抢占 xff1a 高优先级的任务先运行时间片轮转 xff1a 同优先级的任务轮流执行空闲任务礼让 xff1a 如果有同是优先级为0的其他就绪任务 xff0c 空闲任务主动放弃一次运行机会函数调用vTaskDelay xD
  • SOAP传输协议

    一 HTTP传输协议 超文本传输协议 xff08 HyperText Transfer Protocol xff0c 缩写 xff1a HTTP xff09 xff0c 它是基于请求 响应的模式协议 xff0c 客户端发出请求 xff0c
  • ONVIF简介

    一 什么是ONVIF ONVIF规范描述了网络视频的模型 接口 数据类型以及数据交互的模式 并复用了一些现有的标准 xff0c 如WS系列标准等 ONVIF规范的目标是实现一个网络视频框架协议 xff0c 使不同厂商所生产的网络视频产品 x
  • gsoap工具生成onvif设备搜索(remotediscovery)代码框架

    什么是gsoap工具 xff1f gSOAP 提供了两个工具来方便开发人员使用 C C 43 43 语言快速开发Web 服务应用 xff0c 通过 gSOAP 提供的这两个工具 xff0c 开发人员可以快速生成服务端与客户端代码框架 xff
  • 001_初识_飞航科技光标飞控

    这两天老潘给我一块飞控 xff0c 让我练手 xff0c 为电赛做准备 xff0c 拿到控挺开心的 xff0c 毕竟省了一笔RMB 本来想着买块正点原子的飞控 资料 xff1a 说起资料简单看了一下发现还蛮全的 xff0c 但是这个资料我居
  • 写出C语言的第一个程序“Hello World”

    这里写自定义目录标题 写出C语言的第一个程序 Hello World 写出C语言的第一个程序 Hello World 下面展示一些 内联代码片 span class token comment A code block span span
  • Eigen库的安装攻略

    Eigen库的安装攻略 转载 xff1a Eigen库安装 xff08 两种方式 xff09 转载 xff1a Eigen库安装 xff08 两种方式 xff09 链接 link
  • 【ROS2基础学习】

    入门篇 前言一 创建一个功能包二 编译三 source总结 前言 提示 xff1a 这里是记录的大概内容 xff1a 随着机器人技术的不断发展 xff0c ROS也越来越重要 xff0c 很多人都开启了学习ROS xff0c 本文就介绍了R
  • Arduino 外部中断重置内部定时器

    Arduino 外部中断重置内部定时器 文章目录 Arduino 外部中断重置内部定时器前言一 准备工作二 代码三 实验效果1 设置1Hz的方波 xff08 外部中断触发 xff09 xff1a 2 观察示波器各个波形 xff1a 3 延迟
  • ALUBI LPMS-IG1 RS232 IMU ROS2驱动安装

    文章目录 前言一 下载官方系列文档二 windows上的上位机程序安装2 Ubuntu上的ROS2驱动安装Offset Mode 2 总结 前言 IMU在自动驾驶领域广泛应用 xff0c 本文主要记录了在ROS2中使用ALUBI LPMS

随机推荐

  • ovn-northd 源码分析

    ovn northd是ovn中的核心后台进程 xff0c 主要负责将ovn的高层配置转换成供ovn controller后台进程使用的逻辑配置 xff0c 更详细的说就是它将ovn northbound数据库中传统意义上的逻辑网络配置转换成
  • 镭神CH128x1系列激光雷达使用记录

    镭神CH128x1系列激光雷达使用记录 文章目录 镭神CH128x1系列激光雷达使用记录前言一 操作步骤1 PC连接雷达 二 实验1 雷达控制器上的接口 xff1a 2 接口定义3 Rviz中显示效果 总结致谢 前言 本条博客的需求来源于自
  • c语言中char数组的结束位

    因为是半路出家学习cpp的 xff0c 所以经常会对c语言里面的字符数组感到困惑 xff0c 这次一次性做个总结 首先 xff0c 结束位 0 只针对字符数组 xff0c 不针对整型或者其他数组 其次 xff0c 字符数组的大小只针对里面的
  • SUMO 使用netconvert报错解决办法

    SUMO 使用netconvert报错 问题描述正确解决方法不适用的解决方法 问题描述 刚开始学习使用sumo xff0c 版本是sumo1 8 0 第一次使用netconvert转换地图时出现报错 xff0c 提示没有PROJ Libra
  • IoTDB基础 初识IoTDB 安装及基本使用(个人学习记录)

    官方文档 http iotdb incubator apache org zh UserGuide V0 13 x API Programming Java Native API html 参考博客 时序数据库IoTDB安装及基本使用htt
  • 树莓派+ L298N 控制二相四线步进电机

    树莓派 43 L298N 控制二相四线步进电机 1 步进电机 步进电机是一种将电脉冲信号转换成相应角位移或线位移的电动机 在非超载的情况下 xff0c 电机的转速 停止的位置只取决于脉冲信号的频率和脉冲数 xff0c 而不受负载变化的影响
  • VTK移动立方体法处理CT图像建立三维模型

    span class token comment 移动立方体 span span class token macro property span class token directive keyword include span span
  • 使用tcp工具调试socket服务端通信

    背景介绍 xff1a 客户端是用tcp连接调试 xff0c 工具链接 https pan baidu com s 1kfjv1jdS8KJgb7YVSu9Wtw 提取码 z34a 服务端是Java代码写的逻辑 xff0c 用byte 流接收
  • Fast Planner 轨迹规划

    文章目录 0 概览1 关键问题2 相关工作3 F a s t P
  • C++继承和多态学习心得

    继承 定义 xff1a 在已有类的基础上创建新类的过程 一个 B 类继承A类 xff0c 或称从类 A 派生类 B 类 A 称为基类 xff08 父类 xff09 xff0c 类 B 称为派生类 xff08 子类 xff09 语法形式 xf
  • Python学习笔记(六):isalpha()函数的用法

    isalpha 方法 xff1a 判断字符串是否只由字母组成 xff0c 如果字符串中所有字符都是字母则返回True xff0c 否则返回False str1 61 34 python 34 print str1 isalpha True
  • ovn-controller源码分析

    ovn controller是运行在chassis hypervisor上的后台进程 xff0c 向上通过OVSDB协议连接到OVN sourthbound数据库 xff0c 向下通过OVSDB协议连接到ovs数据库 xff0c 并通过op
  • ROS学习笔记(十一) rospy介绍(一)

    rospy介绍 xff08 一 xff09 rospy是Python版本的ROS客户端库 xff0c 提供了Python程序需要的接口 xff08 rospy就是一个Python模块 xff09 xff0c 位于 opt ros kinee
  • ROS学习笔记(十三) TF介绍(一)

    TF介绍 xff08 一 xff09 TF xff1a 机器人不停部位之间的坐标转换 坐标转换包括位置和姿态两方面 xff0c ROS中的tf是一个让用户随时记录多个坐标系的软件包 tf保持缓存的树形结构中的坐标系之间的关系 xff0c 并
  • SLAM基础(三) --图优化

    滤波器的缺点 xff1a EKF SLAM不仅要维护自身的状态 xff0c 还需要维护地图 xff08 特征 xff09 于是必须在内存上做出牺牲 xff0c 比如500个特征 xff0c 每个特征在二维环境中是两个点 xff08 x轴 y
  • 前端JS十种继承方式-图解通俗易懂

    1 学习JS继承一定要拿指针的概念去审视 xff0c 不能死记 2 首先要明白 xff1a 原型 xff08 对象 xff09 xff0c let a 61 new A 会发生构成原型链图 xff0c 类对象的prototype指向他的原型
  • ros发布和订阅图像的压缩——高效图传(适用带宽不足问题)

    ros话题机制默认通过TCP进行传输 因此特别容易堵塞 必须要有compressed的图像 xff0c img raw传输速度非常慢 参考 xff1a https blog csdn net qq 30460905 article deta
  • BLAM源码解析(三)—— 定时器总揽大局

    上一节介绍了激光数据的回调 xff0c 最终被依次推入到容器之中 xff0c 存储在pcl pcld queue 那么激光数据的使用是怎么实现的 xff0c 就是这一节要介绍的内容 回想第一节我们介绍的定时器estimate update
  • BLAM源码解析(四)—— 基于ICP的位姿更新

    第三节我们介绍了定时器的定时回调 xff0c 实现对激光数据的批量循环处理 xff0c 在每一个激光数据的循环当中 xff0c 除了一开始filter 的点云过滤 xff0c 最重要的其实是下面的基于ICP的位姿更新 xff0c 即 if
  • BLAM源码解析(五)—— 回环检测

    上一节介绍了BLAM的帧间匹配和帧图匹配 xff0c 代码简洁明了 本节介绍BLAM的回环检测模块 具体代码块如下 xff1a Check for new loop closures bool new keyframe if HandleL