Il y a beaucoup de fond ici, faites défiler vers le bas pour la question
J'essaie l'algorithme de jointure de carte décrit dans À quelle distance est SLAM d'un problème de moindres carrés linéaires ; en particulier, la formule (36). Le code que j'ai écrit semble toujours prendre les valeurs de la deuxième carte pour les positions de points de repère. Ma question est, est-ce que je comprends bien le texte ou est-ce que je fais une sorte d'erreur. Je vais essayer d'expliquer les formules telles que je les comprends et montrer comment mon code implémente cela. J'essaie de faire le cas simple de joindre seulement deux cartes locales.
D'après l'article (36), joindre deux cartes locales revient à trouver un vecteur d'état qui minimise:
Développé pour deux cartes locales et ^ X L 2 J'ai:
Je ne suis pas convaincu que mon évaluation ci-dessous soit correcte:
Le prochain groupe d'éléments sont ceux communs à la carte 1 et à la carte 2, qui sont transformés en cadre de référence de la carte 1.
Les dernières lignes sont les caractéristiques propres à la carte 2, dans le cadre de la première carte.
Mon implémentation matlab est la suivante:
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
J'utilise la boîte à outils d'optimisation pour trouver le minimum de la fonction fitness décrite ci-dessus. Je pense que la fonction fitness en elle-même est assez simple. La fonction H renvoie le vecteur H décrit ci-dessus.
Le résultat est: lorsque j'exécute join_maps sur les deux vecteurs
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)
La sortie est:
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
La question:
Mon programme donne la carte 2 est le minimum de la fonction de jonction de carte. Il semble que le minimum devrait se situer quelque part entre la carte 1 et la carte 2. Je suis sûr que le problème vient de la matrice H. Qu'est-ce que je fais mal?