Skip to content

Commit f63bfab

Browse files
committed
preparing release 3.2.0
1 parent 9dff663 commit f63bfab

19 files changed

+107
-184
lines changed

CHANGELOG.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
Changelog for package behaviortree_cpp
33
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44

5-
Forthcoming
6-
-----------
5+
3.2.0 (2020-03-22)
6+
------------------
77
* root_node removed in favour of a method. tickRoot() added
88
* Moving to c++14
99
* fixed compilation on ROS2 and ubuntu 18.94

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ project(behaviortree_cpp_v3)
55
set(CMAKE_CONFIG_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake")
66
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CONFIG_PATH}")
77

8-
#---- Enable C++11 ----
8+
#---- Enable C++14 ----
99
set(CMAKE_CXX_STANDARD 14)
1010
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1111

conan/test_package/test_package.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ int main()
6262
std::this_thread::sleep_for(std::chrono::milliseconds(100));
6363
}
6464

65-
haltAllActions(&root);
65+
6666

6767
return 0;
6868
}

examples/broken_sequence.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ int main()
6363
std::this_thread::sleep_for(std::chrono::milliseconds(100));
6464
}
6565

66-
haltAllActions(&root);
66+
6767

6868
return 0;
6969
}

include/behaviortree_cpp_v3/action_node.h

+23-26
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <atomic>
1818
#include <thread>
19+
#include <future>
1920
#include "leaf_node.h"
2021

2122
namespace BT
@@ -96,48 +97,44 @@ class SimpleActionNode : public SyncActionNode
9697
};
9798

9899
/**
99-
* @brief The AsyncActionNode uses a different thread where the action will be
100+
* @brief The AsyncActionNode uses a different thread, where the action will be
100101
* executed.
101102
*
102-
* The user must implement the methods tick() and halt().
103+
* IMPORTANT: this action is quite hard to implement correctly. Please be sure that you know what you are doing.
103104
*
104-
* WARNING: this should probably be deprecated. It is too easy to use incorrectly
105-
* and there is not a good way to halt it in a thread safe way.
105+
* - In your overriden tick() method, you must check periodically
106+
* the result of the method isHaltRequested() and stop your execution accordingly.
106107
*
107-
* Use it at your own risk.
108+
* - in the overriden halt() method, you can do some cleanup, but do not forget to
109+
* invoke the base class method AsyncActionNode::halt();
110+
*
111+
* - remember, with few exceptions, a halted AsyncAction must return NodeStatus::IDLE.
112+
*
113+
* For a complete example, look at __AsyncActionTest__ in action_test_node.h in the folder test.
108114
*/
109115
class AsyncActionNode : public ActionNodeBase
110116
{
111117
public:
112118

113-
AsyncActionNode(const std::string& name, const NodeConfiguration& config);
114-
virtual ~AsyncActionNode() override;
119+
AsyncActionNode(const std::string& name, const NodeConfiguration& config):ActionNodeBase(name, config)
120+
{
121+
}
122+
123+
bool isHaltRequested() const
124+
{
125+
return halt_requested_.load();
126+
}
115127

116-
// This method triggers the TickEngine. Do NOT remove the "final" keyword.
128+
// This method spawn a new thread. Do NOT remove the "final" keyword.
117129
virtual NodeStatus executeTick() override final;
118130

119-
void stopAndJoinThread();
131+
virtual void halt() override;
120132

121133
private:
122134

123-
// The method that will be executed by the thread
124-
void asyncThreadLoop();
125-
126-
void waitStart();
127-
128-
void notifyStart();
129-
130-
std::atomic<bool> keep_thread_alive_;
131-
132-
bool start_action_;
133-
134-
std::mutex start_mutex_;
135-
136-
std::condition_variable start_signal_;
137-
138135
std::exception_ptr exptr_;
139-
140-
std::thread thread_;
136+
std::atomic_bool halt_requested_;
137+
std::future<NodeStatus> thread_handle_;
141138
};
142139

143140
/**

include/behaviortree_cpp_v3/behavior_tree.h

-5
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,6 @@ void applyRecursiveVisitor(TreeNode* root_node, const std::function<void(TreeNod
5454
*/
5555
void printTreeRecursively(const TreeNode* root_node);
5656

57-
/// Invoke AsyncActionNode::stopAndJoinThread() to the entire tree,
58-
/// when needed.
59-
void haltAllActions(TreeNode* root_node);
60-
61-
6257
typedef std::vector<std::pair<uint16_t, uint8_t>> SerializedTreeStatus;
6358

6459
/**

include/behaviortree_cpp_v3/bt_factory.h

+4
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ class Tree
156156

157157
void haltTree()
158158
{
159+
if(!rootNode())
160+
{
161+
return;
162+
}
159163
// the halt should propagate to all the node if the nodes
160164
// have been implemented correctly
161165
rootNode()->halt();

package.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0"?>
22
<package format="3">
33
<name>behaviortree_cpp_v3</name>
4-
<version>3.1.1</version>
4+
<version>3.2.0</version>
55
<description>
66
This package provides the Behavior Trees core library.
77
</description>

src/action_node.cpp

+41-96
Original file line numberDiff line numberDiff line change
@@ -50,102 +50,6 @@ NodeStatus SimpleActionNode::tick()
5050

5151
//-------------------------------------------------------
5252

53-
AsyncActionNode::AsyncActionNode(const std::string& name, const NodeConfiguration& config)
54-
: ActionNodeBase(name, config)
55-
{
56-
57-
}
58-
59-
AsyncActionNode::~AsyncActionNode()
60-
{
61-
if (thread_.joinable())
62-
{
63-
stopAndJoinThread();
64-
}
65-
}
66-
67-
void AsyncActionNode::waitStart()
68-
{
69-
std::unique_lock<std::mutex> lock(start_mutex_);
70-
while (!start_action_)
71-
{
72-
start_signal_.wait(lock);
73-
}
74-
start_action_ = false;
75-
}
76-
77-
void AsyncActionNode::notifyStart()
78-
{
79-
std::unique_lock<std::mutex> lock(start_mutex_);
80-
start_action_ = true;
81-
start_signal_.notify_all();
82-
}
83-
84-
void AsyncActionNode::asyncThreadLoop()
85-
{
86-
while (keep_thread_alive_.load())
87-
{
88-
waitStart();
89-
90-
// check keep_thread_alive_ again because the tick_engine_ could be
91-
// notified from the method stopAndJoinThread
92-
if (keep_thread_alive_)
93-
{
94-
// this will execute the blocking code.
95-
try {
96-
setStatus(tick());
97-
}
98-
catch (std::exception&)
99-
{
100-
std::cerr << "\nUncaught exception from the method tick() of an AsyncActionNode: ["
101-
<< registrationName() << "/" << name() << "]\n" << std::endl;
102-
exptr_ = std::current_exception();
103-
keep_thread_alive_ = false;
104-
}
105-
}
106-
}
107-
}
108-
109-
NodeStatus AsyncActionNode::executeTick()
110-
{
111-
//send signal to other thread.
112-
// The other thread is in charge for changing the status
113-
if (status() == NodeStatus::IDLE)
114-
{
115-
if( thread_.joinable() == false) {
116-
keep_thread_alive_ = true;
117-
thread_ = std::thread(&AsyncActionNode::asyncThreadLoop, this);
118-
}
119-
setStatus( NodeStatus::RUNNING );
120-
notifyStart();
121-
}
122-
123-
if( exptr_ )
124-
{
125-
std::rethrow_exception(exptr_);
126-
}
127-
return status();
128-
}
129-
130-
void AsyncActionNode::stopAndJoinThread()
131-
{
132-
keep_thread_alive_.store(false);
133-
if( status() == NodeStatus::RUNNING )
134-
{
135-
halt();
136-
}
137-
else{
138-
// loop in asyncThreadLoop() is blocked at waitStart(). Unblock it.
139-
notifyStart();
140-
}
141-
142-
if (thread_.joinable())
143-
{
144-
thread_.join();
145-
}
146-
}
147-
148-
14953
SyncActionNode::SyncActionNode(const std::string &name, const NodeConfiguration& config):
15054
ActionNodeBase(name, config)
15155
{}
@@ -260,3 +164,44 @@ void StatefulActionNode::halt()
260164
}
261165
setStatus(NodeStatus::IDLE);
262166
}
167+
168+
NodeStatus BT::AsyncActionNode::executeTick()
169+
{
170+
//send signal to other thread.
171+
// The other thread is in charge for changing the status
172+
if (status() == NodeStatus::IDLE)
173+
{
174+
setStatus( NodeStatus::RUNNING );
175+
halt_requested_ = false;
176+
thread_handle_ = std::async(std::launch::async, [this]() {
177+
178+
try {
179+
setStatus(tick());
180+
}
181+
catch (std::exception&)
182+
{
183+
std::cerr << "\nUncaught exception from the method tick(): ["
184+
<< registrationName() << "/" << name() << "]\n" << std::endl;
185+
exptr_ = std::current_exception();
186+
thread_handle_.wait();
187+
}
188+
return status();
189+
});
190+
}
191+
192+
if( exptr_ )
193+
{
194+
std::rethrow_exception(exptr_);
195+
}
196+
return status();
197+
}
198+
199+
void AsyncActionNode::halt()
200+
{
201+
halt_requested_.store(true);
202+
203+
if( thread_handle_.valid() ){
204+
thread_handle_.wait();
205+
}
206+
thread_handle_ = {};
207+
}

src/behavior_tree.cpp

-11
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,4 @@ void buildSerializedStatusSnapshot(TreeNode* root_node, SerializedTreeStatus& se
107107
applyRecursiveVisitor(root_node, visitor);
108108
}
109109

110-
void haltAllActions(TreeNode* root_node)
111-
{
112-
auto visitor = [](TreeNode* node) {
113-
if (auto action = dynamic_cast<AsyncActionNode*>(node))
114-
{
115-
action->stopAndJoinThread();
116-
}
117-
};
118-
applyRecursiveVisitor(root_node, visitor);
119-
}
120-
121110
} // end namespace

src/bt_factory.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,7 @@ Tree BehaviorTreeFactory::createTreeFromFile(const std::string &file_path,
261261

262262
Tree::~Tree()
263263
{
264-
if (rootNode()) {
265-
haltAllActions(rootNode());
266-
}
264+
haltTree();
267265
}
268266

269267
Blackboard::Ptr Tree::rootBlackboard()

tests/gtest_decorator.cpp

+3-7
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ struct DeadlineTest : testing::Test
3030
}
3131
~DeadlineTest()
3232
{
33-
haltAllActions(&root);
33+
3434
}
3535
};
3636

@@ -45,7 +45,7 @@ struct RepeatTest : testing::Test
4545
}
4646
~RepeatTest()
4747
{
48-
haltAllActions(&root);
48+
4949
}
5050
};
5151

@@ -60,7 +60,7 @@ struct RetryTest : testing::Test
6060
}
6161
~RetryTest()
6262
{
63-
haltAllActions(&root);
63+
6464
}
6565
};
6666

@@ -78,10 +78,6 @@ struct TimeoutAndRetry : testing::Test
7878
timeout_root.setChild(&retry);
7979
retry.setChild(&action);
8080
}
81-
~TimeoutAndRetry()
82-
{
83-
haltAllActions(&timeout_root);
84-
}
8581
};
8682

8783
/****************TESTS START HERE***************************/

tests/gtest_fallback.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct SimpleFallbackTest : testing::Test
3434
}
3535
~SimpleFallbackTest()
3636
{
37-
haltAllActions(&root);
37+
3838
}
3939
};
4040

@@ -57,7 +57,7 @@ struct ReactiveFallbackTest : testing::Test
5757
}
5858
~ReactiveFallbackTest()
5959
{
60-
haltAllActions(&root);
60+
6161
}
6262
};
6363

@@ -77,7 +77,7 @@ struct SimpleFallbackWithMemoryTest : testing::Test
7777
}
7878
~SimpleFallbackWithMemoryTest()
7979
{
80-
haltAllActions(&root);
80+
8181
}
8282
};
8383

@@ -116,7 +116,7 @@ struct ComplexFallbackWithMemoryTest : testing::Test
116116
}
117117
~ComplexFallbackWithMemoryTest()
118118
{
119-
haltAllActions(&root);
119+
120120
}
121121
};
122122

0 commit comments

Comments
 (0)