rayli commited on
Commit
472020a
Β·
verified Β·
1 Parent(s): 126a18f

Scale motion axes with mesh extent

Browse files
instruct_particulate/utils/visualization_utils.py CHANGED
@@ -232,6 +232,7 @@ def get_3D_arrow_on_points(
232
  points: np.ndarray,
233
  fixed_point: Optional[np.ndarray] = None,
234
  extension: float = 0.05,
 
235
  ) -> Tuple[float, float]:
236
  """
237
  Build a 3-D arrow (cylinder + cone) that encloses `points` along `direction`.
@@ -257,11 +258,12 @@ def get_3D_arrow_on_points(
257
  # ── project points onto axis to find extents ──────────────────────────
258
  scalars = np.dot(points - P0, d_hat)
259
  if scalars.shape[0] > 0:
260
- s_min = scalars.min() - max(extension * (scalars.max() - scalars.min()), 0.1)
261
- s_max = scalars.max() + max(extension * (scalars.max() - scalars.min()), 0.1)
 
262
  else:
263
- s_min = -0.1
264
- s_max = 0.1
265
 
266
  start_pt = P0 + s_min * d_hat
267
  end_pt = P0 + s_max * d_hat
@@ -269,6 +271,19 @@ def get_3D_arrow_on_points(
269
  return start_pt, end_pt
270
 
271
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  def create_motion_axis_meshes(
273
  mesh_parts,
274
  unique_part_ids: np.ndarray,
@@ -279,6 +294,13 @@ def create_motion_axis_meshes(
279
  ):
280
  """Create arrow/ring meshes visualizing predicted joint motion."""
281
  axes = []
 
 
 
 
 
 
 
282
  for mesh_part, part_id in zip(mesh_parts, unique_part_ids, strict=True):
283
  if is_part_revolute[part_id]:
284
  axis_direction, axis_point = plucker_to_axis_point(revolute_plucker[part_id])
@@ -287,14 +309,15 @@ def create_motion_axis_meshes(
287
  mesh_part.vertices,
288
  fixed_point=axis_point,
289
  extension=0.2,
 
290
  )
291
  axes.append(
292
  create_arrow(
293
  arrow_start,
294
  arrow_end,
295
  color=ARROW_COLOR_REVOLUTE,
296
- radius=0.01,
297
- radius_tip=0.018,
298
  )
299
  )
300
  arrow_direction = arrow_end - arrow_start
@@ -302,8 +325,8 @@ def create_motion_axis_meshes(
302
  create_ring(
303
  arrow_start,
304
  arrow_direction,
305
- major_radius=0.03,
306
- minor_radius=0.006,
307
  color=ARROW_COLOR_REVOLUTE,
308
  )
309
  )
@@ -311,8 +334,8 @@ def create_motion_axis_meshes(
311
  create_ring(
312
  arrow_end,
313
  arrow_direction,
314
- major_radius=0.03,
315
- minor_radius=0.006,
316
  color=ARROW_COLOR_REVOLUTE,
317
  )
318
  )
@@ -321,14 +344,15 @@ def create_motion_axis_meshes(
321
  prismatic_axis[part_id],
322
  mesh_part.vertices,
323
  extension=0.2,
 
324
  )
325
  axes.append(
326
  create_arrow(
327
  arrow_start,
328
  arrow_end,
329
  color=ARROW_COLOR_PRISMATIC,
330
- radius=0.01,
331
- radius_tip=0.018,
332
  )
333
  )
334
  return axes
 
232
  points: np.ndarray,
233
  fixed_point: Optional[np.ndarray] = None,
234
  extension: float = 0.05,
235
+ min_extension: float = 0.1,
236
  ) -> Tuple[float, float]:
237
  """
238
  Build a 3-D arrow (cylinder + cone) that encloses `points` along `direction`.
 
258
  # ── project points onto axis to find extents ──────────────────────────
259
  scalars = np.dot(points - P0, d_hat)
260
  if scalars.shape[0] > 0:
261
+ padding = max(extension * (scalars.max() - scalars.min()), min_extension)
262
+ s_min = scalars.min() - padding
263
+ s_max = scalars.max() + padding
264
  else:
265
+ s_min = -min_extension
266
+ s_max = min_extension
267
 
268
  start_pt = P0 + s_min * d_hat
269
  end_pt = P0 + s_max * d_hat
 
271
  return start_pt, end_pt
272
 
273
 
274
+ def _mesh_parts_max_extent(mesh_parts) -> float:
275
+ vertices = [
276
+ np.asarray(mesh_part.vertices, dtype=np.float64)
277
+ for mesh_part in mesh_parts
278
+ if len(mesh_part.vertices) > 0
279
+ ]
280
+ if not vertices:
281
+ return 1.0
282
+ points = np.concatenate(vertices, axis=0)
283
+ max_extent = float(np.ptp(points, axis=0).max())
284
+ return max(max_extent, 1e-6)
285
+
286
+
287
  def create_motion_axis_meshes(
288
  mesh_parts,
289
  unique_part_ids: np.ndarray,
 
294
  ):
295
  """Create arrow/ring meshes visualizing predicted joint motion."""
296
  axes = []
297
+ visual_scale = _mesh_parts_max_extent(mesh_parts)
298
+ arrow_radius = 0.01 * visual_scale
299
+ arrow_tip_radius = 0.018 * visual_scale
300
+ ring_major_radius = 0.03 * visual_scale
301
+ ring_minor_radius = 0.006 * visual_scale
302
+ min_axis_extension = 0.1 * visual_scale
303
+
304
  for mesh_part, part_id in zip(mesh_parts, unique_part_ids, strict=True):
305
  if is_part_revolute[part_id]:
306
  axis_direction, axis_point = plucker_to_axis_point(revolute_plucker[part_id])
 
309
  mesh_part.vertices,
310
  fixed_point=axis_point,
311
  extension=0.2,
312
+ min_extension=min_axis_extension,
313
  )
314
  axes.append(
315
  create_arrow(
316
  arrow_start,
317
  arrow_end,
318
  color=ARROW_COLOR_REVOLUTE,
319
+ radius=arrow_radius,
320
+ radius_tip=arrow_tip_radius,
321
  )
322
  )
323
  arrow_direction = arrow_end - arrow_start
 
325
  create_ring(
326
  arrow_start,
327
  arrow_direction,
328
+ major_radius=ring_major_radius,
329
+ minor_radius=ring_minor_radius,
330
  color=ARROW_COLOR_REVOLUTE,
331
  )
332
  )
 
334
  create_ring(
335
  arrow_end,
336
  arrow_direction,
337
+ major_radius=ring_major_radius,
338
+ minor_radius=ring_minor_radius,
339
  color=ARROW_COLOR_REVOLUTE,
340
  )
341
  )
 
344
  prismatic_axis[part_id],
345
  mesh_part.vertices,
346
  extension=0.2,
347
+ min_extension=min_axis_extension,
348
  )
349
  axes.append(
350
  create_arrow(
351
  arrow_start,
352
  arrow_end,
353
  color=ARROW_COLOR_PRISMATIC,
354
+ radius=arrow_radius,
355
+ radius_tip=arrow_tip_radius,
356
  )
357
  )
358
  return axes