313 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			313 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
| /* ----------------------------------------------------------------------------
 | |
| 
 | |
|  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
 | |
|  * Atlanta, Georgia 30332-0415
 | |
|  * All Rights Reserved
 | |
|  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
 | |
| 
 | |
|  * See LICENSE for the license information
 | |
| 
 | |
|  * -------------------------------------------------------------------------- */
 | |
| 
 | |
| /**
 | |
|  * @file DynamicValues.h
 | |
|  * @author Richard Roberts
 | |
|  *
 | |
|  * @brief A non-templated config holding any types of Manifold-group elements
 | |
|  *
 | |
|  *  Detailed story:
 | |
|  *  A values structure is a map from keys to values. It is used to specify the value of a bunch
 | |
|  *  of variables in a factor graph. A Values is a values structure which can hold variables that
 | |
|  *  are elements on manifolds, not just vectors. It then, as a whole, implements a aggregate type
 | |
|  *  which is also a manifold element, and hence supports operations dim, retract, and localCoordinates.
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <string>
 | |
| 
 | |
| #include <gtsam/base/Value.h>
 | |
| #include <gtsam/base/FastMap.h>
 | |
| #include <gtsam/linear/VectorValues.h>
 | |
| #include <gtsam/nonlinear/Key.h>
 | |
| #include <gtsam/nonlinear/Ordering.h>
 | |
| 
 | |
| namespace gtsam {
 | |
| 
 | |
|   class DynamicValues {
 | |
| 
 | |
|   private:
 | |
| 
 | |
|     typedef std::auto_ptr<const Value> ValuePtr;
 | |
|     typedef FastMap<Symbol, std::auto_ptr<const Value> > KeyValueMap;
 | |
|     typedef KeyValueMap::value_type KeyValuePair;
 | |
|     KeyValueMap values_;
 | |
| 
 | |
|   public:
 | |
| 
 | |
|     typedef KeyValueMap::iterator iterator;
 | |
|     typedef KeyValueMap::const_iterator const_iterator;
 | |
|     typedef KeyValueMap::reverse_iterator reverse_iterator;
 | |
|     typedef KeyValueMap::const_reverse_iterator const_reverse_iterator;
 | |
| 
 | |
|     /** Default constructor creates an empty DynamicValues class */
 | |
|     DynamicValues() {}
 | |
| 
 | |
|     /** Copy constructor duplicates all keys and values */
 | |
|     DynamicValues(const DynamicValues& other);
 | |
| 
 | |
|     /// @name Testable
 | |
|     /// @{
 | |
| 
 | |
|     /** print method for testing and debugging */
 | |
|     void print(const std::string& str = "") const;
 | |
| 
 | |
|     /** Test whether the sets of keys and values are identical */
 | |
|     bool equals(const DynamicValues& other, double tol=1e-9) const;
 | |
| 
 | |
|     /// @}
 | |
| 
 | |
|     /** Retrieve a variable by key \c j.  The type of the value associated with
 | |
|      * this key is supplied as a template argument to this function.
 | |
|      * @param j Retrieve the value associated with this key
 | |
|      * @tparam Value The type of the value stored with this key, this method
 | |
|      * throws DynamicValuesIncorrectType if this requested type is not correct.
 | |
|      * @return A const reference to the stored value
 | |
|      */
 | |
|     template<typename Value>
 | |
|     const Value& at(const Symbol& j) const;
 | |
| 
 | |
|     /** Retrieve a variable using a special key (typically TypedSymbol), which
 | |
|      * contains the type of the value associated with the key, and which must
 | |
|      * be conversion constructible to a Symbol, e.g.
 | |
|      * <tt>Symbol(const TypedKey&)</tt>.  Throws DynamicValuesKeyDoesNotExist
 | |
|      * the key is not found, and DynamicValuesIncorrectType if the value type
 | |
|      * associated with the requested key does not match the stored value type.
 | |
|      */
 | |
|     template<class TypedKey>
 | |
|     const typename TypedKey::Value& at(const TypedKey& j) const;
 | |
| 
 | |
|     /** operator[] syntax for at(const TypedKey& j) */
 | |
|     template<class TypedKey>
 | |
|     const typename TypedKey::Value& operator[](const TypedKey& j) const {
 | |
|       return at(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
 | |
|      * exists. */
 | |
|     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<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.
 | |
|      * Uses a special key (typically TypedSymbol), which contains the type of
 | |
|      * the value associated with the key, and which must be conversion
 | |
|      * constructible to a Symbol, e.g. <tt>Symbol(const TypedKey&)</tt>. Throws
 | |
|      * DynamicValuesIncorrectType if the value type associated with the
 | |
|      * requested key does not match the stored value type.
 | |
|      */
 | |
|     template<class TypedKey>
 | |
|     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(); }
 | |
| 
 | |
|     /** whether the config is empty */
 | |
|     bool empty() const { return values_.empty(); }
 | |
| 
 | |
|     /** Get a zero VectorValues of the correct structure */
 | |
|     VectorValues zeroVectors(const Ordering& ordering) const;
 | |
| 
 | |
|     const_iterator begin() const { return values_.begin(); }
 | |
|     const_iterator end() const { return values_.end(); }
 | |
|     iterator begin() { return values_.begin(); }
 | |
|     iterator end() { return values_.end(); }
 | |
|     const_reverse_iterator rbegin() const { return values_.rbegin(); }
 | |
|     const_reverse_iterator rend() const { return values_.rend(); }
 | |
|     reverse_iterator rbegin() { return values_.rbegin(); }
 | |
|     reverse_iterator rend() { return values_.rend(); }
 | |
| 
 | |
|     /// @name Manifold Operations
 | |
|     /// @{
 | |
| 
 | |
|     /** Add a delta config to current config and returns a new config */
 | |
|     DynamicValues retract(const VectorValues& delta, const Ordering& ordering) const;
 | |
| 
 | |
|     /** Get a delta config about a linearization point c0 (*this) */
 | |
|     VectorValues localCoordinates(const DynamicValues& cp, const Ordering& ordering) const;
 | |
| 
 | |
|     /** Get a delta config about a linearization point c0 (*this) */
 | |
|     void localCoordinates(const DynamicValues& cp, const Ordering& ordering, VectorValues& delta) const;
 | |
| 
 | |
|     ///@}
 | |
| 
 | |
|     // imperative methods:
 | |
| 
 | |
|     /** Add a variable with the given j, throws KeyAlreadyExists<J> if j is already present */
 | |
|     template<class ValueType>
 | |
|     void insert(const Symbol& j, const ValueType& val);
 | |
| 
 | |
|     /** Add a set of variables, throws KeyAlreadyExists<J> if a key is already present */
 | |
|     void insert(const DynamicValues& cfg);
 | |
| 
 | |
|     /** update the current available values without adding new ones */
 | |
|     void update(const DynamicValues& cfg);
 | |
| 
 | |
|     /** single element change of existing element */
 | |
|     template<class ValueType>
 | |
|     void update(const Symbol& j, const ValueType& val);
 | |
| 
 | |
|     /** Remove a variable from the config, throws KeyDoesNotExist<J> if j is not present */
 | |
|     void erase(const Symbol& j);
 | |
| 
 | |
|     /** Remove a variable from the config while returning the dimensionality of
 | |
|      * the removed element (normally not needed by user code), throws
 | |
|      * KeyDoesNotExist<J> if j is not present.
 | |
|      */
 | |
|     //void erase(const J& j, size_t& dim);
 | |
| 
 | |
|     /**
 | |
|      * Returns a set of keys in the config
 | |
|      * Note: by construction, the list is ordered
 | |
|      */
 | |
|     std::list<Symbol> keys() const;
 | |
| 
 | |
|     /** Replace all keys and variables */
 | |
|     DynamicValues& operator=(const DynamicValues& rhs) {
 | |
|       values_ = rhs.values_;
 | |
|       return (*this);
 | |
|     }
 | |
| 
 | |
|     /** Remove all variables from the config */
 | |
|     void clear() {
 | |
|       values_.clear();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Apply a class with an application operator() to a const_iterator over
 | |
|      * every <key,value> pair.  The operator must be able to handle such an
 | |
|      * iterator for every type in the Values, (i.e. through templating).
 | |
|      */
 | |
|     template<typename A>
 | |
|     void apply(A& operation) {
 | |
|       for(iterator it = begin(); it != end(); ++it)
 | |
|         operation(it);
 | |
|     }
 | |
|     template<typename A>
 | |
|     void apply(A& operation) const {
 | |
|       for(const_iterator it = begin(); it != end(); ++it)
 | |
|         operation(it);
 | |
|     }
 | |
| 
 | |
|     /** Create an array of variable dimensions using the given ordering */
 | |
|     std::vector<size_t> dims(const Ordering& ordering) const;
 | |
| 
 | |
|     /**
 | |
|      * Generate a default ordering, simply in key sort order.  To instead
 | |
|      * create a fill-reducing ordering, use
 | |
|      * NonlinearFactorGraph::orderingCOLAMD().  Alternatively, you may permute
 | |
|      * this ordering yourself (as orderingCOLAMD() does internally).
 | |
|      */
 | |
|     Ordering::shared_ptr orderingArbitrary(Index firstVar = 0) const;
 | |
| 
 | |
|   };
 | |
| 
 | |
|   /* ************************************************************************* */
 | |
|   class DynamicValuesKeyAlreadyExists : public std::exception {
 | |
|   protected:
 | |
|     const Symbol key_; ///< The key that already existed
 | |
| 
 | |
|   private:
 | |
|     mutable std::string message_;
 | |
| 
 | |
|   public:
 | |
|     /// Construct with the key-value pair attemped to be added
 | |
|     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 message to be displayed to the user
 | |
|     virtual const char* what() const throw();
 | |
|   };
 | |
| 
 | |
|   /* ************************************************************************* */
 | |
|   class DynamicValuesKeyDoesNotExist : public std::exception {
 | |
|   protected:
 | |
|     const char* operation_; ///< The operation that attempted to access the key
 | |
|     const Symbol key_; ///< The key that does not exist
 | |
| 
 | |
|   private:
 | |
|     mutable std::string message_;
 | |
| 
 | |
|   public:
 | |
|     /// Construct with the key that does not exist in the values
 | |
|     DynamicValuesKeyDoesNotExist(const char* operation, const Symbol& key) throw() :
 | |
|       operation_(operation), key_(key) {}
 | |
| 
 | |
|     virtual ~DynamicValuesKeyDoesNotExist() throw() {}
 | |
| 
 | |
|     /// The key that was attempted to be accessed that does not exist
 | |
|     const Symbol& key() const throw() { return key_; }
 | |
| 
 | |
|     /// The message to be displayed to the user
 | |
|     virtual const char* what() const throw();
 | |
|   };
 | |
| 
 | |
|   /* ************************************************************************* */
 | |
|   class DynamicValuesIncorrectType : public std::exception {
 | |
|   protected:
 | |
|     const Symbol key_; ///< The key requested
 | |
|     const std::type_info& storedTypeId_;
 | |
|     const std::type_info& requestedTypeId_;
 | |
| 
 | |
|   private:
 | |
|     mutable std::string message_;
 | |
| 
 | |
|   public:
 | |
|     /// Construct with the key that does not exist in the values
 | |
|     DynamicValuesIncorrectType(const Symbol& key,
 | |
|         const std::type_info& storedTypeId, const std::type_info& requestedTypeId) throw() :
 | |
|       key_(key), storedTypeId_(storedTypeId), requestedTypeId_(requestedTypeId) {}
 | |
| 
 | |
|     virtual ~DynamicValuesIncorrectType() throw() {}
 | |
| 
 | |
|     /// The key that was attempted to be accessed that does not exist
 | |
|     const Symbol& key() const throw() { return key_; }
 | |
| 
 | |
|     /// The typeid of the value stores in the DynamicValues
 | |
|     const std::type_info& storedTypeId() const { return storedTypeId_; }
 | |
| 
 | |
|     /// The requested typeid
 | |
|     const std::type_info& requestedTypeId() const { return requestedTypeId_; }
 | |
| 
 | |
|     /// The message to be displayed to the user
 | |
|     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>
 |