Skip to content

Commit

Permalink
add popf and popf2 planners
Browse files Browse the repository at this point in the history
  • Loading branch information
oscar-lima committed Aug 19, 2019
1 parent a7e3216 commit 2ffda59
Show file tree
Hide file tree
Showing 36 changed files with 16,614 additions and 1 deletion.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,19 @@
# task_planners
AI model based task planners for decision making in ROSPlan

AI model based task planners for decision making in [ROSPlan](https://github.com/KCL-Planning/ROSPlan)

ROS wrappers for AI task planning open source planners.

The design is based on the [mk](http://wiki.ros.org/mk) ros pkg, to import 3rdparty code.

It performs 3 steps: download a planner source code from the original author website, patches the code by replacing

some files from custom ones, build the code and offers launch files and sample pddl files for manual testing purposes.

User is advised to check sub-pkgs README files for specifics.

Supported planners are:

- [popf](https://nms.kcl.ac.uk/planning/software/popf.html) v1, v2 from KCL University.
- [tfd](http://gki.informatik.uni-freiburg.de/tools/tfd) from Freiburg University.
- [mercury_planner]
14 changes: 14 additions & 0 deletions temporal/popf2_planner/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 2.8.3)
project(popf2_planner)
find_package(catkin REQUIRED COMPONENTS
mk
)

add_custom_target(
popf2_planner ALL
COMMAND cmake -E chdir ${PROJECT_SOURCE_DIR} make -f Makefile.tarball
COMMAND cmake -E make_directory ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_LIB_DESTINATION}/${PROJECT_NAME}
COMMAND cmake -E copy_if_different ${PROJECT_SOURCE_DIR}/build/tempo-sat-popf2/compile/popf2/popf3-clp ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_LIB_DESTINATION}/${PROJECT_NAME}/popf2
)

catkin_package()
23 changes: 23 additions & 0 deletions temporal/popf2_planner/Makefile.tarball
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
all: tfd_planner

TARBALL = build/popf2-11jun2011.tar.bz2
TARBALL_URL = 'https://datapacket.dl.sourceforge.net/project/tsgp/POPF/popf2-11jun2011.tar.bz2'
SOURCE_DIR = build/tempo-sat-popf2
UNPACK_CMD = tar -jxf
include $(shell rospack find mk)/download_unpack_build.mk

tfd_planner: $(SOURCE_DIR)/unpacked
echo "hello: " $(SOURCE_DIR)
echo 'Patching popf planner (1/2) ...'
cp patch/ptree.h $(SOURCE_DIR)/src/VALfiles/parsing/ptree.h
cp patch/FFSolver.cpp $(SOURCE_DIR)/src/popf2/FFSolver.cpp
cp patch/FFEvent.cpp $(SOURCE_DIR)/src/popf2/FFEvent.cpp
cp patch/popfMain.cpp $(SOURCE_DIR)/src/popf2/popfMain.cpp
echo 'Compiling popf planner (2/2) ...'
cd $(SOURCE_DIR)/compile && cmake ../src -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=TRUE && $(MAKE) popf3-clp -Wno-dev

clean:
cd $(SOURCE_DIR)/compile && $(MAKE) clean

wipe:
rm -rf build
57 changes: 57 additions & 0 deletions temporal/popf2_planner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# popf2_planner

POPF is forward-chaining temporal planner developed by KCL University in London.

See [popf website](https://nms.kcl.ac.uk/planning/software/popf.html) for more details.

This package is a ROS wrapper that allows easy integration of the planner with [ROSPlan](https://github.com/KCL-Planning/ROSPlan) framework.

## Difference between popf_planner and popf2_planner

popf_planner -> downloads popf-1.1.tar.gz from [sourceforge](https://sourceforge.net/projects/tsgp/files/POPF)

popf2_planner -> downloads popf2-11jun2011.tar.bz2 from [sourceforge](https://sourceforge.net/projects/tsgp/files/POPF)

## Installation

Make sure you have an active internet connection, then build the ROS pkg.

catkin build popf2_planner

See below for an explanation of the steps it performs.

## Explanation

This pkg performs the following steps automatically for you, when you trigger building:

1. Download [popf2 planner](https://datapacket.dl.sourceforge.net/project/tsgp/POPF/popf2-11jun2011.tar.bz2)

2. Unzip and build popf2 planner

cd build/tempo-sat-popf2/compile && cmake ../src -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=TRUE && $(MAKE) popf3-clp -Wno-dev

3. Patch. This pkg ships with a "patch" folder. Inside it contains files that solve compilation errors and warnings in the popf2 code.

Most of the changes are small, like for example the addition of a header that for some reason is needed in newer gcc versions but was not in the past.

This patch files get automatically copied in the right location for you when you build the ros pkg with the usual catkin build commands.

## Test

This pkg ships with an example launch file to demo the use of this planner in [ROSPlan](https://github.com/KCL-Planning/ROSPlan).

First make sure you have [ROSPlan](https://github.com/KCL-Planning/ROSPlan) installed on your system.

This demo requires four terminals. The order in which you execute the commands is important.

# launch example
roslaunch popf2_planner popf2_planner_example.launch

# listen to planner output
rostopic echo /rosplan_planner_interface/planner_output

# generate a pddl problem
rosservice call /rosplan_problem_interface/problem_generation_server "{}"

# make plan
rosservice call /rosplan_planner_interface/planning_server "{}"
32 changes: 32 additions & 0 deletions temporal/popf2_planner/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0"?>
<package>
<name>popf2_planner</name>
<version>1.0.0</version>
<description>
Forward chaining temporal planner (POPF), temporal task planning system.
Used for decision making in robotics, directly usable in ROSPlan framework.

"The latest version available, POPF2, corresponds to POPF2 from the 2011
International Planning competition plus fixes for a few bugs that have been found since then"
(Information taken from the authors website).
</description>

<maintainer email="[email protected]">Oscar Lima</maintainer>

<license>BSD</license>

<url type="website">https://nms.kcl.ac.uk/planning/software/popf.html</url>

<!-- Author of this wrapper only, see list below for a list of planner authors -->
<author email="[email protected]">Oscar Lima</author>

<!-- The following is a list of the original authors of the planner, as stated in their website -->
<author email="[email protected]">Amanda Coles</author>
<author email="[email protected]">Andrew Coles</author>
<author email="[email protected]">Maria Fox</author>
<author email="[email protected]">Derek Long</author>

<buildtool_depend>catkin</buildtool_depend>
<build_depend>mk</build_depend>

</package>
223 changes: 223 additions & 0 deletions temporal/popf2_planner/patch/FFEvent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
#include "FFEvent.h"
#include "RPGBuilder.h"

#ifdef STOCHASTICDURATIONS
#include "StochasticDurations.h"
#endif

#include <cassert>
#include <limits>
#include <sstream>
#include <iostream>

using std::ostringstream;
using std::endl;

#include <sys/times.h>

#include <unistd.h>

namespace Planner {

int FFEvent::tilLimit = 0;

FFEvent::~FFEvent() {
#ifdef STOCHASTICDURATIONS
delete stochasticTimestamp;
#endif
}

FFEvent::FFEvent(instantiatedOp* a, const double & dMin, const double & dMax)
: action(a), time_spec(VAL::E_AT_START), minDuration(dMin), maxDuration(dMax), pairWithStep(-1),
getEffects(true),
lpTimestamp(-1.0),lpMinTimestamp(-1.0), lpMaxTimestamp(std::numeric_limits<double>::max()),
divisionID(-1)
{
//cout << "FFEvent start\n";
#ifdef STOCHASTICDURATIONS
stochasticTimestamp = 0;
#endif

}

FFEvent::FFEvent(instantiatedOp* a, const int & pw, const double & dMin, const double & dMax)
: action(a), time_spec(VAL::E_AT_END), minDuration(dMin), maxDuration(dMax), pairWithStep(pw),
getEffects(true), lpTimestamp(-1.0), /*lpEndTimestamp(-1.0), */lpMinTimestamp(-1.0), lpMaxTimestamp(std::numeric_limits<double>::max()), divisionID(-1)
{
//cout << "FFEvent end\n";
#ifdef STOCHASTICDURATIONS
stochasticTimestamp = 0;
#endif

}

FFEvent::FFEvent(instantiatedOp* a, const int & s, const int & pw, const double & dMin, const double & dMax)
: action(a), time_spec(VAL::E_OVER_ALL), minDuration(dMin), maxDuration(dMax), pairWithStep(pw),
getEffects(true), lpTimestamp(-1.0), /*lpEndTimestamp(-1.0), */lpMinTimestamp(-1.0), lpMaxTimestamp(std::numeric_limits<double>::max()), divisionID(s)
{
//cout << "FFEvent end\n";
#ifdef STOCHASTICDURATIONS
stochasticTimestamp = 0;
#endif

}

FFEvent::FFEvent(const int & t)
: action(0), time_spec(VAL::E_AT), minDuration(-1.0), maxDuration(-1.0), pairWithStep(-1), getEffects(true),
lpTimestamp(-1.0), /*lpEndTimestamp(-1.0), */lpMinTimestamp(-1.0), lpMaxTimestamp(std::numeric_limits<double>::max()), divisionID(t)
{
assert(divisionID <= tilLimit);
//cout << "FFEvent start\n";
#ifdef STOCHASTICDURATIONS
stochasticTimestamp = 0;
#endif

}


FFEvent::FFEvent(const FFEvent & f)
: action(f.action), time_spec(f.time_spec), minDuration(f.minDuration), maxDuration(f.maxDuration),
pairWithStep(f.pairWithStep), getEffects(f.getEffects) , lpTimestamp(f.lpTimestamp),
lpMinTimestamp(f.lpMinTimestamp), lpMaxTimestamp(f.lpMaxTimestamp), divisionID(f.divisionID), needToFinish(f.needToFinish)
{
//cout << "FFEvent copy\n";
#ifdef STOCHASTICDURATIONS
stochasticTimestamp = (f.stochasticTimestamp ? f.stochasticTimestamp->clone() : 0);
#endif

}

FFEvent::FFEvent()
: action(0), time_spec(VAL::E_AT_START), minDuration(0.0), maxDuration(0.0), lpTimestamp(-1.0),
lpMinTimestamp(-1.0), lpMaxTimestamp(std::numeric_limits<double>::max()), divisionID(-1)
{
//cout << "FFEvent default\n";
#ifdef STOCHASTICDURATIONS
stochasticTimestamp = 0;
#endif

}

FFEvent & FFEvent::operator=(const FFEvent & f)
{
//cout << "FFEvent assignment op\n";
action = f.action;
time_spec = f.time_spec;
minDuration = f.minDuration;
maxDuration = f.maxDuration;
pairWithStep = f.pairWithStep;
getEffects = f.getEffects;
lpTimestamp = f.lpTimestamp;
lpMinTimestamp = f.lpMinTimestamp;
lpMaxTimestamp = f.lpMaxTimestamp;
divisionID = f.divisionID;
needToFinish = f.needToFinish;

#ifdef STOCHASTICDURATIONS
delete stochasticTimestamp;
stochasticTimestamp = (f.stochasticTimestamp ? f.stochasticTimestamp->clone() : 0);
#endif

return *this;
}


string threeDP(double d)
{
ostringstream toReturn;

d *= 1000;

int asInt = d;

d -= asInt;
if (d >= 0.5) {
asInt += 1;
}

int fractionalPart = asInt % 1000;

toReturn << asInt / 1000 << ".";

if (fractionalPart < 100) {
toReturn << "0";
}
if (fractionalPart < 10) {
toReturn << "0";
}

toReturn << asInt % 1000;

return toReturn.str();
}

void FFEvent::printPlan(const list<FFEvent> & toPrint)
{
tms refReturn;
times(&refReturn);

double secs = ((double)refReturn.tms_utime + (double)refReturn.tms_stime) / ((double) sysconf(_SC_CLK_TCK));

int twodp = (int)(secs * 100.0);
int wholesecs = twodp / 100;
int centisecs = twodp % 100;

cout << "; Time " << wholesecs << ".";
if (centisecs < 10) cout << "0";
cout << centisecs << "\n";
list<FFEvent>::const_iterator planItr = toPrint.begin();
const list<FFEvent>::const_iterator planEnd = toPrint.end();
const int planSize = toPrint.size();
vector<double> endTS(planSize);
#ifdef STOCHASTICDURATIONS
vector<double> endSTS(planSize);
#endif
vector<const FFEvent*> planVector(planSize);
map<double, list<int> > sorted;
for (int i = 0; planItr != planEnd; ++planItr, ++i) {
if (planItr->time_spec == VAL::E_AT_START) {
sorted[planItr->lpTimestamp].push_back(i);
planVector[i] = &(*planItr);
} else if (planItr->time_spec == VAL::E_AT_END) {
endTS[i] = planItr->lpTimestamp;
#ifdef STOCHASTICDURATIONS
endSTS[i] = planItr->stochasticTimestamp->getTimestampForRPGHeuristic();
#endif
}
}
map<double, list<int> >::iterator sortedItr = sorted.begin();
const map<double, list<int> >::iterator sortedEnd = sorted.end();

for (; sortedItr != sortedEnd; ++sortedItr) {
list<int>::iterator iItr = sortedItr->second.begin();
const list<int>::iterator iEnd = sortedItr->second.end();

for (; iItr != iEnd; ++iItr) {
const FFEvent * const planItr = planVector[*iItr];
if (planItr->lpTimestamp < 0.0000001) {
cout << "0.000";
} else {
cout << threeDP(planItr->lpTimestamp);
}
cout << ": " << *(planItr->action) << " ";
if (planItr->pairWithStep >= 0) {
const double dur = endTS[planItr->pairWithStep] - planItr->lpTimestamp;
cout << " [" << threeDP(dur) << "]";
#ifdef STOCHASTICDURATIONS
cout << ";\t\t {" << planItr->stochasticTimestamp->getTimestampForRPGHeuristic() << "} {" << endSTS[planItr->pairWithStep] << "}";
#endif
} else if (RPGBuilder::getRPGDEs(planItr->action->getID()).empty()) {
cout << " [" << threeDP(RPGBuilder::getNonTemporalDurationToPrint()[planItr->action->getID()]) << "]";
#ifdef STOCHASTICDURATIONS
cout << ";\t\t {" << planItr->stochasticTimestamp->getTimestampForRPGHeuristic() << "} {" << EPSILON + planItr->stochasticTimestamp->getTimestampForRPGHeuristic() << "}";
#endif
} else {
assert(false);
}
cout << endl;
}
}
}

};

Loading

0 comments on commit 2ffda59

Please sign in to comment.