gtsam  4.0.0
gtsam
utilities.h
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 
18 #pragma once
19 
20 #include <gtsam/inference/Symbol.h>
22 #include <gtsam/linear/Sampler.h>
25 #include <gtsam/nonlinear/Values.h>
26 #include <gtsam/geometry/Point2.h>
27 #include <gtsam/geometry/Point3.h>
28 #include <gtsam/geometry/Pose2.h>
29 #include <gtsam/geometry/Pose3.h>
30 #include <gtsam/geometry/Cal3_S2.h>
32 
33 #include <exception>
34 
35 namespace gtsam {
36 
37 namespace utilities {
38 
39 // Create a KeyList from indices
40 FastList<Key> createKeyList(const Vector& I) {
41  FastList<Key> set;
42  for (int i = 0; i < I.size(); i++)
43  set.push_back(I[i]);
44  return set;
45 }
46 
47 // Create a KeyList from indices using symbol
48 FastList<Key> createKeyList(std::string s, const Vector& I) {
49  FastList<Key> set;
50  char c = s[0];
51  for (int i = 0; i < I.size(); i++)
52  set.push_back(Symbol(c, I[i]));
53  return set;
54 }
55 
56 // Create a KeyVector from indices
57 KeyVector createKeyVector(const Vector& I) {
58  KeyVector set;
59  for (int i = 0; i < I.size(); i++)
60  set.push_back(I[i]);
61  return set;
62 }
63 
64 // Create a KeyVector from indices using symbol
65 KeyVector createKeyVector(std::string s, const Vector& I) {
66  KeyVector set;
67  char c = s[0];
68  for (int i = 0; i < I.size(); i++)
69  set.push_back(Symbol(c, I[i]));
70  return set;
71 }
72 
73 // Create a KeySet from indices
74 KeySet createKeySet(const Vector& I) {
75  KeySet set;
76  for (int i = 0; i < I.size(); i++)
77  set.insert(I[i]);
78  return set;
79 }
80 
81 // Create a KeySet from indices using symbol
82 KeySet createKeySet(std::string s, const Vector& I) {
83  KeySet set;
84  char c = s[0];
85  for (int i = 0; i < I.size(); i++)
86  set.insert(symbol(c, I[i]));
87  return set;
88 }
89 
91 Matrix extractPoint2(const Values& values) {
92  size_t j = 0;
93  Values::ConstFiltered<Point2> points = values.filter<Point2>();
94  Matrix result(points.size(), 2);
95  for(const auto& key_value: points)
96  result.row(j++) = key_value.value;
97  return result;
98 }
99 
101 Matrix extractPoint3(const Values& values) {
102  Values::ConstFiltered<Point3> points = values.filter<Point3>();
103  Matrix result(points.size(), 3);
104  size_t j = 0;
105  for(const auto& key_value: points)
106  result.row(j++) = key_value.value;
107  return result;
108 }
109 
111 Matrix extractPose2(const Values& values) {
112  Values::ConstFiltered<Pose2> poses = values.filter<Pose2>();
113  Matrix result(poses.size(), 3);
114  size_t j = 0;
115  for(const auto& key_value: poses)
116  result.row(j++) << key_value.value.x(), key_value.value.y(), key_value.value.theta();
117  return result;
118 }
119 
121 Values allPose3s(const Values& values) {
122  return values.filter<Pose3>();
123 }
124 
126 Matrix extractPose3(const Values& values) {
127  Values::ConstFiltered<Pose3> poses = values.filter<Pose3>();
128  Matrix result(poses.size(), 12);
129  size_t j = 0;
130  for(const auto& key_value: poses) {
131  result.row(j).segment(0, 3) << key_value.value.rotation().matrix().row(0);
132  result.row(j).segment(3, 3) << key_value.value.rotation().matrix().row(1);
133  result.row(j).segment(6, 3) << key_value.value.rotation().matrix().row(2);
134  result.row(j).tail(3) = key_value.value.translation();
135  j++;
136  }
137  return result;
138 }
139 
141 void perturbPoint2(Values& values, double sigma, int32_t seed = 42u) {
142  noiseModel::Isotropic::shared_ptr model = noiseModel::Isotropic::Sigma(2,
143  sigma);
144  Sampler sampler(model, seed);
145  for(const auto& key_value: values.filter<Point2>()) {
146  values.update<Point2>(key_value.key, key_value.value + Point2(sampler.sample()));
147  }
148 }
149 
151 void perturbPose2(Values& values, double sigmaT, double sigmaR, int32_t seed =
152  42u) {
153  noiseModel::Diagonal::shared_ptr model = noiseModel::Diagonal::Sigmas(
154  Vector3(sigmaT, sigmaT, sigmaR));
155  Sampler sampler(model, seed);
156  for(const auto& key_value: values.filter<Pose2>()) {
157  values.update<Pose2>(key_value.key, key_value.value.retract(sampler.sample()));
158  }
159 }
160 
162 void perturbPoint3(Values& values, double sigma, int32_t seed = 42u) {
163  noiseModel::Isotropic::shared_ptr model = noiseModel::Isotropic::Sigma(3,
164  sigma);
165  Sampler sampler(model, seed);
166  for(const auto& key_value: values.filter<Point3>()) {
167  values.update<Point3>(key_value.key, key_value.value + Point3(sampler.sample()));
168  }
169 }
170 
172 void insertBackprojections(Values& values, const SimpleCamera& camera,
173  const Vector& J, const Matrix& Z, double depth) {
174  if (Z.rows() != 2)
175  throw std::invalid_argument("insertBackProjections: Z must be 2*K");
176  if (Z.cols() != J.size())
177  throw std::invalid_argument(
178  "insertBackProjections: J and Z must have same number of entries");
179  for (int k = 0; k < Z.cols(); k++) {
180  Point2 p(Z(0, k), Z(1, k));
181  Point3 P = camera.backproject(p, depth);
182  values.insert(J(k), P);
183  }
184 }
185 
187 void insertProjectionFactors(NonlinearFactorGraph& graph, Key i,
188  const Vector& J, const Matrix& Z, const SharedNoiseModel& model,
189  const Cal3_S2::shared_ptr K, const Pose3& body_P_sensor = Pose3()) {
190  if (Z.rows() != 2)
191  throw std::invalid_argument("addMeasurements: Z must be 2*K");
192  if (Z.cols() != J.size())
193  throw std::invalid_argument(
194  "addMeasurements: J and Z must have same number of entries");
195  for (int k = 0; k < Z.cols(); k++) {
196  graph.push_back(
197  boost::make_shared<GenericProjectionFactor<Pose3, Point3> >(
198  Point2(Z(0, k), Z(1, k)), model, i, Key(J(k)), K, body_P_sensor));
199  }
200 }
201 
203 Matrix reprojectionErrors(const NonlinearFactorGraph& graph,
204  const Values& values) {
205  // first count
206  size_t K = 0, k = 0;
207  for(const NonlinearFactor::shared_ptr& f: graph)
208  if (boost::dynamic_pointer_cast<const GenericProjectionFactor<Pose3, Point3> >(
209  f))
210  ++K;
211  // now fill
212  Matrix errors(2, K);
213  for(const NonlinearFactor::shared_ptr& f: graph) {
214  boost::shared_ptr<const GenericProjectionFactor<Pose3, Point3> > p =
215  boost::dynamic_pointer_cast<const GenericProjectionFactor<Pose3, Point3> >(
216  f);
217  if (p)
218  errors.col(k++) = p->unwhitenedError(values);
219  }
220  return errors;
221 }
222 
224 Values localToWorld(const Values& local, const Pose2& base,
225  const KeyVector user_keys = KeyVector()) {
226 
227  Values world;
228 
229  // if no keys given, get all keys from local values
230  KeyVector keys(user_keys);
231  if (keys.size()==0)
232  keys = local.keys();
233 
234  // Loop over all keys
235  for(Key key: keys) {
236  try {
237  // if value is a Pose2, compose it with base pose
238  Pose2 pose = local.at<Pose2>(key);
239  world.insert(key, base.compose(pose));
240  } catch (std::exception e1) {
241  try {
242  // if value is a Point2, transform it from base pose
243  Point2 point = local.at<Point2>(key);
244  world.insert(key, base.transformFrom(point));
245  } catch (std::exception e2) {
246  // if not Pose2 or Point2, do nothing
247  }
248  }
249  }
250  return world;
251 }
252 
253 } // namespace utilities
254 
261 struct RedirectCout {
263  RedirectCout() : ssBuffer_(), coutBuffer_(std::cout.rdbuf(ssBuffer_.rdbuf())) {}
264 
266  std::string str() const {
267  return ssBuffer_.str();
268  }
269 
272  std::cout.rdbuf(coutBuffer_);
273  }
274 
275 private:
276  std::stringstream ssBuffer_;
277  std::streambuf* coutBuffer_;
278 };
279 
280 }
281 
Filtered< Value > filter(const boost::function< bool(Key)> &filterFcn)
Return a filtered view of this Values class, without copying any data.
Definition: Values-inl.h:237
~RedirectCout()
destructor – redirect stdout buffer to its original buffer
Definition: utilities.h:271
The most common 5DOF 3D->2D calibration.
A simple camera class with a Cal3_S2 calibration.
static shared_ptr Sigmas(const Vector &sigmas, bool smart=true)
A diagonal noise model created by specifying a Vector of sigmas, i.e.
Definition: NoiseModel.cpp:264
For Python str().
Definition: utilities.h:261
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:57
sampling that can be parameterized using a NoiseModel to generate samples fromthe given distribution
boost::shared_ptr< Cal3_S2 > shared_ptr
shared pointer to calibration object
Definition: Cal3_S2.h:39
2D Point
Factor Graph Constsiting of non-linear factors.
std::string str() const
return the string
Definition: utilities.h:266
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:56
Basic bearing factor from 2D measurement.
Non-linear factor base classes.
3D Pose
A non-templated config holding any types of Manifold-group elements.
3D Point
RedirectCout()
constructor – redirect stdout buffer to a stringstream buffer
Definition: utilities.h:263
Global functions in a separate testing namespace.
Definition: chartTesting.h:28
2D Pose
noiseModel::Base::shared_ptr SharedNoiseModel
Note, deliberately not in noiseModel namespace.
Definition: NoiseModel.h:1072
Key symbol(unsigned char c, std::uint64_t j)
Create a symbol key from a character and index, i.e.
Definition: Symbol.h:127
static shared_ptr Sigma(size_t dim, double sigma, bool smart=true)
An isotropic noise model created by specifying a standard devation sigma.
Definition: NoiseModel.cpp:561