diff --git a/core/include/moveit/task_constructor/properties.h b/core/include/moveit/task_constructor/properties.h index 1599515b..643f0f88 100644 --- a/core/include/moveit/task_constructor/properties.h +++ b/core/include/moveit/task_constructor/properties.h @@ -60,8 +60,12 @@ enum PropertyInitializerSource { /** Property is a wrapper for a boost::any value, also providing a default value and a description. * - * Properties can be configured to be initialized from another PropertyMap. + * Properties can be configured to be initialized from another PropertyMap - if still undefined. * Potential sources are the properties of the parent of a stage, or the properties passed in the interface. + * + * Setting the value via setValue() updates both, the current value and the default value. + * Using reset() the default value can be restored. + * Using setCurrentValue() only updates the current value, allowing for later reset to the original default. */ class Property { friend class PropertyMap; @@ -72,11 +76,23 @@ public: Property(const std::type_index& type_index, const std::string& description, const boost::any& default_value); + /// set current value and default value void setValue(const boost::any& value); + void setCurrentValue(const boost::any& value); - const boost::any& value() const; + /// reset to default value (which can be empty) + void reset(); + + inline bool defined() const { return !value_.empty(); } + + /// get current value + inline const boost::any& value() const { return value_; } + /// get default value const boost::any& defaultValue() const { return default_; } + + /// get description text const std::string& description() const { return description_; } + /// get typename std::string typeName() const { return type_index_.name(); } /// configure initialization from source using an arbitrary function @@ -84,6 +100,9 @@ public: /// configure initialization from source using given other property name Property &configureInitFrom(PropertyInitializerSource source, const std::string& name); + /// set current value using configured initializers + void performInitFrom(PropertyInitializerSource source, const PropertyMap& other); + private: std::string description_; std::type_index type_index_; @@ -127,8 +146,10 @@ public: /// allow initialization from given source for listed properties - always using the same name void configureInitFrom(PropertyInitializerSource source, const std::set &properties = {}); - /// set the value of a property + /// set (and, if neccessary, declare) the value of a property void set(const std::string& name, const boost::any& value); + /// temporarily set the value of a property + void setCurrent(const std::string& name, const boost::any& value); /// get the value of a property const boost::any& get(const std::string& name) const; @@ -143,12 +164,11 @@ public: /// count number of defined properties from given list size_t countDefined(const std::vector& list) const; - /// reset properties to nil, if they have initializers + /// reset all properties to their defaults void reset(); - /// perform initialization of properties using configured initializers - void performInitFrom(PropertyInitializerSource source, const PropertyMap& other, - bool checkConsistency = false); + /// perform initialization of still undefined properties using configured initializers + void performInitFrom(PropertyInitializerSource source, const PropertyMap& other, bool enforce = false); }; } // namespace task_constructor diff --git a/core/src/properties.cpp b/core/src/properties.cpp index 04996f86..e69fdeac 100644 --- a/core/src/properties.cpp +++ b/core/src/properties.cpp @@ -48,6 +48,7 @@ Property::Property(const std::type_index& type_index, const std::string& descrip : description_(description) , type_index_(type_index) , default_(default_value) + , value_(default_value) { if (!default_.empty() && std::type_index(default_.type()) != type_index_) throw std::runtime_error("type of default value doesn't match declared type"); @@ -64,16 +65,24 @@ void typeCheck(const boost::any& value, const std::type_index& type_index) } void Property::setValue(const boost::any &value) { - typeCheck(value, type_index_); - value_ = value; - // clear all initializers when value was explicitly set - initializers_.clear(); + setCurrentValue(value); + default_ = value_; } -const boost::any &Property::value() const { - return value_.empty() ? default_ : value_; +void Property::setCurrentValue(const boost::any &value) +{ + if (!value.empty()) + typeCheck(value, type_index_); + value_ = value; } +void Property::reset() +{ + value_ = default_; +} + + + Property& Property::configureInitFrom(PropertyInitializerSource source, const Property::InitializerFunction &f) { initializers_[source] = f; @@ -86,6 +95,14 @@ Property &Property::configureInitFrom(PropertyInitializerSource source, const st return *this; } +void Property::performInitFrom(PropertyInitializerSource source, const PropertyMap &other) +{ + auto it = initializers_.find(source); + if (it == initializers_.end()) return; + + setCurrentValue(it->second(other)); +} + Property& PropertyMap::declare(const std::string &name, const std::type_info &type, const std::string &description, const boost::any &default_value) @@ -128,6 +145,11 @@ void PropertyMap::set(const std::string &name, const boost::any &value) } } +void PropertyMap::setCurrent(const std::string &name, const boost::any &value) +{ + property(name).setCurrentValue(value); +} + const boost::any &PropertyMap::get(const std::string &name) const { return property(name).value(); @@ -144,31 +166,16 @@ size_t PropertyMap::countDefined(const std::vector &list) const void PropertyMap::reset() { - for (auto& pair : props_) { - Property &p = pair.second; - if (!p.initializers_.empty()) - // if there are initializers, reset property value - // explicitly setting the value, clears initializers - p.value_ = boost::any(); - } + for (auto& pair : props_) + pair.second.reset(); } -void PropertyMap::performInitFrom(PropertyInitializerSource source, const PropertyMap &other, - bool checkConsistency) +void PropertyMap::performInitFrom(PropertyInitializerSource source, const PropertyMap &other, bool enforce) { for (auto& pair : props_) { Property &p = pair.second; - auto it = p.initializers_.find(source); - if (it == p.initializers_.end()) continue; - const boost::any& value = it->second(other); - if (value.empty()) continue; - - typeCheck(value, p.type_index_); -#if 0 // TODO: we cannot generically check for equality of boost::anys - if (checkConsistency && !p.value_.empty() && p.value_ != value) - throw std::runtime_error ("inconsistent values for property '" + pair.first + "'"); -#endif - p.value_ = value; + if (enforce || !p.defined()) + p.performInitFrom(source, other); } }