(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