Hay muchos antecedentes aquí, desplácese hacia abajo para la pregunta
Estoy probando el algoritmo de unión de mapas descrito en Cuán lejos está SLAM de un problema de mínimos cuadrados lineales ; específicamente, fórmula (36). El código que he escrito parece tomar siempre los valores del segundo mapa para las posiciones de referencia. Mi pregunta es, ¿estoy entendiendo el texto correctamente o estoy cometiendo algún tipo de error? Trataré de explicar las fórmulas tal como las entiendo y mostraré cómo mi código implementa eso. Estoy tratando de hacer el caso simple de unir solo dos mapas locales.
Del documento (36) dice que unir dos mapas locales es encontrar un vector de estado que minimiza:
Ampliado para dos mapas locales y Tengo:
Según tengo entendido, un submapa puede verse como una observación integrada para un mapa global, por lo que es el ruido asociado con el submapa (en lugar de ser el ruido del proceso en el EKF que usé para hacer el submapa, que puede o no puede no ser diferente).
El vector es la pose del primer mapa, la pose del segundo mapa y la unión de los puntos de referencia en ambos mapas.
La función es:
No estoy convencido de que mi evaluación a continuación sea correcta:
Los dos primeros elementos son la pose del robot en el marco de referencia del mapa anterior. Por ejemplo, para el mapa 1, la pose estará en el cuadro inicial en ; para el mapa 2, estará en el marco del mapa 1.
El siguiente grupo de elementos son los comunes al mapa 1 y al mapa 2, que se transforman en el marco de referencia del mapa 1.
Las filas finales son las características exclusivas del mapa 2, en el marco del primer mapa.
Mi implementación de matlab es la siguiente:
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
Estoy usando la caja de herramientas de optimización para encontrar el mínimo de la función de condición física descrita anteriormente. La función de fitness en sí es bastante sencilla, creo. La función H devuelve el vector H descrito anteriormente.
El resultado es: cuando ejecuto join_maps en los dos vectores
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)
El resultado es:
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 pregunta:
Mi programa proporciona el mapa 2 es el mínimo de la función de unión de mapa. Parece que el mínimo debería estar en algún lugar entre el mapa 1 y el mapa 2. Estoy bastante seguro de que el problema está en la matriz H. ¿Qué estoy haciendo mal?