激光雷达的基础理解以及size_t和unsigned无符号数的补充

激光雷达:
激光雷达测量的数据是雷达周围一个个的点,是激光发射后第一个碰到的障碍物,当完成一次扫描后,生成一次点云图,包含一组点的信息。

激光雷达的测距原理一般分为两种:三角测距法和脉冲法(TOF)。

脉冲法是根据简单的光速*时间/2,问题是需要精确的计时器和高质量的脉冲光,所以成本较高。

我们车上的思岚A1雷达是脉冲法,原理简单。
下面介绍一下三角测距法:
在这里插入图片描述在这里插入图片描述

从图中我们可以发现激光发射器Laser是有一个倾斜角B的,这个是已知量。反射光被接收端CMOS(一种图像传感器)接收,而接收端和发射端的相对位置是固定的,因此可以通过公式计算出物体的距离。

  1. FPS(frame per second),指每秒传输帧数。
  2. SLAM,Simultaneous localization and mapping缩写,意为“同步定位与建图”。
  3. 雷达的线数:就是一线激光。一般的2D激光雷达是单线激光,可以构建2维地图。除了水平维度的其他线加入后,便可以构建分辨率越来越高的三维地图了。
  4. 一个点云数据包含:x方向偏移量,y方向偏移量,(z方向偏移量),反射激光强度。这里的偏移量应该是雷达坐标系下的。

雷达的数据处理:

  1. 数据预处理(坐标转换,去噪声)
  2. 聚类(根据点云距离或反射强度)
  3. 提取聚类后的特征,根据特征进行分类等后处理工作。

激光点云地图存储的是传感器对环境的原始扫描点云,优点是保留信息完整,缺点是计算量大、不能直接用于导航避障;特征地图存储的是环境中的特殊几何特征,如电线杆、路标、障碍物边缘等,其计算量小但保留信息过少需进行过滤后才能进行使用。

激光点云栅格化核心思想是将激光雷达所扫描到的区域用网格进行处理,每个栅格代表空间的一小块区域,内含一部分点云,点云栅格化处理分为二维栅格化和三维栅格化,二维其实就是将三维点云进行一个投影。不考虑z值的变化。
这里我们先讲一下二维栅格化的处理:
   我们假设地面相对平坦,即地面扫描点的 z 轴方向的波动较小,通过将扫描区域进行栅格划分,将扫描点云投影到 xy 的栅格平面,通过统计栅格中 z 轴方面的最高点和最低点的差值(即,极差),判断栅格中的点是否为地面点或障碍物点。

基于滤波的SLAM主要经历了卡尔曼滤波器(Kalman Filter, KF)、粒子滤波(Particle Filters, PF)和RBPF(混合卡尔曼滤波器MKF)这三个阶段。

基于RBPF的SLAM方案(如Gmapping)是先完成定位,再完成建图。RBPF算法的主要方式是用许多粒子去获取准确的地图,因此要对RBPF算法进行优化的主要方向是减少粒子的数量。

Gmapping在RBPF的基础上完成了两个改进:
①为了减小粒子数Gmapping提出了改进提议分布;
②为了减少重采样的次数Gmapping提出了选择性重采样。

对于size_t和unsigned:
size_t在C语言中就有了。
它是一种“整型”类型,里面保存的是一个整数,就像int、long那样。这种整数用来记录一个大小(size)。size_t的全称应该是size type,就是说“一种用来记录大小的数据类型”。
通常我们用sizeof(XXX)操作,这个操作所得到的结果就是size_t类型。
因为size_t类型的数据其实是保存了一个整数,所以它也可以做加减乘除,也可以转化为int并赋值给int类型的变量。
类似的还有wchar_t, ptrdiff_t。
wchar_t就是wide char type,“一种用来记录一个宽字符的数据类型”。
ptrdiff_t就是pointer difference type,“一种用来记录两个指针之间的距离的数据类型”。
通常,size_t和ptrdiff_t都是用typedef来实现的。你可能在某个头文件里面找到类似的语句:
typedef unsigned int size_t;
而wchar_t则稍有不同。在一些旧的编译器中,wchar_t也可能是用typedef来实现,但是新的标准中wchar_t已经是C/C++语言的关键字,wchar_t类型的地位已经和char, int的地位等同了。
在标准C/C++的语法中,只有int float char bool等基本的数据类型,至于size_t或size_type都是以后的编程人员为了方便记忆所定义的一些便于理解的由基本数据类型的变体类型。
例如:typedef int size_t;定义了size_t为整型。

在C++中,设计size_t 就是为了适应多个平台的。size_t的引入增强了程序在不同平台上的可移植性。size_t是针对系统定制的一种数据类型,一般是整型,因为C/C++标准只定义一最低的位数,而不是必需的固定位数。而且在内存里,对数的高位对齐存储还是低位对齐存储各系统都不一样。
为了提高代码的可移植性,就有必要定义这样的数据类型。一般这种类型都会定义到它具体占几位内存等。当然,有些是编译器或系统已经给定义好的。经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。

我们知道,整数在计算机中通常是以补码的形式存在的,而-1的补码(用4个字节储存)为1111,1111,1111,1111。而C语言对于强制类型转换是怎么处理的呢? 对大多数C语言的实现,处理同样字长的有符号数和无符号数之间的相互转换的一般规则是:数值可能会改变,但是位模式不变。也就是说,将unsigned int强制类型转换成int,或将int转换成unsigned int底层的位表示保持不变。

也就是说,即使是-1转换成unsigned int之后,它在内存中的表示还是没有改变,即1111,1111,1111,1111。我们知道在计算机的底层,数据是没有类型可言的,所有的数据非0即1。数据类型只有在高层的应用程序才有意义,也就是说,同样的储存表示对于应用程序而言可能对应着不同的数据,例如1111,1111,1111,1111对于有符号数而言它表示-1,但对于无符号数而言,它表示UMax,但是它们的底层存储都是一样的。现在你应该明白为什么-1转换成无符号数之后,就成了UMax了吧。

总结:
size_t和unsigned都是特殊的无符号的数据类型。
size_t的真实类型与操作系统有关,在32位架构中被普遍定义为:
typedef unsigned int size_t;
而在64位架构中被定义为:
typedef unsigned long size_t;
size_t在32位架构上是4字节,在64位架构上是8字节,在不同架构上进行编译时需要注意这个问题。
不同平台的size_t会用不同的类型实现,使用size_t而非int或unsigned可以写出扩展行更好的代码,即是为了提供一种可移植的代码形式。
参数中带有size_t的函数通常会含有局部变量用来对数组的大小或者索引进行计算,在这种情况下,size_t是个不错的选择。
  适当地使用size_t还会使你的代码变得如同自带文档。当你看到一个对象声明为size_t类型,你马上就知道它代表字节大小或数组索引,而不是错误代码或者是一个普通的算术值。

unsigned无符号在进行与有符号数(int,long…)之间的混合计算时很可能会出错,因为会自动将有符号数转换为无符号数进行计算或比较大小,还是用的补码形式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值