| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  | 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); | 
					
						
							| 
									
										
										
										
											2014-12-07 13:41:12 +08:00
										 |  |  |   prev_pose = smartValues.atPose2(key_prev); | 
					
						
							|  |  |  |   curr_pose = smartValues.atPose2(key_curr); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |   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); | 
					
						
							|  |  |  |        | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef1 = RangeFactor2D(key_prev, lmkKey(1), r1, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       fullGraph.add(rangef1);  | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef2 = RangeFactor2D(key_curr, lmkKey(1), r2, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       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);     | 
					
						
							|  |  |  |        | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef3 = RangeFactor2D(key_curr, lmkKey(1), r3, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       fullGraph.add(rangef3);  | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef4 = RangeFactor2D(key_curr, lmkKey(2), r4, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       % 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);  | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef5 = RangeFactor2D(key_curr, lmkKey(2), r5, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       fullGraph.add(rangef5);  | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef6 = RangeFactor2D(key_curr, lmkKey(3), r6, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       % 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);  | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef7 = RangeFactor2D(key_curr, lmkKey(2), r7, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       fullGraph.add(rangef7);  | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef8 = RangeFactor2D(key_curr, lmkKey(3), r8, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       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); | 
					
						
							|  |  |  |        | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef9 = RangeFactor2D(key_curr, lmkKey(3), r9, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       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); | 
					
						
							|  |  |  |        | 
					
						
							| 
									
										
										
										
											2019-01-01 00:19:46 +08:00
										 |  |  |       rangef10 = RangeFactor2D(key_curr, lmkKey(3), r10, noiseRange); | 
					
						
							| 
									
										
										
										
											2013-09-14 08:21:10 +08:00
										 |  |  |       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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |