38 from __future__
import print_function
41 from functools
import partial
43 from ConstrainedPlanningCommon
import *
47 norm = np.linalg.norm(x)
48 if norm > 0
and np.isfinite(norm):
60 def __init__(self, offset, thickness, width, joint_radius, wallType):
63 self.
width = width + joint_radius
73 def checkJoint(self, v):
102 def __init__(self, links, obstacles=0, extra=1):
103 super(ChainConstraint, self).__init__(3 * links, links + extra)
105 self.length = ChainConstraint.LINK_LENGTH
106 self.
width = ChainConstraint.WALL_WIDTH
107 self.radius = links - 2
108 self.jointRadius = ChainConstraint.JOINT_RADIUS
109 self.obstacles = obstacles
111 step = 2. * self.radius / (obstacles + 1.)
113 self.
width, self.jointRadius, i % 2)
114 for i
in range(obstacles)]
116 def function(self, x, out):
118 for i
in range(self.links):
119 joint2 = x[(3 * i):(3 * i + 3)]
120 out[i] = np.linalg.norm(joint1 - joint2) - self.length
124 out[self.links] = np.linalg.norm(x[-3:]) - self.radius
129 out[self.links + 1] = x[(o + 0) * 3 + 2] - x[(o + 1) * 3 + 2]
131 out[self.links + 2] = x[(o + 1) * 3 + 0] - x[(o + 2) * 3 + 0]
133 out[self.links + 3] = x[(o + 2) * 3 + 2] - x[(o + 3) * 3 + 2]
135 def jacobian(self, x, out):
136 out[:, :] = np.zeros(
137 (self.getCoDimension(), self.getAmbientDimension()), dtype=np.float64)
139 plus = np.zeros(3 * (self.links + 1))
140 plus[:(3 * self.links)] = x[:(3 * self.links)]
142 minus = np.zeros(3 * (self.links + 1))
143 minus[-(3 * self.links):] = x[:(3 * self.links)]
145 diagonal = plus - minus
147 for i
in range(self.links):
148 out[i, (3 * i):(3 * i + 3)] = normalize(diagonal[(3 * i):(3 * i + 3)])
149 out[1:self.links, 0:(3 * self.links - 3)
150 ] -= out[1:self.links, 3:(3 * self.links)]
153 out[self.links, -3:] = -normalize(diagonal[-3:])
158 out[self.links + 1, (o * 3 + 2):(o * 3 + 5)] = [1, -1]
160 out[self.links + 2, (o * 3 + 2):(o * 3 + 5)] = [1, -1]
162 out[self.links + 3, (o * 3 + 2):(o * 3 + 5)] = [1, -1]
166 def isValid(self, state):
167 x = np.array([state[i]
for i
in range(self.getAmbientDimension())])
168 for i
in range(self.links):
169 joint = x[(3 * i):(3 * i + 3)]
172 if np.linalg.norm(joint) >= self.radius - self.jointRadius:
173 for wall
in self.walls:
174 if not wall.checkJoint(joint):
177 for i
in range(self.links):
178 joint1 = x[(3 * i):(3 * i + 3)]
179 if np.max(np.absolute(joint1)) < self.jointRadius:
182 for j
in range(i + 1, self.links):
183 joint2 = x[(3 * j):(3 * j + 3)]
184 if np.max(np.absolute(joint1 - joint2)) < self.jointRadius:
189 def createSpace(self):
193 for i
in range(self.links):
194 bounds.setLow(3 * i + 0, -i - 1)
195 bounds.setHigh(3 * i + 0, i + 1)
197 bounds.setLow(3 * i + 1, -i - 1)
198 bounds.setHigh(3 * i + 1, i + 1)
200 bounds.setLow(3 * i + 2, -i - 1)
201 bounds.setHigh(3 * i + 2, i + 1)
203 rvss.setBounds(bounds)
206 def getStartAndGoalStates(self):
207 start = np.zeros(3 * self.links)
208 goal = np.zeros(3 * self.links)
210 for i
in range(self.links - 3):
215 goal[3 * i] = -(i + 1)
222 start[3 * i + 1] = -1
232 start[3 * i + 1] = -1
245 goal[3 * i] = -(i - 1)
254 def getProjection(self, space):
257 def __init__(self, space, links, radius):
258 super(ChainProjection, self).__init__(space)
262 self.defaultCellSizes()
264 def getDimension(self):
267 def defaultCellSizes(self):
268 self.cellSizes_ = list2vec([.1, .1])
270 def project(self, state, projection):
271 s = 3 * (self.links - 1)
272 projection[0] = math.atan2(state[s + 1], state[s])
273 projection[1] = math.acos(state[s + 2] / self.radius)
275 return ChainProjection(space, self.links, self.radius)
277 def dump(self, outfile):
278 print(self.links, file=outfile)
279 print(self.obstacles, file=outfile)
280 print(self.extra, file=outfile)
281 print(self.jointRadius, file=outfile)
282 print(self.length, file=outfile)
283 print(self.radius, file=outfile)
284 print(self.
width, file=outfile)
286 def addBenchmarkParameters(self, bench):
287 bench.addExperimentParameter(
"links",
"INTEGER", str(self.links))
288 bench.addExperimentParameter(
289 "obstacles",
"INTEGER", str(self.obstacles))
290 bench.addExperimentParameter(
"extra",
"INTEGER", str(self.extra))
293 def chainPlanningOnce(cp, planner, output):
294 cp.setPlanner(planner,
"chain")
297 stat = cp.solveOnce(output,
"chain")
300 ou.OMPL_INFORM(
"Dumping problem information to `chain_info.txt`.")
301 with open(
"chain_info.txt",
"w")
as infofile:
302 print(cp.spaceType, file=infofile)
303 cp.constraint.dump(infofile)
309 def chainPlanningBench(cp, planners):
310 cp.setupBenchmark(planners,
"chain")
311 cp.constraint.addBenchmarkParameters(cp.bench)
315 def chainPlanning(options):
318 options.links, options.obstacles, options.extra)
321 options.space, constraint.createSpace(), constraint, options)
323 cp.css.registerProjection(
"chain", constraint.getProjection(cp.css))
325 start, goal = constraint.getStartAndGoalStates()
328 for i
in range(cp.css.getDimension()):
331 cp.setStartAndGoalStates(sstart, sgoal)
333 ChainConstraint.isValid, constraint)))
335 planners = options.planner.split(
",")
336 if not options.bench:
337 chainPlanningOnce(cp, planners[0], options.output)
339 chainPlanningBench(cp, planners)
342 if __name__ ==
"__main__":
343 parser = argparse.ArgumentParser()
344 parser.add_argument(
"-o",
"--output", action=
"store_true",
345 help=
"Dump found solution path (if one exists) in plain text and planning "
346 "graph in GraphML to `torus_path.txt` and `torus_graph.graphml` "
348 parser.add_argument(
"--bench", action=
"store_true",
349 help=
"Do benchmarking on provided planner list.")
350 parser.add_argument(
"-l",
"--links", type=int, default=5,
351 help=
"Number of links in the kinematic chain. Minimum is 4.")
352 parser.add_argument(
"-x",
"--obstacles", type=int, default=0, choices=[0, 1, 2],
353 help=
"Number of `wall' obstacles on the surface of the sphere. Ranges from "
355 parser.add_argument(
"-e",
"--extra", type=int, default=1,
356 help=
"Number of extra constraints to add to the chain. Extra constraints "
358 "1: End-effector is constrained to be on the surface of a sphere of radius "
360 "2: (links-5)th and (links-4)th ball have the same z-value\n"
361 "3: (links-4)th and (links-3)th ball have the same x-value\n"
362 "4: (links-3)th and (links-2)th ball have the same z-value")
363 addSpaceOption(parser)
364 addPlannerOption(parser)
365 addConstrainedOptions(parser)
366 addAtlasOptions(parser)
368 chainPlanning(parser.parse_args())