| 
									
										
										
										
											2014-04-18 02:11:18 +08:00
										 |  |  | function [values, measurements] = covarianceAnalysisCreateTrajectory( options, metadata )
 | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  | % Create a trajectory for running covariance analysis scripts. | 
					
						
							|  |  |  | % 'options' contains fields for including various factor types and setting trajectory length | 
					
						
							|  |  |  | % 'metadata' is a storage variable for miscellaneous factor-specific values | 
					
						
							|  |  |  | % Authors: Luca Carlone, David Jensen | 
					
						
							|  |  |  | % Date: 2014/04/16 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import gtsam.*; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | values = Values; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-16 03:57:22 +08:00
										 |  |  | warning('Rotating Pose inside getPoseFromGtScenario! TODO: Use a body_P_sensor transform in the factors') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-18 02:11:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  | if options.useRealData == 1 | 
					
						
							|  |  |  |   %% Create a ground truth trajectory from Real data (if available) | 
					
						
							|  |  |  |   fprintf('\nUsing real data as ground truth\n'); | 
					
						
							|  |  |  |   gtScenario = load('truth_scen2.mat', 'Time', 'Lat', 'Lon', 'Alt', 'Roll', 'Pitch', 'Heading',... | 
					
						
							|  |  |  |     'VEast', 'VNorth', 'VUp'); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   % Limit the trajectory length | 
					
						
							| 
									
										
										
										
											2014-05-09 03:27:32 +08:00
										 |  |  |   options.trajectoryLength = min([length(gtScenario.Lat)/options.subsampleStep options.trajectoryLength]); | 
					
						
							| 
									
										
										
										
											2014-04-17 22:09:53 +08:00
										 |  |  |   fprintf('Scenario Ind: '); | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |    | 
					
						
							|  |  |  |   for i=0:options.trajectoryLength | 
					
						
							|  |  |  |     scenarioInd = options.subsampleStep * i + 1; | 
					
						
							| 
									
										
										
										
											2014-04-17 22:09:53 +08:00
										 |  |  |     fprintf('%d, ', scenarioInd); | 
					
						
							| 
									
										
										
										
											2014-04-24 00:39:47 +08:00
										 |  |  |     if (mod(i,12) == 0) fprintf('\n'); end | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |     %% Generate the current pose | 
					
						
							|  |  |  |     currentPoseKey = symbol('x', i); | 
					
						
							|  |  |  |     currentPose = imuSimulator.getPoseFromGtScenario(gtScenario,scenarioInd); | 
					
						
							| 
									
										
										
										
											2014-05-16 03:57:22 +08:00
										 |  |  |      | 
					
						
							|  |  |  |     %% FOR TESTING - this is currently moved to getPoseFromGtScenario | 
					
						
							|  |  |  |     %currentPose = currentPose.compose(metadata.camera.bodyPoseCamera); | 
					
						
							|  |  |  |     %currentPose = currentPose.compose(Pose3.Expmap([-pi/2;0;0;0;0;0])); | 
					
						
							| 
									
										
										
										
											2014-05-15 22:01:53 +08:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |     % add to values | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  |     values.insert(currentPoseKey, currentPose); | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |     %% gt Between measurements | 
					
						
							|  |  |  |     if options.includeBetweenFactors == 1 && i > 0 | 
					
						
							| 
									
										
										
										
											2020-08-18 02:37:12 +08:00
										 |  |  |       prevPose = values.atPose3(currentPoseKey - 1); | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  |       deltaPose = prevPose.between(currentPose); | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |       measurements(i).deltaVector = Pose3.Logmap(deltaPose); | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |      | 
					
						
							|  |  |  |     %% gt IMU measurements | 
					
						
							|  |  |  |     if options.includeIMUFactors == 1 | 
					
						
							|  |  |  |       currentVelKey = symbol('v', i); | 
					
						
							|  |  |  |       currentBiasKey = symbol('b', i); | 
					
						
							| 
									
										
										
										
											2014-04-30 03:46:43 +08:00
										 |  |  |       deltaT = 1;   % amount of time between IMU measurements | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |       if i == 0 | 
					
						
							|  |  |  |         currentVel = [0 0 0]'; | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2014-04-18 04:08:38 +08:00
										 |  |  |         % integrate & store intermediate measurements        | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |         for j=1:options.subsampleStep % we integrate all the intermediate measurements | 
					
						
							| 
									
										
										
										
											2014-04-18 04:08:38 +08:00
										 |  |  |           previousScenarioInd = options.subsampleStep * (i-1) + 1; | 
					
						
							|  |  |  |           scenarioIndIMU1 = previousScenarioInd+j-1; | 
					
						
							|  |  |  |           scenarioIndIMU2 = previousScenarioInd+j; | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |           IMUPose1 = imuSimulator.getPoseFromGtScenario(gtScenario,scenarioIndIMU1); | 
					
						
							|  |  |  |           IMUPose2 = imuSimulator.getPoseFromGtScenario(gtScenario,scenarioIndIMU2); | 
					
						
							| 
									
										
										
										
											2014-05-16 03:57:22 +08:00
										 |  |  |           IMURot1 = IMUPose1.rotation.matrix; | 
					
						
							| 
									
										
										
										
											2014-04-18 04:14:32 +08:00
										 |  |  |                      | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |           IMUdeltaPose = IMUPose1.between(IMUPose2); | 
					
						
							|  |  |  |           IMUdeltaPoseVector     = Pose3.Logmap(IMUdeltaPose); | 
					
						
							|  |  |  |           IMUdeltaRotVector      = IMUdeltaPoseVector(1:3); | 
					
						
							| 
									
										
										
										
											2020-08-18 02:37:12 +08:00
										 |  |  |           IMUdeltaPositionVector = IMUPose2.translation - IMUPose1.translation; % translation in absolute frame | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |            | 
					
						
							|  |  |  |           measurements(i).imu(j).deltaT = deltaT; | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |           % gyro rate: Logmap(R_i' * R_i+1) / deltaT | 
					
						
							|  |  |  |           measurements(i).imu(j).gyro = IMUdeltaRotVector./deltaT; | 
					
						
							|  |  |  |            | 
					
						
							| 
									
										
										
										
											2014-04-18 04:00:18 +08:00
										 |  |  |           % deltaPij += deltaVij * deltaT + 0.5 * deltaRij.matrix() * biasHat.correctAccelerometer(measuredAcc) * deltaT*deltaT; | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |           % acc = (deltaPosition - initialVel * dT) * (2/dt^2) | 
					
						
							| 
									
										
										
										
											2014-05-16 03:57:22 +08:00
										 |  |  |           measurements(i).imu(j).accel = IMURot1' * (IMUdeltaPositionVector - currentVel.*deltaT).*(2/(deltaT*deltaT)); | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |            | 
					
						
							|  |  |  |           % Update velocity | 
					
						
							| 
									
										
										
										
											2014-05-16 03:57:22 +08:00
										 |  |  |           currentVel = currentVel + IMURot1 * measurements(i).imu(j).accel * deltaT; | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       % Add Values: velocity and bias | 
					
						
							| 
									
										
										
										
											2022-01-03 03:46:39 +08:00
										 |  |  |       values.insert(currentVelKey, currentVel); | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |       values.insert(currentBiasKey, metadata.imu.zeroBias); | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2014-04-24 00:39:47 +08:00
										 |  |  |     %% gt GPS measurements | 
					
						
							|  |  |  |     if options.includeGPSFactors == 1 && i > 0 | 
					
						
							| 
									
										
										
										
											2020-08-18 02:37:12 +08:00
										 |  |  |       gpsPositionVector = imuSimulator.getPoseFromGtScenario(gtScenario,scenarioInd).translation; | 
					
						
							| 
									
										
										
										
											2014-04-24 02:45:17 +08:00
										 |  |  |       measurements(i).gpsPositionVector = gpsPositionVector; | 
					
						
							| 
									
										
										
										
											2014-04-24 00:39:47 +08:00
										 |  |  |     end | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2014-05-09 03:27:32 +08:00
										 |  |  |     %% gt Camera measurements | 
					
						
							| 
									
										
										
										
											2014-05-15 22:01:53 +08:00
										 |  |  |     if options.includeCameraFactors == 1 && i > 0      | 
					
						
							|  |  |  |       % Create the camera based on the current pose and the pose of the | 
					
						
							|  |  |  |       % camera in the body | 
					
						
							|  |  |  |       cameraPose = currentPose.compose(metadata.camera.bodyPoseCamera); | 
					
						
							| 
									
										
										
										
											2020-02-22 08:42:55 +08:00
										 |  |  |       camera = PinholeCameraCal3_S2(cameraPose, metadata.camera.calibration); | 
					
						
							|  |  |  |       %camera = PinholeCameraCal3_S2(currentPose, metadata.camera.calibration); | 
					
						
							| 
									
										
										
										
											2014-05-15 22:01:53 +08:00
										 |  |  |        | 
					
						
							|  |  |  |       % Record measurements if the landmark is within visual range | 
					
						
							| 
									
										
										
										
											2014-05-09 03:27:32 +08:00
										 |  |  |       for j=1:length(metadata.camera.gtLandmarkPoints) | 
					
						
							| 
									
										
										
										
											2014-05-15 22:01:53 +08:00
										 |  |  |         distanceToLandmark = camera.pose.range(metadata.camera.gtLandmarkPoints(j)); | 
					
						
							|  |  |  |         if distanceToLandmark < metadata.camera.visualRange | 
					
						
							|  |  |  |           try | 
					
						
							|  |  |  |             z = camera.project(metadata.camera.gtLandmarkPoints(j)); | 
					
						
							|  |  |  |             measurements(i).landmarks(j) = z; | 
					
						
							|  |  |  |           catch | 
					
						
							| 
									
										
										
										
											2014-05-09 03:27:32 +08:00
										 |  |  |             % point is probably out of the camera's view | 
					
						
							| 
									
										
										
										
											2014-05-15 22:01:53 +08:00
										 |  |  |           end | 
					
						
							| 
									
										
										
										
											2014-05-09 03:27:32 +08:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-04-17 22:09:53 +08:00
										 |  |  |   fprintf('\n'); | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  | else | 
					
						
							| 
									
										
										
										
											2014-04-18 03:23:01 +08:00
										 |  |  |   error('Please use RealData') | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  |   %% Create a random trajectory as ground truth | 
					
						
							|  |  |  |   currentPose = Pose3; % initial pose  % initial pose | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   unsmooth_DP = 0.5; % controls smoothness on translation norm | 
					
						
							|  |  |  |   unsmooth_DR = 0.1; % controls smoothness on rotation norm | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   fprintf('\nCreating a random ground truth trajectory\n'); | 
					
						
							|  |  |  |   currentPoseKey = symbol('x', 0); | 
					
						
							|  |  |  |   values.insert(currentPoseKey, currentPose); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   for i=1:options.trajectoryLength | 
					
						
							|  |  |  |     % Update the pose key | 
					
						
							|  |  |  |     currentPoseKey = symbol('x', i); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     % Generate the new measurements | 
					
						
							|  |  |  |     gtDeltaPosition = unsmooth_DP*randn(3,1) + [20;0;0]; % create random vector with mean = [20 0 0] | 
					
						
							|  |  |  |     gtDeltaRotation = unsmooth_DR*randn(3,1) + [0;0;0]; % create random rotation with mean [0 0 0] | 
					
						
							|  |  |  |     measurements.deltaMatrix(i,:) = [gtDeltaRotation; gtDeltaPosition]; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     % Create the next pose | 
					
						
							|  |  |  |     deltaPose = Pose3.Expmap(measurements.deltaMatrix(i,:)'); | 
					
						
							|  |  |  |     currentPose = currentPose.compose(deltaPose); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     % Add the current pose as a value | 
					
						
							|  |  |  |     values.insert(currentPoseKey, currentPose); | 
					
						
							|  |  |  |   end  % end of random trajectory creation | 
					
						
							|  |  |  | end % end of else | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-18 02:11:18 +08:00
										 |  |  | end % end of function | 
					
						
							| 
									
										
										
										
											2014-04-17 03:01:12 +08:00
										 |  |  | 
 |