gtsam
Loading...
Searching...
No Matches
SmartRangeFactor.h
Go to the documentation of this file.
1
9
10#pragma once
11
14#include <gtsam/inference/Key.h>
16#include <gtsam_unstable/dllexport.h>
17
18#include <list>
19#include <map>
20#include <optional>
21#include <stdexcept>
22#include <string>
23#include <vector>
24
25namespace gtsam {
26
32 protected:
33 struct Circle2 {
34 Circle2(const Point2& p, double r) :
35 center(p), radius(r) {
36 }
37 Point2 center;
38 double radius;
39 };
40
41 typedef SmartRangeFactor This;
42
43 std::vector<double> measurements_;
44 double variance_;
45
46 public:
47
48 // Provide access to the Matrix& version of unwhitenedError
50
54
59 explicit SmartRangeFactor(double s) :
60 NoiseModelFactor(noiseModel::Isotropic::Sigma(1, s)), variance_(s * s) {
61 }
62
63 ~SmartRangeFactor() override {
64 }
65
67 void addRange(Key key, double measuredRange) {
68 if(std::find(keys_.begin(), keys_.end(), key) != keys_.end()) {
69 throw std::invalid_argument(
70 "SmartRangeFactor::addRange: adding duplicate measurement for key.");
71 }
72 keys_.push_back(key);
73 measurements_.push_back(measuredRange);
74 size_t n = keys_.size();
75 // Since we add the errors, the noise variance adds
76 noiseModel_ = noiseModel::Isotropic::Variance(1, n * variance_);
77 }
78
79 // Testable
80
82 void print(const std::string& s = "",
83 const KeyFormatter& keyFormatter = DefaultKeyFormatter) const override {
84 std::cout << s << "SmartRangeFactor with " << size() << " measurements\n";
86 }
87
89 bool equals(const NonlinearFactor& f, double tol = 1e-9) const override {
90 return false;
91 }
92
93 // factor interface
94
100 Point2 triangulate(const Values& x) const {
101 // create n circles corresponding to measured range around each pose
102 std::list<Circle2> circles;
103 size_t n = size();
104 for (size_t j = 0; j < n; j++) {
105 const Pose2& pose = x.at<Pose2>(keys_[j]);
106 circles.push_back(Circle2(pose.translation(), measurements_[j]));
107 }
108
109 Circle2 circle1 = circles.front();
110 std::optional<Point2> best_fh;
111 std::optional<Circle2> bestCircle2 = std::nullopt; // fixes issue #38
112
113 // loop over all circles
114 for (const Circle2& it : circles) {
115 // distance between circle centers.
116 double d = distance2(circle1.center, it.center);
117 if (d < 1e-9)
118 continue; // skip circles that are in the same location
119 // Find f and h, the intersection points in normalized circles
120 std::optional<Point2> fh = circleCircleIntersection(
121 circle1.radius / d, it.radius / d);
122 // Check if this pair is better by checking h = fh->y()
123 // if h is large, the intersections are well defined.
124 if (fh && (!best_fh || fh->y() > best_fh->y())) {
125 best_fh = fh;
126 bestCircle2 = it;
127 }
128 }
129
130 // use best fh to find actual intersection points
131 if (bestCircle2 && best_fh) {
132 auto bestCircleCenter = bestCircle2->center;
133 std::list<Point2> intersections =
134 circleCircleIntersection(circle1.center, bestCircleCenter, best_fh);
135
136 // pick winner based on other measurements
137 double error1 = 0, error2 = 0;
138 Point2 p1 = intersections.front(), p2 = intersections.back();
139 for (const Circle2& it : circles) {
140 error1 += distance2(it.center, p1);
141 error2 += distance2(it.center, p2);
142 }
143 return (error1 < error2) ? p1 : p2;
144 } else {
145 throw std::runtime_error("triangulate failed");
146 }
147 }
148
152 Vector unwhitenedError(const Values& x, OptionalMatrixVecType H = nullptr) const override {
153 size_t n = size();
154 if (n < 3) {
155 if (H) {
156 // set Jacobians to zero for n<3
157 for (size_t j = 0; j < n; j++)
158 (*H)[j] = Matrix::Zero(3, 1);
159 }
160 return Z_1x1;
161 } else {
162 Vector error = Z_1x1;
163
164 // triangulate to get the optimized point
165 // TODO(dellaert): Should we have a (better?) variant that does this in relative coordinates ?
166 Point2 optimizedPoint = triangulate(x);
167
168 // TODO(dellaert): triangulation should be followed by an optimization given poses
169 // now evaluate the errors between predicted and measured range
170 for (size_t j = 0; j < n; j++) {
171 const Pose2& pose = x.at<Pose2>(keys_[j]);
172 if (H)
173 // also calculate 1*3 derivative for each of the n poses
174 error[0] += pose.range(optimizedPoint, (*H)[j]) - measurements_[j];
175 else
176 error[0] += pose.range(optimizedPoint) - measurements_[j];
177 }
178 return error;
179 }
180 }
181
183 gtsam::NonlinearFactor::shared_ptr clone() const override {
184 return std::static_pointer_cast<gtsam::NonlinearFactor>(
185 gtsam::NonlinearFactor::shared_ptr(new This(*this)));
186 }
187};
188} // \namespace gtsam
Macros for Matrix constants to avoid excessive template instantiation.
2D Pose
Non-linear factor base classes.
Global functions in a separate testing namespace.
Definition chartTesting.h:28
KeyFormatter DefaultKeyFormatter
Assign default key formatter.
Definition Key.cpp:30
double distance2(const Point2 &p, const Point2 &q, OptionalJacobian< 1, 2 > H1, OptionalJacobian< 1, 2 > H2)
distance between two points
Definition Point2.cpp:39
Vector2 Point2
As of GTSAM 4, in order to make GTSAM more lean, it is now possible to just typedef Point2 to Vector2...
Definition Point2.h:32
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition Key.h:35
std::vector< Matrix > * OptionalMatrixVecType
The OptionalMatrixVecType is a pointer to a vector of matrices.
Definition NonlinearFactor.h:63
std::uint64_t Key
Integer nonlinear key type.
Definition types.h:43
A 2D pose (Point2,Rot2).
Definition Pose2.h:39
double range(const Point2 &point, OptionalJacobian< 1, 3 > H1={}, OptionalJacobian< 1, 2 > H2={}) const
Calculate range to a landmark.
Definition Pose2.cpp:301
const Point2 & translation(OptionalJacobian< 2, 3 > Hself={}) const
translation
Definition Pose2.h:252
KeyVector keys_
The keys involved in this factor.
Definition Factor.h:88
size_t size() const
Definition Factor.h:160
static shared_ptr Variance(size_t dim, double variance, bool smart=true)
An isotropic noise model created by specifying a variance = sigma^2.
Definition NoiseModel.cpp:714
Nonlinear factor base class.
Definition NonlinearFactor.h:70
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
Print.
Definition NonlinearFactor.cpp:82
virtual Vector unwhitenedError(const Values &x, OptionalMatrixVecType H=nullptr) const =0
Error function without the NoiseModel, .
double error(const Values &c) const override
Calculate the error of the factor.
Definition NonlinearFactor.cpp:146
NoiseModelFactor()
Default constructor for I/O only.
Definition NonlinearFactor.h:223
const SharedNoiseModel & noiseModel() const
access to the noise model
Definition NonlinearFactor.h:258
A non-templated config holding any types of Manifold-group elements.
Definition Values.h:65
const ValueType at(Key j) const
Retrieve a variable by key j.
Definition Values-inl.h:260
Smart factor for range SLAM.
Definition SmartRangeFactor.h:31
void addRange(Key key, double measuredRange)
Add a range measurement to a pose with given key.
Definition SmartRangeFactor.h:67
Vector unwhitenedError(const Values &x, OptionalMatrixVecType H=nullptr) const override
Error function without the NoiseModel, .
Definition SmartRangeFactor.h:152
std::vector< double > measurements_
Range measurements.
Definition SmartRangeFactor.h:43
void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const override
print
Definition SmartRangeFactor.h:82
double variance_
variance on noise
Definition SmartRangeFactor.h:44
bool equals(const NonlinearFactor &f, double tol=1e-9) const override
Check if two factors are equal.
Definition SmartRangeFactor.h:89
SmartRangeFactor()
Default constructor: don't use directly.
Definition SmartRangeFactor.h:52
SmartRangeFactor(double s)
Constructor.
Definition SmartRangeFactor.h:59
Point2 triangulate(const Values &x) const
Triangulate a point from at least three pose-range pairs Checks for best pair that includes first poi...
Definition SmartRangeFactor.h:100
gtsam::NonlinearFactor::shared_ptr clone() const override
Definition SmartRangeFactor.h:183
Definition SmartRangeFactor.h:33
An isotropic noise model corresponds to a scaled diagonal covariance To construct,...
Definition NoiseModel.h:581