行为树 — [2] BehaviorTree.CPP的轻量化

上篇中,在编译BehaviorTree.CPP时,使用了Boost,ZeroMQ和Curses库,尤其是Boost,这个库很庞大,本文讲述如何轻量化BehaviorTree.CPP,不依赖Boost,ZeroMQ和ncurse库。


一 修改BehaviorTree.CPP的CMakeLists.txt

下载好BehaviorTree.CPP后,打开里面的CMakeLists.txt,找到Boost的find_package,然后注释掉,
在这里插入图片描述
接着找到ZMQ的find_package,也注释掉,
在这里插入图片描述
最后是找到Curses的find_package,也注释掉,
在这里插入图片描述
以上可以根据自己的需要来进行选择。Boost提供了协程,ZeroMQ会影响PublishedZMQ和bt_recorder的编译,Curses是个图形库,应该是用来写一些界面的。

最后,还有4个配置选项,全部改成OFF,(也可根据需要调整)
在这里插入图片描述


二 搭建工程并运行

工程结构如下,
在这里插入图片描述
BehaviorTree.CPP是上节下载的源码。

工程目录下的CMakeLists.txt内容如下,

cmake_minimum_required(VERSION 3.5)

project(lite_demo)

# 编译BehaviorTree.CPP
add_subdirectory(BehaviorTree.CPP)

find_package(Threads)

include_directories(BehaviorTree.CPP/include)
include_directories(BehaviorTree.CPP/sample_nodes)

add_executable(main src/main.cpp BehaviorTree.CPP/sample_nodes/dummy_nodes.cpp)

target_link_libraries(main behaviortree_cpp_v3 ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} )

src下有个main.cpp,内容如下,

#include "behaviortree_cpp_v3/bt_factory.h"

#define MANUAL_STATIC_LINKING

#ifdef MANUAL_STATIC_LINKING
#include "dummy_nodes.h"
#endif

using namespace BT;

/** Behavior Tree are used to create a logic to decide what
 * to "do" and when. For this reason, our main building blocks are
 * Actions and Conditions.
 *
 * In this tutorial, we will learn how to create custom ActionNodes.
 * It is important to remember that NodeTree are just a way to
 * invoke callbacks (called tick() ). These callbacks are implemented by the user.
 */

// clang-format off
static const char* xml_text = R"(

 <root main_tree_to_execute = "MainTree" >

     <BehaviorTree ID="MainTree">
        <Sequence name="root_sequence">
            <CheckBattery   name="battery_ok"/>
            <OpenGripper    name="open_gripper"/>
            <ApproachObject name="approach_object"/>
            <CloseGripper   name="close_gripper"/>
        </Sequence>
     </BehaviorTree>

 </root>
 )";

// clang-format on

int main()
{
    // We use the BehaviorTreeFactory to register our custom nodes
    BehaviorTreeFactory factory;

    /* There are two ways to register nodes:
    *    - statically, i.e. registering all the nodes one by one.
    *    - dynamically, loading the TreeNodes from a shared library (plugin).
    * */

#ifdef MANUAL_STATIC_LINKING
    // Note: the name used to register should be the same used in the XML.
    // Note that the same operations could be done using DummyNodes::RegisterNodes(factory)

    using namespace DummyNodes;

    // The recommended way to create a Node is through inheritance.
    // Even if it requires more boilerplate, it allows you to use more functionalities
    // like ports (we will discuss this in future tutorials).
    factory.registerNodeType<ApproachObject>("ApproachObject");

    // Registering a SimpleActionNode using a function pointer.
    // you may also use C++11 lambdas instead of std::bind
    factory.registerSimpleCondition("CheckBattery", std::bind(CheckBattery));

    //You can also create SimpleActionNodes using methods of a class
    GripperInterface gripper;
    factory.registerSimpleAction("OpenGripper", std::bind(&GripperInterface::open, &gripper));
    factory.registerSimpleAction("CloseGripper", std::bind(&GripperInterface::close, &gripper));

#else
    // Load dynamically a plugin and register the TreeNodes it contains
    // it automated the registering step.
    factory.registerFromPlugin("./libdummy_nodes_dyn.so");
#endif

    // Trees are created at deployment-time (i.e. at run-time, but only once at the beginning).
    // The currently supported format is XML.
    // IMPORTANT: when the object "tree" goes out of scope, all the TreeNodes are destroyed
    auto tree = factory.createTreeFromText(xml_text);

    // To "execute" a Tree you need to "tick" it.
    // The tick is propagated to the children based on the logic of the tree.
    // In this case, the entire sequence is executed, because all the children
    // of the Sequence return SUCCESS.
    tree.tickRoot();

    return 0;
}

/* Expected output:
*
       [ Battery: OK ]
       GripperInterface::open
       ApproachObject: approach_object
       GripperInterface::close
*/

cd进入build目录,执行下面命令,

cmake .. && make

最后在build目录下生成main,
在这里插入图片描述
执行它,

./main

结果如下,
在这里插入图片描述

© 版权声明
THE END
喜欢就支持一下吧
点赞553 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容