【地图构建(1)】占用栅格地图构建Occupancy grid mapping

news2024/11/18 1:31:58

本文主要参考Probabilistic Robotics《概率机器人》一书。
其他参考:
弗莱堡大学课件
博客
含代码博客

0.引言

位姿已知的地图构建(mapping with known poses)的定义:已知机器人的位姿 x 1 : t x_{1:t} x1:t和传感器的观测数据 z 1 : t z_{1:t} z1:t求解最可能的地图 m ∗ = arg ⁡ max ⁡ m P ( m ∣ x 1 : t , z 1 : t ) m^*=\arg\max_mP(m|x_{1:t},z_{1:t}) m=argmaxmP(mx1:t,z1:t)
占用栅格地图,顾名思义地图形式是栅格形式,即将环境分为小格子
在这里插入图片描述 m i m_i mi表示第i个栅格单元,占用栅格地图将空间分割为有限多个栅格地图 m = { m i } m=\{m_i\} m={mi},每个 m i m_i mi与一个二值占用变量相对应,该变量指示出该单元是否被占用,被占用设为1,未被占用设为0。 p ( m i ) p(m_i) p(mi)表示该栅格单元被占用的可能性。
为所有的栅格建立后验概率 p ( m i ∣ z 1 : t , x 1 : t ) p(m_i|z_{1:t},x_{1:t}) p(miz1:t,x1:t),那么构建地图公式变为
P ( m ∣ x 1 : t , z 1 : t ) = p ( m 1 , m 2 , . . . , m n ∣ x 1 : t , z 1 : t ) = ∑ i = 1 n p ( m i ∣ z 1 : t , x 1 : t ) (假设每个格子独立同分布) P(m|x_{1:t},z_{1:t})=p(m_1,m_2,...,m_n|x_{1:t},z_{1:t})\\ =\sum^n_{i=1}p(m_i|z_{1:t},x_{1:t}) (假设每个格子独立同分布) P(mx1:t,z1:t)=p(m1,m2,...,mnx1:t,z1:t)=i=1np(miz1:t,x1:t)(假设每个格子独立同分布)

但是这种独立同分布抛弃了相邻单元之间的联系,并不是最优解,对于这一点,我们暂且不讨论。

1. 静态二值贝叶斯滤波

上面这个独立同分布的地图构建公式可以看作一个静态二值贝叶斯滤波(binary Bayes filter)——不随时间变化的二值状态的最优估计问题。
对于一个格子被占有的概率记为——置信度 b e l ( m i ) = p ( m i ∣ x 1 : t , z 1 : t ) bel(m_i)=p(m_i|x_{1:t},z_{1:t}) bel(mi)=p(mix1:t,z1:t),最终通过设置阈值来确定哪些格子是占有栅格(例如 b e l ( m i ) > 0.6 bel(m_i)\gt0.6 bel(mi)>0.6),哪些是空闲栅格(例如 b e l ( m i ) < 0.4 bel(m_i)\lt0.4 bel(mi)<0.4),哪些是未知栅格( 0.4 ≤ b e l ( m i ) ≤ 0.6 0.4\le bel(m_i)\le0.6 0.4bel(mi)0.6)。
求解占有栅格的置信度:
b e l t ( m i ) = p ( m i ∣ z 1 : t , x 1 : t ) bel_t(m_i)=p(m_i|z_{1:t},x_{1:t}) belt(mi)=p(miz1:t,x1:t)
在这里插入图片描述
同理可得出空闲栅格的置信度
在这里插入图片描述利用两式相除消去部分未知部分:
在这里插入图片描述在这里插入图片描述二值Bayes滤波递归更新公式 l t , i = l t − 1 , i + l i n v , i − l 0 l_{t,i}=l_{t-1,i}+l_{inv,i}-l_0 lt,i=lt1,i+linv,il0,更新后在求置信度:
b e l t m i = 1 − 1 1 + exp ⁡ ( l t , i ) bel_t{m_i}=1-\frac{1}{1+\exp(l_{t,i})} beltmi=11+exp(lt,i)1
初始时刻栅格的占用情况未知,将其置信度设为 b e l 0 ( m i ) = 0.5 bel_0(m_i)=0.5 bel0(mi)=0.5,则先验概率 l 0 = 0 l_0=0 l0=0
在这里插入图片描述

2.反演测量模型

2.1 声纳模型

来自PR一书和弗莱堡大学ppt中的模型,当某一个测量点距离为z,分别设置了z-d1,z+d1,z+d2,z+d3的占据概率。其中0-(z-d1)为free,(z-d1)-(z+d3)为occ,(z+d3)之后为no info。
在这里插入图片描述

2.2激光传感器模型

在这里插入图片描述

#include <occ_grid_mapping/grid_mapper.h>

GridMapper::GridMapper ( GridMap* map, Pose2d& T_r_l, double& P_occ, double& P_free, double& P_prior):
map_(map), T_r_l_(T_r_l), P_occ_(P_occ), P_free_(P_free), P_prior_(P_prior){}

void GridMapper::updateMap ( const sensor_msgs::LaserScanConstPtr& scan,  Pose2d& robot_pose )
{
    /* 获取激光的信息 */
    const double& ang_min = scan->angle_min;        //雷达起始角度
    const double& ang_max = scan->angle_max;        //雷达终止角度
    const double& ang_inc = scan->angle_increment;  //角度增量(角度分辨率)
    const double& range_max = scan->range_max;      //雷达数据的最小值
    const double& range_min = scan->range_min;      //雷达数据的最大值
    
    /* 设置遍历的步长,沿着一条激光线遍历 */
    const double& cell_size = map_->getCellSize();
    const double inc_step = 1.0 * cell_size;

    /* for every laser beam */
    for(size_t i = 0; i < scan->ranges.size(); i ++)
    {
        /* 获取当前beam的距离 */
        double R = scan->ranges.at(i); 
        if(R > range_max || R < range_min)
            continue;
        
        /* 沿着激光射线以inc_step步进,更新地图*/
        double angle = ang_inc * i + ang_min;
        double cangle = cos(angle);
        double sangle = sin(angle);
        Eigen::Vector2d last_grid(Eigen::Infinity, Eigen::Infinity); //上一步更新的grid位置,防止重复更新
        for(double r = 0; r < R + cell_size; r += inc_step)
        {
            Eigen::Vector2d p_l(
                r * cangle,
                r * sangle
            ); //在激光雷达坐标系下的坐标
            
            /* 转换到世界坐标系下 */
            Pose2d laser_pose = robot_pose * T_r_l_;
            Eigen::Vector2d p_w = laser_pose * p_l;

            /* 更新这个grid */
            if(p_w == last_grid) //避免重复更新
                continue;
            
            updateGrid(p_w, laserInvModel(r, R, cell_size));    //更新占据概率
            	    
            last_grid = p_w;
        }//for each step
    }// for each beam
}

void GridMapper::updateGrid ( const Eigen::Vector2d& grid, const double& pmzx )
{
    /* TODO 这个过程写的太低效了 */
    double log_bel;
    if(  ! map_->getGridLogBel( grid(0), grid(1), log_bel )  ) //获取log的bel
        return;
    log_bel += log( pmzx / (1.0 - pmzx) ); //更新
    map_->setGridLogBel( grid(0), grid(1), log_bel  ); //设置回地图
}

//雷达的反演测量模型
double GridMapper::laserInvModel ( const double& r, const double& R, const double& cell_size )
{
    if(r < ( R - 0.5*cell_size) )
        return P_free_;
    
    if(r > ( R + 0.5*cell_size) )
        return P_prior_;
    
    return P_occ_;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

绝地求生:报告长官!速去领取PUBG7周年礼包及7周年活动攻略【附方法】

奖励都需要长官们绑定全球账号&#xff0c;在游戏个人资料处查看是否有绑定&#xff01; PUBG七周年礼包详情&#xff1a; 包含7周年快乐甜筒帽 7周年快乐背包&#xff08;3级&#xff09; 戴墨镜的幽灵 黑货票券 x30 档案管理员宝箱 x1 钥匙 x1 绑定ID登录&#xff0c;或…

【FIneBI可视化工具的使用】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;书生♡&#xff0c;今天主要和大家分享一下可视化的工具FineBI的详细使用,希望对大家有所帮助。感谢大家关注点赞。 &#x1f49e;&#x1f49e;前路漫漫&#xff0c;希望大家坚持下去&#xff0c;不忘初心&…

大型驱动水冷负载电阻、缓冲器、滤波器和快速放电电阻

EAK业界首创双面水冷负载电阻器&#xff0c;独特的设计&#xff0c;用户更方便的串联并联使用&#xff0c;强大的水流带走更多因充放电带来的热量。AlN高可靠性氮化铝基板保证了热膨胀不会影响电阻的工作。 液冷电阻器使用水或离子水作为冷却剂。通过添加乙二醇&#xff0c;可以…

单调栈(C++)

单调栈,即栈中元素是单调递增的或是单调递减的,是一个比较好用的数据结构. 柱状图中最大的矩形 84. 柱状图中最大的矩形 - 力扣&#xff08;LeetCode&#xff09; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。…

【SAP2000】在框架结构中应用分布式面板荷载Applying Distributed Panel Loads to Frame Structures

在框架结构中应用分布式面板荷载 Applying Distributed Panel Loads to Frame Structures 使用"Uniform to Frame"选项,可以简单地将荷载用于更多样化的情况。 With the “Uniform to Frame” option, loads can be easily used for a greater diversity of situat…

【书生·浦语大模型实战营第二期】学习笔记1

1. Introduction 开源llm举例&#xff1a;LLaMA 、Qwen 、Mistral 和Deepseek 大型语言模型的发展包括预训练、监督微调&#xff08;SFT&#xff09;和基于人类反馈的强化学习&#xff08;RLHF&#xff09;等主要阶段 InternLM2的显著特点 采用分组查询注意力&#xff08;GQA…

蓝桥杯基础练习汇总详细解析(三)——字母图形、01字符串、闰年判断(详细解题思路、代码实现、Python)

试题 基础练习 字母图形 提交此题 评测记录 资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 利用字母可以组成一些美丽的图形&#xff0c;下面给出了一个例子&#…

web开发发展历程-前端、后端、消息队列、后端架构演进

文章目录 摘要主要内容不同的时代对应不同的技术前端技术的中间阶段-单页面应用前后端分离后端技术演化-云计算平台总体趋势反应式编程 消息队列发展史kafka&#xff0c;rocketmq&#xff0c;pulsar网易后端架构演进架构瓶颈数据库瓶颈服务器瓶颈数据库缓存瓶颈-缓存击穿、雪崩…

Spring Boot:Web开发之三大组件的整合

Spring Boot 前言Spring Boot 整合 ServletSpring Boot 整合 FilterSpring Boot 整合 Listener 前言 在 Web 开发中&#xff0c;Servlet 、Filter 和 Listener 是 Java Web 应用中的三大组件。Servlet 是 Java 代码&#xff0c;通过 Java 的 API 动态的向客户端输出内容。Filt…

7.3*3卷积核生成

1.卷积核 在数字图像处理中的各种边沿检测、滤波、腐蚀膨胀等操作都离不开卷积核的生成。下面介绍如何生成各种3X3的卷积核。为后面的数字图像操作打下基础。   由于图像经过卷积操作后会减少两行两列&#xff0c;因此在生成卷积核的时候一般会对图像进行填充&#xff0c;填充…

day 36 贪心算法 part05● 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

一遍过。首先把区间按左端点排序&#xff0c;然后右端点有两种情况。 假设是a区间&#xff0c;b区间。。。这样排列的顺序&#xff0c;那么 假设a[1]>b[0],如果a[1]>b[1]&#xff0c;就应该以b[1]为准&#xff0c;否则以a[1]为准。 class Solution { public:static bo…

一个基于.NET Core构建的简单、跨平台、模块化的商城系统

前言 今天大姚给大家分享一个基于.NET Core构建的简单、跨平台、模块化、完全开源免费&#xff08;MIT License&#xff09;的商城系统&#xff1a;Module Shop。 商城后台管理端功能 商品&#xff1a;分类、品牌、单位、选项&#xff08;销售属性&#xff09;、属性、属性模…

人脸68关键点与K210疲劳检测

目录 人脸68关键点检测 检测闭眼睁眼 双眼关键点检测 计算眼睛的闭合程度&#xff1a; 原理: 设置阈值进行判断 实时监测和更新 拓展&#xff1a;通过判断上下眼皮重合程度去判断是否闭眼 检测嘴巴是否闭合 提取嘴唇上下轮廓的关键点 计算嘴唇上下轮廓关键点之间的距…

LangChain入门:2.OpenAPI调用ChatGPT模型

快速入门 本篇文章正式进入LangChain的编码阶段&#xff0c;今天实现的功能是使用OpenAPI调用ChatGPT模型来进行文本问答。 1. 申请OpenAPI的访问令牌 这里介绍两种获取到OpenAPI访问令牌的方式&#xff0c;大家按照自己需求进行选择&#xff0c;之后的文章我会基于第二种选…

政安晨:【深度学习神经网络基础】(二)—— 神经元与层

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 神经元是深度学习神经网络中的基本单元&#xff0c;模拟了…

淘宝详情数据采集(商品上货,数据分析,属性详情,价格监控),海量数据值得get

淘宝详情数据采集涉及多个环节&#xff0c;包括商品上货、数据分析、属性详情以及价格监控等。在采集这些数据时&#xff0c;尤其是面对海量数据时&#xff0c;需要采取有效的方法和技术来确保数据的准确性和完整性。以下是一些关于淘宝详情数据采集的建议&#xff1a; 请求示…

DevSecOps平台架构系列-互联网企业私有化DevSecOps平台典型架构

目录 一、概述 二、私有化DevSecOps平台建设思路 2.1 采用GitOps公有云建设 2.2 采用GitOps私有云建设 2.3 总结 三、GitOps及其生态组件 3.1 采用GitOps的好处 3.1.1 周边生态系统齐全 3.1.2 便于自动化的实现 3.1.3 开发人员属性GitOps 3.2 GitOps部分生态组件介绍…

红黑树的Java实现

红黑树的Java实现 文章目录 红黑树的Java实现一、概述二、添加元素三、删除元素四、完整代码总结 一、概述 红黑树也是一种二叉平衡搜索树&#xff0c;向比与AVL树&#xff0c;是一种弱平衡树。因为AVL树是通过平衡因子&#xff0c;左右树的高度相差不能大于1来保证平衡&#…

实测梳理一下kafka分区分组的作用

清空topickafka-topics.sh --bootstrap-server localhost:9092 --delete --topic second创建分区kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 3 --topic second发kafka-console-producer.sh --bootstrap-server localhos…

ospf实验

基础配置 如上图所示&#xff0c;按照上图所示的配置&#xff0c;俩个路由器之间按照12.12.12.X/30网段配置&#xff0c;左端的路由器和交换机之间按照192.168.1.X网段配置&#xff0c;右端的路由器和交换机之间按照192.168.2.X网段配置&#xff0c;下面的两个pc机按照所对应的…