Current section
Files
Jump to
Current section
Files
src/bt_engine/runners/run_task.erl
-module(run_task).
-include("../bt_node_behaviours/bt_nodes.hrl").
-export([
run/3,
preempt/3
]).
%% should call init first if state is undefined but init function is defined.
%% should call run with args, state, blackboard, event if run/4 is defined; otherwise args, blackboard, event
%% if return is success or failure, should set state as undefined and return success/failure
%% otherwise update state and blackboard with NewState and NewBB and return running
run3param(TaskNode, Module, BB, Event) when is_record(TaskNode, task) ->
{Status, NewBB} = Module:run(TaskNode#task.args, BB, Event),
%% since it doesn't need state, setting it to undefined only.
{Status, undefined, NewBB}.
run4param(TaskNode, Module, BB, Event) when is_record(TaskNode, task) ->
%% init if not already
StartingState = case TaskNode#task.state of
undefined -> Module:init(TaskNode#task.args, BB);
AlreadyInit -> AlreadyInit
end,
Module:run(TaskNode#task.args, StartingState, BB, Event).
-spec run(TaskNode :: task(), BB :: blackboard(), Event :: event()) -> {Status :: status(), NewTaskNode :: task(), NewBB :: blackboard()}.
run(TaskNode, BB, Event) when is_record(TaskNode, task) ->
Module = TaskNode#task.module,
%% check if run/4 is defined; otherwise do run/3
{Status, NewState, NewBB} = case erlang:function_exported(Module, run, 4) of
false -> run3param(TaskNode, Module, BB, Event);
true -> run4param(TaskNode, Module, BB, Event)
end,
case Status of
running -> {running, TaskNode#task{state = NewState}, NewBB};
%% TODO: do we need to return old bb in case of failure or is this fine?
%% resetting state to undefined in case of both success and failure. this means node was terminated
failure -> {failure, TaskNode#task{state = undefined}, NewBB};
success -> {success, TaskNode#task{state = undefined}, NewBB}
end.
%% just clear state and return?
-spec preempt(TaskNode :: task(), BB :: blackboard(), ShouldCleanBB :: boolean()) -> {NewNode :: term(), NewBB :: blackboard()}.
preempt(TaskNode, BB, _ShouldCleanBB) when is_record(TaskNode, task) ->
{TaskNode#task{state = undefined}, BB}.