├── .gitignore
├── .travis.yml
├── BTppUserManual.pdf
├── CMakeLists.txt
├── LICENSE
├── README.md
├── conf
├── BTppConfig.cmake.in
└── BTppConfigVersion.cmake.in
├── contributors.txt
├── gtest
├── gtest_tree.cpp
├── include
│ ├── action_test_node.h
│ └── condition_test_node.h
└── src
│ ├── action_test_node.cpp
│ └── condition_test_node.cpp
├── include
├── action_node.h
├── behavior_tree.h
├── condition_node.h
├── control_node.h
├── decorator_negation_node.h
├── decorator_retry_node.h
├── draw.h
├── exceptions.h
├── fallback_node.h
├── fallback_node_with_memory.h
├── leaf_node.h
├── parallel_node.h
├── sequence_node.h
├── sequence_node_with_memory.h
├── tick_engine.h
└── tree_node.h
├── src
├── action_node.cpp
├── behavior_tree.cpp
├── condition_node.cpp
├── control_node.cpp
├── decorator_negation_node.cpp
├── decorator_retry_node.cpp
├── draw.cpp
├── example.cpp
├── exceptions.cpp
├── fallback_node.cpp
├── fallback_node_with_memory.cpp
├── leaf_node.cpp
├── parallel_node.cpp
├── sequence_node.cpp
├── sequence_node_with_memory.cpp
├── tick_engine.cpp
├── tree.cpp
└── tree_node.cpp
└── templates
├── action_node_template.cpp
└── condition_node_template.cpp
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | dist: trusty
3 | language: cpp
4 |
5 | os:
6 | - linux
7 |
8 | compiler:
9 | - gcc
10 | - clang
11 |
12 | before_install:
13 | - sudo apt-get update && sudo apt-get --reinstall install -qq build-essential freeglut3-dev libxmu-dev libxi-dev
14 |
15 | before_script:
16 | # Prepare build directory
17 | - mkdir -p build
18 |
19 | script:
20 | # Build BTpp
21 | - (cd build; cmake .. ;cmake --build . )
22 | #Install BTpp
23 | - (cd build; sudo make install)
24 |
25 |
--------------------------------------------------------------------------------
/BTppUserManual.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miccol/Behavior-Tree/5e25de7aa65ca947698f5506c4a56502472bc3de/BTppUserManual.pdf
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.0)
2 | project(BTpp)
3 |
4 | set(CMAKE_BUILD_TYPE Release)
5 | add_definitions(-lX11 -Wall -lglut -lGL -lgtest -std=c++11 -lrt )
6 | # Needed for using threads
7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
8 |
9 | #########################################################
10 | # FIND X11
11 | #########################################################
12 | find_package(X11 REQUIRED)
13 | include_directories(${X11_INCLUDE_DIR})
14 | link_directories(${X11_LIBRARIES})
15 |
16 | #########################################################
17 | # FIND GTest
18 | #########################################################
19 | find_package(GTest)
20 | include_directories(${GTEST_INCLUDE_DIRS})
21 | if(NOT GTEST_FOUND)
22 | message(WARINING " GTest not found!")
23 | endif(NOT GTEST_FOUND)
24 |
25 | #########################################################
26 | # FIND GLUT
27 | #########################################################
28 | find_package(GLUT REQUIRED)
29 | include_directories(${GLUT_INCLUDE_DIRS})
30 | link_directories(${GLUT_LIBRARY_DIRS})
31 | add_definitions(${GLUT_DEFINITIONS})
32 | if(NOT GLUT_FOUND)
33 | message(ERROR " GLUT not found!")
34 | endif(NOT GLUT_FOUND)
35 |
36 | #########################################################
37 | # FIND OPENGL
38 | #########################################################
39 | find_package(OpenGL REQUIRED)
40 | include_directories(${OpenGL_INCLUDE_DIRS})
41 | link_directories(${OpenGL_LIBRARY_DIRS})
42 | add_definitions(${OpenGL_DEFINITIONS})
43 | if(NOT OPENGL_FOUND)
44 | message(ERROR " OPENGL not found!")
45 | endif(NOT OPENGL_FOUND)
46 |
47 |
48 | INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include/)
49 | INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/gtest/include/)
50 |
51 | if(APPLE)
52 | include_directories(AFTER "/opt/X11/include")
53 | set(CMAKE_OSX_ARCHITECTURES "x86_64")
54 | if(CMAKE_GENERATOR STREQUAL Xcode)
55 | set(CMAKE_OSX_DEPLOYMENT_TARGET "10.8")
56 | endif()
57 | endif()
58 |
59 |
60 | #########################################################
61 | # Make relative paths absolute (needed later on)
62 | #########################################################
63 |
64 | foreach(p LIB BIN INCLUDE CMAKE)
65 | set(var INSTALL_${p}_DIR)
66 | if(NOT IS_ABSOLUTE "${${var}}")
67 | set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
68 | endif()
69 | endforeach()
70 |
71 |
72 |
73 |
74 | file(GLOB_RECURSE BTHeadLibrary include/*.h)
75 |
76 | set(BTSrcLibrary
77 | src/action_node.cpp
78 | src/behavior_tree.cpp
79 | src/condition_node.cpp
80 | src/control_node.cpp
81 | src/draw.cpp
82 | src/exceptions.cpp
83 | src/leaf_node.cpp
84 | src/tick_engine.cpp
85 | src/parallel_node.cpp
86 | src/fallback_node.cpp
87 | src/sequence_node.cpp
88 | src/fallback_node_with_memory.cpp
89 | src/sequence_node_with_memory.cpp
90 | src/tree_node.cpp
91 |
92 | gtest/src/action_test_node.cpp
93 | gtest/src/condition_test_node.cpp
94 | )
95 |
96 |
97 | ######################################################
98 | # SETTING BINARIES AND LIBRARY OUTPUT LOCATIONS
99 | ######################################################
100 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/sample)
101 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
102 |
103 | ######################################################
104 | # COMPILING GTEST
105 | ######################################################
106 | if(GTEST_FOUND)
107 | #add_executable(btpp_gtest gtest/gtest_tree.cpp ${BTSrcLibrary} ${BTHeadLibrary})
108 | #target_link_libraries(btpp_gtest ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} ${X11_LIBRARIES})
109 | endif(GTEST_FOUND)
110 |
111 | ######################################################
112 | # COMPILING SAMPLE EXAMPLE
113 | ######################################################
114 | add_executable(btpp_example src/example.cpp ${BTSrcLibrary} ${BTHeadLibrary})
115 | target_link_libraries(btpp_example ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${X11_LIBRARIES})
116 |
117 | ######################################################
118 | # COMPILING LIBRARY
119 | ######################################################
120 | add_library(BTppLib STATIC ${BTSrcLibrary} ${BTHeadLibrary})
121 | target_link_libraries(BTppLib ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${X11_LIBRARIES})
122 |
123 | ######################################################
124 | # INSTALLATION OF LIBRARY AND EXECUTABLE
125 | ######################################################
126 |
127 |
128 |
129 | # Add all targets to the build-tree export set
130 | export(TARGETS BTppLib
131 | FILE "${PROJECT_BINARY_DIR}/BTppTargets.cmake")
132 |
133 | # Export the package for use from the build-tree
134 | # (this registers the build-tree with a global CMake-registry)
135 | export(PACKAGE BTpp)
136 |
137 |
138 | install(FILES ${BTHeadLibrary} DESTINATION ${INSTALL_INCLUDE_DIR}/include/BTpp)
139 |
140 |
141 | install(TARGETS BTppLib
142 | # IMPORTANT: Add the library to the "export-set"
143 | EXPORT BTppTargets
144 | ARCHIVE DESTINATION "${INSTALL_CMAKE_DIR}/BTpp/lib"
145 | RUNTIME DESTINATION "${PROJECT_BINARY_DIR}/bin" COMPONENT ${PROJECT_BINARY_DIR}/bin
146 | LIBRARY DESTINATION "${PROJECT_BINARY_DIR}/lib" COMPONENT ${PROJECT_BINARY_DIR}/shlib
147 | PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}/include/BTpp"
148 | COMPONENT ${INSTALL_CMAKE_DIR}"include/BTpp")
149 |
150 |
151 | # Create the BTppConfig.cmake and BTppConfigVersion files
152 | file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}"
153 | "${INSTALL_INCLUDE_DIR}")
154 | # ... for the build tree
155 |
156 |
157 | set(CONF_INCLUDE_DIRS "${INSTALL_INCLUDE_DIR}include/BTpp")
158 | configure_file(conf/BTppConfig.cmake.in
159 | "${PROJECT_BINARY_DIR}/BTppConfig.cmake" @ONLY)
160 |
161 | # ... for the install tree
162 | #set(CONF_INCLUDE_DIRS "\${BTpp_CMAKE_DIR}/${REL_INCLUDE_DIR}")
163 | configure_file(conf/BTppConfig.cmake.in
164 | "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/BTppConfig.cmake" @ONLY)
165 | # ... for both
166 | configure_file(conf/BTppConfigVersion.cmake.in
167 | "${PROJECT_BINARY_DIR}/BTppConfigVersion.cmake" @ONLY)
168 |
169 | # Install the BTppConfig.cmake and BTppConfigVersion.cmake
170 | install(FILES
171 | "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/BTppConfig.cmake"
172 | "${PROJECT_BINARY_DIR}/BTppConfigVersion.cmake"
173 | DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)
174 |
175 | # Install the export set for use with the install-tree
176 | install(EXPORT BTppTargets DESTINATION
177 | "${INSTALL_CMAKE_DIR}" COMPONENT dev)
178 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 - 2018 Michele Colledanchise
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | A lightweight behavior tree library in `C++`.
2 |
3 |
4 |
5 | NEWS!
6 | -----------
7 | :boom: Thanks to [Davide Faconti](https://github.com/facontidavide) there is now a more sophisticated version of the library. The new version of this library is available [here](https://github.com/BehaviorTree/BehaviorTree.CPP). There is also GUI available [here](https://github.com/BehaviorTree/Groot).
8 |
9 |
10 |
11 |
12 | Our book **Behavior Trees in Robotics and AI**, published by CRC Press Taylor & Francis, is available for purchase (ebook and hardcover) on the CRC Press Store or Amazon. The Preprint version (**free**) is available here: https://arxiv.org/abs/1709.00084
13 | **Tutorials** available at https://btirai.github.io/
14 |
15 |
16 |
17 |
18 |
19 | -----------
20 |
21 |
BT++
22 | ====
23 |  
24 |
25 |
26 |
27 | REFERENCE
28 | ------------
29 | Please refer to the following paper when using the library:
30 |
31 | **How Behavior Trees Modularize Hybrid Control Systems and Generalize Sequential Behavior Compositions, the Subsumption Architecture, and Decision Trees.** Michele Colledanchise and Petter Ogren. IEEE Transaction on Robotics 2017.
32 |
33 | bibtex entry:
34 |
35 | `@ARTICLE{TRO17Colledanchise,`
36 | `author={M. Colledanchise and P. Ögren},`
37 | `journal={IEEE Transactions on Robotics},`
38 | `title={{How Behavior Trees Modularize Hybrid Control Systems and Generalize Sequential Behavior Compositions, the Subsumption Architecture, and Decision Trees}},`
39 | `year={2017},`
40 | `volume={33},`
41 | `number={2},`
42 | `pages={372-389},`
43 | `keywords={Computer architecture;Decision trees;High definition video;Robot control;Switches;Behavior trees (BTs);decision trees;finite state machines (FSMs);hybrid dynamical systems (HDSs);modularity;sequential behavior compositions;subsumption architecture}, `
44 | `doi={10.1109/TRO.2016.2633567},`
45 | `ISSN={1552-3098},`
46 | `month={April},}`
47 |
48 | DEPENDENCIES
49 | ------------
50 |
51 | Regarding visualization purposes:
52 | * [OpenGL](https://www.opengl.org/)
53 | * [Glut](https://www.opengl.org/resources/libraries/glut/)
54 |
55 | Regarding tests:
56 | * [GTests](https://github.com/google/googletest)
57 |
58 | BT NODES SUPPORT
59 | ----------------
60 | **Fallback:** Fallback nodes are used to find and execute the first child that does not fail. A Selector node will return immediately with a status code of success or running when one of its children returns success or running. The children are ticked in order of importance, from `left` to `right`.
61 |
62 | **Sequence:** Sequence nodes are used to find and execute the first child that has not yet succeeded. A sequence node will return immediately with a status code of `failure` or `running` when one of its children returns failure or running. The children are ticked in order, from `left` to `right`.
63 |
64 | **Parallel:** The parallel node ticks its children in parallel and returns success if `M ≤ N` children return success, it returns failure if `N − M + 1` children return failure, and it returns running otherwise.
65 |
66 | **Decorator:** The decorator node manipulates the return status of its child according to the policy defined by the user (e.g. it inverts the success/failure status of the child). In this library the decorators implemented are the two common ones: *Decorator Retry* which retries the execution of a node if this fails; and *Decorator Negation* That inverts the Success/Failure outcome.
67 |
68 | **Action:** An Action node performs an action, and returns Success if the action is completed, Failure if it can not be completed and Running if completion is under way.
69 |
70 | **Condition:** A Condition node determines if a desired condition `c` has been met. Conditions are technically a subset of the Actions, but are given a separate category and graphical symbol to improve readability of the BT and emphasize the fact that they never return running and do not change any internal states/variables of the BT.
71 |
72 | A user manual is available in the project folder ([BTppUserManual.pdf](https://github.com/miccol/Behavior-Tree/blob/master/BTppUserManual.pdf)).
73 |
74 | SETUP
75 | -----------
76 |
77 | The first step to use BT++ is to retrieve its source code. You can either download it
78 | here (https://github.com/miccol/Behavior-Tree) or clone the repository:
79 |
80 | `$ cd /path/to/folder`
81 | `$ git clone https://github.com/miccol/Behavior−Tree.git`
82 |
83 | Once you have the repository, compile the library:
84 |
85 | `$ cd /path/to/folder/`
86 | `$ mkdir ./build`
87 | `$ cd build`
88 | `$ cmake ..`
89 | `$ make`
90 |
91 |
92 | **NOTE**
93 | In case you get the following error:
94 |
95 | `CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
96 | Please set them or make sure they are set and tested correctly in the CMake files:
97 | GLUT_Xmu_LIBRARY (ADVANCED)`
98 |
99 | please see solution [here](https://ubuntuforums.org/archive/index.php/t-1703770.html). Thanks [miquelramirez](https://github.com/miquelramirez) for this.
100 |
101 |
102 | Check the installation by running a sample example.
103 |
104 | `$ cd /path/to/folder/`
105 | `$ cd build/sample`
106 | `$ ./btpp_example`
107 |
108 | INSTALL THE LIBRARY SYSTEM-WIDE (tested on Ubuntu 14.04 and 16.04)
109 | -------------------------------
110 |
111 | If you would like to install the library system-wide, then run:
112 |
113 | `$ cd /path/to/folder/`
114 | `$ cd build`
115 | `$ sudo make install`
116 |
117 | On Ubuntu, this will install the library (libbtpp.so) in `/usr/local/lib`.
118 | In an external project, just call in your CMakeLists 'find_package(BTpp)' to find the library.
119 | The include directory is defined as `BTpp_INCLUDE_DIRS` and the libraries to link as `BTpp_LIBRARIES`.
120 | The repository [my-behavior-tree-project](https://github.com/miccol/my-behavior-tree-project) shows an example on how to use the library once system-wide installed.
121 |
122 |
123 | CREATE YOUR OWN ACTION NODE
124 | ------
125 | 1) Implement your action node class extending the abstract class `BT::ActionNode`.
126 | 2) Implement the method `BT::ReturnStatus Tick()` with the code you want to execute while the action is running. Use the method `is_halted()` to check if the action has been prempted. When the execution of your action finished, return `BT::SUCCESS` or `BT::FAILURE` accordingly.
127 | 3) Implement the method `void Halt()` with the code you want to execute when the action gets preempted (halted).
128 | See the file `src/example.cpp` for an example.
129 |
130 | CREATE YOUR OWN CONDITION NODE
131 | ------
132 | 1) Implement your condition node class extending the abstract class `BT::ConditionNode`.
133 | 2) Implement the method `BT::ReturnStatus Tick()` with the code you want to execute to check the condition. Return `BT::SUCCESS` or `BT::FAILURE` accordingly.
134 | See the file `src/example.cpp` for an example.
135 |
136 |
137 | NOTES
138 | -------
139 | In case you are puzzled about why a sequence (or fallback) node with 2 or more actions as children never get past the first action, see [this](https://github.com/miccol/ROS-Behavior-Tree/issues/16) discussion.
140 |
141 | LICENSE
142 | -------
143 | The MIT License (MIT)
144 |
145 | Copyright (c) 2014-2018 Michele Colledanchise
146 |
147 | Permission is hereby granted, free of charge, to any person obtaining a copy
148 | of this software and associated documentation files (the "Software"), to deal
149 | in the Software without restriction, including without limitation the rights
150 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
151 | copies of the Software, and to permit persons to whom the Software is
152 | furnished to do so, subject to the following conditions:
153 |
154 | The above copyright notice and this permission notice shall be included in all
155 | copies or substantial portions of the Software.
156 |
157 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
158 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
159 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
160 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
161 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
162 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
163 | SOFTWARE.
164 |
--------------------------------------------------------------------------------
/conf/BTppConfig.cmake.in:
--------------------------------------------------------------------------------
1 | get_filename_component(BTpp_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
2 | set(BTpp_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@")
3 |
4 | # Our library dependencies (contains definitions for IMPORTED targets)
5 | if(NOT TARGET BTpp AND NOT BTpp_BINARY_DIR)
6 | include("${BTpp_CMAKE_DIR}/BTppTargets.cmake")
7 | endif()
8 |
9 | # These are IMPORTED targets created by YARPBTCoreargets.cmake
10 | set(BTpp_LIBRARIES BTppLib)
11 |
--------------------------------------------------------------------------------
/conf/BTppConfigVersion.cmake.in:
--------------------------------------------------------------------------------
1 | set(PACKAGE_VERSION "@BTpp_VERSION@")
2 |
3 | # Check whether the requested PACKAGE_FIND_VERSION is compatible
4 | if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
5 | set(PACKAGE_VERSION_COMPATIBLE FALSE)
6 | else()
7 | set(PACKAGE_VERSION_COMPATIBLE TRUE)
8 | if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
9 | set(PACKAGE_VERSION_EXACT TRUE)
10 | endif()
11 | endif()
12 |
--------------------------------------------------------------------------------
/contributors.txt:
--------------------------------------------------------------------------------
1 | Michele Colledanchise
2 | Rocco Santomo
3 |
4 |
--------------------------------------------------------------------------------
/gtest/gtest_tree.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015-2017 Michele Colledanchise - All Rights Reserved
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
4 | * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
5 | * 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:
6 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 | *
8 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 | * 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,
10 | * 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.
11 | */
12 |
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 |
20 |
21 | struct SimpleSequenceTest : testing::Test
22 | {
23 | BT:: SequenceNode* root;
24 | BT::ActionTestNode* action;
25 | BT::ConditionTestNode* condition;
26 | SimpleSequenceTest()
27 | {
28 | action = new BT::ActionTestNode("action");
29 | condition = new BT::ConditionTestNode("condition");
30 |
31 | root = new BT::SequenceNode("seq1");
32 |
33 | root->AddChild(condition);
34 | root->AddChild(action);
35 | }
36 | };
37 |
38 |
39 | struct ComplexSequenceTest : testing::Test
40 | {
41 | BT:: SequenceNode* root;
42 | BT::ActionTestNode* action_1;
43 | BT::ConditionTestNode* condition_1;
44 | BT::ConditionTestNode* condition_2;
45 |
46 | BT:: SequenceNode* seq_conditions;
47 |
48 | ComplexSequenceTest()
49 | {
50 | action_1 = new BT::ActionTestNode("action 1");
51 |
52 | condition_1 = new BT::ConditionTestNode("condition 1");
53 | condition_2 = new BT::ConditionTestNode("condition 2");
54 | seq_conditions = new BT::SequenceNode("sequence_conditions");
55 |
56 | seq_conditions->AddChild(condition_1);
57 | seq_conditions->AddChild(condition_2);
58 |
59 | root = new BT::SequenceNode("root");
60 | root->AddChild(seq_conditions);
61 | root->AddChild(action_1);
62 | }
63 | };
64 |
65 |
66 | struct ComplexSequence2ActionsTest : testing::Test
67 | {
68 | BT:: SequenceNode* root;
69 | BT::ActionTestNode* action_1;
70 | BT::ActionTestNode* action_2;
71 |
72 | BT::ConditionTestNode* condition_1;
73 | BT::ConditionTestNode* condition_2;
74 |
75 | BT:: SequenceNode* seq_1;
76 | BT:: SequenceNode* seq_2;
77 |
78 | ComplexSequence2ActionsTest()
79 | {
80 | action_1 = new BT::ActionTestNode("action 1");
81 | action_2 = new BT::ActionTestNode("action 2");
82 | seq_1 = new BT::SequenceNode("sequence_1");
83 | seq_2 = new BT::SequenceNode("sequence_c2");
84 |
85 | condition_1 = new BT::ConditionTestNode("condition 1");
86 | condition_2 = new BT::ConditionTestNode("condition 2");
87 |
88 | seq_1->AddChild(condition_1);
89 | seq_1->AddChild(action_1);
90 |
91 | seq_2->AddChild(condition_2);
92 | seq_2->AddChild(action_2);
93 |
94 |
95 | root = new BT::SequenceNode("root");
96 | root->AddChild(seq_1);
97 | root->AddChild(seq_2);
98 | }
99 | };
100 |
101 |
102 | struct SimpleFallbackTest : testing::Test
103 | {
104 | BT:: FallbackNode* root;
105 | BT::ActionTestNode* action;
106 | BT::ConditionTestNode* condition;
107 | SimpleFallbackTest()
108 | {
109 | action = new BT::ActionTestNode("action");
110 | condition = new BT::ConditionTestNode("condition");
111 |
112 | root = new BT::FallbackNode("seq1");
113 |
114 | root->AddChild(condition);
115 | root->AddChild(action);
116 | }
117 | };
118 |
119 |
120 | struct ComplexFallbackTest : testing::Test
121 | {
122 | BT:: FallbackNode* root;
123 | BT::ActionTestNode* action_1;
124 | BT::ConditionTestNode* condition_1;
125 | BT::ConditionTestNode* condition_2;
126 |
127 | BT:: FallbackNode* sel_conditions;
128 |
129 | ComplexFallbackTest()
130 | {
131 | action_1 = new BT::ActionTestNode("action 1");
132 | condition_1 = new BT::ConditionTestNode("condition 1");
133 | condition_2 = new BT::ConditionTestNode("condition 2");
134 | sel_conditions = new BT::FallbackNode("fallback_conditions");
135 |
136 | sel_conditions->AddChild(condition_1);
137 | sel_conditions->AddChild(condition_2);
138 |
139 | root = new BT::FallbackNode("root");
140 | root->AddChild(sel_conditions);
141 | root->AddChild(action_1);
142 | }
143 | };
144 |
145 |
146 |
147 |
148 | struct BehaviorTreeTest : testing::Test
149 | {
150 | BT:: SequenceNode* root;
151 | BT::ActionTestNode* action_1;
152 | BT::ConditionTestNode* condition_1;
153 | BT::ConditionTestNode* condition_2;
154 |
155 | BT:: FallbackNode* sel_conditions;
156 |
157 | BehaviorTreeTest()
158 | {
159 | action_1 = new BT::ActionTestNode("action 1");
160 | condition_1 = new BT::ConditionTestNode("condition 1");
161 | condition_2 = new BT::ConditionTestNode("condition 2");
162 | sel_conditions = new BT::FallbackNode("fallback_conditions");
163 |
164 | sel_conditions->AddChild(condition_1);
165 | sel_conditions->AddChild(condition_2);
166 |
167 | root = new BT::SequenceNode("root");
168 | root->AddChild(sel_conditions);
169 | root->AddChild(action_1);
170 | }
171 | };
172 |
173 |
174 |
175 |
176 | struct SimpleSequenceWithMemoryTest : testing::Test
177 | {
178 | BT:: SequenceNodeWithMemory* root;
179 | BT::ActionTestNode* action;
180 | BT::ConditionTestNode* condition;
181 | SimpleSequenceWithMemoryTest()
182 | {
183 | action = new BT::ActionTestNode("action");
184 | condition = new BT::ConditionTestNode("condition");
185 |
186 | root = new BT::SequenceNodeWithMemory("seq1");
187 |
188 | root->AddChild(condition);
189 | root->AddChild(action);
190 | }
191 | };
192 |
193 | struct ComplexSequenceWithMemoryTest : testing::Test
194 | {
195 | BT:: SequenceNodeWithMemory* root;
196 |
197 | BT::ActionTestNode* action_1;
198 | BT::ActionTestNode* action_2;
199 |
200 | BT::ConditionTestNode* condition_1;
201 | BT::ConditionTestNode* condition_2;
202 |
203 | BT:: SequenceNodeWithMemory* seq_conditions;
204 | BT:: SequenceNodeWithMemory* seq_actions;
205 |
206 | ComplexSequenceWithMemoryTest()
207 | {
208 | action_1 = new BT::ActionTestNode("action 1");
209 | action_2 = new BT::ActionTestNode("action 2");
210 |
211 |
212 | condition_1 = new BT::ConditionTestNode("condition 1");
213 | condition_2 = new BT::ConditionTestNode("condition 2");
214 |
215 | seq_conditions = new BT::SequenceNodeWithMemory("sequence_conditions");
216 | seq_actions = new BT::SequenceNodeWithMemory("sequence_actions");
217 |
218 | seq_actions->AddChild(action_1);
219 | seq_actions->AddChild(action_2);
220 |
221 | seq_conditions->AddChild(condition_1);
222 | seq_conditions->AddChild(condition_2);
223 |
224 | root = new BT::SequenceNodeWithMemory("root");
225 | root->AddChild(seq_conditions);
226 | root->AddChild(seq_actions);
227 | }
228 | };
229 |
230 | struct SimpleFallbackWithMemoryTest : testing::Test
231 | {
232 | BT::FallbackNodeWithMemory* root;
233 | BT::ActionTestNode* action;
234 | BT::ConditionTestNode* condition;
235 | SimpleFallbackWithMemoryTest()
236 | {
237 | action = new BT::ActionTestNode("action");
238 | condition = new BT::ConditionTestNode("condition");
239 |
240 | root = new BT::FallbackNodeWithMemory("seq1");
241 |
242 | root->AddChild(condition);
243 | root->AddChild(action);
244 | }
245 | };
246 |
247 | struct ComplexFallbackWithMemoryTest : testing::Test
248 | {
249 | BT:: FallbackNodeWithMemory* root;
250 |
251 | BT::ActionTestNode* action_1;
252 | BT::ActionTestNode* action_2;
253 |
254 | BT::ConditionTestNode* condition_1;
255 | BT::ConditionTestNode* condition_2;
256 |
257 | BT:: FallbackNodeWithMemory* fal_conditions;
258 | BT:: FallbackNodeWithMemory* fal_actions;
259 |
260 | ComplexFallbackWithMemoryTest()
261 | {
262 | action_1 = new BT::ActionTestNode("action 1");
263 | action_2 = new BT::ActionTestNode("action 2");
264 | condition_1 = new BT::ConditionTestNode("condition 1");
265 | condition_2 = new BT::ConditionTestNode("condition 2");
266 |
267 | fal_conditions = new BT::FallbackNodeWithMemory("fallback_conditions");
268 | fal_actions = new BT::FallbackNodeWithMemory("fallback_actions");
269 |
270 | fal_actions->AddChild(action_1);
271 | fal_actions->AddChild(action_2);
272 |
273 | fal_conditions->AddChild(condition_1);
274 | fal_conditions->AddChild(condition_2);
275 |
276 | root = new BT::FallbackNodeWithMemory("root");
277 | root->AddChild(fal_conditions);
278 | root->AddChild(fal_actions);
279 | }
280 | };
281 |
282 |
283 | struct SimpleParallelTest : testing::Test
284 | {
285 | BT::ParallelNode* root;
286 | BT::ActionTestNode* action_1;
287 | BT::ConditionTestNode* condition_1;
288 |
289 | BT::ActionTestNode* action_2;
290 | BT::ConditionTestNode* condition_2;
291 |
292 | SimpleParallelTest()
293 | {
294 | action_1 = new BT::ActionTestNode("action 1");
295 | condition_1 = new BT::ConditionTestNode("condition 1");
296 |
297 |
298 | action_2 = new BT::ActionTestNode("action 2");
299 | condition_2 = new BT::ConditionTestNode("condition 2");
300 |
301 | root = new BT::ParallelNode("par", 4);
302 |
303 | root->AddChild(condition_1);
304 | root->AddChild(action_1);
305 | root->AddChild(condition_2);
306 | root->AddChild(action_2);
307 | }
308 | };
309 |
310 |
311 | struct ComplexParallelTest : testing::Test
312 | {
313 | BT::ParallelNode* root;
314 | BT::ParallelNode* parallel_1;
315 | BT::ParallelNode* parallel_2;
316 |
317 | BT::ActionTestNode* action_1;
318 | BT::ConditionTestNode* condition_1;
319 |
320 | BT::ActionTestNode* action_2;
321 | BT::ConditionTestNode* condition_2;
322 |
323 | BT::ActionTestNode* action_3;
324 | BT::ConditionTestNode* condition_3;
325 |
326 | ComplexParallelTest()
327 | {
328 | action_1 = new BT::ActionTestNode("action 1");
329 | condition_1 = new BT::ConditionTestNode("condition 1");
330 |
331 |
332 | action_2 = new BT::ActionTestNode("action 2");
333 | condition_2 = new BT::ConditionTestNode("condition 2");
334 |
335 |
336 | action_3 = new BT::ActionTestNode("action 3");
337 | condition_3 = new BT::ConditionTestNode("condition 3");
338 |
339 | root = new BT::ParallelNode("root", 2);
340 | parallel_1 = new BT::ParallelNode("par1", 3);
341 | parallel_2 = new BT::ParallelNode("par2", 1);
342 |
343 | parallel_1->AddChild(condition_1);
344 | parallel_1->AddChild(action_1);
345 | parallel_1->AddChild(condition_2);
346 | parallel_1->AddChild(action_2);
347 |
348 | parallel_2->AddChild(condition_3);
349 | parallel_2->AddChild(action_3);
350 |
351 | root->AddChild(parallel_1);
352 | root->AddChild(parallel_2);
353 | }
354 | };
355 |
356 |
357 |
358 | /****************TESTS START HERE***************************/
359 |
360 |
361 |
362 | TEST_F(SimpleSequenceTest, ConditionTrue)
363 | {
364 | std::cout << "Ticking the root node !" << std::endl << std::endl;
365 | // Ticking the root node
366 | BT::ReturnStatus state = root->Tick();
367 |
368 | ASSERT_EQ(BT::RUNNING, action->get_status());
369 | ASSERT_EQ(BT::RUNNING, state);
370 | root->Halt();
371 | }
372 |
373 |
374 | TEST_F(SimpleSequenceTest, ConditionTurnToFalse)
375 | {
376 | BT::ReturnStatus state = root->Tick();
377 | condition->set_boolean_value(false);
378 |
379 | state = root->Tick();
380 | ASSERT_EQ(BT::FAILURE, state);
381 | ASSERT_EQ(BT::HALTED, action->get_status());
382 | root->Halt();
383 | }
384 |
385 |
386 | TEST_F(ComplexSequenceTest, ComplexSequenceConditionsTrue)
387 | {
388 | BT::ReturnStatus state = root->Tick();
389 |
390 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
391 | ASSERT_EQ(BT::RUNNING, state);
392 | root->Halt();
393 | }
394 |
395 |
396 | TEST_F(ComplexSequence2ActionsTest, ConditionsTrue)
397 | {
398 | BT::ReturnStatus state = root->Tick();
399 |
400 | state = root->Tick();
401 |
402 | std::this_thread::sleep_for(std::chrono::seconds(5));
403 | state = root->Tick();
404 | state = root->Tick();
405 |
406 |
407 | ASSERT_EQ(BT::RUNNING, state);
408 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
409 | ASSERT_EQ(BT::RUNNING, seq_1->get_status());
410 | ASSERT_EQ(BT::HALTED, seq_2->get_status());
411 | ASSERT_EQ(BT::HALTED, action_2->get_status());
412 |
413 | root->Halt();
414 | }
415 |
416 | TEST_F(ComplexSequenceTest, ComplexSequenceConditions1ToFalse)
417 | {
418 | BT::ReturnStatus state = root->Tick();
419 |
420 | condition_1->set_boolean_value(false);
421 |
422 | state = root->Tick();
423 |
424 | ASSERT_EQ(BT::FAILURE, state);
425 | ASSERT_EQ(BT::HALTED, action_1->get_status());
426 | root->Halt();
427 | }
428 |
429 | TEST_F(ComplexSequenceTest, ComplexSequenceConditions2ToFalse)
430 | {
431 | BT::ReturnStatus state = root->Tick();
432 |
433 | condition_2->set_boolean_value(false);
434 |
435 | state = root->Tick();
436 |
437 | ASSERT_EQ(BT::FAILURE, state);
438 | ASSERT_EQ(BT::HALTED, action_1->get_status());
439 | root->Halt();
440 | }
441 |
442 |
443 |
444 | TEST_F(SimpleFallbackTest, ConditionTrue)
445 | {
446 | std::cout << "Ticking the root node !" << std::endl << std::endl;
447 | // Ticking the root node
448 | condition->set_boolean_value(true);
449 | BT::ReturnStatus state = root->Tick();
450 |
451 | ASSERT_EQ(BT::IDLE, action->get_status());
452 | ASSERT_EQ(BT::SUCCESS, state);
453 | root->Halt();
454 | }
455 |
456 |
457 | TEST_F(SimpleFallbackTest, ConditionToFalse)
458 | {
459 | condition->set_boolean_value(false);
460 |
461 | BT::ReturnStatus state = root->Tick();
462 | condition->set_boolean_value(true);
463 |
464 |
465 | state = root->Tick();
466 |
467 | ASSERT_EQ(BT::SUCCESS, state);
468 | ASSERT_EQ(BT::HALTED, action->get_status());
469 | root->Halt();
470 | }
471 |
472 |
473 | TEST_F(ComplexFallbackTest, Condition1ToTrue)
474 | {
475 | condition_1->set_boolean_value(false);
476 | condition_2->set_boolean_value(false);
477 |
478 | BT::ReturnStatus state = root->Tick();
479 |
480 | condition_1->set_boolean_value(true);
481 |
482 | state = root->Tick();
483 |
484 | ASSERT_EQ(BT::SUCCESS, state);
485 |
486 | ASSERT_EQ(BT::HALTED, action_1->get_status());
487 | root->Halt();
488 | }
489 |
490 | TEST_F(ComplexFallbackTest, Condition2ToTrue)
491 | {
492 | condition_1->set_boolean_value(false);
493 | condition_2->set_boolean_value(false);
494 |
495 | BT::ReturnStatus state = root->Tick();
496 |
497 | condition_2->set_boolean_value(true);
498 |
499 | state = root->Tick();
500 |
501 | ASSERT_EQ(BT::SUCCESS, state);
502 | ASSERT_EQ(BT::HALTED, action_1->get_status());
503 | root->Halt();
504 | }
505 |
506 |
507 |
508 | TEST_F(BehaviorTreeTest, Condition1ToFalseCondition2True)
509 | {
510 | condition_1->set_boolean_value(false);
511 | condition_2->set_boolean_value(true);
512 |
513 | BT::ReturnStatus state = root->Tick();
514 |
515 | ASSERT_EQ(BT::RUNNING, state);
516 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
517 |
518 | root->Halt();
519 | }
520 |
521 | TEST_F(BehaviorTreeTest, Condition2ToFalseCondition1True)
522 | {
523 | condition_2->set_boolean_value(false);
524 | condition_1->set_boolean_value(true);
525 |
526 | BT::ReturnStatus state = root->Tick();
527 |
528 | ASSERT_EQ(BT::RUNNING, state);
529 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
530 |
531 | root->Halt();
532 | }
533 |
534 |
535 | TEST_F(SimpleSequenceWithMemoryTest, ConditionTrue)
536 | {
537 | std::cout << "Ticking the root node !" << std::endl << std::endl;
538 | // Ticking the root node
539 | BT::ReturnStatus state = root->Tick();
540 | std::this_thread::sleep_for(std::chrono::seconds(1));
541 |
542 | ASSERT_EQ(BT::RUNNING, action->get_status());
543 | ASSERT_EQ(BT::RUNNING, state);
544 | root->Halt();
545 | }
546 |
547 |
548 | TEST_F(SimpleSequenceWithMemoryTest, ConditionTurnToFalse)
549 | {
550 | BT::ReturnStatus state = root->Tick();
551 |
552 | condition->set_boolean_value(false);
553 |
554 | state = root->Tick();
555 |
556 | ASSERT_EQ(BT::RUNNING, state);
557 | ASSERT_EQ(BT::RUNNING, action->get_status());
558 |
559 | root->Halt();
560 | }
561 |
562 |
563 | TEST_F(ComplexSequenceWithMemoryTest, ConditionsTrue)
564 | {
565 | BT::ReturnStatus state = root->Tick();
566 |
567 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
568 | ASSERT_EQ(BT::IDLE, action_2->get_status());
569 | ASSERT_EQ(BT::RUNNING, state);
570 |
571 | root->Halt();
572 | }
573 |
574 |
575 | TEST_F(ComplexSequenceWithMemoryTest, Conditions1ToFalse)
576 | {
577 | BT::ReturnStatus state = root->Tick();
578 |
579 | condition_1->set_boolean_value(false);
580 |
581 | state = root->Tick();
582 |
583 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
584 | ASSERT_EQ(BT::IDLE, action_2->get_status());
585 | ASSERT_EQ(BT::RUNNING, state);
586 | root->Halt();
587 | }
588 |
589 | TEST_F(ComplexSequenceWithMemoryTest, Conditions2ToFalse)
590 | {
591 | BT::ReturnStatus state = root->Tick();
592 |
593 | condition_2->set_boolean_value(false);
594 |
595 | state = root->Tick();
596 |
597 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
598 | ASSERT_EQ(BT::IDLE, action_2->get_status());
599 | ASSERT_EQ(BT::RUNNING, state);
600 |
601 | root->Halt();
602 | }
603 |
604 | TEST_F(ComplexSequenceWithMemoryTest, Action1Done)
605 | {
606 | root->Tick();
607 |
608 | condition_2->set_boolean_value(false);
609 |
610 | root->Tick();
611 | std::this_thread::sleep_for(std::chrono::seconds(10));
612 | root->Tick();
613 |
614 | ASSERT_EQ(BT::RUNNING, action_2->get_status());
615 |
616 | root->Halt();
617 | }
618 |
619 | TEST_F(SimpleFallbackWithMemoryTest, ConditionFalse)
620 | {
621 | std::cout << "Ticking the root node !" << std::endl << std::endl;
622 | // Ticking the root node
623 | condition->set_boolean_value(false);
624 | BT::ReturnStatus state = root->Tick();
625 | std::this_thread::sleep_for(std::chrono::seconds(1));
626 |
627 | ASSERT_EQ(BT::RUNNING, action->get_status());
628 | ASSERT_EQ(BT::RUNNING, state);
629 |
630 | root->Halt();
631 | }
632 |
633 |
634 | TEST_F(SimpleFallbackWithMemoryTest, ConditionTurnToTrue)
635 | {
636 | condition->set_boolean_value(false);
637 |
638 | BT::ReturnStatus state = root->Tick();
639 | condition->set_boolean_value(true);
640 |
641 | state = root->Tick();
642 |
643 | ASSERT_EQ(BT::RUNNING, state);
644 | ASSERT_EQ(BT::RUNNING, action->get_status());
645 |
646 | root->Halt();
647 | }
648 |
649 |
650 |
651 | TEST_F(ComplexFallbackWithMemoryTest, ConditionsTrue)
652 | {
653 | BT::ReturnStatus state = root->Tick();
654 |
655 | ASSERT_EQ(BT::IDLE, action_1->get_status());
656 | ASSERT_EQ(BT::IDLE, action_2->get_status());
657 | ASSERT_EQ(BT::SUCCESS, state);
658 |
659 | root->Halt();
660 | }
661 |
662 | TEST_F(ComplexFallbackWithMemoryTest, Condition1False)
663 | {
664 | condition_1->set_boolean_value(false);
665 | BT::ReturnStatus state = root->Tick();
666 |
667 | ASSERT_EQ(BT::IDLE, action_1->get_status());
668 | ASSERT_EQ(BT::IDLE, action_2->get_status());
669 | ASSERT_EQ(BT::SUCCESS, state);
670 |
671 | root->Halt();
672 | }
673 |
674 |
675 | TEST_F(ComplexFallbackWithMemoryTest, ConditionsFalse)
676 | {
677 | condition_1->set_boolean_value(false);
678 | condition_2->set_boolean_value(false);
679 | BT::ReturnStatus state = root->Tick();
680 |
681 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
682 | ASSERT_EQ(BT::IDLE, action_2->get_status());
683 | ASSERT_EQ(BT::RUNNING, state);
684 |
685 | root->Halt();
686 | }
687 |
688 |
689 |
690 |
691 | TEST_F(ComplexFallbackWithMemoryTest, Conditions1ToTrue)
692 | {
693 | condition_1->set_boolean_value(false);
694 | condition_2->set_boolean_value(false);
695 | BT::ReturnStatus state = root->Tick();
696 | condition_1->set_boolean_value(true);
697 |
698 | state = root->Tick();
699 |
700 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
701 | ASSERT_EQ(BT::IDLE, action_2->get_status());
702 | ASSERT_EQ(BT::RUNNING, state);
703 |
704 | root->Halt();
705 | }
706 |
707 | TEST_F(ComplexFallbackWithMemoryTest, Conditions2ToTrue)
708 | {
709 | condition_1->set_boolean_value(false);
710 |
711 | condition_2->set_boolean_value(false);
712 |
713 | BT::ReturnStatus state = root->Tick();
714 |
715 | condition_2->set_boolean_value(true);
716 |
717 | state = root->Tick();
718 |
719 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
720 | ASSERT_EQ(BT::IDLE, action_2->get_status());
721 | ASSERT_EQ(BT::RUNNING, state);
722 |
723 | root->Halt();
724 | }
725 |
726 | TEST_F(ComplexFallbackWithMemoryTest, Action1Failed)
727 | {
728 | action_1->set_boolean_value(false);
729 | condition_1->set_boolean_value(false);
730 | condition_2->set_boolean_value(false);
731 |
732 | BT::ReturnStatus state = root->Tick();
733 |
734 | state = root->Tick();
735 | std::this_thread::sleep_for(std::chrono::seconds(5));
736 | state = root->Tick();
737 |
738 | ASSERT_EQ(BT::IDLE, action_1->get_status());
739 | ASSERT_EQ(BT::RUNNING, action_2->get_status());
740 | ASSERT_EQ(BT::RUNNING, state);
741 |
742 | root->Halt();
743 | }
744 |
745 |
746 | TEST_F(SimpleParallelTest, ConditionsTrue)
747 | {
748 | BT::ReturnStatus state = root->Tick();
749 |
750 | ASSERT_EQ(BT::IDLE, condition_1->get_status());
751 | ASSERT_EQ(BT::IDLE, condition_2->get_status());
752 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
753 | ASSERT_EQ(BT::RUNNING, action_2->get_status());
754 | ASSERT_EQ(BT::RUNNING, state);
755 |
756 | root->Halt();
757 | }
758 |
759 |
760 | TEST_F(SimpleParallelTest, Threshold_3)
761 | {
762 | root->set_threshold_M(3);
763 | action_2->set_time(200);
764 | root->Tick();
765 | std::this_thread::sleep_for(std::chrono::seconds(5));
766 | BT::ReturnStatus state = root->Tick();
767 |
768 | ASSERT_EQ(BT::IDLE, condition_1->get_status());
769 | ASSERT_EQ(BT::IDLE, condition_2->get_status());
770 | ASSERT_EQ(BT::IDLE, action_1->get_status());
771 | ASSERT_EQ(BT::HALTED, action_2->get_status());
772 | ASSERT_EQ(BT::SUCCESS, state);
773 |
774 | root->Halt();
775 | }
776 |
777 |
778 | TEST_F(SimpleParallelTest, Threshold_1)
779 | {
780 | root->set_threshold_M(1);
781 | BT::ReturnStatus state = root->Tick();
782 |
783 | ASSERT_EQ(BT::IDLE, condition_1->get_status());
784 | ASSERT_EQ(BT::IDLE, condition_2->get_status());
785 | ASSERT_EQ(BT::IDLE, action_1->get_status());
786 | ASSERT_EQ(BT::IDLE, action_2->get_status());
787 | ASSERT_EQ(BT::SUCCESS, state);
788 |
789 | root->Halt();
790 | }
791 | TEST_F(ComplexParallelTest, ConditionsTrue)
792 | {
793 | BT::ReturnStatus state = root->Tick();
794 |
795 | ASSERT_EQ(BT::IDLE, condition_1->get_status());
796 | ASSERT_EQ(BT::IDLE, condition_2->get_status());
797 | ASSERT_EQ(BT::IDLE, condition_3->get_status());
798 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
799 | ASSERT_EQ(BT::RUNNING, action_2->get_status());
800 | ASSERT_EQ(BT::IDLE, action_3->get_status());
801 | ASSERT_EQ(BT::RUNNING, parallel_1->get_status());
802 | ASSERT_EQ(BT::IDLE, parallel_2->get_status());
803 | ASSERT_EQ(BT::RUNNING, state);
804 |
805 | root->Halt();
806 | }
807 |
808 |
809 |
810 | TEST_F(ComplexParallelTest, Condition3False)
811 | {
812 | condition_3->set_boolean_value(false);
813 | BT::ReturnStatus state = root->Tick();
814 |
815 | ASSERT_EQ(BT::IDLE, condition_1->get_status());
816 | ASSERT_EQ(BT::IDLE, condition_2->get_status());
817 | ASSERT_EQ(BT::IDLE, condition_3->get_status());
818 | ASSERT_EQ(BT::RUNNING, action_1->get_status());
819 | ASSERT_EQ(BT::RUNNING, action_2->get_status());
820 | ASSERT_EQ(BT::RUNNING, action_3->get_status());
821 | ASSERT_EQ(BT::RUNNING, parallel_1->get_status());
822 | ASSERT_EQ(BT::RUNNING, parallel_2->get_status());
823 | ASSERT_EQ(BT::RUNNING, state);
824 |
825 | root->Halt();
826 | }
827 |
828 |
829 | TEST_F(ComplexParallelTest, Condition3FalseAction1Done)
830 | {
831 | action_2->set_time(10);
832 | action_3->set_time(10);
833 |
834 | condition_3->set_boolean_value(false);
835 | BT::ReturnStatus state = root->Tick();
836 | std::this_thread::sleep_for(std::chrono::seconds(5));
837 |
838 |
839 | ASSERT_EQ(BT::IDLE, condition_1->get_status());
840 | ASSERT_EQ(BT::IDLE, condition_2->get_status());
841 | ASSERT_EQ(BT::IDLE, condition_3->get_status());
842 | ASSERT_EQ(BT::SUCCESS, action_1->get_status()); // success not read yet by the node parallel_1
843 | ASSERT_EQ(BT::RUNNING, parallel_1->get_status()); // parallel_1 hasn't realize (yet) that action_1 has succeeded
844 |
845 | state = root->Tick();
846 |
847 | ASSERT_EQ(BT::IDLE, action_1->get_status());
848 | ASSERT_EQ(BT::IDLE, parallel_1->get_status());
849 | ASSERT_EQ(BT::HALTED, action_2->get_status());
850 | ASSERT_EQ(BT::RUNNING, action_3->get_status());
851 | ASSERT_EQ(BT::RUNNING, parallel_2->get_status());
852 | ASSERT_EQ(BT::RUNNING, state);
853 |
854 |
855 | state = root->Tick();
856 | std::this_thread::sleep_for(std::chrono::seconds(15));
857 | state = root->Tick();
858 |
859 | ASSERT_EQ(BT::IDLE, parallel_2->get_status());
860 | ASSERT_EQ(BT::IDLE, action_1->get_status());
861 | ASSERT_EQ(BT::IDLE, parallel_1->get_status());
862 | ASSERT_EQ(BT::IDLE, action_3->get_status());
863 | ASSERT_EQ(BT::IDLE, parallel_2->get_status());
864 | ASSERT_EQ(BT::SUCCESS, state);
865 |
866 | root->Halt();
867 | }
868 |
869 | int main(int argc, char **argv)
870 | {
871 | testing::InitGoogleTest(&argc, argv);
872 | return RUN_ALL_TESTS();
873 | }
874 |
875 |
876 |
--------------------------------------------------------------------------------
/gtest/include/action_test_node.h:
--------------------------------------------------------------------------------
1 | #ifndef ACTIONTEST_H
2 | #define ACTIONTEST_H
3 |
4 | #include
5 |
6 | namespace BT
7 | {
8 | class ActionTestNode : public ActionNode
9 | {
10 |
11 | public:
12 | // Constructor
13 | ActionTestNode(std::string Name);
14 | ~ActionTestNode();
15 |
16 | // The method that is going to be executed by the thread
17 | BT::ReturnStatus Tick();
18 | void set_time(int time);
19 |
20 | // The method used to interrupt the execution of the node
21 | void Halt();
22 | void set_boolean_value(bool boolean_value);
23 | private:
24 | int time_;
25 | bool boolean_value_;
26 |
27 | ///ReturnStatus status_;
28 |
29 | };
30 | }
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/gtest/include/condition_test_node.h:
--------------------------------------------------------------------------------
1 | #ifndef CONDITIONTEST_H
2 | #define CONDITIONTEST_H
3 |
4 | #include
5 |
6 | namespace BT
7 | {
8 | class ConditionTestNode : public ConditionNode
9 | {
10 | public:
11 | // Constructor
12 | ConditionTestNode(std::string Name);
13 | ~ConditionTestNode();
14 | void set_boolean_value(bool boolean_value);
15 |
16 | // The method that is going to be executed by the thread
17 | BT::ReturnStatus Tick();
18 | private:
19 | bool boolean_value_;
20 | };
21 | }
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/gtest/src/action_test_node.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015-2017 Michele Colledanchise - All Rights Reserved
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
4 | * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
5 | * 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:
6 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 | *
8 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 | * 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,
10 | * 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.
11 | */
12 |
13 |
14 | #include
15 | #include
16 |
17 |
18 | BT::ActionTestNode::ActionTestNode(std::string name) : ActionNode::ActionNode(name)
19 | {
20 | boolean_value_ = true;
21 | time_ = 3;
22 | }
23 |
24 | BT::ActionTestNode::~ActionTestNode() {}
25 |
26 | BT::ReturnStatus BT::ActionTestNode::Tick()
27 | {
28 |
29 | int i = 0;
30 | while (get_status() != BT::HALTED && i++ < time_)
31 | {
32 | DEBUG_STDOUT(" Action " << get_name() << "running! Thread id:" << std::this_thread::get_id());
33 | std::this_thread::sleep_for(std::chrono::seconds(1));
34 | }
35 | if (get_status() != BT::HALTED)
36 | {
37 | if (boolean_value_)
38 | {
39 | DEBUG_STDOUT(" Action " << get_name() << " Done!");
40 | return BT::SUCCESS;
41 | }
42 | else
43 | {
44 | DEBUG_STDOUT(" Action " << get_name() << " FAILED!");
45 | return BT::FAILURE;
46 | }
47 | }
48 | else
49 | {
50 | return BT::HALTED;
51 | }
52 | }
53 |
54 | void BT::ActionTestNode::Halt()
55 | {
56 | set_status(BT::HALTED);
57 | DEBUG_STDOUT("HALTED state set!");
58 | }
59 |
60 |
61 | void BT::ActionTestNode::set_time(int time)
62 | {
63 | time_ = time;
64 | }
65 |
66 |
67 |
68 | void BT::ActionTestNode::set_boolean_value(bool boolean_value)
69 | {
70 | boolean_value_ = boolean_value;
71 | }
72 |
73 |
74 |
--------------------------------------------------------------------------------
/gtest/src/condition_test_node.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2015-2017 Michele Colledanchise - All Rights Reserved
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
4 | * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
5 | * 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:
6 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 | *
8 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 | * 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,
10 | * 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.
11 | */
12 |
13 |
14 | #include
15 | #include
16 |
17 | BT::ConditionTestNode::ConditionTestNode(std::string name) : ConditionNode::ConditionNode(name)
18 | {
19 | boolean_value_ = true;
20 | }
21 |
22 | BT::ConditionTestNode::~ConditionTestNode() {}
23 |
24 | BT::ReturnStatus BT::ConditionTestNode::Tick()
25 | {
26 | // Condition checking and state update
27 |
28 | if (boolean_value_)
29 | {
30 | set_status(BT::SUCCESS);
31 | return BT::SUCCESS;
32 | }
33 | else
34 | {
35 | set_status(BT::FAILURE);
36 | return BT::FAILURE;
37 | }
38 | }
39 |
40 |
41 |
42 |
43 | void BT::ConditionTestNode::set_boolean_value(bool boolean_value)
44 | {
45 | boolean_value_ = boolean_value;
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/include/action_node.h:
--------------------------------------------------------------------------------
1 | #ifndef BEHAVIORTREECORE_ACTIONNODE_H
2 | #define BEHAVIORTREECORE_ACTIONNODE_H
3 |
4 | #include "leaf_node.h"
5 |
6 | namespace BT
7 | {
8 |
9 | class ActionNode : public LeafNode
10 | {
11 | public:
12 | // Constructor
13 | ActionNode(std::string name);
14 | ~ActionNode();
15 |
16 | // The method that is going to be executed by the thread
17 | void WaitForTick();
18 | virtual BT::ReturnStatus Tick() = 0;
19 |
20 | // The method used to interrupt the execution of the node
21 | virtual void Halt() = 0;
22 |
23 | // Methods used to access the node state without the
24 | // conditional waiting (only mutual access)
25 | bool WriteState(ReturnStatus new_state);
26 | int DrawType();
27 | };
28 | }
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/include/behavior_tree.h:
--------------------------------------------------------------------------------
1 | #ifndef BEHAVIORTREE_H
2 | #define BEHAVIORTREE_H
3 |
4 |
5 |
6 |
7 |
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 |
17 |
18 | #include
19 | #include
20 |
21 | #include
22 |
23 | #include
24 | #include