gtsam  4.0.0
gtsam
SmartRangeFactor.h
Go to the documentation of this file.
1 
10 #pragma once
11 
14 #include <gtsam/inference/Key.h>
15 #include <gtsam/geometry/Pose2.h>
16 #include <gtsam/base/timing.h>
17 
18 #include <list>
19 #include <map>
20 #include <stdexcept>
21 #include <string>
22 #include <vector>
23 
24 namespace gtsam {
25 
31  protected:
32  struct Circle2 {
33  Circle2(const Point2& p, double r) :
34  center(p), radius(r) {
35  }
36  Point2 center;
37  double radius;
38  };
39 
40  typedef SmartRangeFactor This;
41 
42  std::vector<double> measurements_;
43  double variance_;
44 
45  public:
48  }
49 
54  explicit SmartRangeFactor(double s) :
55  NoiseModelFactor(noiseModel::Isotropic::Sigma(1, s)), variance_(s * s) {
56  }
57 
58  virtual ~SmartRangeFactor() {
59  }
60 
62  void addRange(Key key, double measuredRange) {
63  keys_.push_back(key);
64  measurements_.push_back(measuredRange);
65  size_t n = keys_.size();
66  // Since we add the errors, the noise variance adds
67  noiseModel_ = noiseModel::Isotropic::Variance(1, n * variance_);
68  }
69 
70  // Testable
71 
73  virtual void print(const std::string& s = "",
74  const KeyFormatter& keyFormatter = DefaultKeyFormatter) const {
75  std::cout << s << "SmartRangeFactor with " << size() << " measurements\n";
77  }
78 
80  virtual bool equals(const NonlinearFactor& f, double tol = 1e-9) const {
81  return false;
82  }
83 
84  // factor interface
85 
91  Point2 triangulate(const Values& x) const {
92  // gttic_(triangulate);
93  // create n circles corresponding to measured range around each pose
94  std::list<Circle2> circles;
95  size_t n = size();
96  for (size_t j = 0; j < n; j++) {
97  const Pose2& pose = x.at<Pose2>(keys_[j]);
98  circles.push_back(Circle2(pose.translation(), measurements_[j]));
99  }
100 
101  Circle2 circle1 = circles.front();
102  boost::optional<Point2> best_fh;
103  boost::optional<Circle2> bestCircle2;
104 
105  // loop over all circles
106  for (const Circle2& it : circles) {
107  // distance between circle centers.
108  double d = distance2(circle1.center, it.center);
109  if (d < 1e-9)
110  continue; // skip circles that are in the same location
111  // Find f and h, the intersection points in normalized circles
112  boost::optional<Point2> fh = circleCircleIntersection(
113  circle1.radius / d, it.radius / d);
114  // Check if this pair is better by checking h = fh->y()
115  // if h is large, the intersections are well defined.
116  if (fh && (!best_fh || fh->y() > best_fh->y())) {
117  best_fh = fh;
118  bestCircle2 = it;
119  }
120  }
121 
122  // use best fh to find actual intersection points
123  if (bestCircle2 && best_fh) {
124  auto bestCircleCenter = bestCircle2->center;
125  std::list<Point2> intersections =
126  circleCircleIntersection(circle1.center, bestCircleCenter, best_fh);
127 
128  // pick winner based on other measurements
129  double error1 = 0, error2 = 0;
130  Point2 p1 = intersections.front(), p2 = intersections.back();
131  for (const Circle2& it : circles) {
132  error1 += distance2(it.center, p1);
133  error2 += distance2(it.center, p2);
134  }
135  return (error1 < error2) ? p1 : p2;
136  } else {
137  throw std::runtime_error("triangulate failed");
138  }
139  // gttoc_(triangulate);
140  }
141 
145  virtual Vector unwhitenedError(const Values& x,
146  boost::optional<std::vector<Matrix>&> H = boost::none) const {
147  size_t n = size();
148  if (n < 3) {
149  if (H) {
150  // set Jacobians to zero for n<3
151  for (size_t j = 0; j < n; j++)
152  (*H)[j] = Matrix::Zero(3, 1);
153  }
154  return Z_1x1;
155  } else {
156  Vector error = Z_1x1;
157 
158  // triangulate to get the optimized point
159  // TODO(dellaert): Should we have a (better?) variant that does this in relative coordinates ?
160  Point2 optimizedPoint = triangulate(x);
161 
162  // TODO(dellaert): triangulation should be followed by an optimization given poses
163  // now evaluate the errors between predicted and measured range
164  for (size_t j = 0; j < n; j++) {
165  const Pose2& pose = x.at<Pose2>(keys_[j]);
166  if (H)
167  // also calculate 1*3 derivative for each of the n poses
168  error[0] += pose.range(optimizedPoint, (*H)[j]) - measurements_[j];
169  else
170  error[0] += pose.range(optimizedPoint) - measurements_[j];
171  }
172  return error;
173  }
174  }
175 
177  virtual gtsam::NonlinearFactor::shared_ptr clone() const {
178  return boost::static_pointer_cast<gtsam::NonlinearFactor>(
179  gtsam::NonlinearFactor::shared_ptr(new This(*this)));
180  }
181 };
182 } // \namespace gtsam
183 
This is the base class for all factor types.
Definition: Factor.h:54
A non-templated config holding any types of Manifold-group elements.
Definition: Values.h:70
double range(const Point2 &point, OptionalJacobian< 1, 3 > H1=boost::none, OptionalJacobian< 1, 2 > H2=boost::none) const
Calculate range to a landmark.
Definition: Pose2.cpp:247
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:91
ValueType at(Key j) const
Retrieve a variable by key j.
Definition: Values-inl.h:342
virtual void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
Print.
Definition: NonlinearFactor.cpp:63
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:57
virtual gtsam::NonlinearFactor::shared_ptr clone() const
Definition: SmartRangeFactor.h:177
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:567
SmartRangeFactor()
Default constructor: don't use directly.
Definition: SmartRangeFactor.h:47
void addRange(Key key, double measuredRange)
Add a range measurement to a pose with given key.
Definition: SmartRangeFactor.h:62
Definition: SmartRangeFactor.h:32
boost::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition: Key.h:33
std::vector< double > measurements_
Range measurements.
Definition: SmartRangeFactor.h:42
const Point2 & translation() const
translation
Definition: Pose2.h:230
Nonlinear factor base class.
Definition: NonlinearFactor.h:50
const SharedNoiseModel & noiseModel() const
access to the noise model
Definition: NonlinearFactor.h:210
size_t size() const
Definition: Factor.h:129
Definition: SmartRangeFactor.h:30
virtual void print(const std::string &s="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
print
Definition: SmartRangeFactor.h:73
A nonlinear sum-of-squares factor with a zero-mean noise model implementing the density Templated on...
Definition: NonlinearFactor.h:161
Definition: Pose2.h:36
Non-linear factor base classes.
Definition: Point2.h:40
double distance2(const Point2 &p, const Point2 &q, OptionalJacobian< 1, 2 > H1, OptionalJacobian< 1, 2 > H2)
distance between two points
Definition: Point2.cpp:39
Timing utilities.
Global functions in a separate testing namespace.
Definition: chartTesting.h:28
2D Pose
KeyVector keys_
The keys involved in this factor.
Definition: Factor.h:72
SmartRangeFactor(double s)
Constructor.
Definition: SmartRangeFactor.h:54
virtual Vector unwhitenedError(const Values &x, boost::optional< std::vector< Matrix > & > H=boost::none) const
Error function without the NoiseModel, .
Definition: SmartRangeFactor.h:145
virtual bool equals(const NonlinearFactor &f, double tol=1e-9) const
Check if two factors are equal.
Definition: SmartRangeFactor.h:80
virtual double error(const Values &c) const
Calculate the error of the factor.
Definition: NonlinearFactor.cpp:97
Symbols for exporting classes and methods from DLLs.
double variance_
variance on noise
Definition: SmartRangeFactor.h:43