Loading...
Searching...
No Matches
vamp_planning.py
1import numpy as np
2import random
3import copy
4import vamp
5import vamp.pointcloud
6from functools import partial
7from fire import Fire
8from ompl import base as ob
9from ompl import geometric as og
10from ompl import tools as ot
11from vamp_state_space import (
12 VampMotionValidator,
13 VampStateValidityChecker,
14 VampStateSpace,
15)
16
17import sys
18import os
19
20sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
21from viser_visualizer.viser_visualizer import ViserVisualizer
22
23import time
24import subprocess
25import os
26import shutil
27
28POINTS_PER_SPHERE = 300
29# Starting configuration
30a = [0.0, -0.785, 0.0, -2.356, 0.0, 1.571, 0.785]
31
32# Goal configuration
33b = [2.35, 1.0, 0.0, -0.8, 0, 2.5, 0.785]
34# Problem specification: a list of sphere centers
35problem = [
36 [0.55, 0, 0.25],
37 [0.35, 0.35, 0.25],
38 [0, 0.55, 0.25],
39 [-0.55, 0, 0.25],
40 [-0.35, -0.35, 0.25],
41 [0, -0.55, 0.25],
42 [0.35, -0.35, 0.25],
43 [0.35, 0.35, 0.8],
44 [0, 0.55, 0.8],
45 [-0.35, 0.35, 0.8],
46 [-0.55, 0, 0.8],
47 [-0.35, -0.35, 0.8],
48 [0, -0.55, 0.8],
49 [0.35, -0.35, 0.8],
50]
51
52
53def isStateValid(
54 s: ob.RealVectorStateType, env: vamp.Environment, dimension: int
55) -> bool:
56 config = s[0:dimension]
57 return vamp.panda.validate(config, env)
58
59
60def create_environment(
61 variation: float = 0.01,
62 radius: float = 0.2,
63 use_point_cloud: bool = False,
64 points_per_sphere: int = POINTS_PER_SPHERE,
65):
66 """Create a VAMP environment with either spheres or point cloud obstacles.
67
68 Returns (env, spheres, point_cloud) where point_cloud is None for sphere mode.
69 """
70 spheres = [np.array(sphere) for sphere in problem]
71 random.shuffle(spheres)
72 spheres_copy = copy.deepcopy(spheres)
73
74 for sphere in spheres_copy:
75 sphere += np.random.uniform(low=-variation, high=variation, size=(3,))
76
77 env = vamp.Environment()
78 point_cloud = None
79
80 if use_point_cloud:
81 # Sample points on the surface of each obstacle sphere to form a point cloud
82 point_cloud = np.vstack(
83 [
84 vamp.pointcloud.sphere_sample_surface(
85 center, radius, points_per_sphere, 0.0
86 )
87 for center in spheres_copy
88 ]
89 ).astype(np.float32)
90
91 # r_min, r_max: smallest and largest collision sphere radii on the robot
92 r_min, r_max = vamp.panda.min_max_radii()
93 # filter_pointcloud(cloud, radius, leaf_size, origin, lower_bound, upper_bound, sort)
94 # - Filters and organizes the point cloud for efficient collision checking
95 filtered_point_cloud_list, elapsed_ns = vamp.filter_pointcloud(
96 point_cloud, r_min, 2, (0, 0, 0), (-2, -2, -2), (2, 2, 2), True
97 )
98 # add_pointcloud(cloud, r_min, r_max, padding)
99 # - padding: extra clearance added around each point
100 n_added = env.add_pointcloud(filtered_point_cloud_list, r_min, r_max, 0.01)
101 else:
102 for sphere in spheres_copy:
103 env.add_sphere(vamp.Sphere(sphere, radius))
104
105 return env, spheres, point_cloud
106
107
108def planOnce(
109 variation: float = 0.01,
110 radius: float = 0.2,
111 use_point_cloud: bool = False,
112 points_per_sphere: int = POINTS_PER_SPHERE,
113 visualize: bool = False,
114):
115 env, spheres, point_cloud = create_environment(
116 variation, radius, use_point_cloud, points_per_sphere
117 )
118
119 # Use VAMP's robot module to initialize state space and validations
120 robot = vamp.panda
121 dimension = robot.dimension()
122 space = VampStateSpace(robot=robot)
123 si = ob.SpaceInformation(space)
124
125 motion_validator = VampMotionValidator(si=si, env=env, robot=robot)
126 state_validity_checker = VampStateValidityChecker(si=si, env=env, robot=robot)
127
128 # Select a planner
129 planner = og.RRTConnect(si)
130
131 # Set validators
132 si.setMotionValidator(motion_validator)
133 si.setStateValidityChecker(state_validity_checker)
134
135 # Build SimpleSetup object
136 ss = og.SimpleSetup(si)
137 ss.setPlanner(planner)
138
139 # Create start and goal states
140 start = si.allocState()
141 start[0:dimension] = a
142 goal = si.allocState()
143 goal[0:dimension] = b
144 ss.setStartAndGoalStates(start, goal)
145
146 # Solve
147 planning_start = time.time()
148 result = ss.solve(5.0)
149 if result:
150 path = ss.getSolutionPath()
151 print(f"Planning time: {time.time() - planning_start}")
152 print(f"Generated path with {path.getStateCount()} states")
153
154 if visualize:
155 visualizer = ViserVisualizer(
156 robot_name="panda", robot_dimension=dimension, port=8080
157 )
158
159 if point_cloud is not None:
160 pc_colors = np.tile([204, 102, 51], (point_cloud.shape[0], 1))
161 visualizer.add_point_cloud(point_cloud, color=pc_colors)
162 else:
163 for sphere in spheres:
164 visualizer.add_sphere(sphere, radius, color=(0.8, 0.4, 0.2))
165
166 path.interpolate(int(path.getStateCount() * 15))
167 states = path.getStates()
168 trajectory = np.array([list(state[0:dimension]) for state in states])
169 visualizer.visualize_trajectory(trajectory)
170 visualizer.play_until_key_pressed()
171 else:
172 print(f"No solution found (time: {time.time() - planning_start})")
173
174
175def planBenchmark(
176 variation: float = 0.01,
177 radius: float = 0.2,
178 use_point_cloud: bool = False,
179 points_per_sphere: int = POINTS_PER_SPHERE,
180 n_trials: int = 100,
181):
182 env, spheres, point_cloud = create_environment(
183 variation, radius, use_point_cloud, points_per_sphere
184 )
185
186 # Use VAMP's robot module to initialize state space and validations
187 robot = vamp.panda
188 dimension = robot.dimension()
189 space = VampStateSpace(robot=robot)
190 si = ob.SpaceInformation(space)
191
192 motion_validator = VampMotionValidator(si=si, env=env, robot=robot)
193 state_validity_checker = VampStateValidityChecker(si=si, env=env, robot=robot)
194
195 # Set validators
196 si.setMotionValidator(motion_validator)
197 si.setStateValidityChecker(state_validity_checker)
198
199 # Build SimpleSetup object
200 ss = og.SimpleSetup(si)
201
202 start = si.allocState()
203 start[0:dimension] = a
204 goal = si.allocState()
205 goal[0:dimension] = b
206 ss.setStartAndGoalStates(start, goal)
207
208 planners = [og.RRTConnect(si), og.RRT(si), og.KPIECE1(si), og.LBKPIECE1(si)]
209
210 # Create Benchmark
211 env_label = "PointCloud" if use_point_cloud else "Sphere"
212 benchmark = ot.Benchmark(ss, f"Vamp Cage Planning Benchmark ({env_label})")
213 for planner in planners:
214 benchmark.addPlanner(planner)
215
216 # Setup Benchmark
217 req = ot.Request()
218 req.maxTime = 1.0
219 req.maxMem = 100.0
220 req.runCount = n_trials
221 req.displayProgress = True
222 benchmark.benchmark(req)
223
224 log_file = "vamp_cage_planning_benchmark_python.log"
225 benchmark.saveResultsToFile(log_file)
226 db_path = "vamp_cage_planning_benchmark_python.db"
227 ot.readBenchmarkLog(db_path, [log_file], moveitformat=False)
228 print(f"Database saved to {db_path}")
229
230 try:
231 import plannerarena.app
232
233 print(f"Displaying benchmark results from {db_path}")
234 plannerarena.app.DATABASE = os.path.abspath(db_path)
235 plannerarena.app.run()
236 except ImportError:
237 print(
238 "PlannerArena not found, please install it from https://github.com/ompl/plannerarena"
239 )
240
241
242def main(
243 variation: float = 0.01,
244 benchmark: bool = False,
245 use_point_cloud: bool = False,
246 n_trials: int = 100,
247 radius: float = 0.2,
248 visualize: bool = False,
249):
250 if benchmark:
251 planBenchmark(variation, radius, use_point_cloud, n_trials=n_trials)
252 else:
253 planOnce(variation, radius, use_point_cloud, visualize=visualize)
254
255
256if __name__ == "__main__":
257 Fire(main)
The base class for space information. This contains all the information about the space planning is d...
Kinematic Planning by Interior-Exterior Cell Exploration.
Definition KPIECE1.h:72
Lazy Bi-directional KPIECE with one level of discretization.
Definition LBKPIECE1.h:79
RRT-Connect (RRTConnect).
Definition RRTConnect.h:62
Rapidly-exploring Random Trees.
Definition RRT.h:66
Create the set of classes typically needed to solve a geometric problem.
Definition SimpleSetup.h:63
Benchmark a set of planners on a problem instance.
Definition Benchmark.h:49