gtsam  4.0.0
gtsam
Values-inl.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 
25 #pragma once
26 
27 #include <utility>
28 
29 #include <gtsam/base/DerivedValue.h>
30 #include <gtsam/nonlinear/Values.h> // Only so Eclipse finds class definition
31 
32 namespace gtsam {
33 
34 
35  /* ************************************************************************* */
36  template<class ValueType>
38  const Key key;
39  ValueType& value;
40 
41  _ValuesKeyValuePair(Key _key, ValueType& _value) : key(_key), value(_value) {}
42  };
43 
44  /* ************************************************************************* */
45  template<class ValueType>
47  const Key key;
48  const ValueType& value;
49 
50  _ValuesConstKeyValuePair(Key _key, const ValueType& _value) :
51  key(_key), value(_value) {
52  }
54  key(rhs.key), value(rhs.value) {
55  }
56  };
57 
58  /* ************************************************************************* */
59 
60  // Cast helpers for making _Values[Const]KeyValuePair's from Values::[Const]KeyValuePair
61  // need to use a struct here for later partial specialization
62  template<class ValueType, class CastedKeyValuePairType, class KeyValuePairType>
64  static CastedKeyValuePairType cast(KeyValuePairType key_value) {
65  // Static cast because we already checked the type during filtering
66  return CastedKeyValuePairType(key_value.key,
67  const_cast<GenericValue<ValueType>&>(static_cast<const GenericValue<
68  ValueType>&>(key_value.value)).value());
69  }
70  };
71  // partial specialized version for ValueType == Value
72  template<class CastedKeyValuePairType, class KeyValuePairType>
73  struct ValuesCastHelper<Value, CastedKeyValuePairType, KeyValuePairType> {
74  static CastedKeyValuePairType cast(KeyValuePairType key_value) {
75  // Static cast because we already checked the type during filtering
76  // in this case the casted and keyvalue pair are essentially the same type
77  // (key, Value&) so perhaps this could be done with just a cast of the key_value?
78  return CastedKeyValuePairType(key_value.key, key_value.value);
79  }
80  };
81  // partial specialized version for ValueType == Value
82  template<class CastedKeyValuePairType, class KeyValuePairType>
83  struct ValuesCastHelper<const Value, CastedKeyValuePairType, KeyValuePairType> {
84  static CastedKeyValuePairType cast(KeyValuePairType key_value) {
85  // Static cast because we already checked the type during filtering
86  // in this case the casted and keyvalue pair are essentially the same type
87  // (key, Value&) so perhaps this could be done with just a cast of the key_value?
88  return CastedKeyValuePairType(key_value.key, key_value.value);
89  }
90  };
91 
92  /* ************************************************************************* */
93  template<class ValueType>
95  public:
99  typedef KeyValuePair value_type;
100 
101  typedef
102  boost::transform_iterator<
103  KeyValuePair(*)(Values::KeyValuePair),
104  boost::filter_iterator<
105  boost::function<bool(const Values::ConstKeyValuePair&)>,
107  iterator;
108 
109  typedef iterator const_iterator;
110 
111  typedef
112  boost::transform_iterator<
113  ConstKeyValuePair(*)(Values::ConstKeyValuePair),
114  boost::filter_iterator<
115  boost::function<bool(const Values::ConstKeyValuePair&)>,
117  const_const_iterator;
118 
119  iterator begin() { return begin_; }
120  iterator end() { return end_; }
121  const_iterator begin() const { return begin_; }
122  const_iterator end() const { return end_; }
123  const_const_iterator beginConst() const { return constBegin_; }
124  const_const_iterator endConst() const { return constEnd_; }
125 
127  size_t size() const {
128  size_t i = 0;
129  for (const_const_iterator it = beginConst(); it != endConst(); ++it)
130  ++i;
131  return i;
132  }
133 
134  private:
135  Filtered(
136  const boost::function<bool(const Values::ConstKeyValuePair&)>& filter,
137  Values& values) :
138  begin_(
139  boost::make_transform_iterator(
140  boost::make_filter_iterator(filter, values.begin(), values.end()),
142  boost::make_transform_iterator(
143  boost::make_filter_iterator(filter, values.end(), values.end()),
145  boost::make_transform_iterator(
146  boost::make_filter_iterator(filter,
147  ((const Values&) values).begin(),
148  ((const Values&) values).end()),
149  &ValuesCastHelper<const ValueType, ConstKeyValuePair,
150  Values::ConstKeyValuePair>::cast)), constEnd_(
151  boost::make_transform_iterator(
152  boost::make_filter_iterator(filter,
153  ((const Values&) values).end(),
154  ((const Values&) values).end()),
155  &ValuesCastHelper<const ValueType, ConstKeyValuePair,
156  Values::ConstKeyValuePair>::cast)) {
157  }
158 
159  friend class Values;
160  iterator begin_;
161  iterator end_;
162  const_const_iterator constBegin_;
163  const_const_iterator constEnd_;
164  };
165 
166  /* ************************************************************************* */
167  template<class ValueType>
169  public:
172  typedef KeyValuePair value_type;
173 
174  typedef typename Filtered<ValueType>::const_const_iterator iterator;
175  typedef typename Filtered<ValueType>::const_const_iterator const_iterator;
176 
179  begin_(rhs.beginConst()),
180  end_(rhs.endConst()) {}
181 
182  iterator begin() { return begin_; }
183  iterator end() { return end_; }
184  const_iterator begin() const { return begin_; }
185  const_iterator end() const { return end_; }
186 
188  size_t size() const {
189  size_t i = 0;
190  for (const_iterator it = begin(); it != end(); ++it)
191  ++i;
192  return i;
193  }
194 
195  FastList<Key> keys() const {
196  FastList<Key> result;
197  for(const_iterator it = begin(); it != end(); ++it)
198  result.push_back(it->key);
199  return result;
200  }
201 
202  private:
203  friend class Values;
204  const_iterator begin_;
205  const_iterator end_;
207  const boost::function<bool(const Values::ConstKeyValuePair&)>& filter,
208  const Values& values) {
209  // We remove the const from values to create a non-const Filtered
210  // view, then pull the const_iterators out of it.
211  const Filtered<ValueType> filtered(filter, const_cast<Values&>(values));
212  begin_ = filtered.beginConst();
213  end_ = filtered.endConst();
214  }
215  };
216 
217  /* ************************************************************************* */
219  template<class ValueType>
221  for(const typename Filtered<ValueType>::KeyValuePair& key_value: view) {
222  Key key = key_value.key;
223  insert(key, static_cast<const ValueType&>(key_value.value));
224  }
225  }
226 
227  /* ************************************************************************* */
228  template<class ValueType>
230  for(const typename ConstFiltered<ValueType>::KeyValuePair& key_value: view) {
231  Key key = key_value.key;
232  insert(key, static_cast<const ValueType&>(key_value.value));
233  }
234  }
235 
236  /* ************************************************************************* */
238  inline Values::filter(const boost::function<bool(Key)>& filterFcn) {
239  return filter<Value>(filterFcn);
240  }
241 
242  /* ************************************************************************* */
243  template<class ValueType>
245  Values::filter(const boost::function<bool(Key)>& filterFcn) {
246  return Filtered<ValueType>(boost::bind(&filterHelper<ValueType>, filterFcn, _1), *this);
247  }
248 
249  /* ************************************************************************* */
251  inline Values::filter(const boost::function<bool(Key)>& filterFcn) const {
252  return filter<Value>(filterFcn);
253  }
254 
255  /* ************************************************************************* */
256  template<class ValueType>
258  Values::filter(const boost::function<bool(Key)>& filterFcn) const {
259  return ConstFiltered<ValueType>(boost::bind(&filterHelper<ValueType>, filterFcn, _1), *this);
260  }
261 
262  /* ************************************************************************* */
263  template<>
264  inline bool Values::filterHelper<Value>(const boost::function<bool(Key)> filter,
265  const ConstKeyValuePair& key_value) {
266  // Filter and check the type
267  return filter(key_value.key);
268  }
269 
270  /* ************************************************************************* */
271 
272  namespace internal {
273 
274  // Check the type and throw exception if incorrect
275  // Generic version, partially specialized below for various Eigen Matrix types
276  template <typename ValueType>
277  struct handle {
278  ValueType operator()(Key j, const Value* const pointer) {
279  try {
280  // value returns a const ValueType&, and the return makes a copy !!!!!
281  return dynamic_cast<const GenericValue<ValueType>&>(*pointer).value();
282  } catch (std::bad_cast&) {
283  throw ValuesIncorrectType(j, typeid(*pointer), typeid(ValueType));
284  }
285  }
286  };
287 
288  template <typename MatrixType, bool isDynamic>
290 
291  // Handle dynamic matrices
292  template <int M, int N>
293  struct handle_matrix<Eigen::Matrix<double, M, N>, true> {
294  Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
295  try {
296  // value returns a const Matrix&, and the return makes a copy !!!!!
297  return dynamic_cast<const GenericValue<Eigen::Matrix<double, M, N>>&>(*pointer).value();
298  } catch (std::bad_cast&) {
299  // If a fixed matrix was stored, we end up here as well.
300  throw ValuesIncorrectType(j, typeid(*pointer), typeid(Eigen::Matrix<double, M, N>));
301  }
302  }
303  };
304 
305  // Handle fixed matrices
306  template <int M, int N>
307  struct handle_matrix<Eigen::Matrix<double, M, N>, false> {
308  Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
309  try {
310  // value returns a const MatrixMN&, and the return makes a copy !!!!!
311  return dynamic_cast<const GenericValue<Eigen::Matrix<double, M, N>>&>(*pointer).value();
312  } catch (std::bad_cast&) {
313  Matrix A;
314  try {
315  // Check if a dynamic matrix was stored
316  A = handle_matrix<Eigen::MatrixXd, true>()(j, pointer); // will throw if not....
317  } catch (const ValuesIncorrectType&) {
318  // Or a dynamic vector
319  A = handle_matrix<Eigen::VectorXd, true>()(j, pointer); // will throw if not....
320  }
321  // Yes: check size, and throw if not a match
322  if (A.rows() != M || A.cols() != N)
323  throw NoMatchFoundForFixed(M, N, A.rows(), A.cols());
324  else
325  return A; // copy but not malloc
326  }
327  }
328  };
329 
330  // Handle matrices
331  template <int M, int N>
332  struct handle<Eigen::Matrix<double, M, N>> {
333  Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
335  (M == Eigen::Dynamic || N == Eigen::Dynamic)>()(j, pointer);
336  }
337  };
338 
339  } // internal
340 
341  /* ************************************************************************* */
342  template<typename ValueType>
343  ValueType Values::at(Key j) const {
344  // Find the item
345  KeyValueMap::const_iterator item = values_.find(j);
346 
347  // Throw exception if it does not exist
348  if(item == values_.end())
349  throw ValuesKeyDoesNotExist("at", j);
350 
351  // Check the type and throw exception if incorrect
352  return internal::handle<ValueType>()(j,item->second);
353  }
354 
355  /* ************************************************************************* */
356  template<typename ValueType>
357  boost::optional<const ValueType&> Values::exists(Key j) const {
358  // Find the item
359  KeyValueMap::const_iterator item = values_.find(j);
360 
361  if(item != values_.end()) {
362  // dynamic cast the type and throw exception if incorrect
363  const Value& value = *item->second;
364  try {
365  return dynamic_cast<const GenericValue<ValueType>&>(value).value();
366  } catch (std::bad_cast &) {
367  // NOTE(abe): clang warns about potential side effects if done in typeid
368  const Value* value = item->second;
369  throw ValuesIncorrectType(j, typeid(*value), typeid(ValueType));
370  }
371  } else {
372  return boost::none;
373  }
374  }
375 
376  /* ************************************************************************* */
377 
378  // insert a templated value
379  template<typename ValueType>
380  void Values::insert(Key j, const ValueType& val) {
381  insert(j, static_cast<const Value&>(GenericValue<ValueType>(val)));
382  }
383 
384  // update with templated value
385  template <typename ValueType>
386  void Values::update(Key j, const ValueType& val) {
387  update(j, static_cast<const Value&>(GenericValue<ValueType>(val)));
388  }
389 
390 }
Definition: Values.h:436
_ValuesKeyValuePair< ValueType > KeyValuePair
A key-value pair, with the value a specific derived Value type.
Definition: Values-inl.h:97
Definition: Values.h:459
A filtered view of a Values, returned from Values::filter.
Definition: Values-inl.h:94
void insert(Key j, const Value &val)
Add a variable with the given j, throws KeyAlreadyExists<J> if j is already present.
Definition: Values.cpp:133
ValueType & value
The value.
Definition: Values-inl.h:39
Definition: Values-inl.h:46
const T & value() const
Return a constant value.
Definition: GenericValue.h:58
A non-templated config holding any types of Manifold-group elements.
const Key key
The key.
Definition: Values-inl.h:38
Definition: FastList.h:38
Wraps any type T so it can play as a Value.
Definition: GenericValue.h:38
boost::transform_iterator< boost::function1< ConstKeyValuePair, const ConstKeyValuePtrPair & >, KeyValueMap::const_iterator > const_iterator
Const forward iterator, with value type ConstKeyValuePair.
Definition: Values.h:123
size_t size() const
Returns the number of values in this view.
Definition: Values-inl.h:127
Definition: Values-inl.h:277
void update(Key j, const Value &val)
single element change of existing element
Definition: Values.cpp:154
A filtered view of a const Values, returned from Values::filter.
Definition: Values-inl.h:168
A non-templated config holding any types of Manifold-group elements.
Definition: Values.h:70
bool exists(Key j) const
Check if a value exists with key j.
Definition: Values.cpp:97
const ValueType & value
The value.
Definition: Values-inl.h:48
ValueType at(Key j) const
Retrieve a variable by key j.
Definition: Values-inl.h:343
const Key key
The key.
Definition: Values-inl.h:47
Values()
Default constructor creates an empty Values class.
Definition: Values.h:144
A key-value pair, which you get by dereferencing iterators.
Definition: Values.h:101
ConstFiltered(const Filtered< ValueType > &rhs)
Conversion from Filtered to ConstFiltered.
Definition: Values-inl.h:178
Definition: Values-inl.h:289
size_t size() const
Returns the number of values in this view.
Definition: Values-inl.h:188
_ValuesConstKeyValuePair< ValueType > KeyValuePair
A const key-value pair, with the value a specific derived Value type.
Definition: Values-inl.h:171
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:238
Definition: Values.h:503
This is the interface class for any value that may be used as a variable assignment in a factor graph...
Definition: Value.h:83
Definition: Values-inl.h:37
boost::transform_iterator< boost::function1< KeyValuePair, const KeyValuePtrPair & >, KeyValueMap::iterator > iterator
Mutable forward iterator, with value type KeyValuePair.
Definition: Values.h:119
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:57
Global functions in a separate testing namespace.
Definition: chartTesting.h:28
A key-value pair, which you get by dereferencing iterators.
Definition: Values.h:109
Definition: Values-inl.h:63