尽量不要用行为树,除非公司里有个人,本来就很擅长行为树,那么可以交给他,其他人没必要参与了。行为树入门难,原因不是它本身多么复杂,而是网上的资料太少,尤其groot的资料更少,全靠自己摸索,一个并不复杂的问题,摸索一整天。有不少资料是游戏设计方面的,用于机器人领域的开源方案目前只有ROS2。资料这么少,肯定是有原因的。
最近从行为树版本3切换到版本4,发现有一些变化,又走了一遍坑之后,我还是认为最好不要用行为树。
安装
安装依赖项,然后去github的release里下载最新的版本1
2
3
4
5sudo apt-get sqlite3
sudo apt-get install libzmq3-dev libboost-dev
sudo apt-get install libboost-coroutine-dev # 需要用到协程
sudo apt-get install qtbase5-dev libqt5svg5-dev libzmq3-dev libdw-dev
cmake老三样编译安装。
普通的cmake设置如下1
2
3
4
5
6
7
8
9
10cmake_minimum_required(VERSION 3.10.2)
project(simple_bt)
set(CMAKE_CXX_SaTANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(behaviortree_cpp)
add_executable(${PROJECT_NAME} "simple_bt.cpp")
target_link_libraries(${PROJECT_NAME} BT::behaviortree_cpp)
ROS2环境的设置如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34cmake_minimum_required(VERSION 3.8)
project(test_node)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
set(CMAKE_CXX_STANDARD 17)
add_compile_options(-Wextra -Wpedantic -Wno-unused-parameter -g)
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(ament_index_cpp)
find_package(behaviortree_cpp)
INCLUDE_DIRECTORIES(/home/user/catkin_ws/src/test_node/include)
add_executable(test_node src/test.cpp)
ament_target_dependencies(test_node
rclcpp
behaviortree_cpp
${BTCPP_LIBRARY}
)
install(TARGETS
test_node
DESTINATION lib/${PROJECT_NAME}
)
ament_package()
package.xml
如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<package format="3">
<name>test_node</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="user@todo.todo">zzp</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>behaviortree_cpp</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
行为树的优点:
- 使用groot编辑,直观容易理解
- 行为逻辑和状态数据分离(减少了耦合),任何节点写好以后可以反复利用
- 重用性高,可用通过重组不同的节点来实现不同的行为树
- 线性的方式扩展,所以扩展性好
- 黑板变量用起来很灵活
缺点:
- 任何一个简单的操作都需要使用节点
- 每次从根节点开始逻辑,占用CPU更多
行为树本身并不具体实现机器人的执行内容,它只负责将执行内容进行编排。以Navigation2为例,具体的执行内容实现是放在各个server中的。行为树上的节点与server进行通信,请求具体的执行内容,然后获得反馈。根据反馈结果又可以请求另外的执行内容。这些不同执行内容间的跳转就是由行为树控制的。
另一种比较常见的组织机器人行为的方式是状态机。ROS1中的move_base就是基于状态机的。它与行为树最显著的区别是状态与执行内容是绑定在一起的。当执行内容需要在多个状态中执行时,各个状态下都需要放置执行内容的逻辑。当业务逻辑代码分散在各处时就不太好维护了
ROS2行为树动态库默认安装在/opt/ros/galactic/lib/libbehaviortree_cpp_v3.so
,头文件在/opt/ros/foxy/include/behaviortree_cpp_v3
xml 文件
xml格式有以下几个要点
- root这个tag是必须的,而且它需要有
main_tree_to_execute
的属性,表示执行哪颗树 - root的子元素必须有BehaviorTree,BehaviorTree必须有ID属性
- 如果root拥有多个BehaviorTree,那么
BehaviorTree
的ID的属性值必须是不同的,此时必须指定main_tree_to_execute
标签 - 如果root只有一个BehaviorTree,那么
main_tree_to_execute
属性可有可无 - BehaviorTree的子元素就是树节点(tree nodes)
TreeNodesModel
标签,主要用于Groot可视化。对于C++程序来说,可以没有。
createTreeFromFile
的文件路径错误时,会报错 what(): Internal error in realpath(): No such file or directory
调试
Groot1的日志工具很不好用,在fbl
文件比较大的时候,很容易卡死。如果总的行为树很大,需要放大才能观看流程,十分不方便。Groot2的日志工具据说很好用,但是收费。
拆分行为树后,在Groot里不方便直接打开子树,只能再开一个Groot打开子树的xml文件. 后来Groot2解决了这个问题,在设置的Editor标签里还可设置是否每次都加载<include>
标签对应的文件。