(!) 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++ Reference

Keywords: decision_making

Tutorial Level: BEGINNER

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)

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:
    • BT_RAISE(/STOP)
      • raise global event
        • BT_RAISE(STOP)
      • raise related to FSM context event

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.

Tasks

Task is a atomic preemtable action. decision making support two types of Tasks

  1. ROS remote task
  2. 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'')

Wiki: decision_making/Tutorials/BehaviorTree(c++) (last edited 2013-12-16 21:03:00 by Ari Yakir)