t03_generic_ports.cpp
Go to the documentation of this file.
00001 #include "behaviortree_cpp/bt_factory.h"
00002 
00003 using namespace BT;
00004 
00005 /* This tutorial will teach you how to deal with ports when its
00006  *  type is not std::string.
00007 */
00008 
00009 
00010 // We want to be able to use this custom type
00011 struct Position2D { double x,y; };
00012 
00013 // It is recommended (or, in some cases, mandatory) to define a template
00014 // specialization of convertFromString that converts a string to Position2D.
00015 namespace BT
00016 {
00017 template <> inline Position2D convertFromString(StringView str)
00018 {
00019     printf("Converting string: \"%s\"\n", str.data() );
00020 
00021     // real numbers separated by semicolons
00022     auto parts = splitString(str, ';');
00023     if (parts.size() != 2)
00024     {
00025         throw RuntimeError("invalid input)");
00026     }
00027     else{
00028         Position2D output;
00029         output.x     = convertFromString<double>(parts[0]);
00030         output.y     = convertFromString<double>(parts[1]);
00031         return output;
00032     }
00033 }
00034 } // end namespace BT
00035 
00036 
00037 class CalculateGoal: public SyncActionNode
00038 {
00039 public:
00040     CalculateGoal(const std::string& name, const NodeConfiguration& config):
00041         SyncActionNode(name,config)
00042     {}
00043 
00044     NodeStatus tick() override
00045     {
00046         Position2D mygoal = {1.1, 2.3};
00047         setOutput("goal", mygoal);
00048         return NodeStatus::SUCCESS;
00049     }
00050     static PortsList providedPorts()
00051     {
00052         return { OutputPort<Position2D>("goal") };
00053     }
00054 };
00055 
00056 
00057 class PrintTarget: public SyncActionNode
00058 {
00059 public:
00060     PrintTarget(const std::string& name, const NodeConfiguration& config):
00061         SyncActionNode(name,config)
00062     {}
00063 
00064     NodeStatus tick() override
00065     {
00066         auto res = getInput<Position2D>("target");
00067         if( !res )
00068         {
00069             throw RuntimeError("error reading port [target]:", res.error() );
00070         }
00071         Position2D goal = res.value();
00072         printf("Target positions: [ %.1f, %.1f ]\n", goal.x, goal.y );
00073         return NodeStatus::SUCCESS;
00074     }
00075 
00076     static PortsList providedPorts()
00077     {
00078         // Optionally, a port can have a human readable description
00079         const char*  description = "Simply print the target on console...";
00080         return { InputPort<Position2D>("target", description) };
00081     }
00082 };
00083 
00084 //----------------------------------------------------------------
00085 
00101 // clang-format off
00102 static const char* xml_text = R"(
00103 
00104  <root main_tree_to_execute = "MainTree" >
00105      <BehaviorTree ID="MainTree">
00106         <Sequence name="root">
00107             <CalculateGoal   goal="{GoalPosition}" />
00108             <PrintTarget     target="{GoalPosition}" />
00109             <SetBlackboard   output_key="OtherGoal" value="-1;3" />
00110             <PrintTarget     target="{OtherGoal}" />
00111         </Sequence>
00112      </BehaviorTree>
00113  </root>
00114  )";
00115 
00116 // clang-format on
00117 
00118 int main()
00119 {
00120     using namespace BT;
00121 
00122     BehaviorTreeFactory factory;
00123     factory.registerNodeType<CalculateGoal>("CalculateGoal");
00124     factory.registerNodeType<PrintTarget>("PrintTarget");
00125 
00126     auto tree = factory.createTreeFromText(xml_text);
00127     tree.root_node->executeTick();
00128 
00129 /* Expected output:
00130  *
00131     Target positions: [ 1.1, 2.3 ]
00132     Converting string: "-1;3"
00133     Target positions: [ -1.0, 3.0 ]
00134 */
00135     return 0;
00136 }
00137 


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Jun 8 2019 20:17:15