IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 滤波融合(二)基于C++完成一个简单的 扩展卡尔曼滤波器的非线性系统模型 -> 正文阅读

[数据结构与算法]滤波融合(二)基于C++完成一个简单的 扩展卡尔曼滤波器的非线性系统模型

之前已经简单的实现过线性卡尔曼滤波:滤波融合(一)基于C++完成一个简单的 卡尔曼滤波器 线性的系统和测量模型
那么对于非线性的系统,区别就是多了线性化的过程,因为高斯映射到非线性函数,其结果不再是一个高斯分布。根据线性化方法的不同还可以区分为EKF、UKF,目前只介绍EKF,UKF以后有机会的话再说吧~
基础的理论部分看见文章:通俗易懂理解扩展卡尔曼滤波EKF用于多源传感器融合
对于线性和非线性的划分,直观的理解就是:只有加法和数乘的就是线性的,除了线性的就都是非线性的。具体可参考:线性和非线性的区别

那么如何线性化一个非线性函数?扩展的卡尔曼滤波使用的方法叫做一阶泰勒展开式。
h ( x ) ≈ h ( μ ) + ? h ( μ ) ? x ( x ? μ ) h(x)\approx h(\mu)+{?h(\mu)\over ?x}(x-\mu) h(x)h(μ)+?x?h(μ)?(x?μ)

还是通过 bfl 库 做对比,使用 bfl 库中提供的例子,相比较线性卡尔曼滤波,系统模型从不带角度信息的,变成带角度信息,使系统方程变成一个非线性函数。
卡尔曼滤波中的更新方程:
X k = X k ? 1 + V k ? 1 ? D e l t a t X_k = X_{k-1}+V_{k-1} *Delta_t Xk?=Xk?1?+Vk?1??Deltat?
扩展卡尔曼滤波中的更新方程:
X k = X k ? 1 + c o s θ ? V k ? 1 ? D e l t a t X_k = X_{k-1} + cos\theta * V_{k-1} * Delta_t Xk?=Xk?1?+cosθ?Vk?1??Deltat?
因为考虑了角度的变化,所以变成非线性函数。但是观测模型依然是一个线性模型,和之前一样。

首先看一下在 bfl 中需要做哪些处理,有两个函数需要自己重写,因为这里的系统模型只有自己才知道,以及对应的雅可比矩阵!

//返回条件概率密度的期望值,期望值由系统方程决定
ColumnVector NonLinearAnalyticConditionalGaussianMobile::ExpectedValueGet() const
{
  ColumnVector state = ConditionalArgumentGet(0);
  ColumnVector vel  = ConditionalArgumentGet(1);
  state(1) += cos(state(3)) * vel(1);
  state(2) += sin(state(3)) * vel(1);
  state(3) += vel(2);
  return state + AdditiveNoiseMuGet();
}

代码与上面系统方程公式所对应,加上了角度信息,state 就是EKF所维护的状态量,分别包括 x , y , θ x,y,\theta xyθ,其中 θ \theta θ 直接累加就可以。然后是系统方程的雅可比矩阵,也就是线性化的关键,因为这里的例子时间间隔都是1,所以 D e l t a t = 1 Delta_t = 1 Deltat?=1 直接带入。
x k = x k ? 1 + c o s θ ? V k ? 1 y k = y k ? 1 + s i n θ ? V k ? 1 θ k = θ k ? 1 + D e t l a θ x_k = x_{k-1} + cos\theta* V_{k-1} \\ y_k = y_{k-1} + sin\theta* V_{k-1} \\ \theta_k = \theta_{k-1} + Detla_{\theta} xk?=xk?1?+cosθ?Vk?1?yk?=yk?1?+sinθ?Vk?1?θk?=θk?1?+Detlaθ? ? x k ( μ ) ? x = 1 ? x k ( μ ) ? y = 0 ? x k ( μ ) ? θ = ? s i n θ ? V k ? 1 {?x_k(\mu)\over ?x} = 1 \qquad {?x_k(\mu)\over ?y} = 0 \qquad {?x_k(\mu)\over ?\theta} = -sin\theta*V_{k-1} ?x?xk?(μ)?=1?y?xk?(μ)?=0?θ?xk?(μ)?=?sinθ?Vk?1? ? y k ( μ ) ? x = 0 ? y k ( μ ) ? y = 1 ? y k ( μ ) ? θ = c o s θ ? V k ? 1 {?y_k(\mu)\over ?x} = 0 \qquad {?y_k(\mu)\over ?y} = 1 \qquad {?y_k(\mu)\over ?\theta} = cos\theta*V_{k-1} ?x?yk?(μ)?=0?y?yk?(μ)?=1?θ?yk?(μ)?=cosθ?Vk?1? ? θ k ( μ ) ? x = 0 ? θ k ( μ ) ? y = 0 ? θ k ( μ ) ? θ = 1 {?{\theta}_k(\mu)\over ?x} = 0 \qquad {?{\theta}_k(\mu)\over ?y} = 0 \qquad {?{\theta}_k(\mu)\over ?\theta} = 1 ?x?θk?(μ)?=0?y?θk?(μ)?=0?θ?θk?(μ)?=1
代码如下所示:

//求第i个条件参数求偏导数。本例中只对状态(第一个条件参数)求偏导数
Matrix NonLinearAnalyticConditionalGaussianMobile::dfGet(unsigned int i) const
{
	if (i==0)//derivative to the first conditional argument (x)
	  {
		ColumnVector state = ConditionalArgumentGet(0);
		ColumnVector vel = ConditionalArgumentGet(1);
		Matrix df(3,3);
		df(1,1)=1;
		df(1,2)=0;
		df(1,3)=-vel(1)*sin(state(3));
		df(2,1)=0;
		df(2,2)=1;
		df(2,3)=vel(1)*cos(state(3));
		df(3,1)=0;
		df(3,2)=0;
		df(3,3)=1;
		return df;
		}
		else ...
}

其他的就和线性卡尔曼滤波一样了,定义完成后在 bfl 库中使用是没有区别的。那么这部分自己该如何实现?


根据一阶泰勒展开式:
h ( x ) ≈ h ( μ ) + ? h ( μ ) ? x ( x ? μ ) h(x)\approx h(\mu)+{?h(\mu)\over ?x}(x-\mu) h(x)h(μ)+?x?h(μ)?(x?μ)
h ( x ) = ( x k y k θ k ) = ( x k ? 1 + c o s θ ? V k ? 1 y k ? 1 + s i n θ ? V k ? 1 θ k ? 1 + D e t l a θ ) h(x) = \begin{pmatrix} x_k \\ y_k \\ \theta_k \\\end{pmatrix}=\begin{pmatrix} x_{k-1} + cos\theta* V_{k-1} \\ y_{k-1} + sin\theta* V_{k-1} \\ \theta_{k-1} + Detla_{\theta} \\\end{pmatrix} h(x)=???xk?yk?θk?????=???xk?1?+cosθ?Vk?1?yk?1?+sinθ?Vk?1?θk?1?+Detlaθ????? ≈ ( x 0 + c o s θ ? V 0 y 0 + s i n θ ? V 0 θ 0 + D e t l a 0 ) + ( 1 0 ? s i n θ 0 ? V 0 0 1 c o s θ 0 ? V 0 0 0 1 ) ( x ? x 0 y ? y 0 θ ? θ 0 ) \approx \begin{pmatrix} x_{0} + cos\theta* V_{0} \\ y_{0} + sin\theta* V_{0} \\ \theta_{0} + Detla_{0} \\\end{pmatrix} + \begin{pmatrix} 1 & 0 & -sin\theta_0 * V_0 \\ 0 & 1 & cos\theta_0 * V_0 \\ 0 & 0 & 1 \\\end{pmatrix}\begin{pmatrix} x-x_0 \\ y-y_0 \\ \theta-\theta_0 \\\end{pmatrix} ???x0?+cosθ?V0?y0?+sinθ?V0?θ0?+Detla0?????+???100?010??sinθ0??V0?cosθ0??V0?1???????x?x0?y?y0?θ?θ0?????

此时取 u = 0 u = 0 u=0,在系统模型非线性的情况下,相比较与线性系统,有两点步骤:

  1. 泰勒在 u = 0 u=0 u=0 处展开,线性化;
  2. 使用非线性系统的雅可比矩阵 F j F_j Fj? ,代替原有的 F F F 矩阵,进行协防差传递。

线性化展开已经做了,并且雅可比矩阵 F j F_j Fj? 也已经求出来:
F j = ( 1 0 ? s i n θ ? V 0 1 c o s θ ? V 0 0 1 ) F_j = \begin{pmatrix} 1 & 0 & -sin\theta * V \\ 0 & 1 & cos\theta * V \\ 0 & 0 & 1 \\\end{pmatrix} Fj?=???100?010??sinθ?Vcosθ?V1????

下面开始修改代码,主要与线性化系统对比说明,线性化系统可以参考滤波融合(一)基于C++完成一个简单的 线性卡尔曼滤波器 进行传感器融合

首先一些基本的参数维度变成三维了!因为我们的状态量多了 θ \theta θ

  ColumnVector X_k(3);// 状态量 (x,y,θ)
  X_k= prior_Mu;      // 先验
  Matrix P(3,3);      // 先验协防差
  P = prior_Cov;
  Matrix Identity(3,3); // 用于数据格式转换
  Identity(1,1) = 1;  Identity(1,2) = 0.0;  Identity(1,3) = 0.0;
  Identity(2,1) = 0.0;  Identity(2,2) = 1;  Identity(2,3) = 0.0;
  Identity(3,1) = 0.0;  Identity(3,2) = 0.0;  Identity(3,3) = 1;

为了对比系统更新模型,这里把线性系统的代码也拿了过来,可以明显看出来区别,状态量和输入并不是简单的相加,而是相乘,导致了系统模型的非线性。所以对于协防差的传递,需要用到雅可比矩阵。

// 线性系统
//Matrix A(2,2);
//A(1,1) = 1.0;  A(1,2) = 0.0;  A(2,1) = 0.0;  A(2,2) = 1.0;
//Matrix B(2,2);
//B(1,1) = cos(0.8);  B(1,2) = 0.0;  B(2,1) = sin(0.8);  B(2,2) = 0.0;
// X_k = A*X_k + B*input + sysNoise_Mu;
// P = A*(P*A.transpose()) + sysNoise_Cov*Identity;

// 非线性系统
X_k(1) += cos(X_k(3)) * input(1) + sys_noise_Mu(1);
X_k(2) += sin(X_k(3)) * input(1) + sys_noise_Mu(2);
X_k(3) += input(2) + sys_noise_Mu(3);

Matrix df(3,3);
df(1,1)=1; df(1,2)=0; df(1,3)=-input(1)*sin(X_k(3));
df(2,1)=0; df(2,2)=1; df(2,3)=input(1)*cos(X_k(3));
df(3,1)=0; df(3,2)=0; df(3,3)=1;

P = df*(P*df.transpose()) + sys_noise_Cov*Identity;

对于观测值更新模型,该例子中依然是线性的,所以并无差异,这里就不再说明了。对于最终的结果可以对比一下,是没问题的~

P:[2,2]((0.0499,0),(0,0.000204951))# 自己更新的协防差
K:[2,1]((0),(-0.163961))
Z - Hx:[1](0.0327018)
K(Z - Hx):[2](0,-0.00536182)
x + K(Z - Hx):[2](6.86707,7.11033) # 自己更新的状态量
 
ExpectedValueGet = [2](6.86707,7.11033) measurement = [1](-14.1006) #BFL库更新的状态量
Covariance = [2,2]((0.05,0),(0,0.000204951)) #BFL库更新的协防差

*当预测模型也是非线性的时候,有两点不同:

  1. y = z ? H x y = z -Hx y=z?Hx 变为 y = z ? h ( x ) y = z -h(x) y=z?h(x)
  2. 使用 h ( x ) h(x) h(x)的雅可比矩阵 H j H_j Hj? 替换 H H H 矩阵。
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 00:19:45  更:2022-04-01 00:22:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:40:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码