From 109647ca5601fbd55d24af35691d8c4b0df7bf31 Mon Sep 17 00:00:00 2001 From: Davide Faconti Date: Tue, 8 Jan 2019 11:39:46 +0100 Subject: [PATCH] user can now add PortsList to SimpleNodes (discussed in #41) --- examples/t03_sequence_star.cpp | 11 +++++--- include/behaviortree_cpp/bt_factory.h | 40 +++++++++++++++++++++------ sample_nodes/dummy_nodes.cpp | 12 ++++++++ sample_nodes/dummy_nodes.h | 4 +++ src/bt_factory.cpp | 21 ++++++++------ src/xml_parsing.cpp | 20 ++++++-------- 6 files changed, 75 insertions(+), 33 deletions(-) diff --git a/examples/t03_sequence_star.cpp b/examples/t03_sequence_star.cpp index 34b8f5667..a683c8235 100644 --- a/examples/t03_sequence_star.cpp +++ b/examples/t03_sequence_star.cpp @@ -15,7 +15,7 @@ using namespace BT; // clang-format off -const std::string xml_text_sequence = R"( +static const char* xml_text_sequence = R"( @@ -25,14 +25,14 @@ const std::string xml_text_sequence = R"( - + )"; -const std::string xml_text_sequence_star = R"( +static const char* xml_text_sequence_star = R"( @@ -42,7 +42,7 @@ const std::string xml_text_sequence_star = R"( - + @@ -67,6 +67,9 @@ int main() factory.registerNodeType("MoveBase"); factory.registerNodeType("SaySomething"); + PortsList say_something_ports = {{"message", PortType::INPUT}}; + factory.registerSimpleAction("SaySomething2", SaySomethingSimple, say_something_ports ); + // Compare the state transitions and messages using either // xml_text_sequence and xml_text_sequence_star diff --git a/include/behaviortree_cpp/bt_factory.h b/include/behaviortree_cpp/bt_factory.h index 67fd398b7..eadbd4caa 100644 --- a/include/behaviortree_cpp/bt_factory.h +++ b/include/behaviortree_cpp/bt_factory.h @@ -51,19 +51,41 @@ class BehaviorTreeFactory bool unregisterBuilder(const std::string& ID); /// The most generic way to register your own builder. - void registerBuilder(const TreeNodeManifest& manifest, NodeBuilder builder); + void registerBuilder(const TreeNodeManifest& manifest, const NodeBuilder& builder); - /// Register a SimpleActionNode + /** + * @brief registerSimpleAction help you register nodes of type SimpleActionNode. + * + * @param ID registration ID + * @param tick_functor the callback to be invoked in the tick() method. + * @param ports if your SimpleNode requires ports, provide the list here. + * + * */ void registerSimpleAction(const std::string& ID, - const SimpleActionNode::TickFunctor& tick_functor); - - /// Register a SimpleConditionNode + const SimpleActionNode::TickFunctor& tick_functor, + PortsList ports = {}); + /** + * @brief registerSimpleCondition help you register nodes of type SimpleConditionNode. + * + * @param ID registration ID + * @param tick_functor the callback to be invoked in the tick() method. + * @param ports if your SimpleNode requires ports, provide the list here. + * + * */ void registerSimpleCondition(const std::string& ID, - const SimpleConditionNode::TickFunctor& tick_functor); - - /// Register a SimpleDecoratorNode + const SimpleConditionNode::TickFunctor& tick_functor, + PortsList ports = {}); + /** + * @brief registerSimpleDecorator help you register nodes of type SimpleDecoratorNode. + * + * @param ID registration ID + * @param tick_functor the callback to be invoked in the tick() method. + * @param ports if your SimpleNode requires ports, provide the list here. + * + * */ void registerSimpleDecorator(const std::string& ID, - const SimpleDecoratorNode::TickFunctor& tick_functor); + const SimpleDecoratorNode::TickFunctor& tick_functor, + PortsList ports = {}); /** * @brief registerFromPlugin load a shared library and execute the function BT_REGISTER_NODES (see macro). diff --git a/sample_nodes/dummy_nodes.cpp b/sample_nodes/dummy_nodes.cpp index 721cba6ac..3e2c397df 100644 --- a/sample_nodes/dummy_nodes.cpp +++ b/sample_nodes/dummy_nodes.cpp @@ -57,4 +57,16 @@ BT::NodeStatus SaySomething::tick() std::cout << "Robot says: " << msg << std::endl; return BT::NodeStatus::SUCCESS; } + +BT::NodeStatus SaySomethingSimple(BT::TreeNode &self) +{ + std::string msg; + if (!self.getInput("message", msg)) + { + throw BT::RuntimeError("missing required input [message]"); + } + std::cout << "Robot says: " << msg << std::endl; + return BT::NodeStatus::SUCCESS; +} + } diff --git a/sample_nodes/dummy_nodes.h b/sample_nodes/dummy_nodes.h index 331b8a5a0..0918381d1 100644 --- a/sample_nodes/dummy_nodes.h +++ b/sample_nodes/dummy_nodes.h @@ -64,6 +64,10 @@ class SaySomething : public BT::SyncActionNode } }; +//Same as class SaySomething, but to be registered with SimpleActionNode +BT::NodeStatus SaySomethingSimple(BT::TreeNode& self); + + inline void RegisterNodes(BT::BehaviorTreeFactory& factory) { static GripperInterface gi; diff --git a/src/bt_factory.cpp b/src/bt_factory.cpp index 2337d2c41..79f7df835 100644 --- a/src/bt_factory.cpp +++ b/src/bt_factory.cpp @@ -63,7 +63,7 @@ bool BehaviorTreeFactory::unregisterBuilder(const std::string& ID) return true; } -void BehaviorTreeFactory::registerBuilder(const TreeNodeManifest& manifest, NodeBuilder builder) +void BehaviorTreeFactory::registerBuilder(const TreeNodeManifest& manifest, const NodeBuilder& builder) { auto it = builders_.find( manifest.registration_ID); if (it != builders_.end()) @@ -75,36 +75,39 @@ void BehaviorTreeFactory::registerBuilder(const TreeNodeManifest& manifest, Node manifests_.insert( {manifest.registration_ID, manifest} ); } -void BehaviorTreeFactory::registerSimpleCondition( - const std::string& ID, const SimpleConditionNode::TickFunctor& tick_functor) +void BehaviorTreeFactory::registerSimpleCondition(const std::string& ID, + const SimpleConditionNode::TickFunctor& tick_functor, + PortsList ports) { NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeConfiguration& config) { return std::unique_ptr(new SimpleConditionNode(name, tick_functor, config)); }; - TreeNodeManifest manifest = { NodeType::CONDITION, ID, {} }; + TreeNodeManifest manifest = { NodeType::CONDITION, ID, std::move(ports) }; registerBuilder(manifest, builder); } void BehaviorTreeFactory::registerSimpleAction(const std::string& ID, - const SimpleActionNode::TickFunctor& tick_functor) + const SimpleActionNode::TickFunctor& tick_functor, + PortsList ports) { NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeConfiguration& config) { return std::unique_ptr(new SimpleActionNode(name, tick_functor, config)); }; - TreeNodeManifest manifest = { NodeType::ACTION, ID, {} }; + TreeNodeManifest manifest = { NodeType::ACTION, ID, std::move(ports) }; registerBuilder(manifest, builder); } -void BehaviorTreeFactory::registerSimpleDecorator( - const std::string& ID, const SimpleDecoratorNode::TickFunctor& tick_functor) +void BehaviorTreeFactory::registerSimpleDecorator(const std::string& ID, + const SimpleDecoratorNode::TickFunctor& tick_functor, + PortsList ports) { NodeBuilder builder = [tick_functor, ID](const std::string& name, const NodeConfiguration& config) { return std::unique_ptr(new SimpleDecoratorNode(name, tick_functor, config)); }; - TreeNodeManifest manifest = { NodeType::DECORATOR, ID, {} }; + TreeNodeManifest manifest = { NodeType::DECORATOR, ID, std::move(ports) }; registerBuilder(manifest, builder); } diff --git a/src/xml_parsing.cpp b/src/xml_parsing.cpp index 16ea521a0..fac0d5bf7 100644 --- a/src/xml_parsing.cpp +++ b/src/xml_parsing.cpp @@ -431,20 +431,18 @@ TreeNode::Ptr XMLParser::Pimpl::createNodeFromXML(const XMLElement *element, for(const auto& remap_it: remapping_parameters) { const auto& port_name = remap_it.first; - auto port_type = PortType::INOUT; // default if missing from manifest - auto port_it = manifest.ports.find( port_name ); if( port_it != manifest.ports.end() ) { - port_type = port_it->second; - } - if( port_type != PortType::OUTPUT ) - { - config.input_ports.insert( remap_it ); - } - if( port_type != PortType::INPUT ) - { - config.output_ports.insert( remap_it ); + auto port_type = port_it->second; + if( port_type != PortType::OUTPUT ) + { + config.input_ports.insert( remap_it ); + } + if( port_type != PortType::INPUT ) + { + config.output_ports.insert( remap_it ); + } } } child_node = factory.instantiateTreeNode(instance_name, ID, config);