gtsam
Loading...
Searching...
No Matches
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
24
25#pragma once
26
27#include <cassert>
28#include <utility>
30
31namespace gtsam {
32
33
34 /* ************************************************************************* */
35 template<class ValueType>
36 struct _ValuesKeyValuePair {
37 const Key key;
38 ValueType& value;
39
40 _ValuesKeyValuePair(Key _key, ValueType& _value) : key(_key), value(_value) {}
41 };
42
43 /* ************************************************************************* */
44 template<class ValueType>
45 struct _ValuesConstKeyValuePair {
46 const Key key;
47 const ValueType& value;
48
49 _ValuesConstKeyValuePair(Key _key, const ValueType& _value) :
50 key(_key), value(_value) {
51 }
53 key(rhs.key), value(rhs.value) {
54 }
55 };
56
57 /* ************************************************************************* */
58
59 // Cast helpers for making _Values[Const]KeyValuePair's from Values::[Const]KeyValuePair
60 // need to use a struct here for later partial specialization
61 template<class ValueType, class CastedKeyValuePairType, class KeyValuePairType>
63 static CastedKeyValuePairType cast(KeyValuePairType key_value) {
64 // Static cast because we already checked the type during filtering
65 return CastedKeyValuePairType(key_value.key,
66 const_cast<GenericValue<ValueType>&>(static_cast<const GenericValue<
67 ValueType>&>(key_value.value)).value());
68 }
69 };
70 // partial specialized version for ValueType == Value
71 template<class CastedKeyValuePairType, class KeyValuePairType>
72 struct ValuesCastHelper<Value, CastedKeyValuePairType, KeyValuePairType> {
73 static CastedKeyValuePairType cast(KeyValuePairType key_value) {
74 // Static cast because we already checked the type during filtering
75 // in this case the casted and keyvalue pair are essentially the same type
76 // (key, Value&) so perhaps this could be done with just a cast of the key_value?
77 return CastedKeyValuePairType(key_value.key, key_value.value);
78 }
79 };
80 // partial specialized version for ValueType == Value
81 template<class CastedKeyValuePairType, class KeyValuePairType>
82 struct ValuesCastHelper<const Value, CastedKeyValuePairType, KeyValuePairType> {
83 static CastedKeyValuePairType cast(KeyValuePairType key_value) {
84 // Static cast because we already checked the type during filtering
85 // in this case the casted and keyvalue pair are essentially the same type
86 // (key, Value&) so perhaps this could be done with just a cast of the key_value?
87 return CastedKeyValuePairType(key_value.key, key_value.value);
88 }
89 };
90
91 /* ************************************************************************* */
92 template <class ValueType>
93 size_t Values::count() const {
94 size_t i = 0;
95 for (const auto& [_, value] : values_) {
96 if (dynamic_cast<const GenericValue<ValueType>*>(value.get())) ++i;
97 }
98 return i;
99 }
100
101 /* ************************************************************************* */
102 template <class ValueType>
103 std::map<Key, ValueType>
104 Values::extract(const std::function<bool(Key)>& filterFcn) const {
105 std::map<Key, ValueType> result;
106 for (const auto& [key,value] : values_) {
107 // Check if key matches
108 if (filterFcn(key)) {
109 // Check if type matches (typically does as symbols matched with types)
110 if (auto t =
111 dynamic_cast<const GenericValue<ValueType>*>(value.get()))
112 result[key] = t->value();
113 }
114 }
115 return result;
116 }
117
118 /* ************************************************************************* */
119 template<>
120 inline bool Values::filterHelper<Value>(const std::function<bool(Key)> filter,
121 const ConstKeyValuePair& key_value) {
122 // Filter and check the type
123 return filter(key_value.key);
124 }
125
126 /* ************************************************************************* */
127
128 namespace internal {
129
130 // Check the type and throw exception if incorrect
131 // Generic version, partially specialized below for various Eigen Matrix types
132 template <typename ValueType>
133 struct handle {
134 ValueType operator()(Key j, const Value* const pointer) {
135 auto ptr = dynamic_cast<const GenericValue<ValueType>*>(pointer);
136 if (ptr) {
137 // value returns a const ValueType&, and the return makes a copy !!!!!
138 return ptr->value();
139 } else {
140 throw ValuesIncorrectType(j, typeid(*pointer), typeid(ValueType));
141 }
142 }
143 };
144
145 template <typename MatrixType, bool isDynamic>
147
148 // Handle dynamic matrices
149 template <int M, int N>
150 struct handle_matrix<Eigen::Matrix<double, M, N>, true> {
151 inline Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
152 auto ptr = dynamic_cast<const GenericValue<Eigen::Matrix<double, M, N>>*>(pointer);
153 if (ptr) {
154 // value returns a const Matrix&, and the return makes a copy !!!!!
155 return ptr->value();
156 } else {
157 // If a fixed matrix was stored, we end up here as well.
158 throw ValuesIncorrectType(j, typeid(*pointer), typeid(Eigen::Matrix<double, M, N>));
159 }
160 }
161 };
162
163 // Handle fixed matrices
164 template <int M, int N>
165 struct handle_matrix<Eigen::Matrix<double, M, N>, false> {
166 inline Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
167 auto ptr = dynamic_cast<const GenericValue<Eigen::Matrix<double, M, N>>*>(pointer);
168 if (ptr) {
169 // value returns a const MatrixMN&, and the return makes a copy !!!!!
170 return ptr->value();
171 } else {
172 Matrix A;
173 // Check if a dynamic matrix was stored
174 auto ptr = dynamic_cast<const GenericValue<Eigen::MatrixXd>*>(pointer);
175 if (ptr) {
176 A = ptr->value();
177 } else {
178 // Or a dynamic vector
179 A = handle_matrix<Eigen::VectorXd, true>()(j, pointer); // will throw if not....
180 }
181 // Yes: check size, and throw if not a match
182 if (A.rows() != M || A.cols() != N)
183 throw NoMatchFoundForFixed(M, N, A.rows(), A.cols());
184 else
185 return A; // copy but not malloc
186 }
187 }
188 };
189
190 // Handle matrices
191 template <int M, int N>
192 struct handle<Eigen::Matrix<double, M, N>> {
193 Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
195 (M == Eigen::Dynamic || N == Eigen::Dynamic)>()(j, pointer);
196 }
197 };
198
199// Added this section for compile gtsam python on windows.
200// msvc don't deduct the template arguments correctly, due possible bug in msvc.
201#ifdef _WIN32
202#if _MSC_VER < 1937
203 // Handle dynamic matrices
204 template <int M, int N>
205 struct handle_matrix<Eigen::Matrix<double, M, N, 0, M, N>, true> {
206 inline Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
207 auto ptr = dynamic_cast<const GenericValue<Eigen::Matrix<double, M, N>>*>(pointer);
208 if (ptr) {
209 // value returns a const Matrix&, and the return makes a copy !!!!!
210 return ptr->value();
211 } else {
212 // If a fixed matrix was stored, we end up here as well.
213 throw ValuesIncorrectType(j, typeid(*pointer), typeid(Eigen::Matrix<double, M, N>));
214 }
215 }
216 };
217
218 // Handle fixed matrices
219 template <int M, int N>
220 struct handle_matrix<Eigen::Matrix<double, M, N, 0, M, N>, false> {
221 inline Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
222 auto ptr = dynamic_cast<const GenericValue<Eigen::Matrix<double, M, N>>*>(pointer);
223 if (ptr) {
224 // value returns a const MatrixMN&, and the return makes a copy !!!!!
225 return ptr->value();
226 } else {
227 Matrix A;
228 // Check if a dynamic matrix was stored
229 auto ptr = dynamic_cast<const GenericValue<Eigen::MatrixXd>*>(pointer);
230 if (ptr) {
231 A = ptr->value();
232 } else {
233 // Or a dynamic vector
234 A = handle_matrix<Eigen::VectorXd, true>()(j, pointer); // will throw if not....
235 }
236 // Yes: check size, and throw if not a match
237 if (A.rows() != M || A.cols() != N)
238 throw NoMatchFoundForFixed(M, N, A.rows(), A.cols());
239 else
240 return A; // copy but not malloc
241 }
242 }
243 };
244
245 // Handle matrices
246 template <int M, int N>
247 struct handle<Eigen::Matrix<double, M, N, 0, M, N>> {
248 Eigen::Matrix<double, M, N> operator()(Key j, const Value* const pointer) {
249 return handle_matrix<Eigen::Matrix<double, M, N, 0, M, N>,
250 (M == Eigen::Dynamic || N == Eigen::Dynamic)>()(j, pointer);
251 }
252 };
253#endif // #if _MSC_VER < 1937
254#endif // #ifdef _WIN32
255
256 } // internal
257
258 /* ************************************************************************* */
259 template <typename ValueType>
260 const ValueType Values::at(Key j) const {
261 // Find the item
262 KeyValueMap::const_iterator item = values_.find(j);
263
264 // Throw exception if it does not exist
265 if (item == values_.end()) throw ValuesKeyDoesNotExist("at", j);
266
267 // Check the type and throw exception if incorrect
268 // h() split in two lines to avoid internal compiler error (MSVC2017)
270 return h(j, item->second.get());
271 }
272
273 /* ************************************************************************* */
274 template <typename ValueType>
275 const ValueType& Values::atRef(Key j) const {
276 // Find the item
277 KeyValueMap::const_iterator item = values_.find(j);
278
279 // Throw exception if it does not exist
280 if (item == values_.end()) throw ValuesKeyDoesNotExist("atRef", j);
281
282 const Value* value = item->second.get();
283#ifndef NDEBUG
284 auto ptr = dynamic_cast<const GenericValue<ValueType>*>(value);
285 assert(ptr && "Values::atRef: incorrect ValueType");
286 if (!ptr) throw ValuesIncorrectType(j, typeid(*value), typeid(ValueType));
287 return ptr->value();
288#else
289 auto ptr = static_cast<const GenericValue<ValueType>*>(value);
290 return ptr->value();
291#endif
292 }
293
294 /* ************************************************************************* */
295 template<typename ValueType>
296 const ValueType * Values::exists(Key j) const {
297 // Find the item
298 KeyValueMap::const_iterator item = values_.find(j);
299
300 if(item != values_.end()) {
301 const Value* value = item->second.get();
302 // dynamic cast the type and throw exception if incorrect
303 auto ptr = dynamic_cast<const GenericValue<ValueType>*>(value);
304 if (ptr) {
305 return &ptr->value();
306 } else {
307 // NOTE(abe): clang warns about potential side effects if done in typeid
308 throw ValuesIncorrectType(j, typeid(*value), typeid(ValueType));
309 }
310 } else {
311 return nullptr;
312 }
313 }
314
315 /* ************************************************************************* */
316
317 // insert a templated value
318 template<typename ValueType>
319 void Values::insert(Key j, const ValueType& val) {
320 insert(j, static_cast<const Value&>(GenericValue<ValueType>(val)));
321 }
322
323 // partial specialization to insert an expression involving unary operators
324 template <typename UnaryOp, typename ValueType>
325 void Values::insert(Key j, const Eigen::CwiseUnaryOp<UnaryOp, const ValueType>& val) {
326 insert(j, val.eval());
327 }
328
329 // partial specialization to insert an expression involving binary operators
330 template <typename BinaryOp, typename ValueType1, typename ValueType2>
331 void Values::insert(Key j, const Eigen::CwiseBinaryOp<BinaryOp, const ValueType1, const ValueType2>& val) {
332 insert(j, val.eval());
333 }
334
335 // update with templated value
336 template <typename ValueType>
337 void Values::update(Key j, const ValueType& val) {
338 update(j, static_cast<const Value&>(GenericValue<ValueType>(val)));
339 }
340
341 // partial specialization to update with an expression involving unary operators
342 template <typename UnaryOp, typename ValueType>
343 void Values::update(Key j, const Eigen::CwiseUnaryOp<UnaryOp, const ValueType>& val) {
344 update(j, val.eval());
345 }
346
347 // partial specialization to update with an expression involving binary operators
348 template <typename BinaryOp, typename ValueType1, typename ValueType2>
349 void Values::update(Key j, const Eigen::CwiseBinaryOp<BinaryOp, const ValueType1, const ValueType2>& val) {
350 update(j, val.eval());
351 }
352
353 // insert_or_assign with templated value
354 template <typename ValueType>
355 void Values::insert_or_assign(Key j, const ValueType& val) {
356 insert_or_assign(j, static_cast<const Value&>(GenericValue<ValueType>(val)));
357 }
358
359 template <typename UnaryOp, typename ValueType>
360 void Values::insert_or_assign(Key j, const Eigen::CwiseUnaryOp<UnaryOp, const ValueType>& val) {
361 insert_or_assign(j, val.eval());
362 }
363
364 template <typename BinaryOp, typename ValueType1, typename ValueType2>
365 void Values::insert_or_assign(Key j, const Eigen::CwiseBinaryOp<BinaryOp, const ValueType1, const ValueType2>& val) {
366 insert_or_assign(j, val.eval());
367 }
368
369}
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:43
Wraps any type T so it can play as a Value.
Definition GenericValue.h:48
const T & value() const
Return a constant value.
Definition GenericValue.h:69
This is the base class for any type to be stored in Values.
Definition Value.h:39
Definition Values-inl.h:36
const Key key
The key.
Definition Values-inl.h:37
ValueType & value
The value.
Definition Values-inl.h:38
Definition Values-inl.h:45
const Key key
The key.
Definition Values-inl.h:46
const ValueType & value
The value.
Definition Values-inl.h:47
Definition Values-inl.h:62
Definition Values-inl.h:133
Definition Values-inl.h:146
void update(Key j, const Value &val)
single element change of existing element
Definition Values.cpp:186
const ValueType at(Key j) const
Retrieve a variable by key j.
Definition Values-inl.h:260
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:170
const ValueType & atRef(Key j) const
Retrieve a variable by key j without copying.
Definition Values-inl.h:275
void insert_or_assign(Key j, const Value &val)
If key j exists, update value, else perform an insert.
Definition Values.cpp:209
Values extract(const KeyVector &keys) const
Returns a new Values holding copies of the values at the given keys, whatever their types.
Definition Values.cpp:252
bool exists(Key j) const
Check if a value exists with key j.
Definition Values.cpp:95
Definition Values.h:467
Definition Values.h:490
Definition Values.h:534