SLAM에 EKF를 사용하고 있으며 업데이트 단계에 문제가 있습니다. K가 단수이고로 rcond평가 된다는 경고가 표시 됩니다 near eps or NaN. Z의 반전에 대한 문제를 추적했다고 생각합니다. 마지막 항을 뒤집지 않고 칼만 게인을 계산하는 방법이 있습니까?
100 % 긍정적이지 않다는 것이 문제의 원인이므로 전체 코드도 여기에 넣었습니다 . 주요 진입 점은 slam2d입니다.
function [ x, P ] = expectation( x, P, lmk_idx, observation)
% expectation
r_idx = [1;2;3];
rl = [r_idx; lmk_idx];
[e, E_r, E_l] = project(x(r), x(lmk_idx));
E_rl = [E_r E_l];
E = E_rl * P(rl,rl) * E_rl';
% innovation
z = observation - e;
Z = E;
% Kalman gain
K = P(:, rl) * E_rl' * Z^-1;
% update
x = x + K * z;
P = P - K * Z * K';
end
function [y, Y_r, Y_p] = project(r, p)
[p_r, PR_r, PR_p] = toFrame2D(r, p);
[y, Y_pr] = scan(p_r);
Y_r = Y_pr * PR_r;
Y_p = Y_pr * PR_p;
end
function [p_r, PR_r, PR_p] = toFrame2D(r , p)
t = r(1:2);
a = r(3);
R = [cos(a) -sin(a) ; sin(a) cos(a)];
p_r = R' * (p - t);
px = p(1);
py = p(2);
x = t(1);
y = t(2);
PR_r = [...
[ -cos(a), -sin(a), cos(a)*(py - y) - sin(a)*(px - x)]
[ sin(a), -cos(a), - cos(a)*(px - x) - sin(a)*(py - y)]];
PR_p = R';
end
function [y, Y_x] = scan(x)
px = x(1);
py = x(2);
d = sqrt(px^2 + py^2);
a = atan2(py, px);
y = [d;a];
Y_x =[...
[ px/(px^2 + py^2)^(1/2), py/(px^2 + py^2)^(1/2)]
[ -py/(px^2*(py^2/px^2 + 1)), 1/(px*(py^2/px^2 + 1))]];
end
편집은 :
project(x(r), x(lmk))있었어야 project(x(r), x(lmk_idx))이제 위의 수정됩니다.
K는 잠시 후 단수로 진행되지만 즉시는 아닙니다. 나는 약 20 초 정도라고 생각합니다. 오늘 밤 집에 가서 결과를 게시 할 때 @josh가 제안한 변경 사항을 시도해 보겠습니다.
업데이트 1 :
(P(rl,rl) * E_rl') * inv( Z )
K는 4.82 초 후에 50Hz (241 단계)로 측정되어 단수가됩니다. 여기 의 조언에 따라 K = (P(:, rl) * E_rl')/ZK가 단수라는 경고가 생성되기 전에 250 단계의 결과를 시도 했습니다.
이것은 문제가 매트릭스 반전과 관련이 없지만 문제를 일으키는 다른 곳이라고 알려줍니다.
업데이트 2
내 주요 루프는 (x, P 및 랜드 마크 포인터를 저장하는 로봇 객체)입니다.
for t = 0:sample_time:max_time
P = robot.P;
x = robot.x;
lmks = robot.lmks;
mapspace = robot.mapspace;
u = robot.control(t);
m = robot.measure(t);
% Added to show eigenvalues at each step
[val, vec] = eig(P);
disp('***')
disp(val)
%%% Motion/Prediction
[x, P] = predict(x, P, u, dt);
%%% Correction
lids = intersect(m(1,:), lmks(1,:)); % find all observed landmarks
lids_new = setdiff(m(1,:), lmks(1,:));
for lid = lids
% expectation
idx = find (lmks(1,:) == lid, 1);
lmk = lmks(2:3, idx);
mid = m(1,:) == lid;
yi = m(2:3, mid);
[x, P] = expectation(x, P, lmk, yi);
end %end correction
%%% New Landmarks
for id = 1:length(lids_new)
% if id ~= 0
lid = lids_new(id);
lmk = find(lmks(1,:)==false, 1);
s = find(mapspace, 2);
if ~isempty(s)
mapspace(s) = 0;
lmks(:,lmk) = [lid; s'];
yi = m(2:3,m(1,:) == lid);
[x(s), L_r, L_y] = backProject(x(r), yi);
P(s,:) = L_r * P(r,:);
P(:,s) = [P(s,:)'; eye(2)];
P(s,s) = L_r * P(r,r) * L_r';
end
end % end new landmarks
%%% Save State
robot.save_state(x, P, mapspace, lmks)
end
end
이 루프가 끝나면 x와 P를 다시 로봇에 저장하므로 각 반복을 통해 공분산을 전파한다고 생각합니다.