Values.cpp
Go to the documentation of this file.
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 #include <gtsam/nonlinear/Values.h>
27 
28 #include <list>
29 #include <memory>
30 #include <sstream>
31 #include <cassert>
32 
33 using namespace std;
34 
35 namespace gtsam {
36 
37  /* ************************************************************************* */
39  this->insert(other);
40  }
41 
42  /* ************************************************************************* */
43  Values::Values(Values&& other) : values_(std::move(other.values_)) {
44  }
45 
46  /* ************************************************************************* */
47  Values::Values(std::initializer_list<ConstKeyValuePair> init) {
48  for (const auto &kv : init)
49  insert(kv.key, kv.value);
50  }
51 
52  /* ************************************************************************* */
54  for (const auto& [key,value] : other.values_) {
56  if (it != delta.end()) {
57  const Vector& v = it->second;
58  Value* retractedValue(value->retract_(v)); // Retract
59  values_.emplace(key, retractedValue); // Add retracted result directly to result values
60  } else {
61  values_.emplace(key, value->clone_()); // Add original version to result values
62  }
63  }
64  }
65 
66  /* ************************************************************************* */
67  void Values::print(const string& str, const KeyFormatter& keyFormatter) const {
68  cout << str << (str.empty() ? "" : "\n");
69  cout << "Values with " << size() << " values:\n";
70  for (const auto& [key,value] : values_) {
71  cout << "Value " << keyFormatter(key) << ": ";
72  value->print("");
73  cout << "\n";
74  }
75  }
76 
77  /* ************************************************************************* */
78  bool Values::equals(const Values& other, double tol) const {
79  if (this->size() != other.size())
80  return false;
81  for (auto it1 = values_.begin(), it2 = other.values_.begin();
82  it1 != values_.end(); ++it1, ++it2) {
83  const Value* value1 = it1->second.get();
84  const Value* value2 = it2->second.get();
85  if (typeid(*value1) != typeid(*value2) || it1->first != it2->first
86  || !value1->equals_(*value2, tol)) {
87  return false;
88  }
89  }
90  return true; // We return false earlier if we find anything that does not match
91 }
92 
93  /* ************************************************************************* */
94  bool Values::exists(Key j) const {
95  return values_.find(j) != values_.end();
96  }
97 
98  /* ************************************************************************* */
100  return Values(*this, delta);
101  }
102 
103  /* ************************************************************************* */
104  void Values::retractMasked(const VectorValues& delta, const KeySet& mask) {
106  assert(this->size() == delta.size());
107  auto key_value = values_.begin();
109 #ifdef GTSAM_USE_TBB
110  for (; key_value != values_.end(); ++key_value) {
111  key_delta = delta.find(key_value->first);
112 #else
113  for (key_delta = delta.begin(); key_value != values_.end();
114  ++key_value, ++key_delta) {
115  assert(key_value->first == key_delta->first);
116 #endif
117  Key var = key_value->first;
118  assert(static_cast<size_t>(delta[var].size()) == key_value->second->dim());
119  assert(delta[var].allFinite());
120  if (mask.exists(var)) {
121  Value* retracted = key_value->second->retract_(delta[var]);
122  // TODO(dellaert): can we use std::move here?
123  *(key_value->second) = *retracted;
124  retracted->deallocate_();
125  }
126  }
127  }
128 
129  /* ************************************************************************* */
131  if(this->size() != cp.size())
132  throw DynamicValuesMismatched();
134  for (auto it1 = values_.begin(), it2 = cp.values_.begin();
135  it1 != values_.end(); ++it1, ++it2) {
136  if(it1->first != it2->first)
137  throw DynamicValuesMismatched(); // If keys do not match
138  // Will throw a dynamic_cast exception if types do not match
139  // NOTE: this is separate from localCoordinates(cp, ordering, result) due to at() vs. insert
140  result.insert(it1->first, it1->second->localCoordinates_(*it2->second));
141  }
142  return result;
143  }
144 
145  /* ************************************************************************* */
146  const Value& Values::at(Key j) const {
147  KeyValueMap::const_iterator it = values_.find(j);
148 
149  // Throw exception if it does not exist
150  if(it == values_.end())
151  throw ValuesKeyDoesNotExist("retrieve", j);
152  return *it->second;
153  }
154 
155  /* ************************************************************************* */
156  void Values::insert(Key j, const Value& val) {
157  auto insertResult = values_.emplace(j, val.clone_());
158  if(!insertResult.second)
159  throw ValuesKeyAlreadyExists(j);
160  }
161 
162  /* ************************************************************************* */
163  void Values::insert(const Values& other) {
164  for (const auto& [key, value] : other.values_) {
165  insert(key, *(value));
166  }
167  }
168 
169  /* ************************************************************************* */
170  void Values::update(Key j, const Value& val) {
171  // Find the value to update
172  KeyValueMap::iterator it = values_.find(j);
173  if (it == values_.end())
174  throw ValuesKeyDoesNotExist("update", j);
175 
176  // Cast to the derived type
177  const Value& old_value = *it->second;
178  if (typeid(old_value) != typeid(val))
179  throw ValuesIncorrectType(j, typeid(old_value), typeid(val));
180 
181  values_.erase(j);
182  values_.emplace(j, val.clone_());
183  }
184 
185  /* ************************************************************************* */
186  void Values::update(const Values& other) {
187  for (auto& [key, value] : other.values_) {
188  this->update(key, *(value));
189  }
190  }
191 
192  /* ************************************************************************ */
193  void Values::insert_or_assign(Key j, const Value& val) {
194  if (this->exists(j)) {
195  // If key already exists, perform an update.
196  this->update(j, val);
197  } else {
198  // If key does not exist, perform an insert.
199  this->insert(j, val);
200  }
201  }
202 
203  /* ************************************************************************ */
205  for (auto& [key, value] : other.values_) {
206  this->insert_or_assign(key, *(value));
207  }
208  }
209 
210  /* ************************************************************************* */
212  KeyValueMap::iterator it = values_.find(j);
213  if(it == values_.end())
214  throw ValuesKeyDoesNotExist("erase", j);
215  values_.erase(it);
216  }
217 
218  /* ************************************************************************* */
221  result.reserve(size());
222  for(const auto& [key,value]: values_)
223  result.push_back(key);
224  return result;
225  }
226 
227  /* ************************************************************************* */
229  KeySet result;
230  for(const auto& [key,value]: values_)
231  result.insert(key);
232  return result;
233  }
234 
235  /* ************************************************************************* */
237  this->clear();
238  this->insert(rhs);
239  return *this;
240  }
241 
242  /* ************************************************************************* */
243  size_t Values::dim() const {
244  size_t result = 0;
245  for (const auto& [key,value] : values_) {
246  result += value->dim();
247  }
248  return result;
249  }
250 
251  /* ************************************************************************* */
252  std::map<Key,size_t> Values::dims() const {
253  std::map<Key,size_t> result;
254  for (const auto& [key,value] : values_) {
255  result.emplace(key, value->dim());
256  }
257  return result;
258  }
259 
260  /* ************************************************************************* */
263  for (const auto& [key,value] : values_)
264  result.insert(key, Vector::Zero(value->dim()));
265  return result;
266  }
267 
268  /* ************************************************************************* */
269  const char* ValuesKeyAlreadyExists::what() const noexcept {
270  if(message_.empty())
271  message_ =
272  "Attempting to add a key-value pair with key \"" + DefaultKeyFormatter(key_) + "\", key already exists.";
273  return message_.c_str();
274  }
275 
276  /* ************************************************************************* */
277  const char* ValuesKeyDoesNotExist::what() const noexcept {
278  if(message_.empty())
279  message_ =
280  "Attempting to " + std::string(operation_) + " the key \"" +
281  DefaultKeyFormatter(key_) + "\", which does not exist in the Values.";
282  return message_.c_str();
283  }
284 
285  /* ************************************************************************* */
286  const char* ValuesIncorrectType::what() const noexcept {
287  if(message_.empty()) {
288  std::string storedTypeName = demangle(storedTypeId_.name());
289  std::string requestedTypeName = demangle(requestedTypeId_.name());
290 
291  if (storedTypeName == requestedTypeName) {
292  message_ = "WARNING: Detected types with same name but different `typeid`. \
293  This is usually caused by incorrect linking/inlining settings when compiling libraries using GTSAM. \
294  If you are a user, please report to the author of the library using GTSAM. \
295  If you are a package maintainer, please consult `cmake/GtsamPybindWrap.cmake`, line 74 for details.";
296  } else {
297  message_ =
298  "Attempting to retrieve value with key \"" + DefaultKeyFormatter(key_) + "\", type stored in Values is " +
299  storedTypeName + " but requested type was " + requestedTypeName;
300  }
301  }
302  return message_.c_str();
303  }
304 
305  /* ************************************************************************* */
306  const char* NoMatchFoundForFixed::what() const noexcept {
307  if(message_.empty()) {
308  ostringstream oss;
309  oss
310  << "Attempting to retrieve fixed-size matrix with dimensions " //
311  << M1_ << "x" << N1_
312  << ", but found dynamic Matrix with mismatched dimensions " //
313  << M2_ << "x" << N2_;
314  message_ = oss.str();
315  }
316  return message_.c_str();
317  }
318 
319 }
gtsam::Value::equals_
virtual bool equals_(const Value &other, double tol=1e-9) const =0
gtsam::Values::exists
bool exists(Key j) const
Definition: Values.cpp:94
gtsam::Values::dims
std::map< Key, size_t > dims() const
Definition: Values.cpp:252
gtsam::Values::keys
KeyVector keys() const
Definition: Values.cpp:219
gtsam::DynamicValuesMismatched
Definition: Values.h:484
gtsam::Values::size
size_t size() const
Definition: Values.h:178
gtsam::ValuesIncorrectType
Definition: Values.h:453
gtsam::FastSet::exists
bool exists(const VALUE &e) const
Definition: FastSet.h:98
gtsam::Values::retractMasked
void retractMasked(const VectorValues &delta, const KeySet &mask)
Definition: Values.cpp:104
gtsam::Value::deallocate_
virtual void deallocate_() const =0
gtsam::FastSet< Key >
gtsam::Values::update
void update(Key j, const Value &val)
Definition: Values.cpp:170
gtsam::Vector
Eigen::VectorXd Vector
Definition: Vector.h:39
gtsam::KeyVector
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:92
result
Values result
Definition: OdometryOptimize.cpp:8
gtsam::Values::values_
KeyValueMap values_
Definition: Values.h:79
gtsam::Values::Values
Values()=default
gtsam::Values::localCoordinates
VectorValues localCoordinates(const Values &cp) const
Definition: Values.cpp:130
gtsam::DefaultKeyFormatter
KeyFormatter DefaultKeyFormatter
Assign default key formatter.
Definition: Key.cpp:30
gtsam::VectorValues::const_iterator
Values::const_iterator const_iterator
Const iterator over vector values.
Definition: VectorValues.h:85
gtsam::Values::at
const ValueType at(Key j) const
Definition: Values-inl.h:261
gtsam::Values::retract
Values retract(const VectorValues &delta) const
Definition: Values.cpp:99
gtsam.examples.PlanarManipulatorExample.delta
def delta(g0, g1)
Definition: PlanarManipulatorExample.py:45
gtsam::Value::clone_
virtual Value * clone_() const =0
gtsam::VectorValues
Definition: VectorValues.h:74
j
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2
gtsam::KeyFormatter
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition: Key.h:35
gtsam::ValuesKeyDoesNotExist::what
const GTSAM_EXPORT char * what() const noexcept override
The message to be displayed to the user.
Definition: Values.cpp:277
gtsam::Value
Definition: Value.h:39
gtsam::Values::dim
size_t dim() const
Definition: Values.cpp:243
gtsam::Values::equals
bool equals(const Values &other, double tol=1e-9) const
Definition: Values.cpp:78
gtsam::NoMatchFoundForFixed::what
const GTSAM_EXPORT char * what() const noexcept override
Definition: Values.cpp:306
VectorValues.h
Factor Graph Values.
gtsam::ValuesKeyAlreadyExists
Definition: Values.h:408
str
Definition: pytypes.h:1558
key
const gtsam::Symbol key('X', 0)
gtsam::Values::zeroVectors
VectorValues zeroVectors() const
Definition: Values.cpp:261
move
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
Definition: cast.h:1243
gtsam::Values::keySet
KeySet keySet() const
Definition: Values.cpp:228
Values
std::vector< float > Values
Definition: sparse_setter.cpp:45
gtsam::Values::print
void print(const std::string &str="", const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
Definition: Values.cpp:67
gtsam
traits
Definition: SFMdata.h:40
gtsam::Values
Definition: Values.h:65
gtsam::ValuesKeyAlreadyExists::what
const GTSAM_EXPORT char * what() const noexcept override
The message to be displayed to the user.
Definition: Values.cpp:269
gtsam::demangle
std::string demangle(const char *name)
Pretty print Value type name.
Definition: types.cpp:37
std
Definition: BFloat16.h:88
gtsam::Values::clear
void clear()
Definition: Values.h:347
gtsam::Values::insert
void insert(Key j, const Value &val)
Definition: Values.cpp:156
gtsam::VectorValues::size
size_t size() const
Definition: VectorValues.h:130
gtsam::ValuesKeyDoesNotExist
Definition: Values.h:430
v
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
gtsam::tol
const G double tol
Definition: Group.h:79
gtsam::Values::erase
void erase(Key j)
Definition: Values.cpp:211
gtsam::Key
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:97
gtsam::ValuesIncorrectType::what
const GTSAM_EXPORT char * what() const noexcept override
The message to be displayed to the user.
Definition: Values.cpp:286
insert
A insert(1, 2)=0
init
Definition: TutorialInplaceLU.cpp:2
gtsam::Values::operator=
Values & operator=(const Values &rhs)
Definition: Values.cpp:236
gtsam::Value::retract_
virtual Value * retract_(const Vector &delta) const =0
test_callbacks.value
value
Definition: test_callbacks.py:160
pybind_wrapper_test_script.other
other
Definition: pybind_wrapper_test_script.py:42
Values.h
A non-templated config holding any types of Manifold-group elements.
gttic
#define gttic(label)
Definition: timing.h:295
gtsam::Values::insert_or_assign
void insert_or_assign(Key j, const Value &val)
If key j exists, update value, else perform an insert.
Definition: Values.cpp:193


gtsam
Author(s):
autogenerated on Sun Dec 22 2024 04:18:23