43 viser_available =
True
45 print(
"Failed to import viser. PlannerData will not be visualized")
46 viser_available =
False
48from ompl
import base
as ob
49from ompl
import geometric
as og
53def isStateValid(state):
54 if state.getY() >= -3
and state.getY() <= 3:
58 and state.getZ() >= -3
66 Visualize planner data graph in 3D using viser.
67 Nodes are displayed at their actual 3D positions, edges as line segments.
69 num_vertices = pd.numVertices()
70 num_edges = pd.numEdges()
73 print(
"No vertices in planner data to visualize")
84 adjacency = [[]
for _
in range(num_vertices)]
87 for v
in range(num_vertices):
88 vertex = pd.getVertex(v)
89 state = vertex.getState()
95 positions.append([x, y, z])
98 if pd.isStartVertex(v):
99 start_indices.append(v)
100 vertex_colors.append([0, 1, 1])
101 vertex_sizes.append(0.3)
102 elif pd.isGoalVertex(v):
103 goal_indices.append(v)
104 vertex_colors.append([0, 1, 0])
105 vertex_sizes.append(0.3)
107 vertex_colors.append([1, 1, 0])
108 vertex_sizes.append(0.15)
111 outgoing = pd.getEdges(v)
112 for target
in outgoing:
113 if pd.edgeExists(v, target):
115 state1 = pd.getVertex(v).getState()
116 state2 = pd.getVertex(target).getState()
117 si = pd.getSpaceInformation()
118 weight = si.distance(state1, state2)
119 adjacency[v].append((target, weight))
120 edge_weights[(v, target)] = weight
122 positions = np.array(positions, dtype=np.float32)
123 vertex_colors = np.array(vertex_colors, dtype=np.float32)
127 len(adjacency[v]) + len(pd.getIncomingEdges(v))
for v
in range(num_vertices)
129 avg_degree = np.mean(degrees)
if degrees
else 0
130 stddev_degree = np.std(degrees)
if degrees
else 0
132 all_weights = list(edge_weights.values())
133 avg_weight = np.mean(all_weights)
if all_weights
else 0
134 stddev_weight = np.std(all_weights)
if all_weights
else 0
137 def dfs_component(v, visited, component):
140 for neighbor, _
in adjacency[v]:
141 if not visited[neighbor]:
142 dfs_component(neighbor, visited, component)
144 for neighbor
in pd.getIncomingEdges(v):
145 if not visited[neighbor]:
146 dfs_component(neighbor, visited, component)
148 visited = [
False] * num_vertices
150 for v
in range(num_vertices):
153 dfs_component(v, visited, component)
154 components.append(component)
156 print(
"---- PLANNER DATA STATISTICS ----")
157 print(f
"{num_vertices} vertices and {num_edges} edges")
159 f
"Average vertex degree (in+out) = {avg_degree:.3f} St. Dev = {stddev_degree:.3f}"
161 print(f
"Average edge weight = {avg_weight:.3f} St. Dev = {stddev_weight:.3f}")
162 print(f
"Connected components: {len(components)}")
166 if start_indices
and goal_indices:
168 start = start_indices[0]
169 goal = goal_indices[0]
174 dist = {v: float(
"inf")
for v
in range(num_vertices)}
175 prev = {v:
None for v
in range(num_vertices)}
180 d, u = heapq.heappop(pq)
187 for v, weight
in adjacency[u]:
188 alt = dist[u] + weight
192 heapq.heappush(pq, (alt, v))
195 for v
in pd.getIncomingEdges(u):
197 if pd.edgeExists(v, u):
198 state1 = pd.getVertex(v).getState()
199 state2 = pd.getVertex(u).getState()
200 si = pd.getSpaceInformation()
201 weight = si.distance(state1, state2)
202 alt = dist[u] + weight
206 heapq.heappush(pq, (alt, v))
209 if prev[goal]
is not None or goal == start:
212 while current
is not None:
214 current = prev[current]
218 for i
in range(len(path) - 1):
219 u, v = path[i], path[i + 1]
220 path_edges.add((u, v))
221 path_edges.add((v, u))
224 server = viser.ViserServer(port=8080, label=
"OMPL Planner Data Visualization")
227 server.scene.add_point_cloud(
228 "/graph/vertices", points=positions, colors=vertex_colors, point_size=0.2
233 regular_edge_lines = []
239 for v
in range(num_vertices):
240 for target, _
in adjacency[v]:
242 if (v, target)
not in added_edges:
243 added_edges.add((v, target))
245 p2 = positions[target]
248 if (v, target)
in path_edges
or (target, v)
in path_edges:
249 path_edge_lines.append([p1, p2])
251 regular_edge_lines.append([p1, p2])
254 if regular_edge_lines:
255 regular_edge_lines = np.array(regular_edge_lines, dtype=np.float32)
257 regular_edge_lines = regular_edge_lines.reshape(-1, 2, 3)
259 server.scene.add_line_segments(
260 "/graph/edges/regular",
261 points=regular_edge_lines,
268 path_edge_lines = np.array(path_edge_lines, dtype=np.float32)
270 path_edge_lines = path_edge_lines.reshape(-1, 2, 3)
272 server.scene.add_line_segments(
274 points=path_edge_lines,
279 print(
"\n3D graph visualization available at http://localhost:8080")
280 print(
"Press Ctrl+C to stop the server")
284 server.sleep_forever()
285 except KeyboardInterrupt:
287 print(
"\nServer stopped")
298 space.setBounds(bounds)
304 start = space.allocState()
308 start.rotation().setIdentity()
311 goal = space.allocState()
315 goal.rotation().setIdentity()
317 ss.setStateValidityChecker(isStateValid)
320 ss.setStartAndGoalStates(start, goal, 0.05)
323 planner =
og.PRM(ss.getSpaceInformation())
326 ss.setPlanner(planner)
330 solved = ss.solve(20.0)
334 print(
"Found solution:\n%s" % ss.getSolutionPath())
338 ss.getPlannerData(pd)
341 pd.computeEdgeWeights()
347if __name__ ==
"__main__":
Object containing planner generated vertex and edge data. It is assumed that all vertices are unique,...
The lower and upper bounds for an Rn space.
A state space representing SE(3).
Probabilistic RoadMap planner.
Create the set of classes typically needed to solve a geometric problem.