-
Notifications
You must be signed in to change notification settings - Fork 17
/
EKF_SLAM_simulation.m
214 lines (166 loc) · 5.22 KB
/
EKF_SLAM_simulation.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
% EKF_SLAM 仿真文件
%
% 纪友州 2019
close all
clear all
% 加载模型参数
simulation_config
% 加载数据
load(MAP_DATA)
% 加载关键点
key_points = data_original.key_points;
% 加载路标
landmarks = data_original.landmarks;
% 加载状态
states = data_original.states;
% 加载路径关键点
wp = data_original.key_points;
% 获取序列长度
length = size(states,2);
if ADD_COLOR_NOISE == 1
noise_V = gen_color_noise(length,Q(1,1),c);
noise_G = gen_color_noise(length,Q(2,2),c);
% noise_r = gen_color_noise(length,R(1,1));
% noise_t = gen_color_noise(length,R(2,2));
for i = 1:1:length
states(i).Vn = states(i).V + noise_V(i);
states(i).Gn = states(i).G + noise_G(i);
% states(i).Vn = states(i).V + noise_r(i);
% states(i).Vn = states(i).V + noise_t(i);
end
end
ture_trajectory = zeros(3,length);
model_pre_trajectory = zeros(3,length);
EKF_pre_trajectory = zeros(3,length);
x= states(1).xtrue; % 状态向量
P= zeros(3); % 协方差矩阵
QE= 2*Q; % 控制变量的协方差矩阵
RE= 2*R; % 传感器协方差矩阵
ftag= 1:size(landmarks,2);
da_table= zeros(1,size(landmarks,2));
dt = DT_CONTROLS;
if ASYNCHRONOUS == 1
dt = DT_OBSERVE;
end
x_model_pre = x;
if SLAM_SAVE_GIF == 1
if exist('ekf_slam.avi','file') == 2
delete('ekf_slam.avi');
end
if exist('ekf_slam.gif','file') == 2
delete('ekf_slam.gif');
end
%创建avi文件对象
aviobj = VideoWriter('ekf_slam.avi','Uncompressed AVI');
open(aviobj)
end
% 循环算法仿真
fig = figure;
hold on;
for k = 1:1:length
% 获取控制量
Vn = states(k).Vn;
Gn = states(k).Gn;
if ASYNCHRONOUS == 0
% EKF更新状态预测值和协方差
[x,P] = EKF_predict (x,P, Vn,Gn,QE, WHEELBASE,dt);
% 获取仅通过模型预测的位姿
x_model_pre = vehicle_model(x_model_pre, Vn,Gn, WHEELBASE,dt);
end
if states(k).observation_update == 1
if ASYNCHRONOUS == 1
% EKF更新状态预测值和协方差
[x,P] = EKF_predict (x,P, Vn,Gn,QE, WHEELBASE,dt);
% 获取仅通过模型预测的位姿
x_model_pre = vehicle_model(x_model_pre, Vn,Gn, WHEELBASE,dt);
end
% 获取观测值
z = states(k).zn;
ftag_visible = states(k).ftag_visible;
if REDUCE_OB_FEATURES == 1
% 削减观测到的landmark数目
if size(z,2) > 1
z = z(:,1);
ftag_visible = ftag_visible(1);
end
end
% 数据关联
if SWITCH_ASSOCIATION_KNOWN == 1
[zf,idf,zn, da_table]= data_associate_known(x,z,ftag_visible, da_table);
else
[zf,idf, zn]= data_associate(x,P,z,RE, GATE_REJECT, GATE_AUGMENT);
end
% 更新状态向量
if SWITCH_USE_IEKF == 1
[x,P]= update_iekf(x,P,zf,RE,idf, 5);
else
[x,P]= EKF_update(x,P,zf,RE,idf, 1);
end
% 添加新的landmark到状态向量中
[x,P]= augment(x,P, zn,RE);
end
xtrue = states(k).xtrue;
iwp = states(k).next_keypoint;
% 清除图像
cla;
axis equal
ture_trajectory(:,k) = xtrue(1:3);
model_pre_trajectory(:,k) = x_model_pre(1:3);
EKF_pre_trajectory(:,k) = x(1:3);
% 画出历史轨迹
plot( ture_trajectory(1, 1:k), ture_trajectory(2, 1:k), 'k--','linewidth',3);
% 画出历史EKF预测轨迹
plot( EKF_pre_trajectory(1, 1:k), EKF_pre_trajectory(2, 1:k), 'r','linewidth',3 );
% 画出历史model预测轨迹
plot( model_pre_trajectory(1, 1:k), model_pre_trajectory(2, 1:k), 'b-.','linewidth',3);
% 画出landmarks
scatter( landmarks(1, :), landmarks(2, :), 'b*' );
% 画出路径关键点
plot( wp(1,:), wp(2, :), 'r.','markersize',26 );
% 画出目标点的位置
if iwp~=0
plot(wp(1,iwp),wp(2,iwp),'bo','markersize',13,'linewidth',1);
end
% 画出车的位姿
draw_car(xtrue,5,'k');
% EKF预测位姿
draw_car(x,5,'r');
% 模型预测位姿
draw_car(x_model_pre,5,'g');
% 画出激光雷达观测范围
draw_circle(xtrue(1), xtrue(2),MAX_RANGE);
if ~isempty(z)
% 画出激光雷达观测线
plines = make_laser_lines(z,xtrue);
plot(plines(1,:),plines(2,:));
% pellipses = make_covariance_ellipses(x,P);
% plot(pellipses(1,:),pellipses(2,:));
end
% legend([truep ekfp,modelp],'true','ekf','model');
pause(0.00000001)
if SLAM_SAVE_GIF == 1
%获取当前画面
F = getframe(fig);
%加入avi对象中
writeVideo(aviobj,F);
%转成gif图片,只能用256色
im = frame2im(F);
[I,map] = rgb2ind(im,256);
%写入 GIF89a 格式文件
if k == 1
imwrite(I,map,'ekf_slam.gif','GIF', 'Loopcount',inf,'DelayTime',0.1);
else
imwrite(I,map,'ekf_slam.gif','GIF','WriteMode','append','DelayTime',0.1);
end
end
sim_result.states(k).xtrue = xtrue;
sim_result.states(k).x_model_pre = x_model_pre;
sim_result.states(k).x = x;
sim_result.states(k).P = P;
end
sim_result.landmarks = landmarks;
sim_result.ture_trajectory = ture_trajectory;
sim_result.EKF_pre_trajectory = EKF_pre_trajectory;
sim_result.model_pre_trajectory = model_pre_trajectory;
sim_result.wp = wp;
save sim_result sim_result;