Tutaj jest dużo tła, przewiń pytanie w dół
Próbuję algorytmu łączenia mapy opisanego w odcinku Jak daleko jest SLAM od problemu liniowych najmniejszych kwadratów ; konkretnie wzór (36). Kod, który napisałem, wydaje się zawsze przyjmować wartości drugiej mapy dla punktów orientacyjnych. Moje pytanie brzmi: czy dobrze rozumiem tekst, czy popełniam jakiś błąd? Spróbuję wyjaśnić formuły, tak jak je rozumiem, i pokażę, jak mój kod to implementuje. Próbuję zrobić prosty przypadek połączenia tylko dwóch lokalnych map.
Z pracy (36) wynika, że dołączenie do dwóch lokalnych map znajduje wektor stanu który minimalizuje:
Rozszerzony dla dwóch lokalnych map i Mam: ^ X L 2
Jak rozumiem, submapa może być postrzegana jako zintegrowana obserwacja mapy globalnej, więc jest hałasem związanym z submapem (w przeciwieństwie do szumu procesowego w EKF, którego użyłem do wykonania submapa, który może lub nie może być inny).
Wektor jest pozą z pierwszej mapy, pozą z drugiej mapy i połączeniem punktów orientacyjnych na obu mapach.
Funkcja to:
Nie jestem przekonany, że moja ocena poniżej jest poprawna:
Pierwsze dwa elementy to pozycja robota w ramce odniesienia poprzedniej mapy. Na przykład dla mapy 1 pozycja będzie w początkowej ramce w czasie ; dla mapy 2 będzie w ramce mapy 1.
Kolejną grupą elementów są te wspólne dla mapy 1 i mapy 2, które są przekształcane w ramkę odniesienia mapy 1.
Ostatnie rzędy są cechami unikalnymi dla mapy 2, w ramce pierwszej mapy.
Moja implementacja Matlaba wygląda następująco:
function [G, fval, output, exitflag] = join_maps(m1, m2)
x = [m2(1:3);m2];
[G,fval,exitflag,output] = fminunc(@(x) fitness(x, m1, m2), x, options);
end
function G = fitness(X, m1, m2)
m1_f = m1(6:3:end);
m2_f = m2(6:3:end);
common = intersect(m1_f, m2_f);
P = eye(size(m1, 1)) * .002;
r = X(1:2);
a = X(3);
X_join = (m1 - H(X, common));
Y_join = (m2 - H(X, common));
G = (X_join' * inv(P) * X_join) + (Y_join' * inv(P) * Y_join);
end
function H_j = H(X, com)
a0 = X(3);
H_j = zeros(size(X(4:end)));
H_j(1:3) = X(4:6);
Y = X(1:2);
len = length(X(7:end));
for i = 7:3:len
id = X(i + 2);
if find(com == id)
H_j(i:i+1) = R(a0) * (X(i:i+1) - Y);
H_j(i+2) = id;
else % new lmk
H_j(i:i+2) = X(i:i+2);
end
end
end
function A = R(a)
A = [cos(a) -sin(a);
sin(a) cos(a)];
end
Korzystam z przybornika optymalizacyjnego, aby znaleźć minimum funkcji fitness opisanej powyżej. Myślę, że sama funkcja fitness jest dość prosta. Funkcja H zwraca wektor H opisany powyżej.
Wynik jest następujący: kiedy uruchamiam join_maps na dwóch wektorach
map_1 = [3.7054;1.0577;-1.9404; %robot x, y, angle
2.5305;-1.0739;81.0000]; % landmark x, y, id
map_2 = [3.7054;1.0577;-1.9404;
2.3402;-1.1463;81.0000]; % note the slightly different x,y
[G,fv,output,exitflag] = join_maps(map_1, map_2)
Dane wyjściowe to:
Warning: Gradient must be provided for trust-region algorithm;
using line-search algorithm instead.
> In fminunc at 341
In join_maps at 7
Local minimum found.
Optimization completed because the size of the gradient is less than
the default value of the function tolerance.
<stopping criteria details>
Local minimum possible.
fminunc stopped because it cannot decrease the objective function
along the current search direction.
<stopping criteria details>
G =
3.7054
1.0577
-1.9404
3.7054
1.0577
-1.9404
2.3402
-1.1463
81.0000
fv =
1.3136e+07
output =
iterations: 1
funcCount: 520
stepsize: 1.0491e-16
firstorderopt: 1.6200e+05
algorithm: 'medium-scale: Quasi-Newton line search'
message: [1x362 char]
exitflag =
5
Pytanie:
Mój program podaje, że mapa 2 to minimum funkcji łączenia mapy. Wydaje się, że minimum powinno znajdować się gdzieś pomiędzy mapą 1 a mapą 2. Jestem prawie pewien, że problem dotyczy macierzy H. Co robię źle?