cartographer全局重定位的实现

cartographer全局重定位的实现

  • 1.简介
    • 核心流程
    • 链接代码:

1.简介

本博客主要介绍cartographer全局重定位的实现,目前已经测试能够实现在6米180度范围内的全局重定位。

核心流程

这个重定位函数的流程,然后逐个部分给出实现代码。

1.创建线程池;
2.点云过一次体素滤波;
3.为每一个 Submap 创建 FastCorrelativeScanMatcher 匹配器,在线程池中执行,并等待所有匹配器创建完成;
4.遍历每一个匹配器,调用 MatchFullSubmap 方法,记录匹配结果和分数,在线程池中执行,并等待所有匹配完成;
5.找出匹配得分最高的位姿,创建 CeresScanMatcher2D 匹配器再次匹配得到准确的位姿。

实现代码如下:

bool PoseGraph2D::PerformGlobalLocalization(cartographer::sensor::PointCloud laser_point_cloud,float cutoff, transform::Rigid2d* best_pose_estimate, float* best_score)
{
    auto my_thread_pool = std::make_unique<common::ThreadPool>(std::thread::hardware_concurrency());
    assert(my_thread_pool != nullptr);
    LOG(INFO) << "laser_point_cloud.points_.size()1 : " << laser_point_cloud.points().size();
    const cartographer::sensor::PointCloud filtered_point_cloud = cartographer::sensor::VoxelFilter(laser_point_cloud, 0.05);  
    // const cartographer::sensor::PointCloud filtered_point_cloud = match_point_cloud_;
    if (filtered_point_cloud.empty()) {
        LOG(ERROR) << "Filtered point cloud is empty!";
        return false;
    }
    LOG(INFO) << "filtered_point_cloud.points_.size() : " << filtered_point_cloud.points().size();
    LOG(INFO) << "cutoff : " << cutoff;
    int32_t submap_size = static_cast<int>(data_.submap_data.size());
    absl::BlockingCounter created_counter{submap_size};
    std::vector<std::shared_ptr<scan_matching::FastCorrelativeScanMatcher2D>> matchers(submap_size);
    std::vector<const cartographer::mapping::Grid2D*> submaps(submap_size);
    LOG(INFO) << "Submap size: " << submap_size;
    size_t index = 0;
    for (const auto& submap_id_data : data_.submap_data) 
    {
        if (submap_id_data.id.trajectory_id != 0) {
            created_counter.DecrementCount();
            continue;
        }
        auto task = absl::make_unique<common::Task>();
        task->SetWorkItem([this, &matchers, &created_counter, index, submap_id = submap_id_data.id, &submaps] {
            try {
                const auto& submap_data = data_.submap_data.at(submap_id);
                if (!submap_data.submap) {
                    LOG(ERROR) << "Submap is null for index " << index;
                    throw std::runtime_error("Submap is null");
                }
                submaps[index] = static_cast<const Submap2D*>(submap_data.submap.get())->grid();
                matchers[index] = std::make_unique<scan_matching::FastCorrelativeScanMatcher2D>(
                    *submaps[index],
                    options_.constraint_builder_options().fast_correlative_scan_matcher_options());
                LOG(INFO) << "Task completed for index: " << index;
            } catch (const std::exception& e) {
                LOG(ERROR) << "Error in task for index " << index << ": " << e.what();
            }
            created_counter.DecrementCount();
        });

        my_thread_pool->Schedule(std::move(task));
        index++;
    }

    LOG(INFO) << "Total submaps processed: " << index;
    created_counter.Wait();
    LOG(INFO) << "PoseGraph2D::PerformGlobalLocalization 728.";
    size_t matcher_size = index;
    std::vector<float> score_set(matcher_size, -std::numeric_limits<float>::infinity());
    std::vector<transform::Rigid2d> pose_set(matcher_size);    
    absl::BlockingCounter matched_counter{matcher_size};
    std::atomic_bool has_matched{false};    
    for (size_t i = 0; i < matcher_size; i++) 
    {
        auto task = absl::make_unique<common::Task>();
        task->SetWorkItem([i, &filtered_point_cloud, &matchers, &score_set, &pose_set, cutoff, &matched_counter, &has_matched] {
            if (!matchers[i]) 
            {
                LOG(ERROR) << "Matcher is null at index " << i;
                matched_counter.DecrementCount();
                return;
            }
            float score = -1;
            transform::Rigid2d pose_estimate = transform::Rigid2d::Identity();
            LOG(INFO) << "Processing2 matcher index: " << i;
            try {
                if (matchers[i]->MatchFullSubmap(filtered_point_cloud, cutoff, &score, &pose_estimate)) 
                {
                    score_set[i] = score;
                    pose_set[i] = pose_estimate;
                    has_matched = true;
                } else {
                  LOG(INFO) << "match failed. ";
                }
            } catch (const std::exception& e) {
                LOG(ERROR) << "Exception in MatchFullSubmap at index " << i << ": " << e.what();
            }

            matched_counter.DecrementCount();
        });
        my_thread_pool->Schedule(std::move(task));
    }

    matched_counter.Wait();

    if (!has_matched) 
    {
        LOG(ERROR) << "No matches found!";
        return false;
    }


    int max_position = std::distance(score_set.begin(), std::max_element(score_set.begin(), score_set.end()));
    *best_score = score_set[max_position];
    *best_pose_estimate = pose_set[max_position];

    auto csm = std::make_unique<scan_matching::CeresScanMatcher2D>(
        options_.constraint_builder_options().ceres_scan_matcher_options());

    ceres::Solver::Summary unused_summary;

    try {
        csm->Match(best_pose_estimate->translation(), *best_pose_estimate,
                   filtered_point_cloud, *submaps[max_position],
                   best_pose_estimate, &unused_summary);
    } catch (const std::exception& e) {
        LOG(ERROR) << "CeresScanMatcher2D failed: " << e.what();
        return false;
    }

    LOG(INFO) << "PoseGraph2D::PerformGlobalLocalization end.";
    return true;
}

链接代码:

https://github.com/zkk123456/cartographer_global_relocation.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/953860.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TensorFlow Quantum快速编程(基本篇)

一、TensorFlow Quantum 概述 1.1 简介 TensorFlow Quantum(TFQ)是由 Google 开发的一款具有开创性意义的开源库,它宛如一座桥梁,巧妙地将量子计算与 TensorFlow 强大的机器学习功能紧密融合。在当今科技飞速发展的时代,传统机器学习虽已取得诸多瞩目成就,然而面对日益…

K8s数据存储之详解(Detailed Explanation of K8s Data Storage)

K8s数据存储相关概念详解&#xff08;临时存储&#xff0c;节点存储&#xff0c;网络存储&#xff0c;PV/PVC&#xff09; 本篇文章分享一下存储卷和数据持久化的相关概念&#xff1a; 存储卷概述 临时存储卷&#xff08;Ephemeral Volumes&#xff09; 节点存储卷&#xff…

java求职学习day12

1 泛型机制&#xff08;熟悉&#xff09; 1.1 基本概念 &#xff08;1&#xff09;通常情况下集合中可以存放不同类型的元素&#xff0c;是因为将所有对象都看作Object类型放入&#xff0c;因此从集合中取出元素时&#xff0c;也是Object类型&#xff0c;为了表达该元素真实的…

相加交互效应函数发布—适用于逻辑回归、cox回归、glmm模型、gee模型

在统计分析中交互作用是指某因素的作用随其他因素水平变化而变化&#xff0c;两因素共同作用不等于两因素单独作用之和(相加交互作用)或之积(相乘交互作用)。相互作用的评估是尺度相关的&#xff1a;乘法或加法。乘法尺度上的相互作用意味着两次暴露的综合效应大于&#xff08;…

Spring Boot 2 学习全攻略

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今快速发展的 Java 后端开发领域&#xff0c;Spring Boot 2 已然成为一股不可忽视的强大力量。它简化了 Spring 应用的初始搭建以及开发过程&#xff0c;让开发者能够更加专注于业务逻辑的实现&am…

【面试题】技术场景 4、负责项目时遇到的棘手问题及解决方法

工作经验一年以上程序员必问问题 面试题概述 问题为在负责项目时遇到的棘手问题及解决方法&#xff0c;主要考察开发经验与技术水平&#xff0c;回答不佳会影响面试印象。提供四个回答方向&#xff0c;准备其中一个方向即可。 1、设计模式应用方向 以登录为例&#xff0c;未…

30分钟内搭建一个全能轻量级springboot 3.4 + 脚手架 <1> 5分钟快速创建一个springboot web项目

快速导航 <1> 5分钟快速创建一个springboot web项目 <2> 5分钟集成好最新版本的开源swagger ui&#xff0c;并使用ui操作调用接口 <3> 5分钟集成好druid并使用druid自带监控工具监控sql请求 <4> 5分钟集成好mybatisplus并使用mybatisplus generator自…

【Rust自学】11.10. 集成测试

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.10.1. 什么是集成测试 在Rust里&#xff0c;集成测试完全位于被测试库的外部。集成测试调用库的方式和其他代码一样&#xff0c;这也…

JAVA实现2048小游戏(附源码)

文章目录 一、设计来源2048小游戏讲解1.1 主界面1.2 4*4难度界面1.3 5*5难度界面1.4 6*6难度界面1.5 挑战失败提示界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载更多优质源码分享 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/a…

【自动化测试】—— Appium安装配置保姆教程(图文详解)

目录 一. 环境准备 二. JDK安装 1. 下载JDK 2. 安装JDK 3. 配置环境 4. 验证安装 三. Android SDK安装 1. 下载Android SDK 2. 安装Android SDK 3. 安装工具 4. 配置环境 5. 验证安装 四. NodeJS安装 1. 下载NodeJS 2. 安装NodeJS 3. 验证安装 4. 安装淘宝镜像…

vs2022+QT6.7.3打包程序流程

1、新建目录test 2、将项目配置为Release X64&#xff0c;生成XXX.exe 3、将XXX.exe放到test目录 4、管理员方式打开Qt 6.7.3 (MSVC 2022 64-bit)&#xff0c;进入test目录&#xff0c;执行&#xff1a;windeployqt6.exe XXX.exe 5、管理员方式打开x64 Native Tools Command…

RabbitMQ---消息确认和持久化

&#xff08;一&#xff09;消息确认 1.概念 生产者发送消息后&#xff0c;到达消费端会有以下情况&#xff1a; 1.消息处理成功 2.消息处理异常 如果RabbitMQ把消息发送给消费者后就把消息删除&#xff0c;那么就可能会导致&#xff0c;消息处理异常想要再获取这条消息的时…

【C++】反向迭代器

反向迭代器 一.源码及框架分析二.反向迭代器实现代码1.ReverseIterator.h2.Vector.h3.List.h4.Test.cpp 一.源码及框架分析 SGI-STL30版本源代码&#xff0c;反向迭代器实现的核心源码在stl_iterator.h中&#xff0c;反向迭代器是一个适配器&#xff0c;各个容器中再适配出自己…

浅谈云计算02 | 云计算模式的演进

云计算计算模式的演进 一、云计算计算模式的起源追溯1.2 个人计算机与桌面计算 二、云计算计算模式的发展阶段2.1 效用计算的出现2.2 客户机/服务器模式2.3 集群计算2.4 服务计算2.5 分布式计算2.6 网格计算 三、云计算计算模式的成熟与多元化3.1 主流云计算服务模式的确立3.1.…

WEB 攻防-通用漏-XSS 跨站脚本攻击-反射型/存储型/DOMBEEF-XSS

XSS跨站脚本攻击技术&#xff08;一&#xff09; XSS的定义 XSS攻击&#xff0c;全称为跨站脚本攻击&#xff0c;是指攻击者通过在网页中插入恶意脚本代码&#xff0c;当用户浏览该网页时&#xff0c;恶意脚本会被执行&#xff0c;从而达到攻击目的的一种安全漏洞。这些恶意脚…

Vue3组件设计模式:高可复用性组件开发实战

Vue3组件设计模式:高可复用性组件开发实战 一、前言 在Vue3中&#xff0c;组件设计和开发是非常重要的&#xff0c;它直接影响到应用的可维护性和可复用性。本文将介绍如何利用Vue3组件设计模式来开发高可复用性的组件&#xff0c;让你的组件更加灵活和易于维护。 二、单一职责…

深度剖析RabbitMQ:从基础组件到管理页面详解

文章目录 一、简介二、Overview2.1 Overview->Totals2.2 Overview->Nodesbroker的属性2.3 Overview->Churn statistics2.4 Overview->Ports and contexts2.5 Overview->Export definitions2.6 Overview->Import definitions 三、Connections连接的属性 四、C…

Unity 语音转文字 Vosk 离线库

市场有很多语音库&#xff0c;这里介绍Vosk SDK 除了支持untiy外还有原生开发服务器等 目录 安装unity示例demo下载语音训练文件运行demo结尾一键三联 注意事项 有可能debug出来的文本是空的&#xff0c;&#xff08;确保麦克风正常&#xff0c;且索引正确&#xff09;分大…

播放音频文件同步音频文本

播放音频同步音频文本 对应单个文本高亮显示 使用audio音频文件对应音频文本资源 音频文本内容&#xff08;Json&#xff09; [{"end": 4875,"index": 0,"speaker": 0,"start": 30,"text": "70号二啊,","tex…

【React】新建React项目

目录 create-react-app基础运用React核心依赖React 核心思想&#xff1a;数据驱动React 采用 MVC体系package.jsonindex.html好书推荐 官方提供了快速构建React 项目的脚手架&#xff1a; create-react-app &#xff0c;目前使用它安装默认是19版本&#xff0c;我们这里降为18…