2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/**
  
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:55:26 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 *  @ file     Pose3SLAMExampleExpressions_BearingRangeWithTransform . cpp 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-05 00:12:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  @ brief    A  simultaneous  optimization  of  trajectory ,  landmarks  and  sensor - pose  with  respect  to  body - pose  using  bearing - range  measurements  done  with  Expressions 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 *  @ author   Thomas  Horstink 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ date     January  4 th ,  2019 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <gtsam/inference/Symbol.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <gtsam/geometry/BearingRange.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <gtsam/slam/expressions.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <gtsam/nonlinear/ExpressionFactorGraph.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <gtsam/nonlinear/LevenbergMarquardtOptimizer.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <gtsam/nonlinear/Values.h> 
  
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <examples/SFMdata.h> 
  
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  namespace  gtsam ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  BearingRange < Pose3 ,  Point3 >  BearingRange3D ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ************************************************************************* */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  main ( int  argc ,  char *  argv [ ] )  {  
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  // Move around so the whole state (including the sensor tf) is observable
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  Pose3  init_pose  =  Pose3 ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  Pose3  delta_pose1  =  Pose3 ( Rot3 ( ) . Yaw ( 2 * M_PI / 8 ) . Pitch ( M_PI / 8 ) ,  Point3 ( 1 ,  0 ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Pose3  delta_pose2  =  Pose3 ( Rot3 ( ) . Pitch ( - M_PI / 8 ) ,  Point3 ( 1 ,  0 ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Pose3  delta_pose3  =  Pose3 ( Rot3 ( ) . Yaw ( - 2 * M_PI / 8 ) ,  Point3 ( 1 ,  0 ,  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  steps  =  4 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  auto  poses   =  createPoses ( init_pose ,  delta_pose1 ,  steps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  poses2  =  createPoses ( init_pose ,  delta_pose2 ,  steps ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  poses3  =  createPoses ( init_pose ,  delta_pose3 ,  steps ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  // Concatenate poses to create trajectory
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  poses . insert (  poses . end ( ) ,  poses2 . begin ( ) ,  poses2 . end ( )  ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  poses . insert (  poses . end ( ) ,  poses3 . begin ( ) ,  poses3 . end ( )  ) ;   // std::vector of Pose3
 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  auto  points  =  createPoints ( ) ;                                // std::vector of Point3
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // (ground-truth) sensor pose in body frame, further an unknown variable
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Pose3  body_T_sensor_gt ( Rot3 : : RzRyRx ( - M_PI_2 ,  0.0 ,  - M_PI_2 ) ,  Point3 ( 0.25 ,  - 0.10 ,  1.0 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  // The graph
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  ExpressionFactorGraph  graph ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  // Specify uncertainty on first pose prior and also for between factor (simplicity reasons)
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  auto  poseNoise  =  noiseModel : : Diagonal : : Sigmas ( ( Vector ( 6 ) < < 0.3 , 0.3 , 0.3 , 0.1 , 0.1 , 0.1 ) . finished ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  // Uncertainty bearing range measurement;
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  bearingRangeNoise  =  noiseModel : : Diagonal : : Sigmas ( ( Vector ( 3 ) < < 0.01 , 0.03 , 0.05 ) . finished ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  // Expressions for body-frame at key 0 and sensor-tf
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  Pose3_  x_ ( ' x ' ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  Pose3_  body_T_sensor_ ( ' T ' ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  // Add a prior on the body-pose
 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  graph . addExpressionFactor ( x_ ,  poses [ 0 ] ,  poseNoise ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:53:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  // Simulated measurements from pose
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  for  ( size_t  i  =  0 ;  i  <  poses . size ( ) ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  world_T_sensor  =  poses [ i ] . compose ( body_T_sensor_gt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  j  =  0 ;  j  <  points . size ( ) ;  + + j )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      // This expression is the key feature of this example: it creates a differentiable expression of the measurement after being displaced by sensor transform.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      auto  prediction_  =  Expression < BearingRange3D > (  BearingRange3D : : Measure ,  Pose3_ ( ' x ' , i ) * body_T_sensor_ ,  Point3_ ( ' l ' , j ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      // Create a *perfect* measurement
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								      auto  measurement  =  BearingRange3D ( world_T_sensor . bearing ( points [ j ] ) ,  world_T_sensor . range ( points [ j ] ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:53:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								      // Add factor
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      graph . addExpressionFactor ( prediction_ ,  measurement ,  bearingRangeNoise ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:53:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    // and add a between factor to the graph
 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    if  ( i  >  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:53:50 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								      // And also we have a *perfect* measurement for the between factor.
 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      graph . addExpressionFactor ( between ( Pose3_ ( ' x ' ,  i - 1 ) , Pose3_ ( ' x ' ,  i ) ) ,  poses [ i - 1 ] . between ( poses [ i ] ) ,  poseNoise ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // Create perturbed initial
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Values  initial ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Pose3  delta ( Rot3 : : Rodrigues ( - 0.1 ,  0.2 ,  0.25 ) ,  Point3 ( 0.05 ,  - 0.10 ,  0.20 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for  ( size_t  i  =  0 ;  i  <  poses . size ( ) ;  + + i ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    initial . insert ( Symbol ( ' x ' ,  i ) ,  poses [ i ] . compose ( delta ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  for  ( size_t  j  =  0 ;  j  <  points . size ( ) ;  + + j ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    initial . insert < Point3 > ( Symbol ( ' l ' ,  j ) ,  points [ j ]  +  Point3 ( - 0.25 ,  0.20 ,  0.15 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 23:17:33 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  // Initialize body_T_sensor wrongly (because we do not know!)
 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-11 22:39:48 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								  initial . insert < Pose3 > ( Symbol ( ' T ' , 0 ) ,  Pose3 ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-04 18:31:41 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : cout  < <  " initial error:  "  < <  graph . error ( initial )  < <  std : : endl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Values  result  =  LevenbergMarquardtOptimizer ( graph ,  initial ) . optimize ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : cout  < <  " final error:  "  < <  graph . error ( result )  < <  std : : endl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  initial . at < Pose3 > ( Symbol ( ' T ' , 0 ) ) . print ( " \n Initial estimate body_T_sensor \n " ) ;  /* initial sensor_P_body estimate */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  result . at < Pose3 > ( Symbol ( ' T ' , 0 ) ) . print ( " \n Final estimate body_T_sensor \n " ) ;     /* optimized sensor_P_body estimate */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  body_T_sensor_gt . print ( " \n Ground truth body_T_sensor \n " ) ;                      /* sensor_P_body ground truth */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ************************************************************************* */