(in branch) more implementation for DynamicValues
parent
ef8a82c8d7
commit
d323d5b963
|
@ -35,4 +35,74 @@ namespace gtsam {
|
|||
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 {
|
||||
|
||||
/* ************************************************************************* */
|
||||
DynamicValues::DynamicValues(const DynamicValues& other) {
|
||||
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void DynamicValues::print(const string& str) const {
|
||||
cout << str << "DynamicValues with " << size() << " values:\n" << endl;
|
||||
BOOST_FOREACH(const KeyValueMap::value_type& key_value, values_) {
|
||||
|
@ -38,10 +44,61 @@ namespace gtsam {
|
|||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
bool DynamicValues::equals(const DynamicValues& other, double tol) const {
|
||||
if(this->size() != other.size())
|
||||
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:
|
||||
|
||||
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_;
|
||||
|
||||
public:
|
||||
|
@ -52,7 +54,7 @@ namespace gtsam {
|
|||
DynamicValues() {}
|
||||
|
||||
/** Copy constructor duplicates all keys and values */
|
||||
DynamicValues(const DynamicValues& other) {}
|
||||
DynamicValues(const DynamicValues& other);
|
||||
|
||||
/// @name Testable
|
||||
/// @{
|
||||
|
@ -93,14 +95,14 @@ namespace gtsam {
|
|||
/** 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
|
||||
* 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
|
||||
* \c Value if the key does exist, or boost::none if it does not exist.
|
||||
* Throws DynamicValuesIncorrectType if the value type associated with the
|
||||
* requested key does not match the stored value type. */
|
||||
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
|
||||
* \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.
|
||||
*/
|
||||
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 */
|
||||
size_t size() const { return values_.size(); }
|
||||
|
@ -120,7 +122,7 @@ namespace gtsam {
|
|||
bool empty() const { return values_.empty(); }
|
||||
|
||||
/** 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 end() const { return values_.end(); }
|
||||
|
@ -134,9 +136,6 @@ namespace gtsam {
|
|||
/// @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 */
|
||||
DynamicValues retract(const VectorValues& delta, const Ordering& ordering) const;
|
||||
|
||||
|
@ -220,28 +219,23 @@ namespace gtsam {
|
|||
};
|
||||
|
||||
/* ************************************************************************* */
|
||||
template<class ValueType>
|
||||
class DynamicValuesKeyAlreadyExists : public std::exception {
|
||||
protected:
|
||||
const Symbol key_; ///< The key that already existed
|
||||
const Value value_; ///< The value attempted to be inserted
|
||||
|
||||
private:
|
||||
mutable std::string message_;
|
||||
|
||||
public:
|
||||
/// Construct with the key-value pair attemped to be added
|
||||
DynamicValuesKeyAlreadyExists(const Symbol& key, const Value& value) throw() :
|
||||
key_(key), value_(value) {}
|
||||
DynamicValuesKeyAlreadyExists(const Symbol& key) throw() :
|
||||
key_(key) {}
|
||||
|
||||
virtual ~DynamicValuesKeyAlreadyExists() throw() {}
|
||||
|
||||
/// The duplicate key that was attemped to be added
|
||||
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
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
@ -300,6 +294,19 @@ namespace gtsam {
|
|||
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>
|
||||
|
|
|
@ -76,6 +76,7 @@ public:
|
|||
std::string latex() const {
|
||||
return (boost::format("%c_{%d}") % C % j_).str();
|
||||
}
|
||||
Symbol symbol() const;
|
||||
|
||||
// logic:
|
||||
|
||||
|
@ -298,6 +299,9 @@ public:
|
|||
std::string label_s = (boost::format("%1%") % label_).str();
|
||||
return (boost::format("%c%s_{%d}") % C % label_s % this->j_).str();
|
||||
}
|
||||
Symbol symbol() const {
|
||||
return Symbol(*this);
|
||||
}
|
||||
|
||||
// Needed for conversion to LabeledSymbol
|
||||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue