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.

PDDL Manager Services

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

Service / Topic

Corresponding Deftemplate(s)

/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.

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.

A comprehensive example for using this integration is given in the Tutorial for using the PDDL Manager with cx_pddl_clips An example for using the interfaces directly without this additional integration can be found in the Tutorial for using the PDDL Manager directly.

Request Execution Model

The CLIPS interface allows users to assert multiple request facts concurrently (e.g., adding fluents, creating goal instances, or checking action conditions). However, most interactions with the external PDDL manager must be processed sequentially per PDDL instance.

To guarantee consistency between CLIPS and the PDDL manager, the rule base ensures that only one request affecting a given PDDL instance is active at a time. Additional requests remain pending until the current operation has completed.

This coordination is handled using the busy-with slot of the pddl-instance fact. While an instance is marked as busy, other rules that would trigger conflicting service calls are temporarily blocked.

Example:

  • A request to add fluents must finish before conditions are checked.

  • Retrieving fluents or predicates waits until previous updates have completed.

  • Goal configuration steps (creating goal instances, setting goals, applying filters) are executed in order.

Parallel Planning

Planning requests are handled differently.

Once a goal instance has been created and the goals are registered, a planning request (e.g., via pddl-plan) is sent to the planner asynchronously. Multiple planning tasks may therefore run in parallel, allowing the system to evaluate different goals or planning configurations concurrently.

When a plan is returned, the CLIPS interface automatically creates the corresponding pddl-plan and pddl-action facts.

Rule Priorities

Internally, the rule base uses custom saliences (priorities) to enforce a deterministic ordering of PDDL-related operations (e.g., instance management, object updates, fluent updates, goal configuration, and planning). This ensures that dependent operations are always processed in a consistent order while allowing CLIPS reasoning to interleave with ROS communication.

THe full list of used rule saliences is depicted below:

 (defglobal
  ?*PRIORITY-PDDL-INSTANCES* = -5100
  ?*PRIORITY-PDDL-GET-ACTION-NAMES* = -5300
  ?*PRIORITY-PDDL-OBJECTS* = -5400
  ?*PRIORITY-PDDL-FLUENTS* = -5500
  ?*PRIORITY-PDDL-APPLY-EFFECT* = -5600
  ?*PRIORITY-PDDL-CLEAR-GOALS* = -5700
  ?*PRIORITY-PDDL-CREATE-GOAL-INSTANCE* = -5800
  ?*PRIORITY-PDDL-SET-ACTION-FILTER* = -5900
  ?*PRIORITY-PDDL-SET-FLUENT-FILTER* = -6000
  ?*PRIORITY-PDDL-SET-OBJECT-FILTER* = -6100
  ?*PRIORITY-PDDL-SET-GOALS* = -6200
  ?*PRIORITY-PDDL-PLAN* = -6300
  ?*PRIORITY-PDDL-CHECK-CONDITION* = -6400
  ?*PRIORITY-PDDL-GET-FLUENTS* = -6500
)

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 cx_pddl_clips Agent Tutorial, this feature is used to extend the notion of PDDL actions.

Using the ROS2 CLIPS-Executive with cx_pddl_clips

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. 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

/**:
  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/pddl.clp"
      ]

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

Example: Loading a PDDL Problem and Obtaining the initial State

The following example rule demonstrates how to initialize the connection to the external PDDL manager and load a PDDL problem into CLIPS.

(defrule example-pddl-add-instance
  " Setup PDDL instance and fetch initial facts "
  =>
  (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))
  )
)

The first step is to initialize the interfaces to a running PDDL manager instance by asserting a respective pddl-manager fact. To create an instance, a pddl-instance fact is asserted, providing the domain and problem files, as well as the directory containing them. In order to fetch the initial fluents of the instance (as provided in the problem file), a pddl-get-fluents fact is asserted.

Provided Deftemplates

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

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))
)

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$)))
)

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))
)

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))
)

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))
)

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))
)

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))
)

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))
)

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$)))
)

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))
)

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))
)

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))
)

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))
)

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))
)

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$)))
)

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))
)

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))
)

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"))
)

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))
)

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))
)

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))
)

Represents a PDDL plan.

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

(deftemplate pddl-plan
  (slot instance (type SYMBOL))
  (slot id (type SYMBOL))
  (slot goal (type SYMBOL))
  (slot goal-ptr (type EXTERNAL-ADDRESS))
  (slot plan-type (type SYMBOL) (allowed-values CLASSICAL TEMPORAL) (default CLASSICAL))
  (slot goal-handle (type EXTERNAL-ADDRESS))
  (slot type (type SYMBOL) (allowed-values TEMPORAL CLASSICAL))
  (slot state (type SYMBOL) (allowed-values PENDING WAITING PLANNING REQUEST-CANCELING CANCELING CANCELED SUCCESS FAILURE) (default PENDING))
  (slot plan-start (type FLOAT) (default 0.0))
)

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))
)

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$)))
)

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))
)

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))
)

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$)))
)