221 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Matlab
		
	
	
			
		
		
	
	
			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
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 |