|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
4 \7 b; q( ?" m" q. I一、简介( V5 I7 ~1 }6 C6 V4 l# x
著名学者Julier等提出近似非线性函数的均值和方差远比近似非线性函数本身更容易,因此提出了基于确定性采样的UKF算法。
% Z" J4 s$ d$ u5 j该算法的核心思想是:采用UT变换,利用一组Sigma采样点来描述随机变量的高斯分布,然后通过非线性函数的传递,再利用加权统计线性回归技术来近似非x线性函数的后验均值和方差。! [5 W3 t8 M! q) T% B8 q+ @
相比于EKF,UKF的估计精度能够达到泰勒级数展开的二阶精度。
; [ V" u. o9 a( Q* Z! F) b0 d T! L! a! O6 d8 X* k2 O
1 UT变换
/ l0 y4 s% \* m# z' R; c' A& n, q& s2 t$ M* m2 H$ J o. d
$ Q. d6 M) W4 b7 Z4 h1 r5 v+ ]+ L
: r; U- E$ u$ c5 X6 b" k8 Z% @4 y q; b8 Z7 x. L7 z
2 采样策略8 K9 n9 W( _0 a% c" H
9 L4 F" c% S: t根据Sigma点采样策略不同,相应的Sigma点以及均值权值和方差权值也不尽相同,因此UT变换的估计精度也会有差异,但总体来说,其估计精度能够达到泰勒级数展开的二阶精度。, Y4 f p+ z6 o1 w2 {& {
为保证随机变量x经过采样之后得到的Sigma采样点仍具有原变量的必要特性,所以采样点的选取应满足:
" Q# G. v! B- G, l3 e4 [) f9 b6 o6 |* ?: G! U
: u% V" v ^% L. b
9 h! `- C& E! B8 m% j5 |7 U# N; I5 a: d9 n* w# d
下面介绍两种经常使用的采样策略:比例采样和比例修正对称采样
$ w; |& |' D/ U: j4 V2 y
, {( @0 E9 O/ V- p, U! M% B
. m, D- }; ^2 ]8 {9 e8 t" V; s( g. `/ O O) E
% {8 ]5 V. `2 @. @2 Q8 P, _
# v, T* d7 f9 n: ]' o- a) d* o! G
; z2 Q. z* J6 L* |% x- G
+ c. b5 e- G9 |+ @( @4 s7 X% a
! Y( X9 g2 T8 G# |
! C6 P7 u3 a; l9 U- F5 c7 m1 T) a5 |. ?9 b; I+ _; j1 A
3 UKF算法流程
- }7 R$ D9 N2 B8 p) _- Z
# d( Y% Z ]* f0 e; a7 f( ^
8 W3 O! O- j6 W1 j4 B A; K8 L
: f+ M( ^+ z, K* Q1 a O% N" U5 H
0 w! _$ ]) d. Y' G
; f, ~* }6 v- b( i( s9 u
# J; {3 j9 j% T5 J# t+ n二、源代码) }8 w& j* ^/ W
% j; z2 H% Y! g8 k. { I0 v- %% UKF bicycle test
- clear all
- close all
- % load params from file
- load('bicycle_data.mat')
- use_laser = 1;
- use_radar = 1;
- stop_for_sigmavis = false;
- %% Data Initialization
- x_pred_all = []; % predicted state history
- x_est_all = []; % estimated state history with time at row number 6
- NIS_radar_all = []; % estimated state history with time at row number 6
- NIS_laser_all = []; % estimated state history with time at row number 6
- est_pos_error_squared_all = [];
- laser_pos_error_squared_all = [];
- P_est = 0.2*eye(n_x); % initial uncertainty matrix
- P_est(4,4) = 0.3; % initial uncertainty
- P_est(5,5) = 0.3; % initial uncertainty
- %% process noise
- acc_per_sec = 0.3; % acc in m/s^2 per sec
- yaw_acc_per_sec = 0.3; % yaw acc in rad/s^2 per sec
- Z_l_read = [];
- std_las1 = 0.15;
- std_las2 = 0.15;
- std_radr = 0.3;
- std_radphi = 0.03;
- std_radrd = 0.3;
- % UKF params
- n_aug = 7;
- kappa = 3-n_aug;
- w = zeros(2*n_aug+1,1);
- w(1) = kappa/(kappa+n_aug);
- for i=2:()2*n_aug+1)
- w(i) = 0.5/(n_aug+kappa);
- end
- %% UKF filter recursion
- %x_est_all(:,1) = GT(:,1);
- Xi_pred_all = [];
- Xi_aug_all = [];
- x_est = [0.1 0.1 0.1 0.1 0.01];
- last_time = 0;
- % load measurement data from file
- fid = fopen('obj_pose-laser-radar-synthetic-ukf-input.txt');
- %% State Initialization
- tline = fgets(fid); % read first line
- % find first laser measurement
- while tline(1) ~= 'L' % laser measurement
- tline = fgets(fid); % go to next line
- end
- line_vector = textscan(tline,'%s %f %f %f %f %f %f %f %f %f');
- last_time = line_vector{4};% get timestamp
- x_est(1) = line_vector{2}; % initialize position p_x
- x_est(2) = line_vector{3}; % initialize position p_y
- tline = fgets(fid); % go to next line
- % counter
- k = 1;
- while ischar(tline) % go through lines of data file
- % find time of measurement
- if tline(1) == 'L' % laser measurement
- if use_laser == false
- tline = fgets(fid); % skip this line and go to next line
- continue;
- else % read laser meas time
- line_vector = textscan(tline,'%s %f %f %f %f %f %f %f %f %f');
- meas_time = line_vector{1,4};
- end
- elseif tline(1) == 'R' % radar measurement
- if use_radar == false
- tline = fgets(fid); % skip this line and go to next line
- continue;
- else % read radar meas time
- line_vector = textscan(tline,'%s %f %f %f %f %f %f %f %f %f %f');
- meas_time = line_vector{5};
- end
- else % neither laser nor radar
- disp('Error: not laser nor radar')
- return;
- end
- delta_t_sec = ( meas_time - last_time ) / 1e6; % us to sec
- last_time = meas_time;
- %% Prediction part
- p1 = x_est(1);
- p2 = x_est(2);
- v = x_est(3);
- yaw = x_est(4);
- yaw_dot = x_est(5); % yaw_dot: yaw velocity
- x = [p1; p2; v; yaw; yaw_dot]; % state vector
- std_a = acc_per_sec; % process noise long. acceleration
- std_ydd = yaw_acc_per_sec; % process noise yaw acceleration
- if std_a == 0
- std_a = 0.0001;
- end
- if std_ydd == 0
- std_ydd = 0.0001;
- end
- % Create sigma points
- x_aug = [x ; 0 ; 0];
- P_aug = [P_est zeros(n_x,2) ; zeros(2,n_x) [std_a^2 0 ; 0 std_ydd^2 ]];
- %P_aug = nearestSPD(P_aug);
- Xi_aug = zeros(n_aug,2*n_aug+1);
- sP_aug = chol(P_aug,'lower'); % Cholesky factorization.
- Xi_aug(:,1) = x_aug;
- for i=1:n_aug
- Xi_aug(:,i+1) = x_aug + sqrt(n_aug+kappa) * sP_aug(:,i);
- Xi_aug(:,i+1+n_aug) = x_aug - sqrt(n_aug+kappa) * sP_aug(:,i);
- end
- % Predict sigma points
- Xi_pred = zeros(n_x,2*n_aug+1);
- for i=1:(2*n_aug+1)
- p1 = Xi_aug(1,i);
- p2 = Xi_aug(2,i);
- v = Xi_aug(3,i);
- yaw = Xi_aug(4,i);
- yaw_dot = Xi_aug(5,i);
- nu_a = Xi_aug(6,i);
- nu_yaw_dd = Xi_aug(7,i);
- if abs(yaw_dot) > 0.001 %turn around
- p1_p = p1 + v/yaw_dot * ( sin (yaw + yaw_dot*delta_t_sec) - sin(yaw));
- p2_p = p2 + v/yaw_dot * ( cos(yaw) - cos(yaw+yaw_dot*delta_t_sec) );
- else %not turn around
- p1_p = p1 + v*delta_t_sec*cos(yaw);
- p2_p = p2 + v*delta_t_sec*sin(yaw);
- end
- v_p = v;
- yaw_p = yaw + yaw_dot*delta_t_sec;
- yaw_dot_p = yaw_dot;
- % add noise
- p1_p = p1_p + 0.5*nu_a*delta_t_sec^2 * cos(yaw);
- p2_p = p2_p + 0.5*nu_a*delta_t_sec^2 * sin(yaw);
- v_p = v_p + nu_a*delta_t_sec;
- yaw_p = yaw_p + 0.5*nu_yaw_dd*delta_t_sec^2;
- yaw_dot_p = yaw_dot_p + nu_yaw_dd*delta_t_sec;
- Xi_pred(1,i) = p1_p;
- Xi_pred(2,i) = p2_p;
- Xi_pred(3,i) = v_p;
- Xi_pred(4,i) = yaw_p;
- Xi_pred(5,i) = yaw_dot_p;
- end
- % average and covar of sigma points
- x_pred = 0;
- P_pred = zeros(5,5);
- for i=1:2*n_aug+1
- x_pred = x_pred + w(i)* Xi_pred(:,i);
- end
- for i=1:2*n_aug+1
- P_pred = P_pred + w(i)* (Xi_pred(:,i) - x_pred)*(Xi_pred(:,i) - x_pred)';
- end
- %% visualize sigma point examples
- if stop_for_sigmavis && k == 25
- disp('Stopping for sigma point visualization');
- % 2d example
- P_s = P_est (1:2,1:2);
- x_s = x(1:2);
- Xi_s = zeros(2,5);
- A = chol(P_s,'lower');
- Xi_s(:,1) = x_s;
- for i=1:2
- Xi_s(:,i+1) = x_s + sqrt(3) * A(:,i);
- Xi_s(:,i+1+2) = x_s - sqrt(3) * A(:,i);
- end
- error_ellipse(P_s,x_s,'conf', 0.4, 'style', 'k-');
- Xi_aug_p1 = squeeze(Xi_s(1,:,:));
- Xi_aug_p2 = squeeze(Xi_s(2,:,:));
- hold on;
- plot(Xi_aug_p1, Xi_aug_p2, 'or');
- legend('P', 'sigma points')
- axis equal
- xlabel('p_x in m');
- ylabel('p_y in m');
- save('sigma_visualization.mat', 'x_s','P_s','A','Xi_s', 'Xi_aug', 'Xi_pred');
- %return;
- end
- k=k+1;* v8 j$ Y( N) g7 L8 P# j( ^8 h- J7 f
. n6 ^3 D& a0 G; ?
2 z! F4 Z* g6 q三、运行结果
5 K" q& z1 Z8 k& m& F
. @6 x" q5 ?0 x
& c4 S2 t! U7 v( ?" T7 a
* Q+ H- U9 G+ V: B$ z4 p9 l
0 @3 k- v: ~3 h
2 i+ L, l$ Z: J9 l
! P% F: P* T9 K3 _. n2 C3 ?2 V
4 t. ]5 {7 Q8 ~5 n
0 R" I! C2 E6 w6 U5 i+ [
' q1 P5 }. \* d; o& j2 z, A6 j# z% {. {* H9 \
|
|