| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation,  | 
					
						
							|  |  |  |  * Atlanta, Georgia 30332-0415 | 
					
						
							|  |  |  |  * All Rights Reserved | 
					
						
							|  |  |  |  * Authors: Frank Dellaert, et al. (see THANKS for the full author list) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * See LICENSE for the license information | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * @file Expression.h | 
					
						
							|  |  |  |  * @date September 18, 2014 | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							|  |  |  |  * @author Paul Furgale | 
					
						
							|  |  |  |  * @brief Expressions for Block Automatic Differentiation | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-30 18:34:03 +08:00
										 |  |  | #include <gtsam_unstable/nonlinear/Expression.h>
 | 
					
						
							| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  | #include <gtsam/nonlinear/NonlinearFactor.h>
 | 
					
						
							| 
									
										
										
										
											2014-10-02 17:01:39 +08:00
										 |  |  | #include <gtsam/base/Testable.h>
 | 
					
						
							| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  |  * Factor that supports arbitrary expressions via AD | 
					
						
							| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | template<class T> | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  | class ExpressionFactor: public NoiseModelFactor { | 
					
						
							| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const T measurement_; | 
					
						
							|  |  |  |   const Expression<T> expression_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Constructor
 | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  |   ExpressionFactor(const SharedNoiseModel& noiseModel, //
 | 
					
						
							| 
									
										
										
										
											2014-10-02 17:01:39 +08:00
										 |  |  |       const T& measurement, const Expression<T>& expression) : | 
					
						
							|  |  |  |       NoiseModelFactor(noiseModel, expression.keys()), //
 | 
					
						
							| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  |       measurement_(measurement), expression_(expression) { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-02 17:01:39 +08:00
										 |  |  |   /**
 | 
					
						
							|  |  |  |    * Error function *without* the NoiseModel, \f$ z-h(x) \f$. | 
					
						
							|  |  |  |    * We override this method to provide | 
					
						
							|  |  |  |    * both the function evaluation and its derivative(s) in H. | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   virtual Vector unwhitenedError(const Values& x, | 
					
						
							|  |  |  |       boost::optional<std::vector<Matrix>&> H = boost::none) const { | 
					
						
							|  |  |  |     if (H) { | 
					
						
							| 
									
										
										
										
											2014-10-02 19:30:16 +08:00
										 |  |  |       assert(H->size()==size()); | 
					
						
							| 
									
										
										
										
											2014-10-13 02:16:08 +08:00
										 |  |  |       JacobianMap jacobians; | 
					
						
							|  |  |  |       T value = expression_.value(x, jacobians); | 
					
						
							| 
									
										
										
										
											2014-10-06 18:13:52 +08:00
										 |  |  |       // move terms to H, which is pre-allocated to correct size
 | 
					
						
							| 
									
										
										
										
											2014-10-13 02:16:08 +08:00
										 |  |  |       move(jacobians, *H); | 
					
						
							|  |  |  |       return measurement_.localCoordinates(value); | 
					
						
							| 
									
										
										
										
											2014-10-02 17:01:39 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |       const T& value = expression_.value(x); | 
					
						
							|  |  |  |       return measurement_.localCoordinates(value); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-11 23:05:53 +08:00
										 |  |  |   virtual boost::shared_ptr<GaussianFactor> linearize(const Values& x) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Only linearize if the factor is active
 | 
					
						
							|  |  |  |     if (!this->active(x)) | 
					
						
							|  |  |  |       return boost::shared_ptr<JacobianFactor>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Evaluate error to get Jacobians and RHS vector b
 | 
					
						
							| 
									
										
										
										
											2014-10-13 02:16:08 +08:00
										 |  |  |     JacobianMap terms; | 
					
						
							|  |  |  |     T value = expression_.value(x, terms); | 
					
						
							|  |  |  |     Vector b = -measurement_.localCoordinates(value); | 
					
						
							| 
									
										
										
										
											2014-10-11 23:05:53 +08:00
										 |  |  |     // check(noiseModel_, b); // TODO: use, but defined in NonlinearFactor.cpp
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Whiten the corresponding system now
 | 
					
						
							|  |  |  |     // TODO ! this->noiseModel_->WhitenSystem(A, b);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Terms, needed to create JacobianFactor below, are already here!
 | 
					
						
							| 
									
										
										
										
											2014-10-12 17:05:43 +08:00
										 |  |  |     size_t n = terms.size(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Get dimensions of matrices
 | 
					
						
							|  |  |  |     std::vector<size_t> dimensions; | 
					
						
							|  |  |  |     dimensions.reserve(n); | 
					
						
							|  |  |  |     std::vector<Key> keys; | 
					
						
							|  |  |  |     keys.reserve(n); | 
					
						
							|  |  |  |     for (JacobianMap::const_iterator it = terms.begin(); it != terms.end(); | 
					
						
							|  |  |  |         ++it) { | 
					
						
							|  |  |  |       const std::pair<Key, Matrix>& term = *it; | 
					
						
							|  |  |  |       Key key = term.first; | 
					
						
							|  |  |  |       const Matrix& Ai = term.second; | 
					
						
							|  |  |  |       dimensions.push_back(Ai.cols()); | 
					
						
							|  |  |  |       keys.push_back(key); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Construct block matrix
 | 
					
						
							|  |  |  |     VerticalBlockMatrix Ab(dimensions, b.size(), true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check and add terms
 | 
					
						
							|  |  |  |     DenseIndex i = 0; // For block index
 | 
					
						
							|  |  |  |     for (JacobianMap::const_iterator it = terms.begin(); it != terms.end(); | 
					
						
							|  |  |  |         ++it) { | 
					
						
							|  |  |  |       const std::pair<Key, Matrix>& term = *it; | 
					
						
							|  |  |  |       const Matrix& Ai = term.second; | 
					
						
							|  |  |  |       Ab(i++) = Ai; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Ab(n).col(0) = b; | 
					
						
							| 
									
										
										
										
											2014-10-11 23:05:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // TODO pass unwhitened + noise model to Gaussian factor
 | 
					
						
							|  |  |  |     // For now, only linearized constrained factors have noise model at linear level!!!
 | 
					
						
							|  |  |  |     noiseModel::Constrained::shared_ptr constrained = //
 | 
					
						
							|  |  |  |         boost::dynamic_pointer_cast<noiseModel::Constrained>(this->noiseModel_); | 
					
						
							|  |  |  |     if (constrained) { | 
					
						
							| 
									
										
										
										
											2014-10-12 17:05:43 +08:00
										 |  |  |       return boost::make_shared<JacobianFactor>(keys, Ab, constrained->unit()); | 
					
						
							| 
									
										
										
										
											2014-10-11 23:05:53 +08:00
										 |  |  |     } else | 
					
						
							| 
									
										
										
										
											2014-10-12 17:05:43 +08:00
										 |  |  |       return boost::make_shared<JacobianFactor>(keys, Ab); | 
					
						
							| 
									
										
										
										
											2014-10-11 23:05:53 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2014-10-09 19:00:56 +08:00
										 |  |  | // ExpressionFactor
 | 
					
						
							| 
									
										
										
										
											2014-09-30 18:30:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |