自动驾驶定位算法-直方图滤波(Histogram Filter)定位

2024-04-11 02:04

本文主要是介绍自动驾驶定位算法-直方图滤波(Histogram Filter)定位,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

自动驾驶定位算法-直方图滤波(Histogram Filter)定位

image

附赠自动驾驶学习资料和量产经验:链接

1、直方图滤波(Histogram Filter)的算法思想

image

image

image

2、1D直方图滤波在自动驾驶定位的应用

如下图所示,无人驾驶汽车在一维的宽度为5m的世界重复循环,因为世界是循环的,所以如果无人驾驶汽车到了最右侧,再往前走一步,它就又回到了最左侧的位置。

image

自动驾驶汽车上安装有Sensor可以检测车辆当前所在位置的颜色,但Sensor本身的存在一定检测错误率,即Sensor对颜色的检测不是100%准确的;

无人驾驶汽车以自认为1m/step的恒定速度向右运动,车辆运动本身也存在误差,即向车辆发出的控制命令是向右移动2m,而实际的车辆运动结果可能是待在原地不动,可能向右移动1m,也可能向右移动3m。

2.1 数学模型

image

2.2 利用直方图滤波(Histogram Filter)进行车辆定位的过程

image

image

3、2D直方图滤波在自动驾驶定位中的应用(一)

1D的直方图滤波可以很好的帮助我们理解直方图滤波的原理以及在如何应用在自动驾驶的定位过程中。但是1D的直方图滤波在实际应用中几乎是不存在的,所以我们从更偏向应用的角度,看看2D直方图滤波在自动驾驶定位中是如何工作的。

3.1 定义二维地图

首先定义一张二维地图,R和G代表地图块的颜色:R为红色,G为绿色。每个地图块的大小根据实际应用而定,比如0.0125m*0.125m、0.025m*0.025m等。地图块越小,定位精度越高,但是地图数据量和计算量也就越大;反之,地图块越大,定位精度越低,但数据量和计算量也相应较低。

grid = [[R,G,G,G,R,R,R],[G,G,R,G,R,G,R],[G,R,G,G,G,G,R],[R,R,G,R,G,G,G],[R,G,R,G,R,R,R],[G,R,R,R,G,R,G],[R,R,R,G,R,G,G],
]

t=0时刻,车辆不知道自己处于地图中的具体位置,转化为数学表述,就是车辆在各个地图块的置信度相同,代码如下:

def initialize_beliefs(grid):height = len(grid)width = len(grid[0])area = height * widthbelief_per_cell = 1.0 / areabeliefs = []for i in range(height):row = []for j in range(width):row.append(belief_per_cell)beliefs.append(row)return beliefs

初始置信度如下:

0.020  0.020  0.020  0.020  0.020  0.020  0.020  
0.020  0.020  0.020  0.020  0.020  0.020  0.020  
0.020  0.020  0.020  0.020  0.020  0.020  0.020  
0.020  0.020  0.020  0.020  0.020  0.020  0.020  
0.020  0.020  0.020  0.020  0.020  0.020  0.020  
0.020  0.020  0.020  0.020  0.020  0.020  0.020  
0.020  0.020  0.020  0.020  0.020  0.020  0.020 

置信度的可视化如下,红色星星位置为车辆的真实初始实际位置,蓝色圈大小代表置信度的高低,蓝色圈越大,置信度越高,蓝色圈越小,置信度越低。t=0时刻,车辆不确定自己的位置,所以各个位置的置信度相等。

image

3.2 运动更新

车辆运动模型简化为x、y两个方向的运动,同时由于运动的不确定性,需要对运动后的位置增加概率性信息。

代码如下:

def move(dy, dx, beliefs, blurring):height = len(beliefs)width = len(beliefs[0])new_G = [[0.0 for i in range(width)] for j in range(height)]for i, row in enumerate(beliefs):for j, cell in enumerate(row):new_i = (i + dy ) % heightnew_j = (j + dx ) % widthnew_G[int(new_i)][int(new_j)] = cellreturn blur(new_G, blurring)

3.3 观测更新

观测更新的过程中,当观测的Color等于地图块的Color时,hit=1, bel=beliefs[i][j] * p_hit;当观测到的Color不等于地图块的Color时,hit=0, bel=beliefs[i][j] * p_miss。

代码如下:

def sense(color, grid, beliefs, p_hit, p_miss):new_beliefs = []height = len(grid)width = len(grid[0])# loop through all grid cellsfor i in range(height):row = []for j in range(width):hit = (color == grid[i][j])row.append(beliefs[i][j] * (hit * p_hit + (1-hit) * p_miss))new_beliefs.append(row)s = sum(map(sum, new_beliefs))for i in range(height):for j in range(width):new_beliefs[i][j] = new_beliefs[i][j] / sreturn new_beliefs

3.4 运行定位流程

单次直方图滤波定位过程中,先进行观测更新,再进行运动更新。

def run(self, num_steps=1):for i in range(num_steps):self.sense()dy, dx = self.random_move()self.move(dy,dx)

设置运动更新的不确定度为0.1,观测更新的错误率:每隔100次观测出现一次观测错误,车辆的真实初始位置为(3,3),注意,这个真实位置车辆自己并不知道,我们只是为了仿真而设置的值。

blur = 0.1
p_hit = 100.0
init_pos = (3,3)
simulation = sim.Simulation(grid, blur, p_hit, init_pos)simulation.run(1)
simulation.show_beliefs()
show_rounded_beliefs(simulation.beliefs)

经过一次直方图滤波定位之后,各个位置的置信度已经发生了变化。

0.003  0.002  0.036  0.002  0.037  0.003  0.038  
0.003  0.037  0.002  0.002  0.001  0.002  0.037  
0.038  0.038  0.003  0.036  0.002  0.002  0.003  
0.038  0.004  0.038  0.003  0.037  0.038  0.038  
0.003  0.038  0.039  0.038  0.003  0.037  0.003  
0.038  0.038  0.038  0.003  0.037  0.003  0.003  
0.038  0.003  0.002  0.002  0.038  0.038  0.038 

置信度的可视化效果如下。可以看到,车辆已经对自己的置信度有了一定的认知,但是还是有大量的可能位置需要进一步确认。

image

连续执行直方图滤波100次,各个位置置信度的数值如下:

0.008  0.000  0.000  0.000  0.000  0.016  0.016  
0.032  0.001  0.000  0.000  0.001  0.032  0.833  
0.016  0.000  0.000  0.000  0.000  0.025  0.017  
0.001  0.000  0.000  0.000  0.000  0.000  0.000  
0.000  0.000  0.000  0.000  0.000  0.000  0.000  
0.000  0.000  0.000  0.000  0.000  0.000  0.000  
0.000  0.000  0.000  0.000  0.000  0.000  0.000

置信度的可视化效果如下,可以看到,车辆已经83.3%的概率可以确定自己所处的位置了。

image

4、2D直方图滤波在自动驾驶定位中的应用(二)

image

车辆的运动模型代码如下:

def motion_model(x, u):F = np.array([[1.0, 0, 0, 0],[0, 1.0, 0, 0],[0, 0, 1.0, 0],[0, 0, 0, 0]])B = np.array([[DT * math.cos(x[2, 0]), 0],[DT * math.sin(x[2, 0]), 0],[0.0, DT],[1.0, 0.0]])x = F @ x + B @ ureturn x

4.1 运动更新

运动更新的过程与前面谈到的车辆运动模型一致,车辆运动有不确定性,所以增加了Gaussian Filter用来处理不确定性。还有一个细节,就是车辆运动距离和直方图滤波的分块地图之间的转换关系:

x_shift = Δ x / map_x_resolution

y_shift = Δ y / map_y_resolution

代码如下:

# grid_map是网格地图,u=(v,w)是车辆运动的控制参数,yaw是车辆朝向
def motion_update(grid_map, u, yaw):# DT是时间间隔grid_map.dx += DT * math.cos(yaw) * u[0]grid_map.dy += DT * math.sin(yaw) * u[0]# grid_map.xy_reso是地图分辨率x_shift = grid_map.dx // grid_map.xy_resoy_shift = grid_map.dy // grid_map.xy_resoif abs(x_shift) >= 1.0 or abs(y_shift) >= 1.0:  # map should be shiftedgrid_map = map_shift(grid_map, int(x_shift), int(y_shift))grid_map.dx -= x_shift * grid_map.xy_resogrid_map.dy -= y_shift * grid_map.xy_reso# MOTION_STD是车辆运动不确定性的标准差grid_map.data = gaussian_filter(grid_map.data, sigma=MOTION_STD)return grid_map

4.2 观测更新

这个例子中通过测量车辆到LandMark的距离来确定自身的位置,LandMark的位置都是已知的。

image

def calc_gaussian_observation_pdf(gmap, z, iz, ix, iy, std):# predicted rangex = ix * gmap.xy_reso + gmap.minxy = iy * gmap.xy_reso + gmap.minyd = math.sqrt((x - z[iz, 1]) ** 2 + (y - z[iz, 2]) ** 2)# likelihoodpdf = (1.0 - norm.cdf(abs(d - z[iz, 0]), 0.0, std))return pdf#z=[(车辆到Landmark的测量距离,Landmark的x坐标,Landmark的y坐标),...],z是所有Landmark测量距离和位置的集合,std是测量误差的标准差
def observation_update(gmap, z, std):for iz in range(z.shape[0]):for ix in range(gmap.xw):for iy in range(gmap.yw):gmap.data[ix][iy] *= calc_gaussian_observation_pdf(gmap, z, iz, ix, iy, std)# 概率归一化gmap = normalize_probability(gmap)return gmap

4.3 运行定位流程

设置地图和测量相关参数:

DT = 0.1  # time tick [s]
MAX_RANGE = 10.0  # maximum observation range
MOTION_STD = 1.0  # standard deviation for motion gaussian distribution
RANGE_STD = 3.0  # standard deviation for observation gaussian distribution# grid map param
XY_RESO = 0.5  # xy grid resolution
MINX = -15.0
MINY = -5.0
MAXX = 15.0
MAXY = 25.0# Landmark Position
RF_ID = np.array([[10.0, 0.0],[10.0, 10.0],[0.0, 15.0],[-5.0, 20.0]])
# 车辆的初始位置(for simulation)
xTrue = np.zeros((4, 1))

通过Observation模拟自动驾驶车辆对各个LandMark的观测结果和车辆速度的误差。

def observation(xTrue, u, RFID):xTrue = motion_model(xTrue, u)z = np.zeros((0, 3))for i in range(len(RFID[:, 0])):dx = xTrue[0, 0] - RFID[i, 0]dy = xTrue[1, 0] - RFID[i, 1]d = math.sqrt(dx ** 2 + dy ** 2)if d <= MAX_RANGE:# add noise to range observationdn = d + np.random.randn() * NOISE_RANGEzi = np.array([dn, RFID[i, 0], RFID[i, 1]])z = np.vstack((z, zi))# add noise to speedud = u[:, :]ud[0] += np.random.randn() * NOISE_SPEEDreturn xTrue, z, ud

执行车辆定位流程:

    while SIM_TIME >= time:time += DTprint("Time:", time)u = calc_input()yaw = xTrue[2, 0]  # Orientation is knownxTrue, z, ud = observation(xTrue, u, RF_ID)grid_map = histogram_filter_localization(grid_map, u, z, yaw)

定位效果如下:

image

这篇关于自动驾驶定位算法-直方图滤波(Histogram Filter)定位的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

微信公众号脚本-获取热搜自动新建草稿并发布文章

《微信公众号脚本-获取热搜自动新建草稿并发布文章》本来想写一个自动化发布微信公众号的小绿书的脚本,但是微信公众号官网没有小绿书的接口,那就写一个获取热搜微信普通文章的脚本吧,:本文主要介绍微信公众... 目录介绍思路前期准备环境要求获取接口token获取热搜获取热搜数据下载热搜图片给图片加上标题文字上传图片

SpringBoot中封装Cors自动配置方式

《SpringBoot中封装Cors自动配置方式》:本文主要介绍SpringBoot中封装Cors自动配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot封装Cors自动配置背景实现步骤1. 创建 GlobalCorsProperties

idea中创建新类时自动添加注释的实现

《idea中创建新类时自动添加注释的实现》在每次使用idea创建一个新类时,过了一段时间发现看不懂这个类是用来干嘛的,为了解决这个问题,我们可以设置在创建一个新类时自动添加注释,帮助我们理解这个类的用... 目录前言:详细操作:步骤一:点击上方的 文件(File),点击&nbmyHIgsp;设置(Setti

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

一文详解SQL Server如何跟踪自动统计信息更新

《一文详解SQLServer如何跟踪自动统计信息更新》SQLServer数据库中,我们都清楚统计信息对于优化器来说非常重要,所以本文就来和大家简单聊一聊SQLServer如何跟踪自动统计信息更新吧... SQL Server数据库中,我们都清楚统计信息对于优化器来说非常重要。一般情况下,我们会开启"自动更新

Spring Boot拦截器Interceptor与过滤器Filter详细教程(示例详解)

《SpringBoot拦截器Interceptor与过滤器Filter详细教程(示例详解)》本文详细介绍了SpringBoot中的拦截器(Interceptor)和过滤器(Filter),包括它们的... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)详细教程1. 概述1

Flask 验证码自动生成的实现示例

《Flask验证码自动生成的实现示例》本文主要介绍了Flask验证码自动生成的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习... 目录生成图片以及结果处理验证码蓝图html页面展示想必验证码大家都有所了解,但是可以自己定义图片验证码

Python Excel实现自动添加编号

《PythonExcel实现自动添加编号》这篇文章主要为大家详细介绍了如何使用Python在Excel中实现自动添加编号效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍简单的说,就是在Excel中有一列h=会有重复

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.