| 
									
										
										
										
											2014-11-25 04:14:59 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-11 22:39:48 +08:00
										 |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | 
					
						
							| 
									
										
										
										
											2014-11-25 04:14:59 +08:00
										 |  |  |  * 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------1------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2014-11-25 04:23:53 +08:00
										 |  |  |  * @file testCustomChartExpression.cpp | 
					
						
							| 
									
										
										
										
											2014-11-25 04:14:59 +08:00
										 |  |  |  * @date September 18, 2014 | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							|  |  |  |  * @author Paul Furgale | 
					
						
							|  |  |  |  * @brief unit tests for Block Automatic Differentiation | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gtsam_unstable/nonlinear/expressionTesting.h>
 | 
					
						
							|  |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							| 
									
										
										
										
											2023-01-24 02:18:24 +08:00
										 |  |  | #include <type_traits>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-25 04:14:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace gtsam; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-25 13:42:36 +08:00
										 |  |  | // A simple prototype custom chart that does two things:
 | 
					
						
							|  |  |  | // 1. it reduces the dimension of the variable being estimated
 | 
					
						
							|  |  |  | // 2. it scales the input to retract.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // The Jacobian of this chart is:
 | 
					
						
							|  |  |  | // [ 2  0 ]
 | 
					
						
							|  |  |  | // [ 0  3 ]
 | 
					
						
							|  |  |  | // [ 0  0 ]
 | 
					
						
							| 
									
										
										
										
											2014-11-25 04:14:59 +08:00
										 |  |  | struct ProjectionChart { | 
					
						
							|  |  |  |   typedef Eigen::Vector3d type; | 
					
						
							|  |  |  |   typedef Eigen::Vector2d vector; | 
					
						
							|  |  |  |   static vector local(const type& origin, const type& other) { | 
					
						
							|  |  |  |     return (other - origin).head<2>(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   static type retract(const type& origin, const vector& d) { | 
					
						
							|  |  |  |     return origin + Eigen::Vector3d(2.0 * d[0], 3.0 * d[1], 0.0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   static int getDimension(const type& origin) { | 
					
						
							|  |  |  |     return 2; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | namespace traits { | 
					
						
							| 
									
										
										
										
											2023-01-24 02:18:24 +08:00
										 |  |  | template<> struct is_chart<ProjectionChart> : public std::true_type {}; | 
					
						
							|  |  |  | template<> struct dimension<ProjectionChart> : public std::integral_constant<int, 2> {}; | 
					
						
							| 
									
										
										
										
											2014-11-25 04:14:59 +08:00
										 |  |  | }  // namespace traits
 | 
					
						
							|  |  |  | }  // namespace gtsam
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST(ExpressionCustomChart, projection) { | 
					
						
							|  |  |  |   // Create expression
 | 
					
						
							|  |  |  |   Expression<Eigen::Vector3d> point(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Eigen::Vector3d pval(1.0, 2.0, 3.0); | 
					
						
							|  |  |  |   Values standard; | 
					
						
							|  |  |  |   standard.insert(1, pval); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Values custom; | 
					
						
							|  |  |  |   custom.insert(1, pval, ProjectionChart()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Eigen::Vector3d pstandard = point.value(standard); | 
					
						
							|  |  |  |   Eigen::Vector3d pcustom = point.value(custom); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // The values should be the same.
 | 
					
						
							|  |  |  |   EXPECT(assert_equal(Matrix(pstandard), Matrix(pcustom), 1e-10)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT_LONGS_EQUAL(3, standard.at(1).dim()); | 
					
						
							|  |  |  |   VectorValues vstandard = standard.zeroVectors(); | 
					
						
							|  |  |  |   EXPECT_LONGS_EQUAL(3, vstandard.at(1).size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT_LONGS_EQUAL(2, custom.at(1).dim()); | 
					
						
							|  |  |  |   VectorValues vcustom = custom.zeroVectors(); | 
					
						
							|  |  |  |   EXPECT_LONGS_EQUAL(2, vcustom.at(1).size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ExpressionFactor<Eigen::Vector3d> f(noiseModel::Unit::Create(pval.size()), pval, point); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-18 06:05:12 +08:00
										 |  |  |   std::shared_ptr<GaussianFactor> gfstandard = f.linearize(standard); | 
					
						
							|  |  |  |   std::shared_ptr<JacobianFactor> jfstandard = //
 | 
					
						
							| 
									
										
										
										
											2023-01-18 06:39:55 +08:00
										 |  |  |       std::dynamic_pointer_cast<JacobianFactor>(gfstandard); | 
					
						
							| 
									
										
										
										
											2014-11-25 04:14:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   typedef std::pair<Eigen::MatrixXd, Eigen::VectorXd> Jacobian; | 
					
						
							|  |  |  |   Jacobian Jstandard = jfstandard->jacobianUnweighted(); | 
					
						
							|  |  |  |   EXPECT(assert_equal(Eigen::Matrix3d::Identity(), Jstandard.first, 1e-10)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-18 06:05:12 +08:00
										 |  |  |   std::shared_ptr<GaussianFactor> gfcustom = f.linearize(custom); | 
					
						
							|  |  |  |   std::shared_ptr<JacobianFactor> jfcustom = //
 | 
					
						
							| 
									
										
										
										
											2023-01-18 06:39:55 +08:00
										 |  |  |       std::dynamic_pointer_cast<JacobianFactor>(gfcustom); | 
					
						
							| 
									
										
										
										
											2014-11-25 04:14:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Eigen::MatrixXd expectedJacobian = Eigen::MatrixXd::Zero(3,2); | 
					
						
							|  |  |  |   expectedJacobian(0,0) = 2.0; | 
					
						
							|  |  |  |   expectedJacobian(1,1) = 3.0; | 
					
						
							|  |  |  |   Jacobian Jcustom = jfcustom->jacobianUnweighted(); | 
					
						
							|  |  |  |   EXPECT(assert_equal(expectedJacobian, Jcustom.first, 1e-10)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Amazingly, the finite differences get the expected Jacobian right.
 | 
					
						
							|  |  |  |   const double fd_step = 1e-5; | 
					
						
							|  |  |  |   const double tolerance = 1e-5; | 
					
						
							|  |  |  |   EXPECT_CORRECT_EXPRESSION_JACOBIANS(point, custom, fd_step, tolerance); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main() { | 
					
						
							|  |  |  |   TestResult tr; | 
					
						
							|  |  |  |   return TestRegistry::runAllTests(tr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | 
 |