8 import subprocess
as sp
29 fl = fcntl.fcntl(fd, fcntl.F_GETFL)
30 fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
42 _result = PDDLPlannerResult()
49 search_option = rospy.get_param(
'~pddl_search_option',
'')
60 problem = goal.problem
62 max_planning_time = goal.max_planning_time.to_sec()
63 rospy.loginfo(
"take a message")
65 rospy.loginfo(
"problem_path => %s" % problem_path)
66 rospy.loginfo(
"domain_path => %s" % domain_path)
70 self.
_result.sequence = [PDDLStep(action = x.split(
' ')[1].lstrip(
"\("),
71 args = re.search(
"\([^\)]+\)", x).group(0).lstrip(
"\(").rstrip(
"\)").split(
' ')[1:],
72 start_time = re.search(
"[0-9]+.[0-9]+:" , x).group(0).rstrip(
":"),
73 action_duration = re.search(
"\[D[^\)]+;", x).group(0).lstrip(
"[D:").rstrip(
";")
76 self.
_result.use_durative_action =
True
78 self.
_result.sequence = [PDDLStep(action = x.split(
' ')[0],
79 args = x.split(
' ')[1:])
82 rospy.loginfo(
"action finished with success")
83 except ActionPreemptedException:
84 rospy.loginfo(
"action preempted")
85 self.
_as.set_preempted()
87 rospy.logerr(
"Failed to parse output")
88 self.
_as.set_aborted()
89 except RuntimeError
as e:
90 rospy.logerr(
"Planner exited with error: %s" % e)
91 self.
_as.set_aborted()
92 except Exception
as e:
93 rospy.logerr(
"Unhandled Error: %s" % e)
94 rospy.logerr(traceback.format_exc())
95 self.
_as.set_aborted()
100 step_before_after = output.split(
"step")
101 if len(step_before_after) == 2:
102 results = [re.sub(
"\s*$",
"", re.sub(
r'^\s*\d+:\s*',
"" , x))
103 for x
in step_before_after[1].split(
"time spent")[0].split(
"\n")]
104 rospy.loginfo(
"result => %s" % results)
105 return filter(
lambda x: x !=
"", results)
109 rospy.loginfo(output)
111 step_before_after = output.split(
"step")
112 if len(step_before_after) == 2:
113 results = [y.group(0)
114 for y
in [re.search(
"\([^\)]+\)", x)
115 for x
in step_before_after[1].split(
"Total cost")[0].split(
"\n")[1:]]
117 results = filter(
lambda a: a.find(
"(REACH-GOAL)") < 0, results)
118 rospy.loginfo(
"result => %s" % results)
124 rospy.loginfo(output)
126 duration_before_after = output.split(
"action Duration")
127 if len(duration_before_after) == 2:
128 results = [y.group(0)
129 for y
in [re.search(
"[0-9][^\]]+\]", x)
130 for x
in duration_before_after[1].split(
"Solution number")[0].split(
"\n")[1:]]
132 rospy.loginfo(
"result => %s" % results)
138 plan_path = path_name
140 while os.path.exists(path_name +
"." + str(i)):
141 plan_path = path_name +
"." + str(i)
143 rospy.loginfo(
"plan_path => %s" % plan_path)
145 with open(plan_path)
as f:
146 plan = f.read().split(
"\n")
149 results = [re.sub(
" \)$",
")", x)
151 rospy.loginfo(results)
156 if max_planning_time > 0.0:
157 command = [
"timeout", str(max_planning_time)] + command
158 rospy.loginfo(
"Command: %s" % command)
159 proc = sp.Popen(command, stdout=sp.PIPE, stderr=sp.PIPE)
161 output, error = str(), str()
164 if rospy.is_shutdown():
166 if self.
_as.is_preempt_requested():
168 if proc.poll()
is not None:
173 if type(data_out) == bytes:
174 data_out = data_out.decode(
'utf-8')
175 if type(data_err) == bytes:
176 data_err = data_err.decode(
'utf-8')
182 data = proc.communicate()
185 if type(data_out) == bytes:
186 data_out = data_out.decode(
'utf-8')
187 if type(data_err) == bytes:
188 data_err = data_err.decode(
'utf-8')
192 if proc.returncode
not in [0, 124]:
196 msg =
"Output:\n" + output +
"\n"
197 msg +=
"Error:\n" + error +
"\n"
198 msg +=
"Exit code: {}\n".format(proc.poll())
199 raise RuntimeError(msg)
205 if proc
is None or proc.poll()
is not None:
209 proc.send_signal(signal.SIGINT)
212 if proc.poll()
is not None:
216 proc.send_signal(signal.SIGTERM)
219 if proc.poll()
is not None:
225 except Exception
as e:
226 rospy.logerr(
"Failed to kill process: %s" % e)
233 output = self.
exec_process([
"rosrun",
"ff",
"ff",
"-f", problem,
"-o", domain],
241 if re.search(
"final domain representation is:", output):
242 tmp = output.split(
"metric:")
249 (fd, path_name) = tempfile.mkstemp(text=
True, prefix=
'plan_')
250 output = self.
exec_process([
"rosrun",
"downward",
"plan", domain, problem] + self.
_search_option + [
"--plan-file", path_name],
252 rospy.loginfo(output)
262 rospy.logfatal(
"set invalid planner: %s !" % self.
_planner_name)
266 search_durative = re.search(
"durative", domain.requirements)
267 rospy.loginfo (
"gen_tmp_pddl_file: requirements:%s" % domain.requirements)
268 if search_durative ==
None:
271 return (problem_file, domain_file)
275 return (problem_file, domain_file)
288 if o.type
in grouped_objects:
289 grouped_objects[o.type].append(o.name)
291 grouped_objects[o.type] = [o.name]
292 return [
" ".join(grouped_objects[t]) +
" - " + t
293 for t
in grouped_objects.keys()]
296 (fd, path_name) = tempfile.mkstemp(text=
True, prefix=
'problem_')
297 path = os.fdopen(fd,
'w')
298 path.write(
"""(define (problem %s)
303 """ % (problem.name, problem.domain,
305 ' '.join(problem.initial), problem.goal))
307 path.write(
"""(:metric %s)""" % problem.metric)
312 (fd, path_name) = tempfile.mkstemp(text=
True, prefix=
'domain_')
313 path = os.fdopen(fd,
'w')
314 path.write(
"(define (domain %s)\n" % domain.name)
315 path.write(
"(:requirements %s)\n" % domain.requirements)
316 path.write(
"(:types \n")
317 for i
in domain.types:
320 if len(domain.constants) > 0:
321 path.write(
"(:constants \n")
322 for i
in domain.constants:
325 path.write(
"(:predicates\n")
326 for i
in domain.predicates:
330 path.write(
"(:functions\n")
331 for i
in domain.functions:
334 for action
in domain.actions:
335 path.write(
"(:action %s\n" % action.name)
336 path.write(
":parameters %s\n" % action.parameters)
337 path.write(
":precondition %s\n" % action.precondition)
338 path.write(
":effect %s\n" % action.effect)
344 rospy.loginfo(
"domain.actions:%s" % domain.actions)
345 (fd, path_name) = tempfile.mkstemp(text=
True, prefix=
'domain_')
346 path = os.fdopen(fd,
'w')
347 path.write(
"(define (domain %s)\n" % domain.name)
348 path.write(
"(:requirements %s)\n" % domain.requirements)
349 path.write(
"(:types \n")
350 for i
in domain.types:
353 if len(domain.constants) > 0:
354 path.write(
"(:constants \n")
355 for i
in domain.constants:
358 path.write(
"(:predicates\n")
359 for i
in domain.predicates:
363 path.write(
"(:functions\n")
364 for i
in domain.functions:
367 for action
in domain.actions:
368 path.write(
"(:durative-action %s\n" % action.name)
369 path.write(
":parameters %s\n" % action.parameters)
370 path.write(
":duration %s\n" % action.action_duration)
371 path.write(
":condition %s\n" % action.precondition)
372 path.write(
":effect %s\n" % action.effect)
378 if __name__ ==
'__main__':
379 rospy.init_node(
'pddl_planner')