39 from __future__
import print_function
41 from ompl
import util
as ou
42 from ompl
import base
as ob
43 from ompl
import geometric
as og
45 from ompl
import tools
as ot
52 from os.path
import abspath, dirname, join
55 0, join(dirname(dirname(dirname(abspath(__file__)))),
'py-bindings'))
56 from ompl
import util
as ou
57 from ompl
import base
as ob
58 from ompl
import geometric
as og
60 from ompl
import tools
as ot
67 def addSpaceOption(parser):
68 parser.add_argument(
"-s",
"--space", default=
"PJ",
69 choices=[
"PJ",
"AT",
"TB"],
70 help=
"""Choose which constraint handling methodology to use. One of:
71 PJ - Projection (Default)
73 TB - Tangent Bundle.""")
76 def addPlannerOption(parser):
77 parser.add_argument(
"-p",
"--planner", default=
"RRT",
78 help=
"Comma-separated list of which motion planner to use (multiple if "
79 "benchmarking, one if planning).\n Choose from, e.g.:\n"
80 "RRT (Default), RRTConnect, RRTstar, "
81 "EST, BiEST, ProjEST, "
87 def addConstrainedOptions(parser):
88 group = parser.add_argument_group(
"Constrained planning options")
89 group.add_argument(
"-d",
"--delta", type=float, default=ob.CONSTRAINED_STATE_SPACE_DELTA,
90 help=
"Step-size for discrete geodesic on manifold.")
91 group.add_argument(
"--lambda", type=float, dest=
"lambda_", metavar=
"LAMBDA",
92 default=ob.CONSTRAINED_STATE_SPACE_LAMBDA,
93 help=
"Maximum `wandering` allowed during atlas traversal. Must be greater "
95 group.add_argument(
"--tolerance", type=float, default=ob.CONSTRAINT_PROJECTION_TOLERANCE,
96 help=
"Constraint satisfaction tolerance.")
97 group.add_argument(
"--time", type=float, default=5.,
98 help=
"Planning time allowed.")
99 group.add_argument(
"--tries", type=int, default=ob.CONSTRAINT_PROJECTION_MAX_ITERATIONS,
100 help=
"Maximum number sample tries per sample.")
101 group.add_argument(
"-r",
"--range", type=float, default=0.,
102 help=
"Planner `range` value for planners that support this parameter. "
103 "Automatically determined otherwise (when 0).")
106 ret = ou.vectorDouble()
111 def clearSpaceAndPlanner(planner):
112 planner.getSpaceInformation().getStateSpace().clear()
116 def addAtlasOptions(parser):
117 group = parser.add_argument_group(
"Atlas options")
118 group.add_argument(
"--epsilon", type=float, default=ob.ATLAS_STATE_SPACE_EPSILON,
119 help=
"Maximum distance from an atlas chart to the manifold. Must be "
121 group.add_argument(
"--rho", type=float, default=ob.CONSTRAINED_STATE_SPACE_DELTA *
122 ob.ATLAS_STATE_SPACE_RHO_MULTIPLIER,
123 help=
"Maximum radius for an atlas chart. Must be positive.")
124 group.add_argument(
"--exploration", type=float, default=ob.ATLAS_STATE_SPACE_EXPLORATION,
125 help=
"Value in [0, 1] which tunes balance of refinement and exploration in "
127 group.add_argument(
"--alpha", type=float, default=ob.ATLAS_STATE_SPACE_ALPHA,
128 help=
"Maximum angle between an atlas chart and the manifold. Must be in "
130 group.add_argument(
"--bias", action=
"store_true",
131 help=
"Sets whether the atlas should use frontier-biased chart sampling "
132 "rather than uniform.")
133 group.add_argument(
"--no-separate", action=
"store_true",
134 help=
"Sets that the atlas should not compute chart separating halfspaces.")
135 group.add_argument(
"--charts", type=int, default=ob.ATLAS_STATE_SPACE_MAX_CHARTS_PER_EXTENSION,
136 help=
"Maximum number of atlas charts that can be generated during one "
137 "manifold traversal.")
142 def __init__(self, spaceType, space, constraint, options):
146 self.
constraint.setTolerance(options.tolerance)
147 self.
constraint.setMaxIterations(options.tries)
153 if spaceType ==
"PJ":
154 ou.OMPL_INFORM(
"Using Projection-Based State Space!")
157 elif spaceType ==
"AT":
158 ou.OMPL_INFORM(
"Using Atlas-Based State Space!")
161 elif spaceType ==
"TB":
162 ou.OMPL_INFORM(
"Using Tangent Bundle-Based State Space!")
167 self.
css.setDelta(options.delta)
168 self.
css.setLambda(options.lambda_)
169 if not spaceType ==
"PJ":
170 self.
css.setExploration(options.exploration)
171 self.
css.setEpsilon(options.epsilon)
172 self.
css.setRho(options.rho)
173 self.
css.setAlpha(options.alpha)
174 self.
css.setMaxChartsPerExtension(options.charts)
176 self.
css.setBiasFunction(ob.AtlasChartBiasFunction(
lambda c, atlas=self.
css:
177 atlas.getChartCount() - c.getNeighborCount() + 1.))
178 if spaceType ==
"AT":
179 self.
css.setSeparated(
not options.no_separate)
183 def setStartAndGoalStates(self, start, goal):
186 self.
css.anchorChart(start())
187 self.
css.anchorChart(goal())
190 self.
ss.setStartAndGoalStates(start, goal)
192 def getPlanner(self, plannerName, projectionName=None):
193 planner = eval(
'og.%s(self.csi)' % plannerName)
197 planner.setRange(self.
css.getRho_s())
199 planner.setRange(self.
options.range)
204 planner.setProjectionEvaluator(projectionName)
209 def setPlanner(self, plannerName, projectionName=None):
211 self.
ss.setPlanner(self.
pp)
213 def solveOnce(self, output=False, name="ompl"):
219 path = self.
ss.getSolutionPath()
221 ou.OMPL_WARN(
"Path fails check!")
223 if stat == ob.PlannerStatus.APPROXIMATE_SOLUTION:
224 ou.OMPL_WARN(
"Solution is approximate.")
227 ou.OMPL_INFORM(
"Simplifying solution...")
228 self.
ss.simplifySolution(5.)
230 simplePath = self.
ss.getSolutionPath()
231 ou.OMPL_INFORM(
"Simplified Path Length: %.3f -> %.3f" %
232 (path.length(), simplePath.length()))
234 if not simplePath.check():
235 ou.OMPL_WARN(
"Simplified path fails check!")
238 ou.OMPL_INFORM(
"Interpolating path...")
242 ou.OMPL_WARN(
"Interpolated simplified path fails check!")
244 ou.OMPL_INFORM(
"Interpolating simplified path...")
245 simplePath.interpolate()
247 if not simplePath.check():
248 ou.OMPL_WARN(
"Interpolated simplified path fails check!")
251 ou.OMPL_INFORM(
"Dumping path to `%s_path.txt`." % name)
252 with open(
'%s_path.txt' % name,
'w')
as pathfile:
253 print(path.printAsMatrix(), file=pathfile)
256 "Dumping simplified path to `%s_simplepath.txt`." % name)
257 with open(
"%s_simplepath.txt" % name,
'w')
as simplepathfile:
258 print(simplePath.printAsMatrix(), file=simplepathfile)
260 ou.OMPL_WARN(
"No solution found.")
264 def setupBenchmark(self, planners, problem):
266 print(
"Benchmarking not available, no ompl.tools")
271 self.
bench.addExperimentParameter(
272 "n",
"INTEGER", str(self.
constraint.getAmbientDimension()))
273 self.
bench.addExperimentParameter(
274 "k",
"INTEGER", str(self.
constraint.getManifoldDimension()))
275 self.
bench.addExperimentParameter(
276 "n - k",
"INTEGER", str(self.
constraint.getCoDimension()))
277 self.
bench.addExperimentParameter(
"space",
"INTEGER", self.
spaceType)
279 self.
request = ot.Benchmark.Request()
283 self.
request.timeBetweenUpdates = 0.1
284 self.
request.saveConsoleOutput =
False
285 for planner
in planners:
288 self.
bench.setPreRunEvent(ot.PreSetupEvent(clearSpaceAndPlanner))
290 def runBenchmark(self):
292 filename = str(datetime.datetime.now()) +
'_' + \
294 self.
bench.saveResultsToFile(filename)
296 def atlasStats(self):
300 ou.OMPL_INFORM(
"Atlas has %d charts" % self.
css.getChartCount())
302 ou.OMPL_INFORM(
"Atlas is approximately %.3f%% open" %
303 self.
css.estimateFrontierPercent())
305 def dumpGraph(self, name):
306 ou.OMPL_INFORM(
"Dumping planner graph to `%s_graph.graphml`." % name)
308 self.
pp.getPlannerData(data)
310 with open(
"%s_graph.graphml" % name,
"w")
as graphfile:
311 print(data.printGraphML(), file=graphfile)
314 ou.OMPL_INFORM(
"Dumping atlas to `%s_atlas.ply`." % name)
315 with open(
"%s_atlas.ply" % name,
"w")
as atlasfile:
316 print(self.
css.printPLY(), file=atlasfile)