PDDL CLIPS Interfaces

The PDDL integration is provided in the form of the PDDL Manager, a ROS lifecycle node that provides ROS interfaces, which can be called through the ROS2 CLIPS-Executive plugins that handle ROS communication.

In order to reduce the manual overhead, the cx_pddl_clips package provides a CLIPS-based interface for interacting with the PDDL Manager node in ROS 2. This allows to interact with the PDDL manager by simply asserting and monitoring CLIPS facts, without the need to do direct ROS communication (e.g., populating ROS messages or waiting for service feedback).

PDDL Manager

The PDDL Manager node has the following responsibilities:

  • Manage multiple PDDL instances concurrently.

  • Load PDDL files (optionally templated via Jinja).

  • Manage fluents, objects, functions, and goals.

  • Check conditions and apply effects of actions.

  • Configure planning goals.

  • Applying planning filters to narrow down problems to a subset of actions, objects, and fluents for more detailed execution models.

  • Trigger planning a for each goal concurrently.

Required ROS2 CLIPS-Executive Plugins

In order to integrate the PDDL manager with the ROS2 CLIPS-Executive, the following plugins are needed:

  • cx::ExecutivePlugin — manages the overall reasoning and control flow, interleaving ROS feedback with CLIPS reasoning.

  • cx::RosMsgsPlugin provides access to ROS interfaces of the PDDL manager from within CLIPS.

  • cx::AmentIndexPlugin resolves package paths via ament_index. While not required, it is very useful in order to load PDDL files.

Also, as the current configuration is compatible with ROS 2 jazzy, action client introspection is not supported, hence the following plugins are needed to trigger temporal planning and obtain the resulting plan:

  • cx::CXCxPddlMsgsPlanTemporalPlugin

  • cx::CXCxPddlMsgsTimedPlanActionPlugin

PDDL Manager Services

The PDDL Manager exposes a wide range of ROS 2 interfaces.

Service / Topic

Corresponding Deftemplate(s)

/add_fluent

pddl-fluent, pddl-fluent-change

/add_pddl_instance

pddl-instance

/check_action_condition

pddl-action-condition

get_action_effects

pddl-action-get-effect

/get_action_names

pddl-action-names

/get_fluents

pddl-get-fluents

/add_fluents

pddl-fluent-change

/rm_fluents

pddl-fluent-change

/add_objects

pddl-object-change

rm_objects

pddl-object-change

set_functions

pddl-numeric-fluent-change

get_functions

pddl-get-numeric-fluents

set_goals

pddl-set-goals

clear_goals

pddl-clear-goals

/set_action_filter

pddl-planning-filter

/set_object_filter

pddl-planning-filter

/set_fluent_filter

pddl-planning-filter

/create_goal_instance

pddl-create-goal-instance

/get_predicates

pddl-get-predicates

/get_type_objects

pddl-get-type-objects

/temp_plan

pddl-plan, pddl-action

/instance_update

pddl-manager

CLIPS Integration

CLIPS needs to interact with the PDDL Manager by creating subscriptions and clients for the endpoints to then utilize the features as desired. In order to reduce manual overhead, predefined rules and deftemplates are available, which are described in the remainder of this document.

An example for using the interfaces directly without this additional abstraction can be found in the Tutorial for using the PDDL Manager directly.

Predefined Interfaces

The idea is to have templates for facts that correspond to the individual endpoints of the PDDL manager. The workflow then is for users to simply assert a fact of a defined template to trigger the request to the PDDL manager, then using rules to observe the provided slots for the outcome.

Example: Loading a PDDL Problem and Pbtaining the initial State

The following example demonstrates how to initialize the connection to the external PDDL manager and load a PDDL problem into CLIPS. It shows two rules:

  1. One rule sets up service clients for communicating with the PDDL manager node.

  2. Another rule creates and registers a PDDL instance, requesting its initial state.

These examples can serve as a starting point for integrating PDDL planning with CLIPS-based reasoning systems.

A more comprehensive example can be found in the Structured PDDL Agent Tutorial.

Creating Service Clients

The first rule initializes the required ROS service clients for the PDDL manager. It also asserts a pddl-services-loaded fact to ensure coherent ordering.

(defrule example-pddl-init
  " Initiate the service clients for the pddl manager "
  =>
  (bind ?services (create$
      add_pddl_instance AddPddlInstance
      get_fluents GetFluents
  ))
  (bind ?index 1)
  (bind ?length (length$ ?services))
  (while (< ?index ?length)
      (bind ?service-name (nth$ ?index ?services))
      (bind ?service-type (nth$ (+ ?index 1) ?services))
      (ros-msgs-create-client
          (str-cat "/pddl_manager" "/" ?service-name)
          (str-cat "cx_pddl_msgs/srv/" ?service-type)
      )
      (bind ?index (+ ?index 2))
  )
  (assert (pddl-services-loaded))
)

Loading the PDDL Instance

Once the service clients are available, the next rule defines and registers a PDDL instance with the external manager. This includes specifying the domain and problem files, as well as the directory containing them. After registration, it triggers fetching of the initial fluents representing the problem’s initial state.

(defrule example-pddl-add-instance
  " Setup PDDL instance and fetch initial facts "
  (pddl-services-loaded)
  =>
  (assert
    (pddl-manager (node "/pddl_manager"))
    (pddl-instance
      (name test)
      (domain "domain.pddl")
      (problem "problem.pddl")
      (directory "<absolute path to directory>")
    )
    (pddl-get-fluents (instance test))
  )
)

Here, three predefined templates are utilized, which are pddl-manager (registering the node name), pddl-instance (creating a PDDL instance from filesand naming it) and pddl-get-fluents (requesting the initial set of fluents). The pddl-get-fluents fact triggers a request to the set of pddl-fluent facts representing the initial state.

ROS2 CLIPS-Executive Configuration

The example configuration below demonstrates how to pre-load the code from the cx_pddl_clips package via batch loading, before loading the example code. Two files are needed. The template definitionsare bundled in deftemplates.clp, while all required rules are loaded through pddl.clp. This split is deliberate, as it allows to override the templates before loading rules, if needed as discussed in more detail later.

/**:
  ros__parameters:
    autostart_node: true
    environments: ["example_agent"]

    structured_pddl_agent:
      plugins: ["executive", "ros_msgs",
                "pddl_files",
                "files"]
      log_clips_to_file: true
      watch: ["facts", "rules"]

    ament_index:
      plugin: "cx::AmentIndexPlugin"

    executive:
      plugin: "cx::ExecutivePlugin"

    ros_msgs:
      plugin: "cx::RosMsgsPlugin"

    pddl_files:
      plugin: "cx::FileLoadPlugin"
      pkg_share_dirs: ["cx_pddl_clips"]
      batch: [
        "clips/cx_pddl_clips/deftemplates.clp",
        "clips/cx_pddl_clips/pddl.clp"

      ]

    files:
      plugin: "cx::FileLoadPlugin"
      pkg_share_dirs: ["cx_pddl_bringup"]
      load: ["clips/structured_agent.clp"]

Template Overrides

The templates provided by the cx_pddl_clips package contain a minimal set of slots to provide the functionality. In practical applications, it might be convenient to store additional information (e.g., context as to why a particular service call is made or hints about how to interpret the results). Therefore, deftemplate definitions are decoupled from the rules, allowing to first load the deftemplates, then loading re-definitions of them as needed, and finally loading the rule set. Potential overrides may add more slots, but need to contain all the original slots, as otherwise the predefined rule base will not work.

In the Structured PDDL Agent Tutorial, this feature is used to extend the notion of PDDL actions.

Provided Deftemplates

In the remainder of this document, all provided deftemplates of the cx_pddl_clips are described.

pddl-action

Represents a grounded PDDL action in a PDDL instance. Automatically created when a plan is received. Can also be asserted directly, if actions are needed in different contexts (e.g., to apply effects). Used to track parameters, plan order, and scheduled times.

(deftemplate pddl-action
  (slot instance (type SYMBOL))
  (slot id (type SYMBOL))
  (slot plan (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
  (slot plan-order-class (type INTEGER))
  (slot planned-start-time (type FLOAT))
  (slot planned-duration (type FLOAT))
)

pddl-action-condition

Represents a condition of a PDDL action. Requires a pddl-action fact with id matching the value in slot action. Obtains the satisfaction state and unsatisfied conditions.

(deftemplate pddl-action-condition
  (slot instance (type SYMBOL))
  (slot action (type SYMBOL))
  (slot condition-type (type SYMBOL) (allowed-values ALL START OVERALL END) (default START))
  (slot state (type SYMBOL) (allowed-values PENDING CHECK-CONDITION CONDITION-SAT CONDITION-UNSAT) (default PENDING))
  (multislot unsatisfied-conditions (type STRING) (default (create$)))
)

pddl-action-get-effect

Request the effect of a grounded PDDL action. Requires a pddl-action fact with id matching the value in slot action. Optionally, the effect can also be directly applied using the slot apply. If effectsa are also applied, corresponding pddl-fluent-change and ref:pddl-numeric-fluent-change facts are asserted, before the state is set to DONE.

(deftemplate pddl-action-get-effect
  (slot action (type SYMBOL))
  (slot effect-type (type SYMBOL) (allowed-values ALL START END) (default ALL))
  (slot apply (type SYMBOL) (allowed-values FALSE TRUE) (default FALSE))
  (slot state (type SYMBOL) (allowed-values PENDING WAITING START-EFFECT-APPLIED DONE ERROR) (default PENDING))
)

pddl-action-names

Retrieve the list of action names for a PDDL instance. This is particularly useful for defining goal filters.

(deftemplate pddl-action-names
  (slot instance (type SYMBOL))
  (multislot action-names (type SYMBOL) (default (create$)))
  (slot state (type SYMBOL) (allowed-values PENDING DONE ERROR) (default PENDING))
  (slot error (type STRING))
)

pddl-clear-goals

Clears all goal conditions for a PDDL instance via the external manager. This assumes that a matching goal instance was created via pddl-create-goal-instance beforehand.

(deftemplate pddl-clear-goals
  (slot instance (type SYMBOL))
  (slot goal (type SYMBOL))
  (slot state (type SYMBOL) (allowed-values PENDING DONE ERROR) (default PENDING))
  (slot error (type STRING))
)

pddl-create-goal-instance

Create a new managed goal instance for a PDDL instance via the external manager.

(deftemplate pddl-create-goal-instance
  (slot instance (type SYMBOL))
  (slot goal (type SYMBOL))
  (slot state (type SYMBOL) (allowed-values PENDING DONE ERROR) (default PENDING))
  (slot error (type STRING))
)

pddl-effect-fluent

Represents a boolean effect of a PDDL action. Asserted when retrieving an action effect via pddl-action-get-effect.

(deftemplate pddl-effect-fluent
  (slot instance (type SYMBOL))
  (slot action (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
  (slot effect-type (type SYMBOL) (allowed-values ALL START END) (default ALL))
)

pddl-effect-numeric-fluent

Represents a numeric effect of a PDDL action at a specific time. Asserted when retrieving an action effect via pddl-action-get-effect.

(deftemplate pddl-effect-numeric-fluent
  (slot instance (type SYMBOL))
  (slot action (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
  (slot value (type FLOAT))
  (slot effect-type (type SYMBOL) (allowed-values ALL START END) (default ALL))
)

pddl-fluent

Represents a boolean fluent in a PDDL instance. Do not assert/retract/modify directly; use pddl-fluent-change to keep the external PDDL manager in sync.

(deftemplate pddl-fluent
  (slot instance (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
)

pddl-fluent-change

Indicates that a boolean fluent should be added or removed. Acts as a transient layer to synchronize with the external PDDL manager. This automatically updates the corresponding pddl-fluent fact.

(deftemplate pddl-fluent-change
  (slot instance (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
  (slot delete (type SYMBOL) (allowed-values FALSE TRUE) (default FALSE))
  (slot request-id (type INTEGER))
  (slot state (type SYMBOL) (allowed-values PENDING WAITING ERROR ON-HOLD) (default PENDING))
  (slot error (type STRING))
)

pddl-get-fluents

Fetch all boolean fluents for a PDDL instance via the external manager. Asserts the corresponding pddl-fluent facts.

(deftemplate pddl-get-fluents
  (slot instance (type SYMBOL))
  (slot state (type SYMBOL) (allowed-values PENDING DONE ERROR) (default PENDING))
  (slot error (type STRING))
)

pddl-get-numeric-fluents

Fetch all numeric fluents for a PDDL instance via the external manager. Asserts the corresponding pddl-numeric-fluent facts.

(deftemplate pddl-get-numeric-fluents
  (slot instance (type SYMBOL))
  (slot state (type SYMBOL) (allowed-values PENDING DONE ERROR) (default PENDING))
  (slot error (type STRING))
)

pddl-get-predicates

Fetch all predicates for a PDDL instance via the external manager. Asserts the corresponding pddl-predicate facts.

(deftemplate pddl-get-predicates
  (slot instance (type SYMBOL))
  (slot state (type SYMBOL) (allowed-values PENDING DONE ERROR) (default PENDING))
  (slot error (type STRING))
)

pddl-get-type-objects

Fetch all objects of a specific type for a PDDL instance via the external manager. Asserts the corresponding pddl-type-objects fact.

(deftemplate pddl-get-type-objects
  (slot instance (type SYMBOL))
  (slot type (type SYMBOL))
  (slot state (type SYMBOL) (allowed-values PENDING DONE ERROR) (default PENDING))
  (slot error (type STRING))
)

pddl-goal-fluent

Represents a positive boolean goal condition for a PDDL instance. Negative conditions are not supported as of now.

(deftemplate pddl-goal-fluent
  (slot instance (type SYMBOL))
  (slot goal (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
)

pddl-goal-numeric-fluent

Represents a numeric goal condition with a specific value in a PDDL instance.

(deftemplate pddl-goal-numeric-fluent
  (slot instance (type SYMBOL))
  (slot goal (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
  (slot value (type FLOAT))
)

pddl-instance

Initialize a PDDL instance with the external manager. Also ensures that no confliction requests are made simultaneously, by always tracking, the current operation.

(deftemplate pddl-instance
  (slot name (type SYMBOL))
  (slot domain (type STRING))
  (slot problem (type STRING))
  (slot directory (type STRING))
  (slot state (type SYMBOL) (allowed-values PENDING LOADED ERROR) (default PENDING))
  (slot busy-with (type SYMBOL) (allowed-values FALSE OBJECTS FLUENTS NUMERIC-FLUENTS ACTION-EFFECTS CREATE-GOAL-INSTANCE CLEAR-GOALS SET-GOALS CHECK-CONDITIONS GET-FLUENTS GET-NUMERIC-FLUENTS GET-PREDICATES GET-TYPE-OBJECTS GET-ACTION-NAMES SET-ACTION-FILTER SET-OBJECT-FILTER SET-FLUENT-FILTER CREATE-GOAL-INSTANCE) (default FALSE))
  (slot error (type STRING))
)

pddl-manager

Assert a fact of this type to specify the name of the PDDL manager node.

(deftemplate pddl-manager
" Store information on the external pddl manager.
"
  (slot node (type STRING) (default "/pddl_manager"))
)

pddl-numeric-fluent

Represents a numeric fluent in a PDDL instance. Use pddl-numeric-fluent-change to update values safely with the external PDDL manager.

(deftemplate pddl-numeric-fluent
  (slot instance (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
  (slot value (type FLOAT))
)

pddl-numeric-fluent-change

Indicates that a numeric fluent should be added or removed. Acts as a transient layer to synchronize with the external PDDL manager.

(deftemplate pddl-numeric-fluent-change
  (slot instance (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot params (type SYMBOL) (default (create$)))
  (slot value (type FLOAT))
  (slot request-id (type INTEGER))
  (slot state (type SYMBOL) (allowed-values PENDING WAITING ERROR ON-HOLD) (default PENDING))
)

pddl-object-change

Indicates that an object should be added or removed from a PDDL instance. Acts as a transient layer to synchronize with the external PDDL manager.

Note that this does not automatically update the pddl-type-objects facts.

(deftemplate pddl-object-change
  (slot instance (type SYMBOL))
  (slot name (type SYMBOL))
  (slot type (type SYMBOL))
  (slot delete (type SYMBOL) (allowed-values FALSE TRUE) (default FALSE))
  (slot request-id (type INTEGER))
  (slot state (type SYMBOL) (allowed-values PENDING WAITING ERROR ON-HOLD) (default PENDING))
  (slot error (type STRING))
)

pddl-plan

Represents a PDDL plan.

Consists of individual pddl-action facts with matching plan id.

(deftemplate pddl-plan
  (slot id (type SYMBOL))
  (slot instance (type SYMBOL))
  (slot duration (type FLOAT))
)

pddl-planning-filter

A transient layer for planning filters between the general PDDL interface and domain-specific usage. Can filter actions, objects, or fluents by defining a whitelist.

(deftemplate pddl-planning-filter
  (slot id (type SYMBOL))
  (slot type (type SYMBOL) (allowed-values ACTIONS OBJECTS FLUENTS))
  (multislot filter (type SYMBOL) (default (create$)))
  (slot instance (type SYMBOL))
  (slot goal (type SYMBOL))
)

pddl-predicate

Represents a predicate in a PDDL instance.

(deftemplate pddl-predicate
  (slot instance (type SYMBOL))
  (slot name (type SYMBOL))
  (multislot param-types (type SYMBOL) (default (create$)))
  (multislot param-names (type SYMBOL) (default (create$)))
)

pddl-service-request-meta

Facts of these types are used internally and should be ignored.

(deftemplate pddl-service-request-meta
  (slot service (type STRING))
  (slot request-id (type INTEGER))
  (slot meta (type SYMBOL))
)

pddl-set-goals

Register goal conditions with the external PDDL manager. The goal conditions are defined using pddl-goal-fluent and pddl-goal-numeric-fluent facts with matching goal ids.

(deftemplate pddl-set-goals
  (slot instance (type SYMBOL))
  (slot goal (type SYMBOL))
  (slot state (type SYMBOL) (allowed-values PENDING DONE ERROR) (default PENDING))
  (slot error (type STRING))
)

pddl-type-objects

Lists all objects of a certain type in a PDDL instance. Created using pddl-get-type-objects.

(deftemplate pddl-type-objects
  (slot instance (type SYMBOL))
  (slot type (type SYMBOL))
  (multislot objects (type STRING) (default (create$)))
)