Planner Integration

The Task Planner Plugin comes not only with some built-in planners, but also provides the ability to integrate other ones with little effort. To do so, a planner integration script has to be written, and used like described in the Setup Form Section. This page explains how to write an integration script for a planner.

Overview

The integration of a planner has to fulfill four tasks:
At first, it has to trigger the planner, to plan the specific task. After this process, the script has to parse the resulting plan into an internal plugin format. The third task is to clean up the system, in case the planner wrote any persistent files, and the last step the script has to accomplish, is to create a report and return it to the plugin.

Integration

To integrate a planner, a class derived from the plugins “PlannerInterface” needs to be created, and the method “plan_scenario” has to be implemented. The purpose of this method is to fulfill the four tasks mentioned above, and described below. This is a skeleton for an integration script:

from rafcontpp.model.planner_interface import PlannerInterface
from rafcontpp.model.planning_report import PlanningReport
from rafcontpp.model.plan_step import PlanStep

class MyIntegration(PlannerInterface)ː
     
     def plan_scenario(self, domain_path, facts_path, planner_argv, storage_path):
        #Do all four tasks here
        return PlanningReport(planning_successful, plan, generated_files, error_message)

1. Trigger the Planner

The first step is to trigger the planner, e.g. make it plan the task. The arguments of “plan_scenario”, which are probably needed are “domain_path”, which contains the path of the pddl domain file as string, “facts_path”, which contains the path of the pddl facts file as string, and “planner_argv” which is a string array, potentially containing additional planner arguments. Worth mentioning is, that the plugin supports concurrent task planning, e.g. More tasks can run at a time. So it may be useful to ensure, that two tasks, using two instances of the same planner, do not interfere with eachother, e.g. Overriding temporary files.

2. Parse the Plan

If planning was successful, the resulting plan has to be parsed into the plugin’s internal format. A parsed plan, is a list of “PlanSteps” in right order, and a PlanStep represents one action in the plan, e.g. Is the name of the instantiated action and a list of its arguments. So the part “cook bob soup” or “(cook bob soup)(1)” in a plan, would result in a PlanStep(‘cook’,[‘bob’,’soup’]). This is the constructor for “PlanStep”:

PlanStep(action_name:String, arguments:[String])

3. Clean Up

When parsing the plan is done, the system should be cleand up. Therefore all files, generated by the planner should be moved into the directory specified in “storage_path”. Also a list should be generated, containing the names of these files. If the planner didn’t generate a persistent plan file, it maybe useful to rectify this here.

4. Create a Planning Report

The last step is to report the planning results. Therefore a planning report has to be generated. It contains the following:

  1. Information about wether planning was successful.
  2. The plan, this is the parsed plan from step two.
  3. The list, containing the names of all generated files from step three.
  4. An error message. If planning was successful, this message is irrelevant, but otherwise it would be useful, if it indicates what went wrong.

These informations are summed up in a “PlanningReport” object, which has to be returned to the plugin. This is it’s constructor:

PlanningReport(planning_successful:Boolean, plan:[PlanStep], generated_files:[String], error_message:String)

That’s it. The planner is now usable within the plugin.

Using the integrated Planner

The script written to integrate the planner, referred to as planner script, is now ready to use. So when the planner should be used to plan a task, this script should be selected as “planner script” and “Other…” as planner in the Planning Setup Form.