Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags. |
Behavior Trees C++ Reference
Description: Behavior Trees C++ ReferenceKeywords: decision_making
Tutorial Level: BEGINNER
Contents
BT Machine and Nodes definition
BT_HEADER
BT_HEADER(BT_NAME)
- All needed definitions for header (.h) files
BT_ROOT
BT_ROOT_BGN(BT_NAME,EVENTS){ ... }BT_END(NAME)
- Define root of BT Machine.
BT
BT_BGN(NAME){ ... }BT_END(NAME)
- Define BT, that you can call from root BT
BT_PAR
BT_PAR_BGN(NAME){ ... }BT_PAR_END(NAME)
- Define Parallel node. All Nodes/Tasks defined in this block run in parallel.
BT_SEQ
BT_SEQ_BGN(NAME){ ... }BT_SEQ_END(NAME)
- Define Sequencer node. This node runs each Nodes/Tasks defined in the block, one by one, up to first task return FAIL.
BT_SEL
BT_SEL_BGN(NAME){ ... }BT_SEL_END(NAME)
- Define Selector node. This node runs each Nodes/Tasks defined in the block, one by one, up to first task return SUCCESS.
BT Task definition
BT_TASK
BT_TASK_BGN(NAME){ TASK_ACTIONS }BT_TASK_END(NAME)
Define custom task. Task actions is a block of c++ code, where you can use special macros.
BT_CALL_TASK
BT_CALL_TASK(TASK_NAME)
- call remote or local task (external robot_task (activelib) client or registered local function.
This macro defines BT_TASK that call TASK_NAME.
BT_CALL_FSM
BT_CALL_FSM(FSM_NAME)
- call other FSM.
This macro defines BT_TASK that call FSM_NAME
BT_CALL_BT
BT_CALL_BT(BT_NAME)
call BehaviorTree. This macro defines BT_TASK that call BT_NAME
Call BT
BT is a class. For running BT, create instance and use void run() method
Example:
BT_ROOT_BGN(NAME,EVENTS){ .... } BT_END(NAME) instance; instance.run();
BT Task Actions
The next macros you can use inside of BT_TASK block.
BT_TASK_RESULT
BT_TASK_RESULT(RESULT)
Set task result: TaskResult::SUCCESS() or TaskResult::FAIL(Error,Description)
Node name, type, pointer utilities for custom BT_TASK
BT_NODE(NODE_NAME)
get instance of NODE_NAME
BT_NODE_TYPE(NODE_NAME)
get type of NODE_NAME
BT_NODE_PTR(NODE_NAME)
get type of pointer on NODE_NAME
BT_NODE_NEW_PTR(NODE_NAME)
make new for NODE_NAME
BT_LAST_NODE
BT_LAST_NODE
- The last created node instance
BT_RUN_LAST_NODE
BT_RUN_LAST_NODE
- Run the last created node
BT_RUN_NODE(NODE_NAME)
Run NODE_NAME node
Example:
BT_TASK_BGN(T1) { BT_TASK_BGN(T1T1) // define custom bt_task { ... } BT_TASK_END(T1T1) BT_LAST_NODE->run(); // run last defined in current block task : run T1T1 for(int i=0;i<3;i++){ BT_CALL_TASK(T1RT1); // define call to remote/local task T1RT1 TaskResult res = BT_NODE(T1RT1)->run(); // run T1RT1 BT_TASK_RESULT(res); // set result of T1RT1 as result of T1 } } TASK_END(T1)
BT Context
BT_RENAME_CONTEXT(NEW_NAME)
Rename type of current BTContext. This is not CallContext (dynamic context). It's static (defined in compilation time) structure.
BT_NEW_CONTEXT(...)
- Replace current BTContext with new one. The access to context, through special local variable context
Example:
BT_NEW_CONTEXT( int x; int y; double bearing; ) BT_ROOT_BGN(B1){ BT_TASK_BGN(T1){ ... cout<<" x,y = "<<context.x<<","<<context.y<<endl; ... context.bearing = M_PI; ... } BT_TASK_END(T1) } BT_END(B1)
FSM Events
EventQueue is a events distribution system. It's used for sharing events inside of FSM/HSM/BT machines. It's possible to insert external events to system (from ROS or other custom source). It's thread safe.
Each Event is a path contains all context names when this event was created and event short name on the end. Example: /Con/tex/Na/me/EventName. When you compare two events you can use Regular Expressions in name of one event by writing @ on the begging of the name. Example: @/Con/.*/Event[NT]...e
Events usage : (STOP event for example)
- Outside of BT:
- Event e("/STOP")
- global / without context
- Event e("STOP",call_context)
- related to call_context
events->raiseEvent(e);
- raise event
- Inside of FSM:
- global / without context
- BT_RAISE(/STOP)
- raise global event
- BT_RAISE(STOP)
- raise related to FSM context event
- raise global event
- Event e("/STOP")
Interface:
- Event waitEvent()
- blocked function up to new event arrived.
Event tryGetEvent(bool& success)
- unblocked function for get new event if exists
- void drop_all()
- clear queue
- void close()
- close event system. release all waited processes.
- bool isTerminated()const
- check if event system is closed.
Common extensions :
RosEventQueue is a connection of ROS (/decision_making/NODE_NAME/events topic) and internal EventQueue. Must be created after ros::init and ros_decision_making_init.
BT_RAISE
BT_RAISE(EVENT)
- Raise event to events publication system.
BT automatic generates event on the end of BT_Task. You can define map from TaskResult value to Event, by MapResultEvent class.
Example
MapResultEvent::map(''TASK_NAME'', ''ERROR_CODE'', ''EVENT_NAME'');
CallContext
This is a class for shearing parameters and call context information through calls of FSM/HSM/BT machines. You can get access to CallContext inside of BT by special local variable call_ctx.
Interface:
- void push(string name)
- add new context name
- void pop()
- remove last context name
- void createParameters(A* a= new A())
- create parameter object of type A (template)
- bool isParametersDefined()const
- check if parameters created
A& parameters()const
- get parameters. if not defined throw exception.
A& parameters()
- get parameters. if not defined create default instance.
- add new context name
Tasks
Task is a atomic preemtable action. decision making support two types of Tasks
- ROS remote task
- Local task
ROS remote task
Special Activelib client. For create this kind of task, you need extend RobotTask class from robot_task package.
Local task
It's a callback function:
TaskResult FUNCTION_NAME( string task_name, const CallContext& context, EventQueue& events)
You need to registrate local task before usage (otherwise, the system assumes that the task is remote).
LocalTasks::registrate(''TASK_NAME'', ''CALLBACK'')