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