Skip to content

Commit

Permalink
prepare 4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
facontidavide committed Mar 18, 2023
1 parent aaab50f commit e781fcd
Show file tree
Hide file tree
Showing 23 changed files with 25,865 additions and 150 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,11 @@ list(APPEND BT_SOURCE
src/shared_library.cpp
src/tree_node.cpp
src/script_parser.cpp
src/json_export.cpp
src/xml_parsing.cpp

src/actions/test_node.cpp

src/decorators/inverter_node.cpp
src/decorators/repeat_node.cpp
src/decorators/retry_node.cpp
Expand All @@ -113,6 +116,7 @@ list(APPEND BT_SOURCE
src/loggers/bt_cout_logger.cpp
src/loggers/bt_file_logger.cpp
src/loggers/bt_minitrace_logger.cpp
src/loggers/bt_observer.cpp

3rdparty/tinyxml2/tinyxml2.cpp
3rdparty/minitrace/minitrace.cpp
Expand Down
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ CompileExample("t06_subtree_port_remapping")
CompileExample("t07_load_multiple_xml")
CompileExample("t08_additional_node_args")
CompileExample("t09_scripting")
CompileExample("t10_observer")
CompileExample("t11_replace_rules")


CompileExample("ex01_wrap_legacy")
Expand Down
86 changes: 86 additions & 0 deletions examples/t10_observer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include "behaviortree_cpp/bt_factory.h"
#include "behaviortree_cpp/loggers/bt_observer.h"

/** Show the use of the TreeObserver.
*/

// clang-format off

static const char* xml_text = R"(
<root BTCPP_format="4">
<BehaviorTree ID="MainTree">
<Sequence>
<Fallback>
<AlwaysFailure name="failing_action"/>
<SubTree ID="SubTreeA" name="mysub"/>
</Fallback>
<AlwaysSuccess name="last_action"/>
</Sequence>
</BehaviorTree>
<BehaviorTree ID="SubTreeA">
<Sequence>
<AlwaysSuccess name="action_subA"/>
<SubTree ID="SubTreeB" name="sub_nested"/>
<SubTree ID="SubTreeB" />
</Sequence>
</BehaviorTree>
<BehaviorTree ID="SubTreeB">
<AlwaysSuccess name="action_subB"/>
</BehaviorTree>
</root>
)";

// clang-format on

int main()
{
BT::BehaviorTreeFactory factory;

factory.registerBehaviorTreeFromText(xml_text);
auto tree = factory.createTree("MainTree");

// Helper function to print the tree.
BT::printTreeRecursively(tree.rootNode());

// The purpose of the observer is to save some statistics about the number of times
// a certain node returns SUCCESS or FAILURE.
// This is particularly useful to create unit tests and to check if
// a certain set of transitions happened as expected
BT::TreeObserver observer(tree);

// Print the unique ID and the corresponding human readable path
// Path is also expected to be unique.
std::map<uint16_t, std::string> ordered_UID_to_path;
for(const auto& [name, uid]: observer.pathToUID()) {
ordered_UID_to_path[uid] = name;
}

for(const auto& [uid, name]: ordered_UID_to_path) {
std::cout << uid << " -> " << name << std::endl;
}

// Tick the tree multiple times, until action_B is finally ticked.
// Since we use const reference, we can check this statistic periodically.
const auto& action_B_stats = observer.getStatistics("last_action");

tree.tickOnce();


std::cout << "----------------" << std::endl;
// print all the statistics
for(const auto& [uid, name]: ordered_UID_to_path) {
const auto& stats = observer.getStatistics(uid);

std::cout << "[" << name
<< "] \tT/S/F: " << stats.tick_count
<< "/" << stats.success_count
<< "/" << stats.failure_count
<< std::endl;
}

return 0;
}
96 changes: 96 additions & 0 deletions examples/t11_replace_rules.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "behaviortree_cpp/bt_factory.h"
#include "dummy_nodes.h"

// clang-format off

static const char* xml_text = R"(
<root BTCPP_format="4">
<BehaviorTree ID="MainTree">
<Sequence>
<SaySomething name="talk" message="hello world"/>
<Fallback>
<AlwaysFailure name="failing_action"/>
<SubTree ID="MySub" name="mysub"/>
</Fallback>
<SaySomething message="before last_action"/>
<Script code="msg:='after last_action'"/>
<AlwaysSuccess name="last_action"/>
<SaySomething message="{msg}"/>
</Sequence>
</BehaviorTree>
<BehaviorTree ID="MySub">
<Sequence>
<AlwaysSuccess name="action_subA"/>
<AlwaysSuccess name="action_subB"/>
</Sequence>
</BehaviorTree>
</root>
)";

// clang-format on

int main(int argc, char** argv)
{
using namespace DummyNodes;
BT::BehaviorTreeFactory factory;

factory.registerNodeType<SaySomething>("SaySomething");

// We use lambdasand registerSimpleAction, to create
// a "dummy" node, that we want to create instead of a given one.

// Simple node that just prints its name and return SUCCESS
factory.registerSimpleAction("TestAction", [](BT::TreeNode& self){
std::cout << "TestAction substituting: "<< self.name() << std::endl;
return BT::NodeStatus::SUCCESS;
});

// Action that is meant to substitute SaySomething.
// It will try to use the input port "message"
factory.registerSimpleAction("TestSaySomething", [](BT::TreeNode& self){
auto msg = self.getInput<std::string>("message");
if (!msg)
{
throw BT::RuntimeError( "missing required input [message]: ", msg.error() );
}
std::cout << "TestSaySomething: " << msg.value() << std::endl;
return BT::NodeStatus::SUCCESS;
});

// These configurations will be passed to a TestNode
BT::TestNodeConfig test_config;
// Convert the node in asynchronous and wait 2000 ms
test_config.async_delay = std::chrono::milliseconds(2000);
// Execute this postcondition, once completed
test_config.post_script = "msg ='message SUBSTITUED'";

//----------------------------
// pass "no_sub" as first argument to avoid adding rules
bool skip_substitution = (argc == 2) && std::string(argv[1]) == "no_sub";

if(!skip_substitution)
{
// Substitute nodes which match this wildcard pattern with TestAction
factory.addSubstitutionRule("mysub/action_*", "TestAction");

// Substitute the node with name [talk] with TestSaySomething
factory.addSubstitutionRule("talk", "TestSaySomething");

// Substitute the node with name [last_action] with a TestNode,
// configured using test_config
factory.addSubstitutionRule("last_action", test_config);
}

factory.registerBehaviorTreeFromText(xml_text);

// During the construction phase of the tree, the substitution
// rules will be used to instantiate the test nodes, instead of the
// original ones.
auto tree = factory.createTree("MainTree");
tree.tickWhileRunning();

return 0;
}
92 changes: 92 additions & 0 deletions include/behaviortree_cpp/actions/test_node.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* Copyright (C) 2022 Davide Faconti - All Rights Reserved
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#pragma once

#include "behaviortree_cpp/action_node.h"
#include "behaviortree_cpp/decorators/timer_queue.h"
#include "behaviortree_cpp/scripting/script_parser.hpp"

namespace BT
{

struct TestNodeConfig
{
/// status to return when the action is completed
NodeStatus return_status = NodeStatus::SUCCESS;

/// script to execute when actions is completed
std::string post_script;

/// if async_delay > 0, this action become asynchronous and wait this amount of time
std::chrono::milliseconds async_delay = std::chrono::milliseconds(0);

/// C++ callback to execute at the beginning
std::function<void()> pre_func;

/// C++ callback to execute at the end
std::function<void()> post_func;
};

/**
* @brief The TestNode is a Node that can be configure to:
*
* 1. Return a specific status (SUCCESS / FAILURE)
* 2. Execute a post condition script (unless halted)
* 3. Either complete immediately (synchronous action), or after a
* given period of time (asynchronous action)
*
* This behavior is changed by the parameters pased with TestNodeConfig.
*
* This particular node is created by the factory when TestNodeConfig is
* added as a substitution rule:
*
* TestNodeConfig test_config;
* // change fields of test_config
* factory.addSubstitutionRule(pattern, test_config);
*
* See tutorial 11 for more details.
*/
class TestNode : public BT::StatefulActionNode
{
public:
TestNode(const std::string& name, const NodeConfig& config) :
StatefulActionNode(name, config)
{
setRegistrationID("TestNode");
}

static PortsList providedPorts()
{
return {};
}

void setConfig(const TestNodeConfig& config);

private:

virtual NodeStatus onStart() override;

virtual NodeStatus onRunning() override;

virtual void onHalted() override;

NodeStatus onCompleted();

TestNodeConfig _test_config;
ScriptFunction _executor;
TimerQueue<> _timer;
std::atomic_bool _completed;
};

} // namespace BT
4 changes: 2 additions & 2 deletions include/behaviortree_cpp/basic_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ enum class NodeStatus
SKIPPED = 4,
};

inline bool StatusActive(const NodeStatus& status)
inline bool isStatusActive(const NodeStatus& status)
{
return status != NodeStatus::IDLE && status != NodeStatus::SKIPPED;
}

inline bool StatusCompleted(const NodeStatus& status)
inline bool isStatusCompleted(const NodeStatus& status)
{
return status == NodeStatus::SUCCESS || status == NodeStatus::FAILURE;
}
Expand Down
1 change: 1 addition & 0 deletions include/behaviortree_cpp/behavior_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "behaviortree_cpp/actions/always_failure_node.h"
#include "behaviortree_cpp/actions/script_node.h"
#include "behaviortree_cpp/actions/set_blackboard_node.h"
#include "behaviortree_cpp/actions/test_node.h"

#include "behaviortree_cpp/decorators/force_success_node.h"
#include "behaviortree_cpp/decorators/force_failure_node.h"
Expand Down
Loading

0 comments on commit e781fcd

Please sign in to comment.