first pass at IMUKittiExampleGPS.py
							parent
							
								
									158d279d59
								
							
						
					
					
						commit
						f6a432961a
					
				|  | @ -0,0 +1,227 @@ | |||
| """ | ||||
| Example of application of ISAM2 for GPS-aided navigation on the KITTI VISION BENCHMARK SUITE | ||||
| """ | ||||
| import argparse | ||||
| from typing import List | ||||
| 
 | ||||
| import gtsam | ||||
| import numpy as np | ||||
| from gtsam import Pose3, Rot3, noiseModel | ||||
| from gtsam.symbol_shorthand import B, V, X | ||||
| 
 | ||||
| 
 | ||||
| class KittiCalibration: | ||||
|     def __init__(self, bodyTimu: gtsam.Pose3): | ||||
|         self.bodyTimu = bodyTimu | ||||
| 
 | ||||
| 
 | ||||
| class ImuMeasurement: | ||||
|     def __init__(self, time, dt, accelerometer, gyroscope): | ||||
|         pass | ||||
| 
 | ||||
| 
 | ||||
| class GpsMeasurement: | ||||
|     def __init__(self, time, position: gtsam.Point3): | ||||
|         self.time = time | ||||
|         self.position = position | ||||
| 
 | ||||
| 
 | ||||
| def lodKittiData(): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| def parse_args(): | ||||
|     parser = argparse.ArgumentParser() | ||||
|     return parser.parse_args() | ||||
| 
 | ||||
| 
 | ||||
| def getImuParams(kitti_calibration): | ||||
|     GRAVITY = 9.8 | ||||
|     w_coriolis = np.zeros(3) | ||||
| 
 | ||||
|     # Set IMU preintegration parameters | ||||
|     measured_acc_cov = np.eye(3) * np.power( | ||||
|         kitti_calibration.accelerometer_sigma, 2) | ||||
|     measured_omega_cov = np.eye(3) * np.powwe( | ||||
|         kitti_calibration.gyroscope_sigma, 2) | ||||
|     # error committed in integrating position from velocities | ||||
|     integration_error_cov = np.eye(3) * np.power( | ||||
|         kitti_calibration.integration_sigma, 2) | ||||
| 
 | ||||
|     imu_params = gtsam.PreintegrationParams.MakeSharedU(GRAVITY) | ||||
|     imu_params.accelerometerCovariance = measured_acc_cov  # acc white noise in continuous | ||||
|     imu_params.integrationCovariance = integration_error_cov  # integration uncertainty continuous | ||||
|     imu_params.gyroscopeCovariance = measured_omega_cov  # gyro white noise in continuous | ||||
|     imu_params.omegaCoriolis = w_coriolis | ||||
| 
 | ||||
|     return imu_params | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     args = parse_args() | ||||
|     kitti_calibration, imu_measurements, gps_measurements = lodKittiData() | ||||
| 
 | ||||
|     if kitti_calibration.bodyTimu != gtsam.Pose3: | ||||
|         raise ValueError( | ||||
|             "Currently only support IMUinBody is identity, i.e. IMU and body frame are the same" | ||||
|         ) | ||||
| 
 | ||||
|     # Configure different variables | ||||
|     first_gps_pose = 1 | ||||
|     gps_skip = 10 | ||||
| 
 | ||||
|     # Configure noise models | ||||
|     noise_model_gps = noiseModel.Diagonal.Precisions( | ||||
|         np.asarray([0, 0, 0, 1.0 / 0.07, 1.0 / 0.07, 1.0 / 0.07])) | ||||
| 
 | ||||
|     # Set initial conditions for the estimated trajectory | ||||
|     # initial pose is the reference frame (navigation frame) | ||||
|     current_pose_global = Pose3(Rot3(), | ||||
|                                 gps_measurements[first_gps_pose].position) | ||||
|     # the vehicle is stationary at the beginning at position 0,0,0 | ||||
|     current_velocity_global = np.zeros(3) | ||||
|     current_bias = gtsam.imuBias.ConstantBias()  # init with zero bias | ||||
| 
 | ||||
|     sigma_init_x = noiseModel.Diagonal.Precisions( | ||||
|         np.asarray([0, 0, 0, 1, 1, 1])) | ||||
|     sigma_init_v = noiseModel.Diagonal.Sigmas(np.ones(3) * 1000.0) | ||||
|     sigma_init_b = noiseModel.Diagonal.Sigmas( | ||||
|         np.asarray([0.1, 0.1, 0.1, 5.00e-05, 5.00e-05, 5.00e-05])) | ||||
| 
 | ||||
|     imu_params = getImuParams() | ||||
| 
 | ||||
|     # Set ISAM2 parameters and create ISAM2 solver object | ||||
|     isam_params = gtsam.ISAM2Params() | ||||
|     isam_params.setFactorization("CHOLESKY") | ||||
|     isam_params.setRelinearizeSkip(10) | ||||
| 
 | ||||
|     isam = gtsam.ISAM2(isam_params) | ||||
| 
 | ||||
|     # Create the factor graph and values object that will store new factors and | ||||
|     # values to add to the incremental graph | ||||
|     new_factors = gtsam.NonlinearFactorGraph() | ||||
|     new_values = gtsam.Values( | ||||
|     )  # values storing the initial estimates of new nodes in the factor graph | ||||
| 
 | ||||
|     # Main loop: | ||||
|     # (1) we read the measurements | ||||
|     # (2) we create the corresponding factors in the graph | ||||
|     # (3) we solve the graph to obtain and optimal estimate of robot trajectory | ||||
|     print( | ||||
|         "-- Starting main loop: inference is performed at each time step, but we plot trajectory every 10 steps\n" | ||||
|     ) | ||||
|     j = 0 | ||||
|     for i in range(first_gps_pose, len(gps_measurements) - 1): | ||||
|         # At each non=IMU measurement we initialize a new node in the graph | ||||
|         current_pose_key = X(i) | ||||
|         current_vel_key = V(i) | ||||
|         current_bias_key = B(i) | ||||
|         t = gps_measurements[i].time | ||||
| 
 | ||||
|         if i == first_gps_pose: | ||||
|             # Create initial estimate and prior on initial pose, velocity, and biases | ||||
|             new_values.insert(current_pose_key, current_pose_global) | ||||
|             new_values.insert(current_vel_key, current_velocity_global) | ||||
|             new_values.insert(current_bias_key, current_bias) | ||||
| 
 | ||||
|             new_factors.addPriorPose3(current_pose_key, current_pose_global, | ||||
|                                       sigma_init_x) | ||||
|             new_factors.addPriorVector(current_vel_key, | ||||
|                                        current_velocity_global, sigma_init_v) | ||||
|             new_factors.addPriorConstantBias(current_bias_key, current_bias, | ||||
|                                              sigma_init_b) | ||||
|         else: | ||||
|             t_previous = gps_measurements[i - 1].time | ||||
| 
 | ||||
|             # Summarize IMU data between the previous GPS measurement and now | ||||
|             current_summarized_measurement = gtsam.PreintegratedImuMeasurements( | ||||
|                 imu_params, current_bias) | ||||
| 
 | ||||
|             included_imu_measurement_count = 0 | ||||
|             while (j < imu_measurements.size() | ||||
|                    and imu_measurements[j].time <= t): | ||||
|                 if imu_measurements[j].time >= t_previous: | ||||
|                     current_summarized_measurement.integrateMeasurement( | ||||
|                         imu_measurements[j].accelerometer, | ||||
|                         imu_measurements[j].gyroscope, imu_measurements[j].dt) | ||||
|                     included_imu_measurement_count += 1 | ||||
|                 j += 1 | ||||
| 
 | ||||
|             # Create IMU factor | ||||
|             previous_pose_key = X(i - 1) | ||||
|             previous_vel_key = V(i - 1) | ||||
|             previous_bias_key = B(i - 1) | ||||
| 
 | ||||
|             new_factors.push_back( | ||||
|                 gtsam.ImuFactor > (previous_pose_key, previous_vel_key, | ||||
|                                    current_pose_key, current_vel_key, | ||||
|                                    previous_bias_key, | ||||
|                                    current_summarized_measurement)) | ||||
| 
 | ||||
|             # Bias evolution as given in the IMU metadata | ||||
|             sigma_between_b = noiseModel.Diagonal.Sigmas( | ||||
|                 np.asarray([ | ||||
|                     np.sqrt(included_imu_measurement_count) * | ||||
|                     kitti_calibration.accelerometer_bias_sigma | ||||
|                 ] * 3 + [ | ||||
|                     np.sqrt(included_imu_measurement_count) * | ||||
|                     kitti_calibration.gyroscope_bias_sigma | ||||
|                 ] * 3)) | ||||
| 
 | ||||
|             new_factors.push_back( | ||||
|                 gtsam.BetweenFactorConstantBias(previous_bias_key, | ||||
|                                                 current_bias_key, | ||||
|                                                 gtsam.imuBias.ConstantBias(), | ||||
|                                                 sigma_between_b)) | ||||
| 
 | ||||
|             # Create GPS factor | ||||
|             gps_pose = Pose3(current_pose_global.rotation(), | ||||
|                              gps_measurements[i].position) | ||||
|             if (i % gps_skip) == 0: | ||||
|                 new_factors.addPriorPose3(current_pose_key, gps_pose, | ||||
|                                           noise_model_gps) | ||||
|                 new_values.insert(current_pose_key, gps_pose) | ||||
| 
 | ||||
|                 print( | ||||
|                     "################ POSE INCLUDED AT TIME %lf ################\n", | ||||
|                     t) | ||||
|                 print(gps_pose.translation(), "\n") | ||||
|             else: | ||||
|                 new_values.insert(current_pose_key, current_pose_global) | ||||
| 
 | ||||
|             # Add initial values for velocity and bias based on the previous | ||||
|             # estimates | ||||
|             new_values.insert(current_vel_key, current_velocity_global) | ||||
|             new_values.insert(current_bias_key, current_bias) | ||||
| 
 | ||||
|             # Update solver | ||||
|             # ======================================================================= | ||||
|             # We accumulate 2*GPSskip GPS measurements before updating the solver at | ||||
|             # first so that the heading becomes observable. | ||||
|             if i > (first_gps_pose + 2 * gps_skip): | ||||
|                 print( | ||||
|                     "################ NEW FACTORS AT TIME %lf ################\n", | ||||
|                     t) | ||||
|                 new_factors.print() | ||||
| 
 | ||||
|                 isam.update(new_factors, new_values) | ||||
| 
 | ||||
|                 # Reset the newFactors and newValues list | ||||
|                 new_factors.resize(0) | ||||
|                 new_values.clear() | ||||
| 
 | ||||
|                 # Extract the result/current estimates | ||||
|                 result = isam.calculateEstimate() | ||||
| 
 | ||||
|                 current_pose_global = result.atPose3(current_pose_key) | ||||
|                 current_velocity_global = result.atVector(current_vel_key) | ||||
|                 current_bias = result.atConstantBias(current_bias_key) | ||||
| 
 | ||||
|                 print("\n################ POSE AT TIME %lf ################\n", | ||||
|                       t) | ||||
|                 current_pose_global.print() | ||||
|                 print("\n\n") | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
		Loading…
	
		Reference in New Issue