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
12/**
13 * @file simulated2D.h
14 * @brief measurement functions and derivatives for simulated 2D robot
15 * @author Frank Dellaert
16 */
17
18// \callgraph
19#pragma once
20
21#include <gtsam/nonlinear/NonlinearFactor.h>
22#include <gtsam/nonlinear/NonlinearFactorGraph.h>
23#include <gtsam/geometry/Point2.h>
24#include "gtsam/base/OptionalJacobian.h"
25
26// \namespace
27
28namespace simulated2D {
29
30 using namespace gtsam;
31
32 // Simulated2D robots have no orientation, just a position
33
34 /**
35 * Custom Values class that holds poses and points, mainly used as a convenience for MATLAB wrapper
36 */
37 class Values: public gtsam::Values {
38 private:
39 int nrPoses_, nrPoints_;
40
41 public:
42 typedef gtsam::Values Base; ///< base class
43 typedef std::shared_ptr<Point2> sharedPoint; ///< shortcut to shared Point type
44
45 /// Constructor
46 Values() : nrPoses_(0), nrPoints_(0) {
47 }
48
49 /// Copy constructor
50 Values(const Base& base) :
51 Base(base), nrPoses_(0), nrPoints_(0) {
52 }
53
54 /// Insert a pose
55 void insertPose(Key i, const Point2& p) {
56 insert(j: i, val: p);
57 nrPoses_++;
58 }
59
60 /// Insert a point
61 void insertPoint(Key j, const Point2& p) {
62 insert(j, val: p);
63 nrPoints_++;
64 }
65
66 /// Number of poses
67 int nrPoses() const {
68 return nrPoses_;
69 }
70
71 /// Number of points
72 int nrPoints() const {
73 return nrPoints_;
74 }
75
76 /// Return pose i
77 Point2 pose(Key i) const {
78 return at<Point2>(j: i);
79 }
80
81 /// Return point j
82 Point2 point(Key j) const {
83 return at<Point2>(j);
84 }
85 };
86
87 /// Prior on a single pose
88 inline Point2 prior(const Point2& x) {
89 return x;
90 }
91
92 /// Prior on a single pose, optionally returns derivative
93 inline Point2 prior(const Point2& x, OptionalJacobian<2,2> H = OptionalNone) {
94 if (H) *H = I_2x2;
95 return x;
96 }
97
98 /// odometry between two poses
99 inline Point2 odo(const Point2& x1, const Point2& x2) {
100 return x2 - x1;
101 }
102
103 /// odometry between two poses, optionally returns derivative
104 inline Point2 odo(const Point2& x1, const Point2& x2,
105 OptionalJacobian<2,2> H1 = OptionalNone,
106 OptionalJacobian<2,2> H2 = OptionalNone) {
107 if (H1) *H1 = -I_2x2;
108 if (H2) *H2 = I_2x2;
109 return x2 - x1;
110 }
111
112 /// measurement between landmark and pose
113 inline Point2 mea(const Point2& x, const Point2& l) {
114 return l - x;
115 }
116
117 /// measurement between landmark and pose, optionally returns derivative
118 inline Point2 mea(const Point2& x, const Point2& l, OptionalJacobian<2,2> H1 =
119 OptionalNone, OptionalMatrixType H2 = OptionalNone) {
120 if (H1) *H1 = -I_2x2;
121 if (H2) *H2 = I_2x2;
122 return l - x;
123 }
124
125 /**
126 * Unary factor encoding a soft prior on a vector
127 */
128 template<class VALUE = Point2>
129 class GenericPrior: public NoiseModelFactorN<VALUE> {
130 public:
131 typedef NoiseModelFactorN<VALUE> Base; ///< base class
132 typedef GenericPrior<VALUE> This;
133 typedef std::shared_ptr<GenericPrior<VALUE> > shared_ptr;
134 typedef VALUE Pose; ///< shortcut to Pose type
135
136 // Provide access to the Matrix& version of evaluateError:
137 using Base::evaluateError;
138
139 Pose measured_; ///< prior mean
140
141 /// Create generic prior
142 GenericPrior(const Pose& z, const SharedNoiseModel& model, Key key) :
143 Base(model, key), measured_(z) {
144 }
145
146 /// Return error and optional derivative
147 Vector evaluateError(const Pose& x, OptionalMatrixType H) const override {
148 return (simulated2D::prior(x, H) - measured_);
149 }
150
151 ~GenericPrior() override {}
152
153 /// @return a deep copy of this factor
154 gtsam::NonlinearFactor::shared_ptr clone() const override {
155 return std::static_pointer_cast<gtsam::NonlinearFactor>(
156 r: gtsam::NonlinearFactor::shared_ptr(new This(*this))); }
157
158 private:
159
160 /// Default constructor
161 GenericPrior() { }
162
163#if GTSAM_ENABLE_BOOST_SERIALIZATION ///
164 /// Serialization function
165 friend class boost::serialization::access;
166 template<class ARCHIVE>
167 void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
168 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
169 ar & BOOST_SERIALIZATION_NVP(measured_);
170 }
171#endif
172 };
173
174 /**
175 * Binary factor simulating "odometry" between two Vectors
176 */
177 template<class VALUE = Point2>
178 class GenericOdometry: public NoiseModelFactorN<VALUE, VALUE> {
179 public:
180 typedef NoiseModelFactorN<VALUE, VALUE> Base; ///< base class
181 typedef GenericOdometry<VALUE> This;
182 typedef std::shared_ptr<GenericOdometry<VALUE> > shared_ptr;
183 typedef VALUE Pose; ///< shortcut to Pose type
184
185 // Provide access to the Matrix& version of evaluateError:
186 using Base::evaluateError;
187
188 Pose measured_; ///< odometry measurement
189
190 /// Create odometry
191 GenericOdometry(const Pose& measured, const SharedNoiseModel& model, Key i1, Key i2) :
192 Base(model, i1, i2), measured_(measured) {
193 }
194
195 /// Evaluate error and optionally return derivatives
196 Vector evaluateError(const Pose& x1, const Pose& x2,
197 OptionalMatrixType H1, OptionalMatrixType H2) const override {
198 return (odo(x1, x2, H1, H2) - measured_);
199 }
200
201 ~GenericOdometry() override {}
202
203 /// @return a deep copy of this factor
204 gtsam::NonlinearFactor::shared_ptr clone() const override {
205 return std::static_pointer_cast<gtsam::NonlinearFactor>(
206 r: gtsam::NonlinearFactor::shared_ptr(new This(*this))); }
207
208 private:
209
210 /// Default constructor
211 GenericOdometry() { }
212
213#if GTSAM_ENABLE_BOOST_SERIALIZATION ///
214 /// Serialization function
215 friend class boost::serialization::access;
216 template<class ARCHIVE>
217 void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
218 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
219 ar & BOOST_SERIALIZATION_NVP(measured_);
220 }
221#endif
222 };
223
224 /**
225 * Binary factor simulating "measurement" between two Vectors
226 */
227 template<class POSE, class LANDMARK>
228 class GenericMeasurement: public NoiseModelFactorN<POSE, LANDMARK> {
229 public:
230 typedef NoiseModelFactorN<POSE, LANDMARK> Base; ///< base class
231 typedef GenericMeasurement<POSE, LANDMARK> This;
232 typedef std::shared_ptr<GenericMeasurement<POSE, LANDMARK> > shared_ptr;
233 typedef POSE Pose; ///< shortcut to Pose type
234 typedef LANDMARK Landmark; ///< shortcut to Landmark type
235
236 // Provide access to the Matrix& version of evaluateError:
237 using Base::evaluateError;
238
239 Landmark measured_; ///< Measurement
240
241 /// Create measurement factor
242 GenericMeasurement(const Landmark& measured, const SharedNoiseModel& model, Key i, Key j) :
243 Base(model, i, j), measured_(measured) {
244 }
245
246 /// Evaluate error and optionally return derivatives
247 Vector evaluateError(const Pose& x1, const Landmark& x2,
248 OptionalMatrixType H1, OptionalMatrixType H2) const override {
249 return (mea(x1, x2, H1, H2) - measured_);
250 }
251
252 ~GenericMeasurement() override {}
253
254 /// @return a deep copy of this factor
255 gtsam::NonlinearFactor::shared_ptr clone() const override {
256 return std::static_pointer_cast<gtsam::NonlinearFactor>(
257 r: gtsam::NonlinearFactor::shared_ptr(new This(*this))); }
258
259 private:
260
261 /// Default constructor
262 GenericMeasurement() { }
263
264#if GTSAM_ENABLE_BOOST_SERIALIZATION ///
265 /// Serialization function
266 friend class boost::serialization::access;
267 template<class ARCHIVE>
268 void serialize(ARCHIVE & ar, const unsigned int /*version*/) {
269 ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base);
270 ar & BOOST_SERIALIZATION_NVP(measured_);
271 }
272#endif
273 };
274
275 /** Typedefs for regular use */
276 typedef GenericPrior<Point2> Prior;
277 typedef GenericOdometry<Point2> Odometry;
278 typedef GenericMeasurement<Point2, Point2> Measurement;
279
280 // Specialization of a graph for this example domain
281 // TODO: add functions to add factor types
282 class Graph : public NonlinearFactorGraph {
283 public:
284 Graph() {}
285 };
286
287} // namespace simulated2D
288
289/// traits
290namespace gtsam {
291template<class POSE, class LANDMARK>
292struct traits<simulated2D::GenericMeasurement<POSE, LANDMARK> > : Testable<
293 simulated2D::GenericMeasurement<POSE, LANDMARK> > {
294};
295
296template<>
297struct traits<simulated2D::Values> : public Testable<simulated2D::Values> {
298};
299}
300
301