粒子滤波器的Matlab实现

2023-11-11

前言:粒子滤波器相较于卡尔曼滤波器或者UKF无迹卡尔曼滤波器而言,可以表达强非线性的变换且无需假设后验分布为高斯分布,在描述多峰分布时具有非常大的优势。粒子滤波器被广泛的应用于机器人系统中,如著名的Gmapping算法便是在粒子滤波器的基础上实现的,但是当前网络中对粒子滤波器的描述往往浅尝则止或长篇大论,导致学习起来往往是了解大概流程而不懂实际代码实现,无法应用于自己机器人中或困于理论推导。因此本文将简要的说明粒子滤波器的流程,然后在matlab中一步步的实现粒子滤波器,其中核心代码仅有20行,非常便于理解从而打通由理论到实际的过程。

原理介绍

算法流程

  1. 根据上一次的粒子分布和控制命令更新粒子位置
  2. 对更新后的粒子计算在该粒子的情况下,获得传感器观测的概率作为权重
  3. 根据权重进行重采样 

一、根据上一次分布和控制指令更新粒子位置

假设某一粒子位置为x = \left[ x,y,\theta \right]^T,控制命令为u_t= \begin{bmatrix} \theta & L \end{bmatrix},即旋转一定角度后前进一定的距离。跟新粒子的位置如下

x = x + R*u_t + rand

%控制机器人前进
function pos = move(robot_pos,set_w,set_v,control_noise)
    % 先进行旋转,加上噪声,并归一化到0~pi*2 
    pos(3) = mod(robot_pos(3) + set_w + control_noise*rand(),2*pi);
    % 前进距离+噪声
    V = set_v + control_noise*rand();
    % 坐标变换,因为前进距离是车体坐标系而要求的是世界坐标系下的
    pos(1) = mod(robot_pos(1) - V*sin(pos(3)),200); 
    pos(2) = mod(robot_pos(2) + V*cos(pos(3)),200); 
end

二、对更新后的粒子计算在该粒子的情况下,获得传感器观测的概率作为权重

计算权重的公式为

p=\eta p(z_t|x_t)

对于某一时刻真实的测量值为Z_t = \begin{bmatrix} z_1& z_2 & \cdots&z_n \end{bmatrix}^T,而对于其中一个粒子假设也进行了一次同样的测量根据地图估计出测量值为Z_t^i = \begin{bmatrix} z_1^i& z_2^i & \cdots&z_n^i \end{bmatrix}^T,则认为传感器的测量噪声是满足高斯分布的,因此该粒子测量值的概率分布为

P(z_t|x_t) = \eta exp\left(-\frac{1}{2}(x-\mu)^T \Sigma^{-1} (x-\mu)\right)

其中x带入传感器测量的真实值,而\mu为当前粒子根据地图信息估计出最可能的测量值,而协方差矩阵为测量传感器的设定的误差。

% 获取机器人在当前位置观测到对应数据的概率
function weight = get_probability(P,Z,landMark,sensor_noise)
    particle_Z = getDistance(P,landMark,sensor_noise);%根据地图获取理论上最有可能的观测结果
    distance = particle_Z - Z;%计算和真实值之间的差值
    noise = zeros([1,12]) + sensor_noise*sensor_noise;%根据设定观测噪声,构建协方差
    sigma = diag(noise);
    %带入多维高斯分布的公式中,这里去掉了归一化常数项
    weight = exp(-1/2 * (distance)' / (sigma) * (distance));
end

三、根据权重进行重采样 

使用如下的重采样策略,假设由M个样本,每个样本的权重为w_i \in R > 0,则根据权重进行归一化

\beta_i =\frac{w_i}{\sum_{i=m}^{M} w_i}

将0~1的圆弧分成M份,每一份的长度为\beta_i,然后在该圆上随机取值,落到哪一段则选取该段对应的粒子,如图所示当前落在2区域内,然后随机生成前进距离,然后根据随机距离进入了第四个粒子的范围则选中第四个粒子,然后不断重复直至找到M个粒子。

    % 粒子滤波:根据权重进行重采样
    sum_weight = sum(weight);
    weight = weight./sum_weight;%归一化权重
    max_weight = max(weight);
    index = ceil(rand()*particle_num);%开始时随机选取一个位置
    for i = 1:particle_num %随机采样的过程
        beta = rand() * 2 * max_weight;%随机生成前进距离,避免太远处或太近,设置为最大值的两倍
        while beta > weight(index+1)%重采样过程
            beta = beta - weight(index+1);
            index = mod(index + 1,particle_num-1);
        end
        temp_particle(:,i) = particle(:,index+1);
    end
    particle = temp_particle;

Matlab代码实现

%% begin
clc;
clear;
%% set param 
map_length = 200;%场地范围为200m
% 路标
landMarkNum = 12;%设定12个路标
%随机生成路标作为地图
landMark = [rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length
            rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length rand()*map_length];
control_noise = 5; %控制机器人运动的噪声
sensor_noise = 10; %传感器对地图的测量噪声
robot_v = 20; %机器人在20m内随机运动
robot_w = 0;%0.1*pi;
T = 20;%进行T次迭代 
particle_num = 1000;%使用1000个粒子
particle = zeros([3,particle_num]);%粒子的位置
temp_particle = zeros([3,particle_num]);%更新粒子时的临时变量
weight = zeros([1,particle_num]);%粒子的权重
%% 粒子滤波步骤         
% 随机生成初始机器人的位置
robot_pos = [rand()*map_length,rand()*map_length,rand()*2*pi]';
% 随机生成初始粒子分布的位置
for i = 1:particle_num
    particle(:,i) = [rand()*map_length,rand()*map_length,rand()*2*pi]';
end
%% plot
plot(robot_pos(1),robot_pos(2),'b*');
xlim([0 200])
ylim([0 200])
hold on;
for i=1:landMarkNum
     plot(landMark(1,i),landMark(2,i),'go');
     hold on;
end
for i=1:particle_num
	plot(particle(1,i),particle(2,i),'y.');
	hold on;
end
for t = 1:T
    % 假设机器人一直在随机运动
    set_v = rand()*robot_v;
    set_w = rand()*robot_w;
    % 将命令给实际的机器人,但是会有一定的误差
    robot_pos = move(robot_pos,set_w,set_v,control_noise/10);
    % 在当前位置测量,测量同样会有一定误差
    Z = getDistance(robot_pos,landMark,sensor_noise);
    % 粒子滤波:根据上一次的分布和当前指令得到预测分布,并计算权重
    for i = 1:particle_num
        particle(:,i) = move(particle(:,i),set_w,set_v,control_noise);
        weight(i) = get_probability(particle(:,i),Z,landMark,sensor_noise);
    end
    % 粒子滤波:根据权重进行重采样
    sum_weight = sum(weight);
    weight = weight./sum_weight;%归一化权重
    max_weight = max(weight);
    index = ceil(rand()*particle_num);%开始时随机选取一个位置
    for i = 1:particle_num %随机采样的过程
        beta = rand() * 2 * max_weight;%随机生成前进距离,避免太远处或太近,设置为最大值的两倍内
        while beta > weight(index+1)%重采样过程
            beta = beta - weight(index+1);
            index = mod(index + 1,particle_num-1);
        end
        temp_particle(:,i) = particle(:,index+1);
    end
    particle = temp_particle;
    %% update plot
    clf;
    for i=1:particle_num
        plot(particle(1,i),particle(2,i),'r.');
        hold on;
    end
    plot(robot_pos(1),robot_pos(2),'b*');
    xlim([0 200])
    ylim([0 200])
    hold on;
    pause(0.1);
end
     
%% function define
% 获取机器人在当前位置观测到对应数据的概率
function weight = get_probability(P,Z,landMark,sensor_noise)
    particle_Z = getDistance(P,landMark,sensor_noise);%根据地图获取理论上最有可能的观测结果
    distance = particle_Z - Z;%计算和真实值之间的差值
    noise = zeros([1,12]) + sensor_noise*sensor_noise;%根据设定观测噪声,构建协方差
    sigma = diag(noise);
    %带入多维高斯分布的公式中,这里去掉了归一化常数项
    weight = exp(-1/2 * (distance)' / (sigma) * (distance));
end
%计算当前机器人位置观测到地图中的地标位置的距离
function distance = getDistance(position,landMark,sensor_noise)
    dis = [0,0,0,0,0,0,0,0,0,0,0,0]';
    for j=1:length(landMark) %遍历所有地标
        % 计算和当前机器人的距离
        l = sqrt((position(1) - landMark(1,j))^2 + (position(2) - landMark(2,j))^2);
        dis(j) = l + sensor_noise*rand();% 加上随机生成的噪声项
    end
    % 返回各距离数据
    distance = dis;
end

%控制机器人前进
function pos = move(robot_pos,set_w,set_v,control_noise)
    % 先进行旋转,加上噪声,并归一化到0~pi*2 
    pos(3) = mod(robot_pos(3) + set_w + control_noise*rand(),2*pi);
    % 前进距离+噪声
    V = set_v + control_noise*rand();
    % 坐标变换,因为前进距离是车体坐标系而要求的是世界坐标系下的
    pos(1) = mod(robot_pos(1) - V*sin(pos(3)),200); 
    pos(2) = mod(robot_pos(2) + V*cos(pos(3)),200); 
end

  

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

粒子滤波器的Matlab实现 的相关文章

  • odoo权限管理详解

    前言 odoo作为ERP框架 必然有不同角色的用户使用这同一系统 对于系统上面的数据 应该对不同角色设置不同的查阅修改权限 odoo框架自带了了比较完善的权限控制机制 这篇博客的实践基于odoo13 其他版本可能略有差别 A 按odoo使用

随机推荐

  • 文举论金:黄金原油全面走势分析策略指导。

    市场没有绝对 涨跌没有定势 所以 对市场行情的涨跌平衡判断就是你的制胜法宝 欲望 有句意大利谚语 让金钱成为我们忠心耿耿的仆人 否则 它就会成为一个专横跋扈的主人 空头 多头都能赚钱 唯有贪心不能赚 是你掌控欲望还是欲望掌控你 古人云 不积
  • MVCC 实现原理

    这里是CS大白话专场 让枯燥的学习变得有趣 没有对象不要怕 我们new一个出来 每天对ta说不尽情话 好记性不如烂键盘 自己总结不如收藏别人 在讲解 MVCC 之前先来看一下 MySQL 中事务的四种隔离级别 读未提交 一个事务可以读到另一
  • ChatGPT生成内容很难脱离标准化,不建议用来写留学文书

    ChatGPT无疑是23年留学届的热门话题 也成为了不少留学生再也离不开的万能工具 从总结文献 润色论文 给教授写email似乎无所不能 各大高校对于学生使用ChatGPT的态度也有所不同 例如 哈佛大学教育代理院长 Anne Harrin
  • Unity游戏编程-——迷宫巡逻兵

    文章目录 游戏设计要求 程序设计要求 基本思路分析 模式基础 架构设计 关键模块 遇到的问题 资源地址 游戏设计要求 创建一个地图和若干巡逻兵 使用动画 每个巡逻兵走一个3 5个边的凸多边型 位置数据是相对地址 即每次确定下一个目标位置 用
  • 字节跳动(飞书)产品测试实习生一面

    下面面试问题的顺序记不清了 所以没按面试官问的顺序写 1 性能测试 2 黑盒和白盒 3 用过飞书吗 知道飞书的产品流程吗 4 谈谈你简历上写的项目 提到购物车功能 仔细讲讲 5 学过软件工程管理 说说整个软件的项目管理流程 6 看有服役的经
  • Linux系统调用指南

    Linux系统调用指南 文章是转载 但是我在后面的案例加了不少注解并debug了 如有疑问 留言交流 其实我也不懂 原文链接 blog packagecloud io https zcfy cc article the definitive
  • QTcpSocket发送数据和自定义数据

    在网络应用中 有时候我们会遇到这样的问题 用TCP不断的接收和发送不同类型的数据 数据大小 格式都不相同 起初看了qt的例子 按照例子写的程序效果相当的不好 尤其是在连续发送大数据的时候 接收端根本无法判断数据是否完整了 也不知道什么时候取
  • 基于VMD-LSTM-IOWA-RBF的碳排放混合预测研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 二氧化碳排放力争于2030年前达到峰值 努
  • uni-app checkbox全选的实现

    界面是这样的 需求 点击全选按钮上述全部选中 再次点击全部取消 解决方案 在js的data里面定义一个allCheck data return allCheck false 上面商品的的checkbox都一样的配置
  • window 无法访问docker_无法在windows中访问docker端口

    我在dockerfile中写了脚本来运行我的角度项目 It将创建集装箱 什么时候我正在运行我的容器我无法在浏览器中访问主机和端口 它说连接被拒绝了 我用windows机器 用工具箱运行docker 我的容器 gt 81471a6fbd35
  • php爬虫简单入门

    前些日子有点空闲就做了一个简单的爬虫 爬取了知乎50W条数据 因为知乎有测试流量过大 导致经常有验证码 本人图片验证码没有研究所以每次都是手动输入 有兴趣的小伙伴可以做个自动识别验证码就可以无限采取了 爬虫使用了curl public fu
  • spring嵌套事务,try-catch事务处理

    spring 事务总结 前置条件 表Teacher 别名 A 表Student 别名 B 分别插入 A中启动事务 B中不启动事务 testDemo01调用方法开启事务 testDemo01开启事务 A中insert中开启事务 调用执行 A中
  • 蓝牙协议介绍

    1 广播 ADV Advertising 1 1 BLE 报文结构 BLE引入access address 概念 用来指明接收者身份 概 其中 0x8E89BED6 这个access address 比较特殊 它表示要发给周边所有设备 即广
  • msys2 安装gcc g++ 命令

    pacman S base devel gcc vim
  • 常见设计模式的解析和实现(C++)之九—Decorator模式

    作用 动态地给一个对象添加一些额外的职责 就增加功能来说 Decorator模式相比生成子类更为灵活 UML结构图 抽象基类 1 Component 定义一个对象接口 可以为这个接口动态地添加职责 2 Decorator 维持一个指向Com
  • 优秀的Windows密码抓取工具

    优秀的工具如下 01 Mimikatz 简介 Mimikat是一个法国人写的轻量级调试器 Mimikat可以从内存中提取纯文本密码 hash PIN码和kerberos票证 mimikatz还可以执行哈希传递 票证传递或构建Golden票证
  • ESP8266 hspi的调试

    这一两个礼拜基本上都在爬这个坑 功夫不负有心人 终于搞定了 其实非常简单 以为这个东西有多么的复杂 其实不是这样的 被一些网上博主给误导了 8266端我用的是 ESP8266 NONOS SDK 3 0 examples periphera
  • 使用ANT打包Android应用

    转自 http blog csdn net liuhe688 article details 6679879 大家好 今天来分享一下如何使用ANT打包Android应用 通常我们习惯用eclipse来开发Android程序 它会自动帮我们打
  • 架构妄想:AJAX + REST

    原文地址 http www infoq com cn news 2011 10 ArchitecturalMirages William Vambenepe的最新文章 AJAX REST是最新的架构妄想 让我们回想起了一个具有15年历史的架
  • 粒子滤波器的Matlab实现

    前言 粒子滤波器相较于卡尔曼滤波器或者UKF无迹卡尔曼滤波器而言 可以表达强非线性的变换且无需假设后验分布为高斯分布 在描述多峰分布时具有非常大的优势 粒子滤波器被广泛的应用于机器人系统中 如著名的Gmapping算法便是在粒子滤波器的基础