在前面的示例中,用户定义的节点包含在内并静态链接到C ++项目中。
我们使用了BehaviorTreeFactory
注册manualy这些自定义TreeNodes。
或者,我们可以使用预编译的动态共享库(即插件)在运行时加载用户定义的TreeNode 。
要创建插件,我们必须将一个或多个TreeNode的注册封装到一个函数中,如下所示:
// This is a macro that defines a function with a single argument
// (BehaviorTreeFactory& factory)
BT_REGISTER_NODES(factory)
{
static GripperInterface gi; // we can't have more than instance
factory.registerSimpleAction("SayHello", std::bind(SayHello) );
factory.registerSimpleAction("OpenGripper",
std::bind( &GripperInterface::open, &gi));
factory.registerSimpleAction("CloseGripper",
std::bind( &GripperInterface::close, &gi));
factory.registerNodeType<ApproachObject>("ApproachObject");
factory.registerNodeType<SaySomething>("SaySomething");
}
此函数必须放在.cpp文件中,而不是头文件中。
这里,我们假设BT_REGISTER_NODES和我们的自定义TreeNodes的定义都在文件dummy_nodes.cpp中定义。
使用cmake编译插件时,请将参数添加SHARED
到 add_library
。
#your CMakeLists.txt
add_library (dummy_nodes SHARED dummy_nodes.cpp )
在Linux中,将创建文件libdummy_nodes.so。
因此,第一个教程变得更加简单:
// This is a macro that defines a function with a single argument
// (BehaviorTreeFactory& factory)
BT_REGISTER_NODES(factory)
{
static GripperInterface gi; // we can't have more than instance
factory.registerSimpleAction("SayHello", std::bind(SayHello) );
factory.registerSimpleAction("OpenGripper",
std::bind( &GripperInterface::open, &gi));
factory.registerSimpleAction("CloseGripper",
std::bind( &GripperInterface::close, &gi));
factory.registerNodeType<ApproachObject>("ApproachObject");
factory.registerNodeType<SaySomething>("SaySomething");
}
显示插件的清单
BehaviorTree.CPP提供了一个名为bt_plugin_manifest的命令行工具 。
它显示了注册到插件中的所有用户定义的TreeNode及其对应的NodeParameters。
$> ./bt_plugin_manifest ./libdummy_nodes.so
---------------
ApproachObject [Action]
NodeParameters: 0
---------------
CloseGripper [Action]
NodeParameters: 0
---------------
OpenGripper [Action]
NodeParameters: 0
---------------
SayHello [Action]
NodeParameters: 0
---------------
SaySomething [Action]
NodeParameters: 1:
- [Key]: "message" / [Default]: ""