lego-loam 同步构建2d栅格导航地图

2023-10-30 20:30

本文主要是介绍lego-loam 同步构建2d栅格导航地图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

lego-loam 同步构建2d栅格导航地图

  • 3d点云预处理
  • keypose保存
  • 根据闭环条件更新2d map
  • 构建和2d map
  • 总结

基于目前移动机器人的应用可知,目前3d slam存储的主要为点云地图,由于其特征点比2D激光器数据更加丰富,因此用于后期的定位具有更好的抗干扰性和鲁棒性。但是用于导航的基本路径规划功能,目前仍主要依赖于2d栅格地图。
其中16年开源的cartographer的3dslam则同步发布了2d map格式,而存储的点云也是基于stream自定义格式,而不是传统的点云地图。因此定位时可直接使用3d定位结果,2d地图结果进行导航。

本文参考cartographer中2d 栅格概率更新的功能,在lego-loam开源代码中实现其2d栅格地图的同步创建,同时2d地图可自动剔除slam过程中的移动物体(注:lego-loam 创建的3d点云地图,没有剔除);其效果图如下:

在这里插入图片描述
操作步骤如下:

3d点云预处理

imageProjection.cpp3d点云分割代码中,根据分割后的结果,将地面上的点以及高过机器人高度的所有点云进行剔除。并计算同一个水平扫描ID下的距离值,并保存。如此可获取投影水平面的2D scan message格式。

  for (size_t j = 0; j < _horizontal_scans; ++j) {float min_range = 1000;size_t id_min = 0;for (size_t i = 0; i < _vertical_scans; ++i) {size_t Ind = j + (i)*_horizontal_scans;float Z = _full_cloud->points[Ind].z;if ((_ground_mat(i, j) != 1) &&(Z > 0.4) && (Z<1.2) &&(_range_mat(i, j)<40)) {                     // 地面上点云忽略, 过高过矮的点忽略, 过远的点忽略if(_range_mat(i, j) < min_range) {           // 计算最小距离min_range = _range_mat(i, j);id_min = Ind;}}}if (min_range<1000) {_scan_msg->push_back(_full_cloud->points[id_min]);}}

keypose保存

类似于基本图优化结构和lego-loam存储keypose轨迹序列,并同步记录每个2d点云的笛卡尔坐标。

  // 将极坐标转换为直角坐标系for(int i = 0; i < _scan_msg->points.size(); ++i) {scan_points.emplace_back(_scan_msg->points[i].x, _scan_msg->points[i].y);}// 定义新的scan格式,每一束光采用直角坐标std::shared_ptr<slam::LaserScan> laser_scan(new slam::LaserScan(scan_points));laser_scan->setId(_scans.size());       // 第一帧激光不做处理,仅记录并放入优化器顶点中// laser_scan->setPose(Eigen::Vector3f(0, 0, 0));laser_scan->setPose(pose);              //记录初始激光帧位置,用于slam建图初始坐标(即创建地图坐标系)laser_scan->transformPointCloud();      //根据激光位置,计算每个点的在map的位置_scans.push_back(laser_scan);           //收集每帧激光
}

根据闭环条件更新2d map

闭环条件由lego-loam 3d slam 触发和后端优化,根据3d位置更新 2d投影位置。

// 若存在闭环处理,则需要对位姿进行修正,将历史的的位姿用优化后的数据进行更新
void MapOptimization::correctPoses() {if (aLoopIsClosed == true) {recentCornerCloudKeyFrames.clear();recentSurfCloudKeyFrames.clear();recentOutlierCloudKeyFrames.clear();// update key posesint numPoses = isamCurrentEstimate.size();for (int i = 0; i < numPoses; ++i) {cloudKeyPoses3D->points[i].x =isamCurrentEstimate.at<Pose3>(i).translation().y();cloudKeyPoses3D->points[i].y =isamCurrentEstimate.at<Pose3>(i).translation().z();cloudKeyPoses3D->points[i].z =isamCurrentEstimate.at<Pose3>(i).translation().x();cloudKeyPoses6D->points[i].x = cloudKeyPoses3D->points[i].x;cloudKeyPoses6D->points[i].y = cloudKeyPoses3D->points[i].y;cloudKeyPoses6D->points[i].z = cloudKeyPoses3D->points[i].z;cloudKeyPoses6D->points[i].roll =isamCurrentEstimate.at<Pose3>(i).rotation().pitch();cloudKeyPoses6D->points[i].pitch =isamCurrentEstimate.at<Pose3>(i).rotation().yaw();cloudKeyPoses6D->points[i].yaw =isamCurrentEstimate.at<Pose3>(i).rotation().roll();// 更新 2d 投影位置_scans[i]->setPose(Eigen::Vector3f(cloudKeyPoses6D->points[i].z,cloudKeyPoses6D->points[i].x,cloudKeyPoses6D->points[i].pitch));_scans[i]->transformPointCloud();}aLoopIsClosed = false;                  // 修正完成}
}

构建和2d map

已知每个时刻的2d绝对位置和对应的range_scan的中所有point笛卡尔坐标,基于cartographer中概率地图的生成和更新,从而构建2d栅格地图。 其中bresenham为经典的画线法,用于更新无障碍栅格,而range_scan的端点用来更新障碍栅格。其具体理论可详看:
cartographer 代码思想解读(4)- probability grid地图更新1
cartographer 代码思想解读(5)- probability grid地图更新2

    for(const std::shared_ptr<LaserScan>& scan : scans) {Eigen::Vector2f start = getMapCoords(scan->getPose());const PointCloud& point_cloud = scan->getTransformedPointCloud();for(const Eigen::Vector2f& point : point_cloud) {Eigen::Vector2f end = getMapCoords(point);std::vector<Eigen::Vector2i> points;bresenham(start[0],  start[1], end[0], end[1], points);int n = points.size();if(n == 0) {continue;}for(int j = 0; j < n - 1; ++j) {int index = getIndex(points[j][0], points[j][1]);if(value_[index] + log_odds_free_ >= log_odds_min_) {value_[index] += log_odds_free_;}}int index = getIndex(points[n - 1][0], points[n - 1][1]);if(value_[index] + log_odds_occupied_ <= log_odds_max_) {value_[index] += log_odds_occupied_;}}}

总结

目前3d slam主要目的是用于移动机器人的后期定位使用,而SLAM主要用于一个新环境的第一次配置。因此,3d定位对应的2d栅格地图十分必要,本文简单理解就是已知定位建图的功能。

这篇关于lego-loam 同步构建2d栅格导航地图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/310395

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

利用命令模式构建高效的手游后端架构

在现代手游开发中,后端架构的设计对于支持高并发、快速迭代和复杂游戏逻辑至关重要。命令模式作为一种行为设计模式,可以有效地解耦请求的发起者与接收者,提升系统的可维护性和扩展性。本文将深入探讨如何利用命令模式构建一个强大且灵活的手游后端架构。 1. 命令模式的概念与优势 命令模式通过将请求封装为对象,使得请求的发起者和接收者之间的耦合度降低。这种模式的主要优势包括: 解耦请求发起者与处理者

Jenkins构建Maven聚合工程,指定构建子模块

一、设置单独编译构建子模块 配置: 1、Root POM指向父pom.xml 2、Goals and options指定构建模块的参数: mvn -pl project1/project1-son -am clean package 单独构建project1-son项目以及它所依赖的其它项目。 说明: mvn clean package -pl 父级模块名/子模块名 -am参数

JAVA用最简单的方法来构建一个高可用的服务端,提升系统可用性

一、什么是提升系统的高可用性 JAVA服务端,顾名思义就是23体验网为用户提供服务的。停工时间,就是不能向用户提供服务的时间。高可用,就是系统具有高度可用性,尽量减少停工时间。如何用最简单的方法来搭建一个高效率可用的服务端JAVA呢? 停工的原因一般有: 服务器故障。例如服务器宕机,服务器网络出现问题,机房或者机架出现问题等;访问量急剧上升,导致服务器压力过大导致访问量急剧上升的原因;时间和