gtsam/matlab/unstable_examples/SmartRangeFactorExample.m

221 lines
6.5 KiB
Matlab

clear all; clear all;
clc
close all
import gtsam.*;
%% Noise settings
t_noise = 0.1; % odometry tranlation error
r_noise = 0.05; % odometry rotation error
range_noise = 0.001; % range measurements error
% Create noise models
noiseRange = noiseModel.Isotropic.Sigma(1, range_noise); % range measurements noise model
noiseOdom = noiseModel.Diagonal.Sigmas([t_noise; t_noise; r_noise]); % odometry noise model
noiseInit = noiseModel.Diagonal.Sigmas([0.01; 0.01; 0.0001]); % for prior on first pose
%% Choose initial guess for landmarks
% if set to 1 we set the landmark guess to the true position
goodInitFlag_lmk1 = 0;
goodInitFlag_lmk2 = 1;
goodInitFlag_lmk3 = 1;
% true positions
lmk1 = Point2([0.5;0.5]);
lmk2 = Point2([1.5;0.5]);
lmk3 = Point2([2.5;0.5]);
% specular positions (to simulate ambiguity in triangulation)
lmk1_bad = Point2([0.5;-0.5]);
lmk2_bad = Point2([1.5;1.5]);
lmk3_bad = Point2([2.5;-0.5]);
%% Create keys
num_poses = 7;
for ind_pose = 1:num_poses
poseKey(ind_pose) = symbol('x',ind_pose); % Key for each pose
end
lmkKey(1) = symbol('l',1); % Key for each pose
lmkKey(2) = symbol('l',2); % Key for each pose
lmkKey(3) = symbol('l',3); % Key for each pose
%% Factor graphs
smartGraph = NonlinearFactorGraph;
smartValues = Values;
fullGraph = NonlinearFactorGraph;
fullValues = Values;
% Add prior on first pose
poseInit = Pose2;
smartValues.insert(poseKey(1), poseInit );
smartGraph.add(PriorFactorPose2(poseKey(1), poseInit, noiseInit));
fullValues.insert(poseKey(1), poseInit );
fullGraph.add(PriorFactorPose2(poseKey(1), poseInit, noiseInit));
currPose = poseInit;
srf1 = SmartRangeFactor(range_noise);
srf2 = SmartRangeFactor(range_noise);
srf3 = SmartRangeFactor(range_noise);
%% Main loop
for ind_pose = 2:7
ind_pose
%% apply command, depending on the time step
switch ind_pose
case 2
v = [1; 0; pi/2];
case 3
v = [1; 0; -pi/2];
case 4
v = [1; 0; -pi/2];
case 5
v = [1; 0; pi/2];
case 6
v = [1; 0; pi/2];
case 7
v = [1; 0; 0];
end
%% compute intial guess for poses (initialized to ground truth)
currPose = currPose.retract(v);
smartValues.insert(poseKey(ind_pose), currPose );
fullValues.insert(poseKey(ind_pose), currPose );
key_prev = poseKey(ind_pose-1);
key_curr = poseKey(ind_pose);
prev_pose = smartValues.atPose2(key_prev);
curr_pose = smartValues.atPose2(key_curr);
GTDeltaPose = prev_pose.between(curr_pose);
noisePose = Pose2([t_noise*rand; t_noise*rand; r_noise*rand]);
NoisyDeltaPose = GTDeltaPose.compose(noisePose);
% add odometry factors
smartGraph.add(BetweenFactorPose2(key_prev, key_curr, NoisyDeltaPose, noiseOdom));
fullGraph.add(BetweenFactorPose2(key_prev, key_curr, NoisyDeltaPose, noiseOdom));
% add range factors
switch ind_pose
%====================================================================
case 2
% x1-lmk1
% x2-lmk1
r1 = prev_pose.range(lmk1); % range of lmk1 wrt x1
srf1.addRange(key_prev, r1);
r2 = curr_pose.range(lmk1); % range of lmk1 wrt x2
srf1.addRange(key_curr, r2);
rangef1 = RangeFactor2D(key_prev, lmkKey(1), r1, noiseRange);
fullGraph.add(rangef1);
rangef2 = RangeFactor2D(key_curr, lmkKey(1), r2, noiseRange);
fullGraph.add(rangef2);
if goodInitFlag_lmk1==1
fullValues.insert(lmkKey(1), lmk1);
else
fullValues.insert(lmkKey(1), lmk1_bad);
end
%====================================================================
case 3
% x3-lmk1
% x3-lmk2
r3 = curr_pose.range(lmk1); % range of lmk1 wrt x3
srf1.addRange(key_curr, r3);
smartGraph.add(srf1);
r4 = curr_pose.range(lmk2); % range of lmk2 wrt x3
srf2.addRange(key_curr, r4);
rangef3 = RangeFactor2D(key_curr, lmkKey(1), r3, noiseRange);
fullGraph.add(rangef3);
rangef4 = RangeFactor2D(key_curr, lmkKey(2), r4, noiseRange);
% IF WE ADD FACTOR HERE IT CRASHES: fullGraph.add(rangef4);
%====================================================================
case 4
% x4-lmk2
% x4-lmk3
r5 = curr_pose.range(lmk2); % range of lmk2 wrt x4
srf2.addRange(key_curr, r5);
r6 = curr_pose.range(lmk3); % range of lmk3 wrt x4
srf3.addRange(key_curr, r6);
% DELAYED INITIALIZATION:
fullGraph.add(rangef4);
rangef5 = RangeFactor2D(key_curr, lmkKey(2), r5, noiseRange);
fullGraph.add(rangef5);
rangef6 = RangeFactor2D(key_curr, lmkKey(3), r6, noiseRange);
% IF WE ADD FACTOR HERE IT CRASHES: fullGraph.add(rangef6);
if goodInitFlag_lmk2==1
fullValues.insert(lmkKey(2), lmk2);
else
fullValues.insert(lmkKey(2), lmk2_bad);
end
%====================================================================
case 5
% x5-lmk2
% x4-lmk3
r7 = curr_pose.range(lmk2); % range of lmk2 wrt x5
srf2.addRange(key_curr, r7);
smartGraph.add(srf2);
r8 = curr_pose.range(lmk3); % range of lmk3 wrt x5
srf3.addRange(key_curr, r8);
% DELAYED INITIALIZATION:
fullGraph.add(rangef6);
rangef7 = RangeFactor2D(key_curr, lmkKey(2), r7, noiseRange);
fullGraph.add(rangef7);
rangef8 = RangeFactor2D(key_curr, lmkKey(3), r8, noiseRange);
fullGraph.add(rangef8);
if goodInitFlag_lmk3==1
fullValues.insert(lmkKey(3), lmk3);
else
fullValues.insert(lmkKey(3), lmk3_bad);
end
%====================================================================
case 6
% x6-lmk3
r9 = curr_pose.range(lmk3); % range of lmk3 wrt x6
srf3.addRange(key_curr, r9);
rangef9 = RangeFactor2D(key_curr, lmkKey(3), r9, noiseRange);
fullGraph.add(rangef9);
case 7
% x6-lmk3
r10 = curr_pose.range(lmk3); % range of lmk3 wrt x7
srf3.addRange(key_curr, r10);
smartGraph.add(srf3);
rangef10 = RangeFactor2D(key_curr, lmkKey(3), r10, noiseRange);
fullGraph.add(rangef10);
end
smartOpt = GaussNewtonOptimizer(smartGraph, smartValues);
smartSolution = smartOpt.optimize;
figure(1)
clf
plot2DTrajectory(smartSolution, 'b.-');
title('Ground truth (g) VS smart estimate (b) VS full estimate (r)')
xlabel('x')
ylabel('y')
zlabel('z')
axis equal
hold on
fullOpt = GaussNewtonOptimizer(fullGraph, fullValues);
fullSolution = fullOpt.optimize;
figure(1)
plot2DTrajectory(fullSolution, 'r.-');
figure(1)
plot2DTrajectory(smartValues, 'g.-');
drawnow;
end