Udacity机器人软件工程师课程笔记(三十二) - 卡尔曼滤波器 - 一维卡尔曼滤波器 - 多维卡尔曼滤波器 - 拓展卡尔曼滤波器(EKF)

本文深入解析卡尔曼滤波原理,涵盖一维与多维高斯分布,详细讲解一维和多维卡尔曼滤波器的工作流程,以及扩展卡尔曼滤波器在非线性系统中的应用。

一、概述

如wiki百科中介绍的那样,卡尔曼滤波(Kalman filter)是一种高效率的递归滤波器(自回归滤波器),它能够从一系列的不完全及包含噪声的测量中,估计动态系统的状态。卡尔曼滤波会根据各测量量在不同时间下的值,考虑各时间下的联合分布,再产生对未知变数的估计,因此会比只以单一测量量为基础的估计方式要准。卡尔曼滤波得名自主要贡献者之一的鲁道夫·卡尔曼。

卡尔曼滤波在技术领域有许多的应用。常见的有飞机及太空船的导引、导航及控制。卡尔曼滤波也广为使用在时间序列的分析中,例如信号处理及计量经济学中。卡尔曼滤波也是机器人运动规划及控制的重要主题之一,有时也包括在轨迹最佳化。卡尔曼滤波也用在中轴神经系统运动控制的建模中。因为从给与运动命令到收到感觉神经的回授之间有时间差,使用卡尔曼滤波有助于建立符合实际的系统,估计运动系统的目前状态,并且更新命令。

二、一维高斯分布

高斯分布是概率分布,是一个连续函数。随机变量x取值介于 X 1 X_1 X1 X 2 X_2 X2
由以下函数的积分给出在 X 1 X_1 X1 X 2 X_2 X2中的x的概率:
p ( X 1 < X < X 2 ) = ∫ X 1 X 2 F X ( x ) d x p(X_1 < X < X_2)= \int_ {X_1} ^ {X_2} F_X(x)dx pX1<X<X2=X1X2FX(x)dx
例如下图中, x x x位于8.7m和9m之间的概率为7%。
在这里插入图片描述

均值和方差

高斯的特征在于两个参数-平均值( μ μ μ)和方差( σ ² σ² σ²)。平均值是最可能出现的值,位于函数的中心,并且方差与曲线的宽度有关。术语“单峰”表示分布中存在单个峰。

高斯分布通常缩写为 N ( x : μ , σ ² ) N(x:μ,σ²) Nxμσ²,并将在以后以这种方式引用。

高斯分布的公式如下所示。 请注意,该公式包含二次函数的指数。 二次将x的值与μ进行比较,在x =μ的情况下,指数等于1( e 0 = 1 e ^ 0 = 1 e0=1)。

p ( x ) = 1 σ 2 π e − ( x − μ ) 2 2 σ 2 p(x) = \frac{1}{\sigma\sqrt{2\pi}}e^{-\frac{(x-\mu)^2}{2\sigma^2}} p(x)=σ2π 1e2σ2(xμ)2

所有选项的概率之和必须是1。因此,函数下面的面积总和总是1。

∫ p ( x ) d x = 1 \int p(x)dx = 1 p(x)dx=1

接下来使用c++编写一维高斯函数,来计算一个值在给定平均值和方差的情况下出现的概率。

#include <iostream>
#include <math.h>

using namespace std;

double f(double mu, double sigma2, double x)
{
   
   
	double prob = 1.0 / sqrt(2.0 * 3.14159 * sigma2) * exp(-0.5 * pow((x - mu), 2.0) / sigma2);
	return prob;
}

int main()
{
   
   
	cout << f(10.0, 4.0, 8.0) << endl;
	return 0;
}

注:从此部分以后大部分程序将使用c++来编写

三、一维卡尔曼滤波器

变量命名约定

x t x_t xt:位置(state)
z t z_t zt:测量值(measurement)
u t u_t ut:控制作用(control action)

卡尔曼滤波循环

卡尔曼滤波的作用方式可以用以下的图表示

初始估计
位置预测
测量值更新

1.测量值更新

(1)平均值计算

在这里插入图片描述
假设由上述概率分布,有先验概率有 μ = 20 , σ 2 = 9 \mu = 20,\sigma^2=9 μ=20σ2=9的高斯分布,现有一个测量值,有 v = 30 , r 2 = 9 v = 30,r^2=9 v=30r2=9的高斯分布,则其平均值 μ ′ , σ 2 ′ \mu',\sigma^{2'} μ,σ2,可以以如下方式进行计算:
μ ′ = r 2 μ + σ 2 v r 2 + σ 2 μ^′=\frac{r^2\mu+\sigma^2v}{r^2+σ^2} μ=r2+σ2r2μ+σ2v
先验的不确定性乘以测量的平均值,以赋予其更大的权重,同样,测量的不确定性乘以先验的平均值。
σ 2 ′ = 1 1 r 2 + 1 σ 2 \sigma^{2'}= \frac{1}{\frac{1}{r^2}+\frac{1}{\sigma^2}} σ2=r21+σ211
在这里插入图片描述

(2)程序实现

接下来以先验概率 N ( x : μ 1 = 10 , σ 2 = 8 ) N(x:\mu_1=10, \sigma^2=8) N(x:μ1=10,σ2=8), 和测量值 N ( x : μ 1 = 13 , σ 2 = 2 ) N(x:\mu_1=13, \sigma^2=2) N(x:μ1=13,σ2=2)为例,计算其平均值:

#include <iostream>
#include <math.h>
#include <tuple>

using namespace std;

double new_mean, new_var;

tuple<double, double> measurement_update(double mean1, double var1, double mean2, double var2)
{
   
   
	new_mean = (var2 * mean1 + var1 * mean2) / (var1 + var2);
	new_var = 1 / (1 / var1 + 1 / var2);
	return make_tuple(new_mean, new_var);
}

int main()
{
   
   

	tie(new_mean, new_var) = measurement_update(10, 8, 13, 2);
	printf("[%f, %f]", new_mean, new_var);
	return 0;
}

输出为

[12.400000, 1.600000]

2.位置预测

在这里插入图片描述

位置预测公式

后验均值: μ ′ = μ 1 + μ 2 \mu' = \mu_1 + \mu_2 μ=μ1+μ2

后验方差: σ 2 ′ = σ 1 2 + σ 2 2 \sigma^{2'} = \sigma_1^{2}+ \sigma_2^{2} σ2=σ12+σ22

#include <iostream>
#include <math.h>
#include <tuple>

using namespace std;

double new_mean, new_var;

tuple<double, double> state_prediction(double mean1, double var1, double mean2, double var2)
{
   
   
    new_mean = mean1 + mean2;
    new_var =  var1 + var2;
    return make_tuple(new_mean, new_var);
}

int main()
{
   
   

    tie(new_mean, new_var) = state_prediction(10, 4, 12, 4);
    printf("[%f, %f]", new_mean, new_var);
    return 0;
}

3.一维卡尔曼滤波器

该代码将遍历可用的测量和运动 并对每个测量和运动应用测量校正或状态预测

#include <iostream>
#include <math.h>
#include <tuple>

using namespace std;

double new_mean, new_var;

tuple<double, double> measurement_update(double mean1, double var1, double mean2, double var2)
{
   
   
	new_mean = (var2 * mean1 + var1 * mean2) / (var1 + var2);
	new_var = 1 / (1 / var1 + 1 / var2);
	return make_tuple(new_mean, new_var);
}

tuple<double, double> state_prediction(double mean1, double var1, double mean2, double var2)
{
   
   
	new_mean = mean1 + mean2;
	new_var = var1 + var2;
	return make_tuple(new_mean, new_var);
}

int main()
{
   
   
	//Measurements and measurement variance
	double measurements[5] = {
   
    5, 6, 7, 9, 10 };
	double measurement_sig = 4;

	//Motions and motion variance
	double motion[5] = {
   
    1, 1, 2, 1, 1 };
	double motion_sig = 2;

	//Initial state
	double mu = 0;
	double sig = 1000;

	for (int i = 0; i < sizeof(measurements) / sizeof(measurements[0]); i++) {
   
   
		tie(mu, sig) = measurement_update(mu, sig, measurements[i], measurement_sig);
		printf("update:  [%f, %f]\n"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Stan Fu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值