ROS2-BDI
A planning based Multi-Agent BDI architecture for ROS2
Bringup
The bringup requires essentially the following:
- PDDL domain defined for the agent, expressing relevant objects and properties of the environment in which is put into wrt. to its knowledge.
-
Action nodes defined in the PDDL domain for the agent implemented by inheriting from the abstract class
BDIActionExecutor
, respecting its requirements and exploiting the provided API calls enabling feedback on the progress, status and leveraging communication among agents.
Other components might be considered optional, nonetheless you need to take them seriously to further boost the capabilities of your agent:
-
Sensor nodes implemented by inheriting from the abstract class
Sensor
, respecting its requirements and exploiting the provided API calls leveraging the update of the corresponding belief set wrt. what's been detected and internal processing performed within the sensor. Technically, they're not necessary, but in most real scenarios you'd find them essential. - Core behaviour tuning via the initialization parameters that can be specified (overriding the default ones) in the launch python script for the agent. They are all documented below.
PDDL domain example
The pddl file below is supposed to be a simple domain definition for a ROS2-BDI agent which acts as a cleaner.
;; domain file: cleaner-domain.pddl
(define (domain cleaner-domain)
(:requirements
:strips :typing
:fluents :durative-actions
)
;; Types ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(:types
waypoint
robot
);; end Types ;;;;;;;;;;;;;;;;;;;;;;;;;
(:predicates
(in ?r - robot ?wp - waypoint)
(workfree ?r - robot)
(recharging_station ?wp - waypoint)
(cleaned ?wp - waypoint)
)
(:functions
(battery_charge ?r - robot)
)
(:durative-action movetoward
:parameters (?r - robot ?wp_from ?wp_to - waypoint)
:duration (= ?duration 4)
:condition (and
(at start (in ?r ?wp_from))
(at start (workfree ?r))
(at start (> (battery_charge ?r) 20))
(over all (> (battery_charge ?r) 10))
)
:effect (and
(at start (not(workfree ?r)))
(at start (not(in ?r ?wp_from)))
(at end (in ?r ?wp_to))
(at end (workfree ?r))
(at end (decrease (battery_charge ?r) 10))
)
)
(:durative-action doclean
:parameters (?r - robot ?wp - waypoint)
:duration (= ?duration 4)
:condition (and
(at start (workfree ?r))
(at start (> (battery_charge ?r) 30))
(over all (> (battery_charge ?r) 10))
(over all (in ?r ?wp))
)
:effect (and
(at start (not(workfree ?r)))
(at end (workfree ?r))
(at end (cleaned ?wp))
(at end (decrease (battery_charge ?r) 20))
)
)
(:durative-action recharge
:parameters (?r - robot ?wp - waypoint)
:duration (= ?duration 4)
:condition (and
(at start (workfree ?r))
(over all (in ?r ?wp))
(over all (recharging_station ?wp))
)
:effect (and
(at start (not(workfree ?r)))
(at end (workfree ?r))
(at end (assign (battery_charge ?r) 100))
)
)
)
Instances of interest might be robotic agent (itself or others) and points of interest in a map.
Predicates of interest are the following:
Predicate | Semantic |
---|---|
(in ?r - robot ?wp - waypoint) | robotic agent ?r is situated in ?wp |
(workfree ?r - robot) | robotic agent ?r is currently "free" to work |
(recharging_station ?wp - waypoint) | robotic agents can recharge their battery in ?wp |
(cleaned ?wp - waypoint) | ?wp is clean |
The only defined Function takes track of the battery charge of a robotic agent.
Actions essentially defines when, which and how properties are supposed to be and change before, after and/or during
their executions. The cleaner agent we have envisioned can essentially move, clean and recharge. IT'S REALLY
IMPORTANT THAT THE FIRST PARAMETER OF EVERY ROS2-BDI ACTION DEFINED IN ITS PDDL DOMAIN WITHOLDS THE REFERENCE TO ITS agent_id
value .
The user won't need to worry to put it there, if the provided python libraries are used to generate
the launch description for the agent. The takeout information is that it's not possible to simply define a move, clean,... action, without
leaving room in the first argument for a reference to the agent, so the proper action executor node (the one belonging to the agent)
will be selected and triggered when the action needs to be run.
NOTE: This is not valid anymore if you break the default behaviour by setting agent_id_as_specialized_arg
to
false
, go back here for further info.
Python bringup example
The following script can basically be copied and pasted in order to be tuned to comply with the user's needs. It allows to easily generate a launch description to boot up all the ROS2-BDI core and auxiliary nodes as well as an instance of PlanSys2 for the agent, while hiding all the complexity. User just needs to put the reference for the implemented Sensors and Actions. as below, specifying the required parameters and the needed tunable ones too.
import sys
from ament_index_python.packages import get_package_share_directory
ros2_bdi_bringup_dir = get_package_share_directory('ros2_bdi_bringup')
sys.path.append(ros2_bdi_bringup_dir + '/launch/')
from bdi_agent import AgentLaunchDescription
from bdi_agent_skills import AgentAction
from bdi_agent_skills import AgentSensor
def generate_launch_description():
AGENT_ID = 'cleaner'
AGENT_GROUP_ID = 'cleaner'
bdi_tests_share_dir = get_package_share_directory('ros2_bdi_tests')
# perform moving toward
action_movetoward = AgentAction(
package='ros2_bdi_tests',
executable='movetoward_bdi',
name='movetoward'
)
# perform cleaning action
action_doclean = AgentAction(
package='ros2_bdi_tests',
executable='doclean_bdi',
name='doclean'
)
# recharging action
action_recharge = AgentAction(
package='ros2_bdi_tests',
executable='recharge_bdi',
name='recharge'
)
# waypoint sensor
wp_sensor = AgentSensor(
package='ros2_bdi_tests',
executable='wp_sensor',
name='wp_sensor',
specific_params=[
{"init_sleep": 2}
])
ld = AgentLaunchDescription(
agent_id=AGENT_ID,
agent_group=AGENT_GROUP_ID,
init_params={
'pddl_file': bdi_tests_share_dir + '/pddl/cleaner_simple/cleaner-domain.pddl',
'init_bset': bdi_tests_share_dir + '/launch/init_cleaner_simple/init_bset.yaml',
'init_dset': bdi_tests_share_dir + '/launch/init_cleaner_simple/init_dset.yaml',
'autosub_prec': True,
'autosub_cont': True,
'reschedule_policy': 'NO_PREEMPT'
},
actions=[action_movetoward, action_doclean, action_recharge],
sensors=[wp_sensor]
)
return ld
Launch Parameters
Required parameters
For every agent, the user must define:
- its unique id
- the id for the agents’ group it belongs to
- its PDDL domain expressing the relevant part of the world it’s interested in and the actions it’s capable of carrying on
Parameter | Type | Description |
---|---|---|
agent_id |
string | Unique id for the given agent, defining the prefix for all of its nodes, topics and services. It’s left to the user the task of ensuring that there are no agents sharing the same id. |
agent_group |
string | Shared id for a group of agents the given agent belongs to. This is necessary to allow or forbid certain communication exchanges. |
pddl_file |
string | Filepath to the PDDL domain loaded by the PlanSys2 instance of the agent, defining everything relevant to the agent wrt. the environment it’s put into and the actions is capable of executing. |
Tunable parameters
Many of the ROS2-BDI agent behaviours can be properly tune wrt. the properties of the agent and/or the context in which it ends up operating. The user can tune them via the following parameters detailed in the table below. Note how all of them have already some default values: it's up to the user to change them or not.
Parameter | Type | Default value | Description |
---|---|---|---|
init_bset |
string | null | Filepath to YAML file compliant to the BeliefSet value prototype definition, which is nonetheless than an array of Belief describing the initial current vision of the world of the ready-to-be launched ROS2-BDI agent. If missing, the set is initialized as empty. |
init_dset |
string | null | Filepath to YAML file compliant to the DesireSet value prototype definition, which is nonetheless than an array of Desire. describing the initial current set of desirable state of the world for the ready-to-be launched ROS2-BDI agent. If missing, the set is initialized as empty. |
init_reactive_rules_set |
string | null | Filepath to YAML file containing an array of items compliant to the Event Listener rules that are specified here. The conditions are checked every time a new belief set update is received to see if a condition matches, entailing further updates to the belief and/or desire set. |
reschedule_policy |
enum {PREEMPT, NO_PREEMPT} |
NO_PREEMPT |
Defines rescheduling policy:
|
comp_plan_tries |
integer in [1-∞] |
8 | Number of times the ROS2-BDI agent tries to compute a plan for a desire before discarding it. |
exec_plan_tries |
integer in [1-∞] |
8 | Number of times the ROS2-BDI agent demands the execution of a plan for a desire before discarding the latter. |
autosub_prec |
boolean | False | If True, performs preconditions autosubmission, meaning that one or more desires will be autosubmitted by the ROS2-BDI agent to fulfill the unsatisfied preconditions of a desire currently present in its desire set. They will be set with a slightly higher priority than the original desire. |
autosub_context |
boolean | False | If True, performs context autosubmission, meaning that one or more desires will be autosubmitted by the ROS2-BDI agent to fulfill the unsatisfied context conditions of a desire currently present in its desire set. They will be set with a slightly lower priority than the original desire. |
rtc_deadline |
float in [1-∞] |
2.0 |
rtc_deadline*target_desire.deadline
represents the limited time before
the Plan Director requests the
abortion of the current plan in
execution fulfilling target_desire .
|
belief_ck |
string[] | [] | List of agents’ groups whose belief CHECK requests can be accepted by the ROS2-BDI agent. |
belief_w |
string[] | [] | List of agents’ groups whose belief WRITE requests can be accepted by the ROS2-BDI agent. |
desire_ck |
string[] | [] | List of agents’ groups whose desire CHECK requests can be accepted by the ROS2-BDI agent. |
desire_w |
string[] | [] | List of agents’ groups whose desire WRITE requests can be accepted by the ROS2-BDI agent. |
desire_pr |
float[] values in [0-1] |
[] |
desire pr[i] is the max accepted
priority for a desire addition
requested by agents belonging to
the agent group desire_w[i]
|