(in branch) more implementation for DynamicValues
parent
ef8a82c8d7
commit
d323d5b963
|
@ -35,4 +35,74 @@ namespace gtsam {
|
||||||
return message_.c_str();
|
return message_.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<typename Value>
|
||||||
|
const Value& DynamicValues::at(const Symbol& j) const {
|
||||||
|
// Find the item
|
||||||
|
const_iterator item = values_.find(j);
|
||||||
|
|
||||||
|
// Throw exception if it does not exist
|
||||||
|
if(item == values_.end())
|
||||||
|
throw DynamicValuesKeyDoesNotExist("retrieve", j);
|
||||||
|
|
||||||
|
// Check the type and throw exception if incorrect
|
||||||
|
if(typeid(*item->second) != typeid(Value))
|
||||||
|
throw DynamicValuesIncorrectType(j, typeid(*item->second), typeid(Value));
|
||||||
|
|
||||||
|
// We have already checked the type, so do a "blind" static_cast, not dynamic_cast
|
||||||
|
return static_cast<const Value&>(*item->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<typename TypedKey>
|
||||||
|
const typename TypedKey::Value& DynamicValues::at(const TypedKey& j) const {
|
||||||
|
// Convert to Symbol
|
||||||
|
const Symbol symbol(j.symbol());
|
||||||
|
|
||||||
|
// Call at with the Value type from the key
|
||||||
|
return at<typename TypedKey::Value>(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<typename Value>
|
||||||
|
boost::optional<Value> DynamicValues::exists(const Symbol& j) const {
|
||||||
|
// Find the item
|
||||||
|
const_iterator item = values_.find(j);
|
||||||
|
|
||||||
|
if(item != values_.end()) {
|
||||||
|
// Check the type and throw exception if incorrect
|
||||||
|
if(typeid(*item->second) != typeid(Value))
|
||||||
|
throw DynamicValuesIncorrectType(j, typeid(*item->second), typeid(Value));
|
||||||
|
|
||||||
|
// We have already checked the type, so do a "blind" static_cast, not dynamic_cast
|
||||||
|
return static_cast<const Value&>(*item->second);
|
||||||
|
} else {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class TypedKey>
|
||||||
|
boost::optional<const typename TypedKey::Value&> exists(const TypedKey& j) const {
|
||||||
|
// Convert to Symbol
|
||||||
|
const Symbol symbol(j.symbol());
|
||||||
|
|
||||||
|
// Call exists with the Value type from the key
|
||||||
|
return exists<typename TypedKey::Value>(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class ValueType>
|
||||||
|
void DynamicValues::insert(const Symbol& j, const ValueType& val) {
|
||||||
|
pair<iterator,bool> insertResult = values_.insert(make_pair(j, ValuePtr(new ValueType(val))));
|
||||||
|
if(!insertResult.second)
|
||||||
|
throw DynamicValuesKeyAlreadyExists(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
void DynamicValues::insert(const DynamicValues& values) {
|
||||||
|
BOOST_FOREACH(const KeyValuePair& key_value, values) {
|
||||||
|
insert(key_value.first, key_value.)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,12 @@ using namespace std;
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
DynamicValues::DynamicValues(const DynamicValues& other) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
void DynamicValues::print(const string& str) const {
|
void DynamicValues::print(const string& str) const {
|
||||||
cout << str << "DynamicValues with " << size() << " values:\n" << endl;
|
cout << str << "DynamicValues with " << size() << " values:\n" << endl;
|
||||||
BOOST_FOREACH(const KeyValueMap::value_type& key_value, values_) {
|
BOOST_FOREACH(const KeyValueMap::value_type& key_value, values_) {
|
||||||
|
@ -38,10 +44,61 @@ namespace gtsam {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
bool DynamicValues::equals(const DynamicValues& other, double tol) const {
|
bool DynamicValues::equals(const DynamicValues& other, double tol) const {
|
||||||
if(this->size() != other.size())
|
if(this->size() != other.size())
|
||||||
return false;
|
return false;
|
||||||
for(const_iterator it1=this->begin(), it2=other.begin(); it1!=this->end(); ++it1, ++it2)
|
for(const_iterator it1=this->begin(), it2=other.begin(); it1!=this->end(); ++it1, ++it2) {
|
||||||
|
if(typeid(*it1->second) != typeid(*it2->second))
|
||||||
|
return false;
|
||||||
|
if(it1->first != it2->first)
|
||||||
|
return false;
|
||||||
|
if(!it1->second->equals_(*it2->second, tol))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true; // We return false earlier if we find anything that does not match
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
bool DynamicValues::exists(const Symbol& j) const {
|
||||||
|
return values_.find(j) != values_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
VectorValues DynamicValues::zeroVectors(const Ordering& ordering) const {
|
||||||
|
return VectorValues::Zero(this->dims(ordering));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
DynamicValues DynamicValues::retract(const VectorValues& delta, const Ordering& ordering) const {
|
||||||
|
DynamicValues result;
|
||||||
|
|
||||||
|
BOOST_FOREACH(const KeyValuePair& key_value, values_) {
|
||||||
|
const SubVector& singleDelta = delta[ordering[key_value.first]]; // Delta for this value
|
||||||
|
const std::auto_ptr<const Value> retractedValue = key_value.second->retract_(singleDelta); // Retract
|
||||||
|
result.values_.insert(make_pair(key_value.first, retractedValue)); // Add retracted result directly to result values
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
VectorValues DynamicValues::localCoordinates(const DynamicValues& cp, const Ordering& ordering) const {
|
||||||
|
VectorValues result(this->dims(ordering));
|
||||||
|
localCoordinates(cp, ordering, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
void DynamicValues::localCoordinates(const DynamicValues& cp, const Ordering& ordering, VectorValues& result) const {
|
||||||
|
if(this->size() != cp.size())
|
||||||
|
throw DynamicValuesMismatched();
|
||||||
|
for(const_iterator it1=this->begin(), it2=other.begin(); it1!=this->end(); ++it1, ++it2) {
|
||||||
|
if(it1->first != it2->first)
|
||||||
|
throw DynamicValuesMismatched(); // If keys do not match
|
||||||
|
result[ordering[it1->first]] = it1->second->localCoordinates_(*it2->second); // Will throw a dynamic_cast exception if types do not match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,9 @@ namespace gtsam {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef FastMap<Symbol, std::auto_ptr<Value> > KeyValueMap;
|
typedef std::auto_ptr<const Value> ValuePtr;
|
||||||
|
typedef FastMap<Symbol, std::auto_ptr<const Value> > KeyValueMap;
|
||||||
|
typedef KeyValueMap::value_type KeyValuePair;
|
||||||
KeyValueMap values_;
|
KeyValueMap values_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -52,7 +54,7 @@ namespace gtsam {
|
||||||
DynamicValues() {}
|
DynamicValues() {}
|
||||||
|
|
||||||
/** Copy constructor duplicates all keys and values */
|
/** Copy constructor duplicates all keys and values */
|
||||||
DynamicValues(const DynamicValues& other) {}
|
DynamicValues(const DynamicValues& other);
|
||||||
|
|
||||||
/// @name Testable
|
/// @name Testable
|
||||||
/// @{
|
/// @{
|
||||||
|
@ -93,14 +95,14 @@ namespace gtsam {
|
||||||
/** Check if a value exists with key \c j. See exists<>(const Symbol& j)
|
/** Check if a value exists with key \c j. See exists<>(const Symbol& j)
|
||||||
* and exists(const TypedKey& j) for versions that return the value if it
|
* and exists(const TypedKey& j) for versions that return the value if it
|
||||||
* exists. */
|
* exists. */
|
||||||
bool exists(const Symbol& i) const;
|
bool exists(const Symbol& j) const;
|
||||||
|
|
||||||
/** Check if a value with key \c j exists, returns the value with type
|
/** Check if a value with key \c j exists, returns the value with type
|
||||||
* \c Value if the key does exist, or boost::none if it does not exist.
|
* \c Value if the key does exist, or boost::none if it does not exist.
|
||||||
* Throws DynamicValuesIncorrectType if the value type associated with the
|
* Throws DynamicValuesIncorrectType if the value type associated with the
|
||||||
* requested key does not match the stored value type. */
|
* requested key does not match the stored value type. */
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
boost::optional<Value> exists(const Symbol& j) const;
|
boost::optional<const Value&> exists(const Symbol& j) const;
|
||||||
|
|
||||||
/** Check if a value with key \c j exists, returns the value with type
|
/** Check if a value with key \c j exists, returns the value with type
|
||||||
* \c Value if the key does exist, or boost::none if it does not exist.
|
* \c Value if the key does exist, or boost::none if it does not exist.
|
||||||
|
@ -111,7 +113,7 @@ namespace gtsam {
|
||||||
* requested key does not match the stored value type.
|
* requested key does not match the stored value type.
|
||||||
*/
|
*/
|
||||||
template<class TypedKey>
|
template<class TypedKey>
|
||||||
boost::optional<typename TypedKey::Value> exists(const TypedKey& j) const;
|
boost::optional<const typename TypedKey::Value&> exists(const TypedKey& j) const;
|
||||||
|
|
||||||
/** The number of variables in this config */
|
/** The number of variables in this config */
|
||||||
size_t size() const { return values_.size(); }
|
size_t size() const { return values_.size(); }
|
||||||
|
@ -120,7 +122,7 @@ namespace gtsam {
|
||||||
bool empty() const { return values_.empty(); }
|
bool empty() const { return values_.empty(); }
|
||||||
|
|
||||||
/** Get a zero VectorValues of the correct structure */
|
/** Get a zero VectorValues of the correct structure */
|
||||||
VectorValues zero(const Ordering& ordering) const;
|
VectorValues zeroVectors(const Ordering& ordering) const;
|
||||||
|
|
||||||
const_iterator begin() const { return values_.begin(); }
|
const_iterator begin() const { return values_.begin(); }
|
||||||
const_iterator end() const { return values_.end(); }
|
const_iterator end() const { return values_.end(); }
|
||||||
|
@ -134,9 +136,6 @@ namespace gtsam {
|
||||||
/// @name Manifold Operations
|
/// @name Manifold Operations
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/** The dimensionality of the tangent space */
|
|
||||||
size_t dim() const;
|
|
||||||
|
|
||||||
/** Add a delta config to current config and returns a new config */
|
/** Add a delta config to current config and returns a new config */
|
||||||
DynamicValues retract(const VectorValues& delta, const Ordering& ordering) const;
|
DynamicValues retract(const VectorValues& delta, const Ordering& ordering) const;
|
||||||
|
|
||||||
|
@ -220,28 +219,23 @@ namespace gtsam {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<class ValueType>
|
|
||||||
class DynamicValuesKeyAlreadyExists : public std::exception {
|
class DynamicValuesKeyAlreadyExists : public std::exception {
|
||||||
protected:
|
protected:
|
||||||
const Symbol key_; ///< The key that already existed
|
const Symbol key_; ///< The key that already existed
|
||||||
const Value value_; ///< The value attempted to be inserted
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable std::string message_;
|
mutable std::string message_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Construct with the key-value pair attemped to be added
|
/// Construct with the key-value pair attemped to be added
|
||||||
DynamicValuesKeyAlreadyExists(const Symbol& key, const Value& value) throw() :
|
DynamicValuesKeyAlreadyExists(const Symbol& key) throw() :
|
||||||
key_(key), value_(value) {}
|
key_(key) {}
|
||||||
|
|
||||||
virtual ~DynamicValuesKeyAlreadyExists() throw() {}
|
virtual ~DynamicValuesKeyAlreadyExists() throw() {}
|
||||||
|
|
||||||
/// The duplicate key that was attemped to be added
|
/// The duplicate key that was attemped to be added
|
||||||
const Symbol& key() const throw() { return key_; }
|
const Symbol& key() const throw() { return key_; }
|
||||||
|
|
||||||
/// The value that was attempted to be added
|
|
||||||
const Value& value() const throw() { return value_; }
|
|
||||||
|
|
||||||
/// The message to be displayed to the user
|
/// The message to be displayed to the user
|
||||||
virtual const char* what() const throw();
|
virtual const char* what() const throw();
|
||||||
};
|
};
|
||||||
|
@ -300,6 +294,19 @@ namespace gtsam {
|
||||||
virtual const char* what() const throw();
|
virtual const char* what() const throw();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
class DynamicValuesMismatched : public std::exception {
|
||||||
|
|
||||||
|
public:
|
||||||
|
DynamicValuesMismatched() throw() {}
|
||||||
|
|
||||||
|
virtual ~DynamicValuesMismatched() throw() {}
|
||||||
|
|
||||||
|
virtual const char* what() const throw() {
|
||||||
|
return "The Values 'this' and the argument passed to DynamicValues::localCoordinates have mismatched keys and values";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <gtsam/nonlinear/DynamicValues-inl.h>
|
#include <gtsam/nonlinear/DynamicValues-inl.h>
|
||||||
|
|
|
@ -76,6 +76,7 @@ public:
|
||||||
std::string latex() const {
|
std::string latex() const {
|
||||||
return (boost::format("%c_{%d}") % C % j_).str();
|
return (boost::format("%c_{%d}") % C % j_).str();
|
||||||
}
|
}
|
||||||
|
Symbol symbol() const;
|
||||||
|
|
||||||
// logic:
|
// logic:
|
||||||
|
|
||||||
|
@ -298,6 +299,9 @@ public:
|
||||||
std::string label_s = (boost::format("%1%") % label_).str();
|
std::string label_s = (boost::format("%1%") % label_).str();
|
||||||
return (boost::format("%c%s_{%d}") % C % label_s % this->j_).str();
|
return (boost::format("%c%s_{%d}") % C % label_s % this->j_).str();
|
||||||
}
|
}
|
||||||
|
Symbol symbol() const {
|
||||||
|
return Symbol(*this);
|
||||||
|
}
|
||||||
|
|
||||||
// Needed for conversion to LabeledSymbol
|
// Needed for conversion to LabeledSymbol
|
||||||
size_t convertLabel() const {
|
size_t convertLabel() const {
|
||||||
|
@ -354,5 +358,11 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
template<class T, char C>
|
||||||
|
Symbol TypedSymbol<T,C>::symbol() const {
|
||||||
|
return Symbol(*this);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace gtsam
|
} // namespace gtsam
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue