testRangeFactor.cpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
19 #include <gtsam/sam/RangeFactor.h>
20 #include <gtsam/geometry/Pose3.h>
21 #include <gtsam/geometry/Pose2.h>
23 #include <gtsam/geometry/Cal3_S2.h>
26 
28 
29 using namespace std::placeholders;
30 using namespace std;
31 using namespace gtsam;
32 
37 
38 // Keys are deliberately *not* in sorted order to test that case.
39 namespace {
40 // Create a noise model for the pixel error
41 static SharedNoiseModel model(noiseModel::Unit::Create(1));
42 
43 constexpr Key poseKey(2);
44 constexpr Key pointKey(1);
45 constexpr double measurement(10.0);
46 
47 Vector factorError2D(const Pose2& pose, const Point2& point,
48  const RangeFactor2D& factor) {
49  return factor.evaluateError(pose, point);
50 }
51 
52 Vector factorError3D(const Pose3& pose, const Point3& point,
53  const RangeFactor3D& factor) {
54  return factor.evaluateError(pose, point);
55 }
56 
57 Vector factorErrorWithTransform2D(const Pose2& pose, const Point2& point,
58  const RangeFactorWithTransform2D& factor) {
59  return factor.evaluateError(pose, point);
60 }
61 
62 Vector factorErrorWithTransform3D(const Pose3& pose, const Point3& point,
63  const RangeFactorWithTransform3D& factor) {
64  return factor.evaluateError(pose, point);
65 }
66 } // namespace
67 
68 /* ************************************************************************* */
69 TEST( RangeFactor, Constructor) {
72 }
73 
74 /* ************************************************************************* */
75 TEST( RangeFactor, ConstructorWithTransform) {
76  Pose2 body_P_sensor_2D(0.25, -0.10, -M_PI_2);
77  Pose3 body_P_sensor_3D(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2),
78  Point3(0.25, -0.10, 1.0));
79 
81  body_P_sensor_2D);
82  KeyVector expected {2, 1};
83  CHECK(factor2D.keys() == expected);
85  body_P_sensor_3D);
86  CHECK(factor3D.keys() == expected);
87 }
88 
89 /* ************************************************************************* */
90 TEST( RangeFactor, Equals ) {
91  // Create two identical factors and make sure they're equal
94  CHECK(assert_equal(factor2D_1, factor2D_2));
95 
98  CHECK(assert_equal(factor3D_1, factor3D_2));
99 }
100 
101 /* ************************************************************************* */
102 TEST( RangeFactor, EqualsWithTransform ) {
103  // Create two identical factors and make sure they're equal
104  Pose2 body_P_sensor_2D(0.25, -0.10, -M_PI_2);
105  Pose3 body_P_sensor_3D(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2),
106  Point3(0.25, -0.10, 1.0));
107 
109  body_P_sensor_2D);
111  body_P_sensor_2D);
112  CHECK(assert_equal(factor2D_1, factor2D_2));
113 
115  body_P_sensor_3D);
117  body_P_sensor_3D);
118  CHECK(assert_equal(factor3D_1, factor3D_2));
119 }
120 /* ************************************************************************* */
121 TEST( RangeFactor, Error2D ) {
122  // Create a factor
124 
125  // Set the linearization point
126  Pose2 pose(1.0, 2.0, 0.57);
127  Point2 point(-4.0, 11.0);
128 
129  // Use the factor to calculate the error
130  Vector actualError(factor.unwhitenedError({{poseKey, genericValue(pose)}, {pointKey, genericValue(point)}}));
131 
132  // The expected error is ||(5.0, 9.0)|| - 10.0 = 0.295630141 meter / UnitCovariance
133  Vector expectedError = (Vector(1) << 0.295630141).finished();
134 
135  // Verify we get the expected error
136  CHECK(assert_equal(expectedError, actualError, 1e-9));
137 }
138 
139 /* ************************************************************************* */
140 TEST( RangeFactor, Error2DWithTransform ) {
141  // Create a factor
142  Pose2 body_P_sensor(0.25, -0.10, -M_PI_2);
144  body_P_sensor);
145 
146  // Set the linearization point
147  Rot2 R(0.57);
148  Point2 t = Point2(1.0, 2.0) - R.rotate(body_P_sensor.translation());
149  Pose2 pose(R, t);
150  Point2 point(-4.0, 11.0);
151 
152  // Use the factor to calculate the error
153  Vector actualError(factor.unwhitenedError({{poseKey, genericValue(pose)}, {pointKey, genericValue(point)}}));
154 
155  // The expected error is ||(5.0, 9.0)|| - 10.0 = 0.295630141 meter / UnitCovariance
156  Vector expectedError = (Vector(1) << 0.295630141).finished();
157 
158  // Verify we get the expected error
159  CHECK(assert_equal(expectedError, actualError, 1e-9));
160 }
161 
162 /* ************************************************************************* */
163 TEST( RangeFactor, Error3D ) {
164  // Create a factor
166 
167  // Set the linearization point
168  Pose3 pose(Rot3::RzRyRx(0.2, -0.3, 1.75), Point3(1.0, 2.0, -3.0));
169  Point3 point(-2.0, 11.0, 1.0);
170 
171  // Use the factor to calculate the error
172  Vector actualError(factor.unwhitenedError({{poseKey, genericValue(pose)}, {pointKey, genericValue(point)}}));
173 
174  // The expected error is ||(3.0, 9.0, 4.0)|| - 10.0 = 0.295630141 meter / UnitCovariance
175  Vector expectedError = (Vector(1) << 0.295630141).finished();
176 
177  // Verify we get the expected error
178  CHECK(assert_equal(expectedError, actualError, 1e-9));
179 }
180 
181 /* ************************************************************************* */
182 TEST( RangeFactor, Error3DWithTransform ) {
183  // Create a factor
184  Pose3 body_P_sensor(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2),
185  Point3(0.25, -0.10, 1.0));
187  body_P_sensor);
188 
189  // Set the linearization point
190  Rot3 R = Rot3::RzRyRx(0.2, -0.3, 1.75);
191  Point3 t = Point3(1.0, 2.0, -3.0) - R.rotate(body_P_sensor.translation());
192  Pose3 pose(R, t);
193  Point3 point(-2.0, 11.0, 1.0);
194 
195  // Use the factor to calculate the error
196  Vector actualError(factor.unwhitenedError({{poseKey, genericValue(pose)}, {pointKey, genericValue(point)}}));
197 
198  // The expected error is ||(3.0, 9.0, 4.0)|| - 10.0 = 0.295630141 meter / UnitCovariance
199  Vector expectedError = (Vector(1) << 0.295630141).finished();
200 
201  // Verify we get the expected error
202  CHECK(assert_equal(expectedError, actualError, 1e-9));
203 }
204 
205 /* ************************************************************************* */
206 TEST( RangeFactor, Jacobian2D ) {
207  // Create a factor
209 
210  // Set the linearization point
211  Pose2 pose(1.0, 2.0, 0.57);
212  Point2 point(-4.0, 11.0);
213 
214  // Use the factor to calculate the Jacobians
215  Matrix H1Actual, H2Actual;
216  factor.evaluateError(pose, point, &H1Actual, &H2Actual);
217 
218  // Use numerical derivatives to calculate the Jacobians
219  Matrix H1Expected, H2Expected;
220  H1Expected = numericalDerivative11<Vector, Pose2>(
221  std::bind(&factorError2D, std::placeholders::_1, point, factor), pose);
222  H2Expected = numericalDerivative11<Vector, Point2>(
223  std::bind(&factorError2D, pose, std::placeholders::_1, factor), point);
224 
225  // Verify the Jacobians are correct
226  CHECK(assert_equal(H1Expected, H1Actual, 1e-9));
227  CHECK(assert_equal(H2Expected, H2Actual, 1e-9));
228 }
229 
230 /* ************************************************************************* */
231 TEST( RangeFactor, Jacobian2DWithTransform ) {
232  // Create a factor
233  Pose2 body_P_sensor(0.25, -0.10, -M_PI_2);
235  body_P_sensor);
236 
237  // Set the linearization point
238  Rot2 R(0.57);
239  Point2 t = Point2(1.0, 2.0) - R.rotate(body_P_sensor.translation());
240  Pose2 pose(R, t);
241  Point2 point(-4.0, 11.0);
242 
243  // Use the factor to calculate the Jacobians
244  std::vector<Matrix> actualHs(2);
245  factor.unwhitenedError({{poseKey, genericValue(pose)}, {pointKey, genericValue(point)}}, actualHs);
246  const Matrix& H1Actual = actualHs.at(0);
247  const Matrix& H2Actual = actualHs.at(1);
248 
249  // Use numerical derivatives to calculate the Jacobians
250  Matrix H1Expected, H2Expected;
251  H1Expected = numericalDerivative11<Vector, Pose2>(
252  std::bind(&factorErrorWithTransform2D, std::placeholders::_1, point, factor), pose);
253  H2Expected = numericalDerivative11<Vector, Point2>(
254  std::bind(&factorErrorWithTransform2D, pose, std::placeholders::_1, factor), point);
255 
256  // Verify the Jacobians are correct
257  CHECK(assert_equal(H1Expected, H1Actual, 1e-9));
258  CHECK(assert_equal(H2Expected, H2Actual, 1e-9));
259 }
260 
261 /* ************************************************************************* */
262 TEST( RangeFactor, Jacobian3D ) {
263  // Create a factor
265 
266  // Set the linearization point
267  Pose3 pose(Rot3::RzRyRx(0.2, -0.3, 1.75), Point3(1.0, 2.0, -3.0));
268  Point3 point(-2.0, 11.0, 1.0);
269 
270  // Use the factor to calculate the Jacobians
271  std::vector<Matrix> actualHs(2);
272  factor.unwhitenedError({{poseKey, genericValue(pose)}, {pointKey, genericValue(point)}}, actualHs);
273  const Matrix& H1Actual = actualHs.at(0);
274  const Matrix& H2Actual = actualHs.at(1);
275 
276  // Use numerical derivatives to calculate the Jacobians
277  Matrix H1Expected, H2Expected;
278  H1Expected = numericalDerivative11<Vector, Pose3>(
279  std::bind(&factorError3D, std::placeholders::_1, point, factor), pose);
280  H2Expected = numericalDerivative11<Vector, Point3>(
281  std::bind(&factorError3D, pose, std::placeholders::_1, factor), point);
282 
283  // Verify the Jacobians are correct
284  CHECK(assert_equal(H1Expected, H1Actual, 1e-9));
285  CHECK(assert_equal(H2Expected, H2Actual, 1e-9));
286 }
287 
288 /* ************************************************************************* */
289 TEST( RangeFactor, Jacobian3DWithTransform ) {
290  // Create a factor
291  Pose3 body_P_sensor(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2),
292  Point3(0.25, -0.10, 1.0));
294  body_P_sensor);
295 
296  // Set the linearization point
297  Rot3 R = Rot3::RzRyRx(0.2, -0.3, 1.75);
298  Point3 t = Point3(1.0, 2.0, -3.0) - R.rotate(body_P_sensor.translation());
299  Pose3 pose(R, t);
300  Point3 point(-2.0, 11.0, 1.0);
301 
302  // Use the factor to calculate the Jacobians
303  std::vector<Matrix> actualHs(2);
304  factor.unwhitenedError({{poseKey, genericValue(pose)}, {pointKey, genericValue(point)}}, actualHs);
305  const Matrix& H1Actual = actualHs.at(0);
306  const Matrix& H2Actual = actualHs.at(1);
307 
308  // Use numerical derivatives to calculate the Jacobians
309  Matrix H1Expected, H2Expected;
310  H1Expected = numericalDerivative11<Vector, Pose3>(
311  std::bind(&factorErrorWithTransform3D, std::placeholders::_1, point, factor), pose);
312  H2Expected = numericalDerivative11<Vector, Point3>(
313  std::bind(&factorErrorWithTransform3D, pose, std::placeholders::_1, factor), point);
314 
315  // Verify the Jacobians are correct
316  CHECK(assert_equal(H1Expected, H1Actual, 1e-9));
317  CHECK(assert_equal(H2Expected, H2Actual, 1e-9));
318 }
319 
320 /* ************************************************************************* */
321 // Do a test with Point2
323  // Create a factor
324  RangeFactor<Point2> factor(11, 22, measurement, model);
325 
326  // Set the linearization point
327  Point2 p11(1.0, 2.0), p22(-4.0, 11.0);
328 
329  // The expected error is ||(5.0, 9.0)|| - 10.0 = 0.295630141 meter
330  Vector expectedError = (Vector(1) << 0.295630141).finished();
331 
332  // Verify we get the expected error
333  Values values {{11, genericValue(p11)}, {22, genericValue(p22)}};
334  CHECK(assert_equal(expectedError, factor.unwhitenedError(values), 1e-9));
335 }
336 
337 /* ************************************************************************* */
338 // Do a test with Point3
340  // Create a factor
341  RangeFactor<Point3> factor(11, 22, measurement, model);
342 
343  // Set the linearization point
344  Point3 p11(1.0, 2.0, 0.0), p22(-4.0, 11.0, 0);
345 
346  // The expected error is ||(5.0, 9.0)|| - 10.0 = 0.295630141 meter
347  Vector expectedError = (Vector(1) << 0.295630141).finished();
348 
349  // Verify we get the expected error
350  Values values {{11, genericValue(p11)}, {22, genericValue(p22)}};
351  CHECK(assert_equal(expectedError, factor.unwhitenedError(values), 1e-9));
352 }
353 
354 /* ************************************************************************* */
355 // Do tests with PinholeCamera<Cal3_S2>
358 
362 }
363 
364 /* ************************************************************************* */
365 // Do a test with non GTSAM types
366 
367 namespace gtsam {
368 template <>
369 struct Range<Vector4, Vector4> {
370  typedef double result_type;
371  double operator()(const Vector4& v1, const Vector4& v2,
373  return (v2 - v1).norm();
374  // derivatives not implemented
375  }
376 };
377 } // namespace gtsam
378 
379 TEST(RangeFactor, NonGTSAM) {
380  // Create a factor
381  Key poseKey(1);
382  Key pointKey(2);
383  double measurement(10.0);
384  RangeFactor<Vector4> factor(poseKey, pointKey, measurement, model);
385 
386  // Set the linearization point
387  Vector4 pose(1.0, 2.0, 00, 0);
388  Vector4 point(-4.0, 11.0, 0, 0);
389 
390  // The expected error is ||(5.0, 9.0)|| - 10.0 = 0.295630141 meter / UnitCovariance
391  Vector expectedError = (Vector(1) << 0.295630141).finished();
392 
393  // Verify we get the expected error
394  CHECK(assert_equal(expectedError, factor.unwhitenedError({{poseKey, genericValue(pose)}, {pointKey, genericValue(point)}}), 1e-9));
395 }
396 
397 /* ************************************************************************* */
398 int main() {
399  TestResult tr;
400  return TestRegistry::runAllTests(tr);
401 }
402 /* ************************************************************************* */
const gtsam::Key poseKey
Provides additional testing facilities for common data structures.
#define CHECK(condition)
Definition: Test.h:108
const Point3 & translation(OptionalJacobian< 3, 6 > Hself={}) const
get translation
Definition: Pose3.cpp:308
Vector v2
static int runAllTests(TestResult &result)
Vector v1
noiseModel::Diagonal::shared_ptr model
Matrix expected
Definition: testMatrix.cpp:971
Vector2 Point2
Definition: Point2.h:32
bool assert_equal(const Matrix &expected, const Matrix &actual, double tol)
Definition: Matrix.cpp:40
Eigen::MatrixXd Matrix
Definition: base/Matrix.h:39
double operator()(const Vector4 &v1, const Vector4 &v2, OptionalJacobian< 1, 4 > H1, OptionalJacobian< 1, 4 > H2)
Rot2 R(Rot2::fromAngle(0.1))
leaf::MyValues values
static Pose3 body_P_sensor(Rot3::RzRyRx(-M_PI_2, 0.0, -M_PI_2), Point3(0.25, -0.10, 1.0))
RangeFactorWithTransform< Pose3, Point3 > RangeFactorWithTransform3D
Definition: BFloat16.h:88
Some functions to compute numerical derivatives.
RangeFactor< Pose3, Point3 > RangeFactor3D
Vector evaluateError(const A1 &a1, const A2 &a2, OptionalMatrixType H1=OptionalNone, OptionalMatrixType H2=OptionalNone) const
Rot3 is a 3D rotation represented as a rotation matrix if the preprocessor symbol GTSAM_USE_QUATERNIO...
Definition: Rot3.h:58
const gtsam::Key pointKey
int main()
Base class for all pinhole cameras.
static Point2 measurement(323.0, 240.0)
TEST(RangeFactor, Constructor)
Eigen::VectorXd Vector
Definition: Vector.h:38
Vector unwhitenedError(const Values &x, OptionalMatrixVecType H=nullptr) const override
Array< double, 1, 3 > e(1./3., 0.5, 2.)
RangeFactor< Pose2, Point2 > RangeFactor2D
traits
Definition: chartTesting.h:28
GenericValue< T > genericValue(const T &v)
Definition: GenericValue.h:211
static const Pose3 pose(Rot3(Vector3(1, -1, -1).asDiagonal()), Point3(0, 0, 0.5))
RangeFactorWithTransform< Pose2, Point2 > RangeFactorWithTransform2D
Point2 rotate(const Point2 &p, OptionalJacobian< 2, 1 > H1={}, OptionalJacobian< 2, 2 > H2={}) const
Definition: Rot2.cpp:100
Vector evaluateError(const A1 &a1, const A2 &a2, OptionalMatrixType H1=OptionalNone, OptionalMatrixType H2=OptionalNone) const
const KeyVector & keys() const
Access the factor&#39;s involved variable keys.
Definition: Factor.h:142
Vector3 Point3
Definition: Point3.h:38
Point3 rotate(const Point3 &p, OptionalJacobian< 3, 3 > H1={}, OptionalJacobian< 3, 3 > H2={}) const
Definition: Rot3M.cpp:148
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:86
2D Pose
Definition: camera.h:36
3D Pose
Eigen::Matrix< double, Eigen::Dynamic, 1 > Vector
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:102
Point2 t(10, 10)
noiseModel::Base::shared_ptr SharedNoiseModel
Definition: NoiseModel.h:741
The most common 5DOF 3D->2D calibration.
const Point2 & translation(OptionalJacobian< 2, 3 > Hself={}) const
translation
Definition: Pose2.h:261


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:39:15