Skip to content

Commit

Permalink
[planning_system] Added a PANDA interface and problem generator
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-mitrevski committed Feb 1, 2020
1 parent 90b3c45 commit 376d04a
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 9 deletions.
5 changes: 5 additions & 0 deletions rosplan_planning_system/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ add_definitions(-Wno-deprecated-declarations)
add_executable(problemInterface src/ProblemGeneration/ProblemInterface.cpp src/ProblemGeneration/PDDLProblemGenerator.cpp
src/ProblemGeneration/ProblemGenerator.cpp
src/ProblemGeneration/RDDLProblemGenerator.cpp
src/ProblemGeneration/HDDLProblemGenerator.cpp
src/ProblemGeneration/ProblemGeneratorFactory.cpp)
add_executable(popf_planner_interface src/PlannerInterface/POPFPlannerInterface.cpp src/PlannerInterface/PlannerInterface.cpp)
add_executable(lama_planner_interface src/PlannerInterface/LAMAPlannerInterface.cpp src/PlannerInterface/PlannerInterface.cpp)
add_executable(panda_planner_interface src/PlannerInterface/PANDAPlannerInterface.cpp src/PlannerInterface/PlannerInterface.cpp)
add_executable(ff_planner_interface src/PlannerInterface/FFPlannerInterface.cpp src/PlannerInterface/PlannerInterface.cpp)
add_executable(rddlsim_planner_interface src/PlannerInterface/RDDLSIMPlannerInterface.cpp src/PlannerInterface/PlannerInterface.cpp)
add_executable(metricff_planner_interface src/PlannerInterface/FFPlannerInterface.cpp src/PlannerInterface/PlannerInterface.cpp)
Expand All @@ -73,6 +75,7 @@ add_executable(simulatedAction src/ActionInterface/RPSimulatedActionInterface.cp
add_dependencies(problemInterface ${catkin_EXPORTED_TARGETS})
add_dependencies(popf_planner_interface ${catkin_EXPORTED_TARGETS})
add_dependencies(lama_planner_interface ${catkin_EXPORTED_TARGETS})
add_dependencies(panda_planner_interface ${catkin_EXPORTED_TARGETS})
add_dependencies(ff_planner_interface ${catkin_EXPORTED_TARGETS})
add_dependencies(rddlsim_planner_interface ${catkin_EXPORTED_TARGETS})
add_dependencies(metricff_planner_interface ${catkin_EXPORTED_TARGETS})
Expand All @@ -95,6 +98,7 @@ add_dependencies(simulatedAction ${catkin_EXPORTED_TARGETS})
target_link_libraries(problemInterface ${catkin_LIBRARIES})
target_link_libraries(popf_planner_interface ${catkin_LIBRARIES})
target_link_libraries(lama_planner_interface ${catkin_LIBRARIES})
target_link_libraries(panda_planner_interface ${catkin_LIBRARIES})
target_link_libraries(ff_planner_interface ${catkin_LIBRARIES})
target_link_libraries(rddlsim_planner_interface ${catkin_LIBRARIES})
target_link_libraries(metricff_planner_interface ${catkin_LIBRARIES})
Expand Down Expand Up @@ -146,6 +150,7 @@ install(TARGETS
problemInterface
popf_planner_interface
lama_planner_interface
panda_planner_interface
ff_planner_interface
metricff_planner_interface
smt_planner_interface
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "PlannerInterface.h"
#include <fstream>
#include <sstream>
#include <string>
#include <ctime>
#include <string>
#include <streambuf>

#ifndef KCL_PANDA_planner_interface
#define KCL_PANDA_planner_interface

/**
* This file contains an interface to the planner.
*/
namespace KCL_rosplan {

class PANDAPlannerInterface: public PlannerInterface
{
private:

/* runs external commands */
std::string runCommand(std::string cmd);

protected:

bool runPlanner();

public:

PANDAPlannerInterface(ros::NodeHandle& nh);
virtual ~PANDAPlannerInterface();
};

} // close namespace

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef ROSPLAN_HDDL_PROBLEM_GENERATOR_H
#define ROSPLAN_HDDL_PROBLEM_GENERATOR_H

#include "PDDLProblemGenerator.h"

namespace KCL_rosplan {

class HDDLProblemGenerator : public PDDLProblemGenerator {
protected:
virtual void makeProblem(std::ofstream &pFile);
void makeTasks(std::ofstream &pFile);
public:
HDDLProblemGenerator(const std::string& kb): PDDLProblemGenerator(kb) {};
};
} // close namespace

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
namespace KCL_rosplan {

class PDDLProblemGenerator : public ProblemGenerator {
private:
void makeHeader(std::ofstream &pFile);
void makeInitialState(std::ofstream &pFile);
void makeGoals(std::ofstream &pFile);
void makeMetric(std::ofstream &pFile);
void printExpression(std::ofstream &pFile, rosplan_knowledge_msgs::ExprComposite &e);
protected:
virtual void makeHeader(std::ofstream &pFile);
virtual void makeInitialState(std::ofstream &pFile);
virtual void makeGoals(std::ofstream &pFile);
virtual void makeMetric(std::ofstream &pFile);
virtual void printExpression(std::ofstream &pFile, rosplan_knowledge_msgs::ExprComposite &e);

void makeProblem(std::ofstream &pFile);
virtual void makeProblem(std::ofstream &pFile);
public:
PDDLProblemGenerator(const std::string& kb): ProblemGenerator(kb) {};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "rosplan_knowledge_msgs/GetDomainAttributeService.h"
#include "rosplan_knowledge_msgs/GetInstanceService.h"
#include "rosplan_knowledge_msgs/GetAttributeService.h"
#include "rosplan_knowledge_msgs/GetTaskService.h"
#include "rosplan_knowledge_msgs/GetMetricService.h"

#ifndef KCL_ProblemGenerator
Expand All @@ -39,6 +40,7 @@ namespace KCL_rosplan {
std::string state_function_service;
std::string state_timed_knowledge_service;
std::string state_goal_service;
std::string task_service;
std::string state_metric_service;

virtual void makeProblem(std::ofstream &pFile) =0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ProblemGenerator.h"
#include "PDDLProblemGenerator.h"
#include "RDDLProblemGenerator.h"
#include "HDDLProblemGenerator.h"

namespace KCL_rosplan {
typedef std::unique_ptr<ProblemGenerator> ProblemGeneratorPtr;
Expand All @@ -16,7 +17,8 @@ namespace KCL_rosplan {
public:
enum ProbGen {
PDDL,
RDDL
RDDL,
HDDL
};

static ProblemGeneratorPtr createProblemGenerator(ProbGen pg_type, const std::string& kb);
Expand Down
139 changes: 139 additions & 0 deletions rosplan_planning_system/src/PlannerInterface/PANDAPlannerInterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include "rosplan_planning_system/PlannerInterface/PANDAPlannerInterface.h"

namespace KCL_rosplan {

/*-------------*/
/* constructor */
/*-------------*/

PANDAPlannerInterface::PANDAPlannerInterface(ros::NodeHandle& nh)
{
node_handle = &nh;

plan_server = new actionlib::SimpleActionServer<rosplan_dispatch_msgs::PlanAction>((*node_handle), "start_planning", boost::bind(&PlannerInterface::runPlanningServerAction, this, _1), false);

// publishing raw planner output
std::string plannerTopic = "planner_output";
node_handle->getParam("planner_topic", plannerTopic);
plan_publisher = node_handle->advertise<std_msgs::String>(plannerTopic, 1, true);

// start planning action server
plan_server->start();
}

PANDAPlannerInterface::~PANDAPlannerInterface()
{
delete plan_server;
}

/**
* Runs external commands
*/
std::string PANDAPlannerInterface::runCommand(std::string cmd) {
std::string data;
FILE *stream;
char buffer[1000];
stream = popen(cmd.c_str(), "r");
while ( fgets(buffer, 1000, stream) != NULL )
data.append(buffer);
pclose(stream);
return data;
}

/*------------------*/
/* Plan and process */
/*------------------*/

/**
* passes the problem to the Planner; the plan to post-processing.
*/
bool PANDAPlannerInterface::runPlanner() {

// save problem to file for PANDA
if(use_problem_topic && problem_instance_received) {
ROS_INFO("KCL: (%s) (%s) Writing problem to file.", ros::this_node::getName().c_str(), problem_name.c_str());
std::ofstream dest;
dest.open((problem_path).c_str());
dest << problem_instance;
dest.close();
}

// prepare the planner command line
std::string str = planner_command;
std::size_t dit = str.find("DOMAIN");
if(dit!=std::string::npos) str.replace(dit,6,domain_path);
std::size_t pit = str.find("PROBLEM");
if(pit!=std::string::npos) str.replace(pit,7,problem_path);
std::string commandString = str + " > " + data_path + "plan.hddl";

// call the planer
ROS_INFO("KCL: (%s) (%s) Running: %s", ros::this_node::getName().c_str(), problem_name.c_str(), commandString.c_str());
std::string plan = runCommand(commandString.c_str());
ROS_INFO("KCL: (%s) (%s) Planning complete", ros::this_node::getName().c_str(), problem_name.c_str());

// check the planner solved the problem
std::ifstream planfile;
planfile.open((data_path + "plan.hddl").c_str());
std::string line;
std::stringstream ss;

int curr, next;
bool solved = false;
double planDuration;

while (std::getline(planfile, line)) {
if (line.find("SOLUTION SEQUENCE", 0) != std::string::npos) {
solved = true;
} else {
// if a solution has been found, we read the plan
if (solved)
{
// read a plan (might not be the last plan)
planDuration = 0;
ss.str("");
while (std::getline(planfile, line)) {
if (line.length()<2)
break;
ss << line << std::endl;
}
planner_output = ss.str();
}
}
}
planfile.close();

if(!solved) ROS_INFO("KCL: (%s) (%s) Plan was unsolvable.", ros::this_node::getName().c_str(), problem_name.c_str());
else ROS_INFO("KCL: (%s) (%s) Plan was solved.", ros::this_node::getName().c_str(), problem_name.c_str());

return solved;
}

} // close namespace

/*-------------*/
/* Main method */
/*-------------*/

int main(int argc, char **argv) {

srand (static_cast <unsigned> (time(0)));

ros::init(argc,argv,"rosplan_planner_interface");
ros::NodeHandle nh("~");

KCL_rosplan::PANDAPlannerInterface pi(nh);

// subscribe to problem instance
std::string problemTopic = "problem_instance";
nh.getParam("problem_topic", problemTopic);
ros::Subscriber problem_sub = nh.subscribe(problemTopic, 1, &KCL_rosplan::PlannerInterface::problemCallback, dynamic_cast<KCL_rosplan::PlannerInterface*>(&pi));

// start the planning services
ros::ServiceServer service1 = nh.advertiseService("planning_server", &KCL_rosplan::PlannerInterface::runPlanningServerDefault, dynamic_cast<KCL_rosplan::PlannerInterface*>(&pi));
ros::ServiceServer service2 = nh.advertiseService("planning_server_params", &KCL_rosplan::PlannerInterface::runPlanningServerParams, dynamic_cast<KCL_rosplan::PlannerInterface*>(&pi));

ROS_INFO("KCL: (%s) Ready to receive", ros::this_node::getName().c_str());
ros::spin();

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "rosplan_planning_system/ProblemGeneration/HDDLProblemGenerator.h"

namespace KCL_rosplan {
void HDDLProblemGenerator::makeTasks(std::ofstream &pFile) {
ros::NodeHandle nh;
ros::ServiceClient getCurrentTasksClient = nh.serviceClient<rosplan_knowledge_msgs::GetTaskService>(task_service);

pFile << "(:htn\n :tasks (and" << std::endl;

// get current tasks
rosplan_knowledge_msgs::GetTaskService currentTaskSrv;
if (!getCurrentTasksClient.call(currentTaskSrv)) {
ROS_ERROR("KCL: (HDDLProblemGenerator) Failed to call service %s", task_service.c_str());
} else {
for(size_t i=0;i<currentTaskSrv.response.attributes.size();i++) {
rosplan_knowledge_msgs::KnowledgeItem attr = currentTaskSrv.response.attributes[i];
if(attr.knowledge_type == rosplan_knowledge_msgs::KnowledgeItem::TASK) {
pFile << " (" + attr.attribute_name;
for(size_t j=0; j<attr.values.size(); j++) {
pFile << " " << attr.values[j].value;
}
pFile << ")" << std::endl;
}
}
}
pFile << "))" << std::endl;
}

void HDDLProblemGenerator::makeProblem(std::ofstream &pFile) {
makeHeader(pFile);
makeInitialState(pFile);
makeTasks(pFile);
makeGoals(pFile);
makeMetric(pFile);

// add end of problem file
pFile << ")" << std::endl;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ namespace KCL_rosplan {
state_goal_service = ss.str();
ss.str("");

ss << "/" << knowledge_base << "/state/tasks";
task_service = ss.str();
ss.str("");

ss << "/" << knowledge_base << "/state/metric";
state_metric_service = ss.str();
ss.str("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ namespace KCL_rosplan {
ProblemGeneratorPtr ProblemGeneratorFactory::createProblemGenerator(ProblemGeneratorFactory::ProbGen pg_type, const std::string& kb) {
if (pg_type == ProbGen::PDDL) return ProblemGeneratorPtr(new PDDLProblemGenerator(kb));
else if (pg_type == ProbGen::RDDL) return ProblemGeneratorPtr(new RDDLProblemGenerator(kb));
else if (pg_type == ProbGen::HDDL) return ProblemGeneratorPtr(new HDDLProblemGenerator(kb));
else {
ROS_ERROR("KCL: (%s) Unknown Problem Generator type.", ros::this_node::getName().c_str());
ros::shutdown();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace KCL_rosplan {
if (not planning_lang.empty()) {
if (planning_lang == "pddl" or planning_lang == "ppddl") pg_type = KCL_rosplan::ProblemGeneratorFactory::PDDL;
else if (planning_lang == "rddl") pg_type = KCL_rosplan::ProblemGeneratorFactory::RDDL;
else if (planning_lang == "hddl") pg_type = KCL_rosplan::ProblemGeneratorFactory::HDDL;
else {
ROS_WARN("KCL: (%s) Unexpected planning language %s. Please specify the planning language as either \"PDDL\" or \"RDDL\".",
ros::this_node::getName().c_str(), planning_lang.c_str());
Expand All @@ -46,6 +47,7 @@ namespace KCL_rosplan {
std::string extension = (problem_path.size() > 5) ? problem_path.substr(problem_path.find_last_of('.')) : "";
if (extension == ".pddl" or extension == ".ppddl") pg_type = KCL_rosplan::ProblemGeneratorFactory::PDDL;
else if (extension == ".rddl") pg_type = KCL_rosplan::ProblemGeneratorFactory::RDDL;
else if (extension == ".hddl") pg_type = KCL_rosplan::ProblemGeneratorFactory::HDDL;
else {
ROS_ERROR("KCL: (%s) Unexpected problem file extension %s. Please provide a problem file written in PDDL (.pddl extension) or RDDL (.rddl extension).",
ros::this_node::getName().c_str(), extension.c_str());
Expand Down

0 comments on commit 376d04a

Please sign in to comment.