ukf非线性滤波实例c语言代码
时间: 2023-05-16 14:02:28 浏览: 409
UKF(Unscented Kalman Filter)是一种非线性滤波器,可以通过模拟离散化的连续系统来估计动态系统的状态。UKF主要用于处理非线性问题,并通过模拟粒子的方式来跟踪系统状态的演变。
以下是一个UKF非线性滤波的实现示例,使用C语言编写:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "matrix.h"
#define n 2 // 状态向量维度
#define m 1 // 观测向量维度
#define alpha 1.0 // UKF调节参数
// 观测矩阵初始化
MATRIX_DEFINE(observation_z, m, 1);
// 状态矩阵初始化
MATRIX_DEFINE(state_x, n, 1);
// 系统噪声初始化
MATRIX_DEFINE(system_Q, n, n);
// 观测噪声初始化
MATRIX_DEFINE(observation_R, m, m);
// 候选 sigma 点初始化
MATRIX_DEFINE(sigma_points, n, (2*n+1));
// 状态函数
MATRIX_DEFINE(f, n, 1);
// 观测函数
MATRIX_DEFINE(h, m, 1);
// sigma 点方差
MATRIX_DEFINE(sigma_cov, n, n);
// 计算 W 矩阵
MATRIX_DEFINE(W, 1, (2*n+1));
// 计算 Wc 矩阵
MATRIX_DEFINE(Wc, 1, (2*n+1));
// 运动噪声矩阵初始化
MATRIX_DEFINE(Q, n, n);
// 测量噪声矩阵初始化
MATRIX_DEFINE(R, m, m);
// 初始化 UKF 参数
void init() {
// 初始化系统噪声和观测噪声
init_matrix(&system_Q, n, n);
init_matrix(&observation_R, m, m);
// 初始化状态向量
init_matrix(&state_x, n, 1);
// 初始化系统方程和观测方程
init_matrix(&f, n, 1);
init_matrix(&h, m, 1);
// 初始化 sigma 点方差和计算 W、Wx
init_matrix(&sigma_cov, n, n);
init_matrix(&W, 1, (2*n+1));
init_matrix(&Wc, 1, (2*n+1));
// 初始化运动噪声和测量噪声
init_matrix(&Q, n, n);
init_matrix(&R, m, m);
}
// 计算 sigma 点并保存到 sigma_points 中
void compute_sigma_points() {
// 计算 sigma 点所需要的参数
double lamda = pow(alpha, 2)*(n+3)-n;
double c = n+lamda;
double gamma = sqrt(c);
// 计算 sigma 点
init_matrix(&sigma_points, n, (2*n+1));
for(int i=0;i<n;i++) {
set_matrix(sigma_points, i, 0, get_matrix(state_x, i, 0));
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
double val = gamma*sqrt(get_matrix(sigma_cov,i,i));
set_matrix(sigma_points, i, j+1, get_matrix(state_x, i, 0) + val);
set_matrix(sigma_points, i, j+1+n, get_matrix(state_x, i, 0) - val);
}
}
}
// 计算 W 和 Wc 矩阵
void compute_W_and_Wc() {
double lamda = pow(alpha, 2)*(n+3)-n;
set_matrix(Wc, 0, 0, lamda/(n+lamda));
set_matrix(W, 0, 0, lamda/(n+lamda)+1-pow(alpha, 2)+1);
for(int i=1;i<(2*n+1);i++) {
set_matrix(Wc, 0, i, 1/(2*(n+lamda)));
set_matrix(W, 0, i, 1/(2*(n+lamda)));
}
}
// 系统方程
void system_function(MATRIX *X, MATRIX *F) {
double x = get_matrix(X, 0, 0);
double y = get_matrix(X, 1, 0);
set_matrix(F, 0, 0, x+y);
set_matrix(F, 1, 0, y+2);
}
// 观测方程
void observation_function(MATRIX *X, MATRIX *H) {
double x = get_matrix(X, 0, 0);
double y = get_matrix(X, 1, 0);
set_matrix(H, 0, 0, y+2);
}
// 计算方程 sigma 点
void compute_system_sigmas() {
for(int i=0;i<(2*n+1);i++) {
MATRIX_DECLARE(point, n, 1);
get_sub_matrix(sigma_points, 0, i, n, 1, &point);
system_function(&point, &f);
set_sub_matrix(sigma_points, &f, 0, i, n, 1);
}
}
// 计算观测 sigma 点
void compute_observation_sigmas() {
for(int i=0;i<(2*n+1);i++) {
MATRIX_DECLARE(point, n, 1);
get_sub_matrix(sigma_points, 0, i, n, 1, &point);
observation_function(&point, &h);
set_sub_matrix(sigma_points, &h, 0, i, m, 1);
}
}
// 计算平均值
void average(MATRIX *X_bar, MATRIX *W, MATRIX *points) {
for(int i=0;i<n;i++) {
double sum = 0;
for(int j=0;j<(2*n+1);j++) {
sum += get_matrix(points, i, j) * get_matrix(W, 0, j);
}
set_matrix(X_bar, i, 0, sum);
}
}
// 计算协方差矩阵
void compute_covariance_matrix(MATRIX *Rxx, MATRIX *Wc, MATRIX *X_bar, MATRIX *sigmas) {
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
double sum = 0;
for(int k=0;k<(2*n+1);k++) {
MATRIX_DECLARE(x_diff, n, 1), s_diff, temp1, temp2;
get_sub_matrix(sigmas, 0, k, n, 1, &s_diff);
subtract_matrix(&s_diff, X_bar, &x_diff);
transpose_matrix(&x_diff, &temp1);
get_sub_matrix(sigmas, 0, k, n, 1, &s_diff);
subtract_matrix(&s_diff, X_bar, &temp2);
matrix_multiply(&x_diff, &temp2, &temp1);
sum += get_matrix(Wc, 0, k) * get_matrix(Rxx, i, j) + get_matrix(W, 0, k) * get_matrix(&temp1, 0, 0);
}
set_matrix(Rxx, i, j, sum);
}
}
}
// 计算 Kalman 增益矩阵
void compute_Kalman_gain(MATRIX *K, MATRIX *P, MATRIX *H, MATRIX *R) {
MATRIX_DECLARE(temp1, m, n);
MATRIX_DECLARE(H_transpose, n, m);
transpose_matrix(H, &H_transpose);
matrix_multiply(P, &H_transpose, &temp1);
MATRIX_DECLARE(temp2, m, m);
matrix_multiply(H, &temp1, &temp2);
matrix_add(&temp2, R, &temp2);
MATRIX_DECLARE(temp3, n, n);
matrix_inverse(&temp2, &temp3);
matrix_multiply(&temp1, &temp3, K);
}
// 更新状态向量
void update_states_and_covariance(MATRIX *K, MATRIX *H, MATRIX *Z, MATRIX *X, MATRIX *P) {
MATRIX_DECLARE(temp1, m, 1);
matrix_multiply(H, X, &temp1);
MATRIX_DECLARE(temp2, m, 1);
subtract_matrix(Z, &temp1, &temp2);
MATRIX_DECLARE(temp3, n, m);
matrix_multiply(K, &temp2, &temp3);
add_matrix(X, &temp3, X);
MATRIX_DECLARE(temp4, n, n);
matrix_multiply(K, H, &temp4);
MATRIX_DECLARE(I, n, n);
identity_matrix(&I);
MATRIX_DECLARE(temp5, n, n);
subtract_matrix(&I, &temp4, &temp5);
MATRIX_DECLARE(temp6, n, n);
matrix_multiply(&temp5, P, &temp6);
matrix_multiply(&temp6, &temp5, P);
}
// UKF 非线性滤波器
void ukf(MATRIX *states, MATRIX *P, MATRIX *R, MATRIX *z) {
compute_sigma_points();
compute_W_and_Wc();
compute_system_sigmas();
average(&state_x, &W, &sigma_points);
compute_covariance_matrix(&sigma_cov, &Wc, &state_x, &sigma_points);
compute_observation_sigmas();
average(&observation_z, &W, &sigma_points);
MATRIX_DECLARE(K, n, m);
compute_Kalman_gain(&K, P, &h, R);
update_states_and_covariance(&K, &h, z, &state_x, P);
copy_matrix(&state_x, states);
}
int main(){
init();
set_matrix(&system_Q, 0, 0, 0.5);
set_matrix(&system_Q, 1, 1, 0.5);
set_matrix(&observation_R, 0, 0, 0.1);
set_matrix(&R, 0, 0, 0.1);
set_matrix(&state_x, 0, 0, 1);
set_matrix(&state_x, 1, 0, 2);
set_matrix(&Q, 0, 0, get_matrix(&system_Q, 0, 0));
set_matrix(&Q, 1, 1, get_matrix(&system_Q, 1, 1));
MATRIX_DECLARE(P, n, n);
identity_matrix(&P);
MATRIX_DECLARE(z, m, 1);
set_matrix(&z, 0, 0, 4.2);
MATRIX_DECLARE(res_states, n, 1);
ukf(&res_states, &P, &R, &z);
matrix_print(&state_x);
matrix_print(&observation_z);
matrix_print(&res_states);
return 0;
}
以上是一个 UKF 非线性滤波的实现示例,通过对运动噪声和测量噪声进行初始化,以及通过计算 sigma 点和计算 W 和 Wc 矩阵来实现对状态向量的非线性滤波处理。
阅读全文