meshcat_visualizer.py
Go to the documentation of this file.
1 # TODO: Remove when 20.04 is not supported
2 from __future__ import annotations
3 
4 import warnings
5 from pathlib import Path
6 from typing import ClassVar
7 
8 import numpy as np
9 
10 from .. import pinocchio_pywrap_default as pin
11 from ..deprecation import DeprecatedWarning
12 from ..utils import npToTuple
13 from . import BaseVisualizer
14 
15 try:
16  import meshcat
17  import meshcat.geometry as mg
18 except ImportError:
19  import_meshcat_succeed = False
20 else:
21  import_meshcat_succeed = True
22 
23 import base64
24 
25 # DaeMeshGeometry
26 import xml.etree.ElementTree as Et
27 from typing import Any
28 
29 # TODO: Remove quote when 20.04 is not supported
30 MsgType = "dict[str, Union[str, bytes, bool, float, 'MsgType']]"
31 
32 try:
33  import hppfcl
34 
35  WITH_HPP_FCL_BINDINGS = True
36 except ImportError:
37  WITH_HPP_FCL_BINDINGS = False
38 
39 DEFAULT_COLOR_PROFILES = {
40  "gray": ([0.98, 0.98, 0.98], [0.8, 0.8, 0.8]),
41  "white": ([1.0, 1.0, 1.0], [1.0, 1.0, 1.0]),
42 }
43 COLOR_PRESETS = DEFAULT_COLOR_PROFILES.copy()
44 
45 FRAME_AXIS_POSITIONS = (
46  np.array([[0, 0, 0], [1, 0, 0], [0, 0, 0], [0, 1, 0], [0, 0, 0], [0, 0, 1]])
47  .astype(np.float32)
48  .T
49 )
50 FRAME_AXIS_COLORS = (
51  np.array([[1, 0, 0], [1, 0.6, 0], [0, 1, 0], [0.6, 1, 0], [0, 0, 1], [0, 0.6, 1]])
52  .astype(np.float32)
53  .T
54 )
55 
56 
57 def getColor(color):
58  assert color is not None
59  color = np.asarray(color)
60  assert color.shape == (3,)
61  return color.clip(0.0, 1.0)
62 
63 
64 def hasMeshFileInfo(geometry_object):
65  """Check whether the geometry object contains a Mesh supported by MeshCat"""
66  if geometry_object.meshPath == "":
67  return False
68 
69  file_extension = Path(geometry_object.meshPath).suffix
70  if file_extension.lower() in [".dae", ".obj", ".stl"]:
71  return True
72 
73  return False
74 
75 
77  homogeneous_transform: np.ndarray, scale: np.ndarray
78 ) -> np.ndarray:
79  assert homogeneous_transform.shape == (4, 4)
80  assert scale.size == 3
81  scale = np.array(scale).flatten()
82  S = np.diag(np.concatenate((scale, [1.0])))
83  return homogeneous_transform @ S
84 
85 
86 if import_meshcat_succeed:
87  # Code adapted from Jiminy
88  class Cone(mg.Geometry):
89  """A cone of the given height and radius. By Three.js convention, the axis
90  of rotational symmetry is aligned with the y-axis.
91  """
92 
93  def __init__(
94  self,
95  height: float,
96  radius: float,
97  radialSegments: float = 32,
98  openEnded: bool = False,
99  ):
100  super().__init__()
101  self.radius = radius
102  self.height = height
103  self.radialSegments = radialSegments
104  self.openEnded = openEnded
105 
106  def lower(self, object_data: Any) -> MsgType:
107  return {
108  "uuid": self.uuid,
109  "type": "ConeGeometry",
110  "radius": self.radius,
111  "height": self.height,
112  "radialSegments": self.radialSegments,
113  "openEnded": self.openEnded,
114  }
115 
116  class DaeMeshGeometry(mg.ReferenceSceneElement):
117  def __init__(self, dae_path: str, cache: set[str] | None = None) -> None:
118  """Load Collada files with texture images.
119  Inspired from
120  https://gist.github.com/danzimmerman/a392f8eadcf1166eb5bd80e3922dbdc5
121  """
122  # Init base class
123  super().__init__()
124 
125  dae_path = Path(dae_path)
126 
127  # Attributes to be specified by the user
128  self.path = None
129  self.material = None
130  self.intrinsic_transform = mg.tf.identity_matrix()
131 
132  # Raw file content
133  dae_dir = dae_path.parent
134  with dae_path.open() as text_file:
135  self.dae_raw = text_file.read()
136 
137  # Parse the image resource in Collada file
138  img_resource_paths: list[Path] = []
139  img_lib_element = Et.parse(dae_path).find(
140  "{http://www.collada.org/2005/11/COLLADASchema}library_images"
141  )
142  if img_lib_element:
143  img_resource_paths = [
144  Path(e.text)
145  for e in img_lib_element.iter()
146  if e.tag.count("init_from")
147  ]
148 
149  # Convert textures to data URL for Three.js ColladaLoader to load them
150  self.img_resources: dict[str, str] = {}
151  for img_path in img_resource_paths:
152  img_key = str(img_path)
153  # Return empty string if already in cache
154  if cache is not None:
155  if img_path in cache:
156  self.img_resources[img_key] = ""
157  continue
158  cache.add(img_path)
159 
160  # Encode texture in base64
161  img_path_abs: Path = img_path
162  if not img_path.is_absolute():
163  img_path_abs = (dae_dir / img_path_abs).resolve()
164  if not img_path_abs.is_file():
165  raise UserWarning(f"Texture '{img_path}' not found.")
166  with img_path_abs.open("rb") as img_file:
167  img_data = base64.b64encode(img_file.read())
168  img_uri = f"data:image/png;base64,{img_data.decode('utf-8')}"
169  self.img_resources[img_key] = img_uri
170 
171  def lower(self) -> dict[str, Any]:
172  """Pack data into a dictionary of the format that must be passed to
173  `Visualizer.window.send`.
174  """
175  data = {
176  "type": "set_object",
177  "path": self.path.lower() if self.path is not None else "",
178  "object": {
179  "metadata": {"version": 4.5, "type": "Object"},
180  "geometries": [],
181  "materials": [],
182  "object": {
183  "uuid": self.uuid,
184  "type": "_meshfile_object",
185  "format": "dae",
186  "data": self.dae_raw,
187  "resources": self.img_resources,
188  "matrix": list(self.intrinsic_transform.flatten()),
189  },
190  },
191  }
192  if self.material is not None:
193  self.material.lower_in_object(data)
194  return data
195 
196  def set_scale(self, scale) -> None:
197  self.intrinsic_transform[:3, :3] = np.diag(scale)
198 
199  # end code adapted from Jiminy
200 
201  class Plane(mg.Geometry):
202  """A plane of the given width and height."""
203 
204  def __init__(
205  self,
206  width: float,
207  height: float,
208  widthSegments: float = 1,
209  heightSegments: float = 1,
210  ):
211  super().__init__()
212  self.width = width
213  self.height = height
214  self.widthSegments = widthSegments
215  self.heightSegments = heightSegments
216 
217  def lower(self, object_data: Any) -> MsgType:
218  return {
219  "uuid": self.uuid,
220  "type": "PlaneGeometry",
221  "width": self.width,
222  "height": self.height,
223  "widthSegments": self.widthSegments,
224  "heightSegments": self.heightSegments,
225  }
226 
227 
228 if (
229  WITH_HPP_FCL_BINDINGS
230  and tuple(map(int, hppfcl.__version__.split("."))) >= (3, 0, 0)
231  and hppfcl.WITH_OCTOMAP
232 ):
233 
234  def loadOctree(octree: hppfcl.OcTree):
235  boxes = octree.toBoxes()
236 
237  if len(boxes) == 0:
238  return
239  bs = boxes[0][3] / 2.0
240  num_boxes = len(boxes)
241 
242  box_corners = np.array(
243  [
244  [bs, bs, bs],
245  [bs, bs, -bs],
246  [bs, -bs, bs],
247  [bs, -bs, -bs],
248  [-bs, bs, bs],
249  [-bs, bs, -bs],
250  [-bs, -bs, bs],
251  [-bs, -bs, -bs],
252  ]
253  )
254 
255  all_points = np.empty((8 * num_boxes, 3))
256  all_faces = np.empty((12 * num_boxes, 3), dtype=int)
257  face_id = 0
258  for box_id, box_properties in enumerate(boxes):
259  box_center = box_properties[:3]
260 
261  corners = box_corners + box_center
262  point_range = range(box_id * 8, (box_id + 1) * 8)
263  all_points[point_range, :] = corners
264 
265  A = box_id * 8
266  B = A + 1
267  C = B + 1
268  D = C + 1
269  E = D + 1
270  F = E + 1
271  G = F + 1
272  H = G + 1
273 
274  all_faces[face_id] = np.array([C, D, B])
275  all_faces[face_id + 1] = np.array([B, A, C])
276  all_faces[face_id + 2] = np.array([A, B, F])
277  all_faces[face_id + 3] = np.array([F, E, A])
278  all_faces[face_id + 4] = np.array([E, F, H])
279  all_faces[face_id + 5] = np.array([H, G, E])
280  all_faces[face_id + 6] = np.array([G, H, D])
281  all_faces[face_id + 7] = np.array([D, C, G])
282  # # top
283  all_faces[face_id + 8] = np.array([A, E, G])
284  all_faces[face_id + 9] = np.array([G, C, A])
285  # # bottom
286  all_faces[face_id + 10] = np.array([B, H, F])
287  all_faces[face_id + 11] = np.array([H, B, D])
288 
289  face_id += 12
290 
291  colors = np.empty((all_points.shape[0], 3))
292  colors[:] = np.ones(3)
293  mesh = mg.TriangularMeshGeometry(all_points, all_faces, colors)
294  return mesh
295 
296 else:
297 
298  def loadOctree(octree):
299  raise NotImplementedError("loadOctree need hppfcl with octomap support")
300 
301 
302 if WITH_HPP_FCL_BINDINGS:
303 
304  def loadMesh(mesh):
305  if isinstance(mesh, (hppfcl.HeightFieldOBBRSS, hppfcl.HeightFieldAABB)):
306  heights = mesh.getHeights()
307  x_grid = mesh.getXGrid()
308  y_grid = mesh.getYGrid()
309  min_height = mesh.getMinHeight()
310 
311  X, Y = np.meshgrid(x_grid, y_grid)
312 
313  nx = len(x_grid) - 1
314  ny = len(y_grid) - 1
315 
316  num_cells = (nx) * (ny) * 2 + (nx + ny) * 4 + 2
317 
318  num_vertices = X.size
319  num_tris = num_cells
320 
321  faces = np.empty((num_tris, 3), dtype=int)
322  vertices = np.vstack(
323  (
324  np.stack(
325  (
326  X.reshape(num_vertices),
327  Y.reshape(num_vertices),
328  heights.reshape(num_vertices),
329  ),
330  axis=1,
331  ),
332  np.stack(
333  (
334  X.reshape(num_vertices),
335  Y.reshape(num_vertices),
336  np.full(num_vertices, min_height),
337  ),
338  axis=1,
339  ),
340  )
341  )
342 
343  face_id = 0
344  for y_id in range(ny):
345  for x_id in range(nx):
346  p0 = x_id + y_id * (nx + 1)
347  p1 = p0 + 1
348  p2 = p1 + nx + 1
349  p3 = p2 - 1
350 
351  faces[face_id] = np.array([p0, p3, p1])
352  face_id += 1
353  faces[face_id] = np.array([p3, p2, p1])
354  face_id += 1
355 
356  if y_id == 0:
357  p0_low = p0 + num_vertices
358  p1_low = p1 + num_vertices
359 
360  faces[face_id] = np.array([p0, p1_low, p0_low])
361  face_id += 1
362  faces[face_id] = np.array([p0, p1, p1_low])
363  face_id += 1
364 
365  if y_id == ny - 1:
366  p2_low = p2 + num_vertices
367  p3_low = p3 + num_vertices
368 
369  faces[face_id] = np.array([p3, p3_low, p2_low])
370  face_id += 1
371  faces[face_id] = np.array([p3, p2_low, p2])
372  face_id += 1
373 
374  if x_id == 0:
375  p0_low = p0 + num_vertices
376  p3_low = p3 + num_vertices
377 
378  faces[face_id] = np.array([p0, p3_low, p3])
379  face_id += 1
380  faces[face_id] = np.array([p0, p0_low, p3_low])
381  face_id += 1
382 
383  if x_id == nx - 1:
384  p1_low = p1 + num_vertices
385  p2_low = p2 + num_vertices
386 
387  faces[face_id] = np.array([p1, p2_low, p2])
388  face_id += 1
389  faces[face_id] = np.array([p1, p1_low, p2_low])
390  face_id += 1
391 
392  # Last face
393  p0 = num_vertices
394  p1 = p0 + nx
395  p2 = 2 * num_vertices - 1
396  p3 = p2 - nx
397 
398  faces[face_id] = np.array([p0, p1, p2])
399  face_id += 1
400  faces[face_id] = np.array([p0, p2, p3])
401  face_id += 1
402 
403  elif isinstance(mesh, (hppfcl.Convex, hppfcl.BVHModelBase)):
404  if isinstance(mesh, hppfcl.BVHModelBase):
405  num_vertices = mesh.num_vertices
406  num_tris = mesh.num_tris
407 
408  call_triangles = mesh.tri_indices
409  call_vertices = mesh.vertices
410 
411  elif isinstance(mesh, hppfcl.Convex):
412  num_vertices = mesh.num_points
413  num_tris = mesh.num_polygons
414 
415  call_triangles = mesh.polygons
416  call_vertices = mesh.points
417 
418  faces = np.empty((num_tris, 3), dtype=int)
419  for k in range(num_tris):
420  tri = call_triangles(k)
421  faces[k] = [tri[i] for i in range(3)]
422 
423  vertices = call_vertices()
424  vertices = vertices.astype(np.float32)
425 
426  if num_tris > 0:
427  mesh = mg.TriangularMeshGeometry(vertices, faces)
428  else:
429  mesh = mg.Points(
430  mg.PointsGeometry(
431  vertices.T, color=np.repeat(np.ones((3, 1)), num_vertices, axis=1)
432  ),
433  mg.PointsMaterial(size=0.002),
434  )
435 
436  return mesh
437 
438 else:
439 
440  def loadMesh(mesh):
441  raise NotImplementedError("loadMesh need hppfcl")
442 
443 
444 def loadPrimitive(geometry_object):
445  import meshcat.geometry as mg
446 
447  # Cylinders need to be rotated
448  R = np.array(
449  [
450  [1.0, 0.0, 0.0, 0.0],
451  [0.0, 0.0, -1.0, 0.0],
452  [0.0, 1.0, 0.0, 0.0],
453  [0.0, 0.0, 0.0, 1.0],
454  ]
455  )
456  RotatedCylinder = type(
457  "RotatedCylinder", (mg.Cylinder,), {"intrinsic_transform": lambda self: R}
458  )
459 
460  geom = geometry_object.geometry
461  obj = None
462  if WITH_HPP_FCL_BINDINGS and isinstance(geom, hppfcl.ShapeBase):
463  if isinstance(geom, hppfcl.Capsule):
464  if hasattr(mg, "TriangularMeshGeometry"):
465  obj = createCapsule(2.0 * geom.halfLength, geom.radius)
466  else:
467  obj = RotatedCylinder(2.0 * geom.halfLength, geom.radius)
468  elif isinstance(geom, hppfcl.Cylinder):
469  obj = RotatedCylinder(2.0 * geom.halfLength, geom.radius)
470  elif isinstance(geom, hppfcl.Cone):
471  obj = RotatedCylinder(2.0 * geom.halfLength, 0, geom.radius, 0)
472  elif isinstance(geom, hppfcl.Box):
473  obj = mg.Box(npToTuple(2.0 * geom.halfSide))
474  elif isinstance(geom, hppfcl.Sphere):
475  obj = mg.Sphere(geom.radius)
476  elif isinstance(geom, hppfcl.ConvexBase):
477  obj = loadMesh(geom)
478 
479  if obj is None:
480  msg = f"Unsupported geometry type for {geometry_object.name} ({type(geom)})"
481  warnings.warn(msg, category=UserWarning, stacklevel=2)
482 
483  return obj
484 
485 
486 def createCapsule(length, radius, radial_resolution=30, cap_resolution=10):
487  nbv = np.array([max(radial_resolution, 4), max(cap_resolution, 4)])
488  h = length
489  r = radius
490  position = 0
491  vertices = np.zeros((nbv[0] * (2 * nbv[1]) + 2, 3))
492  for j in range(nbv[0]):
493  phi = (2 * np.pi * j) / nbv[0]
494  for i in range(nbv[1]):
495  theta = (np.pi / 2 * i) / nbv[1]
496  vertices[position + i, :] = np.array(
497  [
498  np.cos(theta) * np.cos(phi) * r,
499  np.cos(theta) * np.sin(phi) * r,
500  -h / 2 - np.sin(theta) * r,
501  ]
502  )
503  vertices[position + i + nbv[1], :] = np.array(
504  [
505  np.cos(theta) * np.cos(phi) * r,
506  np.cos(theta) * np.sin(phi) * r,
507  h / 2 + np.sin(theta) * r,
508  ]
509  )
510  position += nbv[1] * 2
511  vertices[-2, :] = np.array([0, 0, -h / 2 - r])
512  vertices[-1, :] = np.array([0, 0, h / 2 + r])
513  indexes = np.zeros((nbv[0] * (4 * (nbv[1] - 1) + 4), 3))
514  index = 0
515  stride = nbv[1] * 2
516  last = nbv[0] * (2 * nbv[1]) + 1
517  for j in range(nbv[0]):
518  j_next = (j + 1) % nbv[0]
519  indexes[index + 0] = np.array(
520  [
521  j_next * stride + nbv[1],
522  j_next * stride,
523  j * stride,
524  ]
525  )
526  indexes[index + 1] = np.array(
527  [
528  j * stride + nbv[1],
529  j_next * stride + nbv[1],
530  j * stride,
531  ]
532  )
533  indexes[index + 2] = np.array(
534  [
535  j * stride + nbv[1] - 1,
536  j_next * stride + nbv[1] - 1,
537  last - 1,
538  ]
539  )
540  indexes[index + 3] = np.array(
541  [
542  j_next * stride + 2 * nbv[1] - 1,
543  j * stride + 2 * nbv[1] - 1,
544  last,
545  ]
546  )
547  for i in range(nbv[1] - 1):
548  indexes[index + 4 + i * 4 + 0] = np.array(
549  [
550  j_next * stride + i,
551  j_next * stride + i + 1,
552  j * stride + i,
553  ]
554  )
555  indexes[index + 4 + i * 4 + 1] = np.array(
556  [
557  j_next * stride + i + 1,
558  j * stride + i + 1,
559  j * stride + i,
560  ]
561  )
562  indexes[index + 4 + i * 4 + 2] = np.array(
563  [
564  j_next * stride + nbv[1] + i + 1,
565  j_next * stride + nbv[1] + i,
566  j * stride + nbv[1] + i,
567  ]
568  )
569  indexes[index + 4 + i * 4 + 3] = np.array(
570  [
571  j_next * stride + nbv[1] + i + 1,
572  j * stride + nbv[1] + i,
573  j * stride + nbv[1] + i + 1,
574  ]
575  )
576  index += 4 * (nbv[1] - 1) + 4
577  return mg.TriangularMeshGeometry(vertices, indexes)
578 
579 
580 class MeshcatVisualizer(BaseVisualizer):
581  """A Pinocchio display using Meshcat"""
582 
583  FORCE_SCALE = 0.06
584  FRAME_VEL_COLOR = 0x00FF00
585  CAMERA_PRESETS: ClassVar = {
586  "preset0": [
587  np.zeros(3), # target
588  [3.0, 0.0, 1.0], # anchor point (x, z, -y) lhs coords
589  ],
590  "preset1": [np.zeros(3), [1.0, 1.0, 1.0]],
591  "preset2": [[0.0, 0.0, 0.6], [0.8, 1.0, 1.2]],
592  "acrobot": [[0.0, 0.1, 0.0], [0.5, 0.0, 0.2]],
593  "cam_ur": [[0.4, 0.6, -0.2], [1.0, 0.4, 1.2]],
594  "cam_ur2": [[0.4, 0.3, 0.0], [0.5, 0.1, 1.4]],
595  "cam_ur3": [[0.4, 0.3, 0.0], [0.6, 1.3, 0.3]],
596  "cam_ur4": [[-1.0, 0.3, 0.0], [1.3, 0.1, 1.2]], # x>0 to x<0
597  "cam_ur5": [[-1.0, 0.3, 0.0], [-0.05, 1.5, 1.2]],
598  "talos": [[0.0, 1.2, 0.0], [1.5, 0.3, 1.5]],
599  "talos2": [[0.0, 1.1, 0.0], [1.2, 0.6, 1.5]],
600  }
601 
602  def __init__(
603  self,
604  model=pin.Model(),
605  collision_model=None,
606  visual_model=None,
607  copy_models=False,
608  data=None,
609  collision_data=None,
610  visual_data=None,
611  ):
612  if not import_meshcat_succeed:
613  msg = (
614  "Error while importing the viewer client.\n"
615  "Check whether meshcat is properly installed "
616  "(pip install --user meshcat)."
617  )
618  raise ImportError(msg)
619 
620  super().__init__(
621  model,
622  collision_model,
623  visual_model,
624  copy_models,
625  data,
626  collision_data,
627  visual_data,
628  )
629  self.static_objects = []
630 
631  def getViewerNodeName(self, geometry_object, geometry_type):
632  """Return the name of the geometry object inside the viewer."""
633  if geometry_type is pin.GeometryType.VISUAL:
634  return self.viewerVisualGroupName + "/" + geometry_object.name
635  elif geometry_type is pin.GeometryType.COLLISION:
636  return self.viewerCollisionGroupName + "/" + geometry_object.name
637 
638  def initViewer(self, viewer=None, open=False, loadModel=False, zmq_url=None):
639  """Start a new MeshCat server and client.
640  Note: the server can also be started separately using the "meshcat-server"
641  command in a terminal:
642  this enables the server to remain active after the current script ends.
643  """
644 
645  self.viewer = meshcat.Visualizer(zmq_url) if viewer is None else viewer
646 
647  self._node_default_cam = self.viewer["/Cameras/default"]
648  self._node_background = self.viewer["/Background"]
649  self._rot_cam_key = "rotated/<object>"
650  self.static_objects = []
651 
653 
654  self._node_default_cam = self.viewer["/Cameras/default"]
655  self._node_background = self.viewer["/Background"]
656  self._rot_cam_key = "rotated/object"
657  self.static_objects = []
658 
660 
661  if open:
662  self.viewer.open()
663 
664  if loadModel:
665  self.loadViewerModel()
666 
667  def reset(self):
668  self.viewer.delete()
669  self.static_objects = []
670 
671  def setBackgroundColor(self, preset_name: str = "gray", col_top=None, col_bot=None):
672  """Set the background."""
673  if col_top is not None:
674  if col_bot is None:
675  col_bot = col_top
676  else:
677  assert preset_name in COLOR_PRESETS.keys()
678  col_top, col_bot = COLOR_PRESETS[preset_name]
679  self._node_background.set_property("top_color", col_top)
680  self._node_background.set_property("bottom_color", col_bot)
681 
682  def setCameraTarget(self, target: np.ndarray):
683  self.viewer.set_cam_target(target)
684 
685  def setCameraPosition(self, position: np.ndarray):
686  self.viewer.set_cam_pos(position)
687 
688  def setCameraPreset(self, preset_key: str):
689  """Set the camera angle and position using a given preset."""
690  assert preset_key in self.CAMERA_PRESETS
691  cam_val = self.CAMERA_PRESETS[preset_key]
692  self.setCameraTarget(cam_val[0])
693  self.setCameraPosition(cam_val[1])
694 
695  def setCameraZoom(self, zoom: float):
696  elt = self._node_default_cam[self._rot_cam_key]
697  elt.set_property("zoom", zoom)
698 
699  def setCameraPose(self, pose):
700  self._node_default_cam.set_transform(pose)
701 
703  self.setCameraPosition([0, 0, 0])
704 
706  self.setCameraPosition([3, 0, 1])
707 
708  def loadPrimitive(self, geometry_object: pin.GeometryObject):
709  import meshcat.geometry as mg
710 
711  # Cylinders need to be rotated
712  basic_three_js_transform = np.array(
713  [
714  [1.0, 0.0, 0.0, 0.0],
715  [0.0, 0.0, -1.0, 0.0],
716  [0.0, 1.0, 0.0, 0.0],
717  [0.0, 0.0, 0.0, 1.0],
718  ]
719  )
720  RotatedCylinder = type(
721  "RotatedCylinder",
722  (mg.Cylinder,),
723  {"intrinsic_transform": lambda self: basic_three_js_transform},
724  )
725 
726  # Cones need to be rotated
727 
728  geom = geometry_object.geometry
729  obj = None
730  if WITH_HPP_FCL_BINDINGS and isinstance(geom, hppfcl.ShapeBase):
731  if isinstance(geom, hppfcl.Capsule):
732  if hasattr(mg, "TriangularMeshGeometry"):
733  obj = createCapsule(2.0 * geom.halfLength, geom.radius)
734  else:
735  obj = RotatedCylinder(2.0 * geom.halfLength, geom.radius)
736  elif isinstance(geom, hppfcl.Cylinder):
737  obj = RotatedCylinder(2.0 * geom.halfLength, geom.radius)
738  elif isinstance(geom, hppfcl.Cone):
739  obj = RotatedCylinder(2.0 * geom.halfLength, 0, geom.radius, 0)
740  elif isinstance(geom, hppfcl.Box):
741  obj = mg.Box(npToTuple(2.0 * geom.halfSide))
742  elif isinstance(geom, hppfcl.Sphere):
743  obj = mg.Sphere(geom.radius)
744  elif isinstance(geom, hppfcl.Plane):
745  To = np.eye(4)
746  To[:3, 3] = geom.d * geom.n
747  TranslatedPlane = type(
748  "TranslatedPlane",
749  (mg.Plane,),
750  {"intrinsic_transform": lambda self: To},
751  )
752  sx = geometry_object.meshScale[0] * 10
753  sy = geometry_object.meshScale[1] * 10
754  obj = TranslatedPlane(sx, sy)
755  elif isinstance(geom, hppfcl.Ellipsoid):
756  obj = mg.Ellipsoid(geom.radii)
757  elif isinstance(geom, (hppfcl.Plane, hppfcl.Halfspace)):
758  plane_transform: pin.SE3 = pin.SE3.Identity()
759  # plane_transform.translation[:] = geom.d # Does not work
760  plane_transform.rotation = pin.Quaternion.FromTwoVectors(
761  pin.ZAxis, geom.n
762  ).toRotationMatrix()
763  TransformedPlane = type(
764  "TransformedPlane",
765  (Plane,),
766  {"intrinsic_transform": lambda self: plane_transform.homogeneous},
767  )
768  obj = TransformedPlane(1000, 1000)
769  elif isinstance(geom, hppfcl.ConvexBase):
770  obj = loadMesh(geom)
771 
772  if obj is None:
773  msg = f"Unsupported geometry type for {geometry_object.name} ({type(geom)})"
774  warnings.warn(msg, category=UserWarning, stacklevel=2)
775  obj = None
776 
777  return obj
778 
779  def loadMeshFromFile(self, geometry_object):
780  # Mesh path is empty if Pinocchio is built without HPP-FCL bindings
781  if geometry_object.meshPath == "":
782  msg = (
783  "Display of geometric primitives is supported only if "
784  "pinocchio is build with HPP-FCL bindings."
785  )
786  warnings.warn(msg, category=UserWarning, stacklevel=2)
787  return None
788 
789  # Get file type from filename extension.
790  file_extension = Path(geometry_object.meshPath).suffix
791  if file_extension.lower() == ".dae":
792  obj = DaeMeshGeometry(geometry_object.meshPath)
793  elif file_extension.lower() == ".obj":
794  obj = mg.ObjMeshGeometry.from_file(geometry_object.meshPath)
795  elif file_extension.lower() == ".stl":
796  obj = mg.StlMeshGeometry.from_file(geometry_object.meshPath)
797  else:
798  msg = f"Unknown mesh file format: {geometry_object.meshPath}."
799  warnings.warn(msg, category=UserWarning, stacklevel=2)
800  obj = None
801 
802  return obj
803 
804  def loadViewerGeometryObject(self, geometry_object, geometry_type, color=None):
805  """Load a single geometry object"""
806  node_name = self.getViewerNodeName(geometry_object, geometry_type)
807  meshcat_node = self.viewer[node_name]
808 
809  try:
810  obj = None
811  if WITH_HPP_FCL_BINDINGS:
812  if isinstance(geometry_object.geometry, hppfcl.ShapeBase):
813  obj = self.loadPrimitive(geometry_object)
814  elif (
815  tuple(map(int, hppfcl.__version__.split("."))) >= (3, 0, 0)
816  and hppfcl.WITH_OCTOMAP
817  and isinstance(geometry_object.geometry, hppfcl.OcTree)
818  ):
819  obj = loadOctree(geometry_object.geometry)
820  elif hasMeshFileInfo(geometry_object):
821  obj = self.loadMeshFromFile(geometry_object)
822  elif isinstance(
823  geometry_object.geometry,
824  (
825  hppfcl.BVHModelBase,
826  hppfcl.HeightFieldOBBRSS,
827  hppfcl.HeightFieldAABB,
828  ),
829  ):
830  obj = loadMesh(geometry_object.geometry)
831  if obj is None and hasMeshFileInfo(geometry_object):
832  obj = self.loadMeshFromFile(geometry_object)
833  if obj is None:
834  msg = (
835  "The geometry object named "
836  + geometry_object.name
837  + " is not supported by Pinocchio/MeshCat for vizualization."
838  )
839  warnings.warn(msg, category=UserWarning, stacklevel=2)
840  return
841  except Exception as e:
842  msg = (
843  "Error while loading geometry object: "
844  f"{geometry_object.name}\nError message:\n{e}"
845  )
846  warnings.warn(msg, category=UserWarning, stacklevel=2)
847  return
848 
849  if isinstance(obj, mg.Object):
850  meshcat_node.set_object(obj)
851  elif isinstance(obj, (mg.Geometry, mg.ReferenceSceneElement)):
852  material = mg.MeshPhongMaterial()
853  # Set material color from URDF, converting for triplet of doubles to a
854  # single int.
855 
856  def to_material_color(rgba) -> int:
857  """Convert rgba color as list into rgba color as int"""
858  return (
859  int(rgba[0] * 255) * 256**2
860  + int(rgba[1] * 255) * 256
861  + int(rgba[2] * 255)
862  )
863 
864  if color is None:
865  meshColor = geometry_object.meshColor
866  else:
867  meshColor = color
868  # Add transparency, if needed.
869  material.color = to_material_color(meshColor)
870 
871  if float(meshColor[3]) != 1.0:
872  material.transparent = True
873  material.opacity = float(meshColor[3])
874 
875  geom_material = geometry_object.meshMaterial
876  if geometry_object.overrideMaterial and isinstance(
877  geom_material, pin.GeometryPhongMaterial
878  ):
879  material.emissive = to_material_color(geom_material.meshEmissionColor)
880  material.specular = to_material_color(geom_material.meshSpecularColor)
881  material.shininess = geom_material.meshShininess * 100.0
882 
883  if isinstance(obj, DaeMeshGeometry):
884  obj.path = meshcat_node.path
885  if geometry_object.overrideMaterial:
886  obj.material = material
887  meshcat_node.window.send(obj)
888  else:
889  meshcat_node.set_object(obj, material)
890 
892  self,
893  rootNodeName="pinocchio",
894  color=None,
895  collision_color=None,
896  visual_color=None,
897  ):
898  """Load the robot in a MeshCat viewer.
899  Parameters:
900  rootNodeName: name to give to the robot in the viewer
901  color: deprecated and optional, color to give to both the collision
902  and visual models of the robot. This setting overwrites any color
903  specified in the robot description. Format is a list of four
904  RGBA floating-point numbers (between 0 and 1)
905  collision_color: optional, color to give to the collision model of
906  the robot. Format is a list of four RGBA floating-point numbers
907  (between 0 and 1)
908  visual_color: optional, color to give to the visual model of
909  the robot. Format is a list of four RGBA floating-point numbers
910  (between 0 and 1)
911  """
912  if color is not None:
913  warnings.warn(
914  "The 'color' argument is deprecated and will be removed in a "
915  "future version of Pinocchio. Consider using "
916  "'collision_color' and 'visual_color' instead.",
917  category=DeprecatedWarning,
918  )
919  collision_color = color
920  visual_color = color
921 
922  # Set viewer to use to gepetto-gui.
923  self.viewerRootNodeName = rootNodeName
924 
925  # Collisions
926  self.viewerCollisionGroupName = self.viewerRootNodeName + "/" + "collisions"
927 
928  if self.collision_model is not None:
929  for collision in self.collision_model.geometryObjects:
931  collision, pin.GeometryType.COLLISION, collision_color
932  )
933  self.displayCollisions(False)
934 
935  # Visuals
936  self.viewerVisualGroupName = self.viewerRootNodeName + "/" + "visuals"
937  if self.visual_model is not None:
938  for visual in self.visual_model.geometryObjects:
940  visual, pin.GeometryType.VISUAL, visual_color
941  )
942  self.displayVisuals(True)
943 
944  # Frames
945  self.viewerFramesGroupName = self.viewerRootNodeName + "/" + "frames"
946  self.displayFrames(False)
947 
948  def reload(self, new_geometry_object, geometry_type=None):
949  """Reload a geometry_object given by its name and its type"""
950  if geometry_type == pin.GeometryType.VISUAL:
951  geom_model = self.visual_model
952  else:
953  geom_model = self.collision_model
954  geometry_type = pin.GeometryType.COLLISION
955 
956  geom_id = geom_model.getGeometryId(new_geometry_object.name)
957  geom_model.geometryObjects[geom_id] = new_geometry_object
958 
959  self.delete(new_geometry_object, geometry_type)
960  visual = geom_model.geometryObjects[geom_id]
961  self.loadViewerGeometryObject(visual, geometry_type)
962 
963  def clean(self):
964  self.viewer.delete()
965 
966  def delete(self, geometry_object, geometry_type):
967  viewer_name = self.getViewerNodeName(geometry_object, geometry_type)
968  self.viewer[viewer_name].delete()
969 
970  def display(self, q=None):
971  """
972  Display the robot at configuration q in the viewer by placing all the bodies
973  """
974  if q is not None:
975  pin.forwardKinematics(self.model, self.data, q)
976 
977  if self.display_collisions:
978  self.updatePlacements(pin.GeometryType.COLLISION)
979 
980  if self.display_visuals:
981  self.updatePlacements(pin.GeometryType.VISUAL)
982 
983  if self.display_frames:
984  self.updateFrames()
985 
986  def updatePlacements(self, geometry_type):
987  if geometry_type == pin.GeometryType.VISUAL:
988  geom_model = self.visual_model
989  geom_data = self.visual_data
990  else:
991  geom_model = self.collision_model
992  geom_data = self.collision_data
993 
994  pin.updateGeometryPlacements(self.model, self.data, geom_model, geom_data)
995  for visual in geom_model.geometryObjects:
996  visual_name = self.getViewerNodeName(visual, geometry_type)
997  # Get mesh pose.
998  M = geom_data.oMg[geom_model.getGeometryId(visual.name)]
999  # Manage scaling: force scaling even if this should be normally handled by
1000  # MeshCat (but there is a bug here)
1001  geom = visual.geometry
1002  if WITH_HPP_FCL_BINDINGS and isinstance(
1003  geom, (hppfcl.Plane, hppfcl.Halfspace)
1004  ):
1005  T = M.copy()
1006  T.translation += M.rotation @ (geom.d * geom.n)
1007  T = T.homogeneous
1008  else:
1009  T = M.homogeneous
1010 
1011  # Update viewer configuration.
1012  T = applyScalingOnHomegeneousTransform(T, visual.meshScale)
1013  self.viewer[visual_name].set_transform(T)
1014 
1015  for visual in self.static_objects:
1016  visual_name = self.getViewerNodeName(visual, pin.GeometryType.VISUAL)
1017  M: pin.SE3 = visual.placement
1018  T = M.homogeneous
1019  T = applyScalingOnHomegeneousTransform(T, visual.meshScale)
1020  self.viewer[visual_name].set_transform(T)
1021 
1022  def addGeometryObject(self, obj: pin.GeometryObject, color=None):
1023  """Add a visual GeometryObject to the viewer, with an optional color."""
1024  self.loadViewerGeometryObject(obj, pin.GeometryType.VISUAL, color)
1025  self.static_objects.append(obj)
1026 
1028  if not hasattr(self.viewer, "get_image"):
1029  warnings.warn(
1030  "meshcat.Visualizer does not have the get_image() method."
1031  " You need meshcat >= 0.2.0 to get this feature."
1032  )
1033 
1034  def captureImage(self, w=None, h=None):
1035  """Capture an image from the Meshcat viewer and return an RGB array."""
1036  if w is not None or h is not None:
1037  # pass arguments when either is not None
1038  img = self.viewer.get_image(w, h)
1039  else:
1040  img = self.viewer.get_image()
1041  img_arr = np.asarray(img)
1042  return img_arr
1043 
1044  def displayCollisions(self, visibility):
1045  """Set whether to display collision objects or not."""
1046  if self.collision_model is None:
1047  self.display_collisions = False
1048  else:
1049  self.display_collisions = visibility
1050  self.viewer[self.viewerCollisionGroupName].set_property("visible", visibility)
1051 
1052  if visibility:
1053  self.updatePlacements(pin.GeometryType.COLLISION)
1054 
1055  def displayVisuals(self, visibility):
1056  """Set whether to display visual objects or not."""
1057  if self.visual_model is None:
1058  self.display_visuals = False
1059  else:
1060  self.display_visuals = visibility
1061  self.viewer[self.viewerVisualGroupName].set_property("visible", visibility)
1062 
1063  if visibility:
1064  self.updatePlacements(pin.GeometryType.VISUAL)
1065 
1066  def displayFrames(self, visibility, frame_ids=None, axis_length=0.2, axis_width=2):
1067  """Set whether to display frames or not."""
1068  self.display_frames = visibility
1069  if visibility:
1070  self.initializeFrames(frame_ids, axis_length, axis_width)
1071  self.viewer[self.viewerFramesGroupName].set_property("visible", visibility)
1072 
1073  def initializeFrames(self, frame_ids=None, axis_length=0.2, axis_width=2):
1074  """Initializes the frame objects for display."""
1075  import meshcat.geometry as mg
1076 
1077  self.viewer[self.viewerFramesGroupName].delete()
1078  self.frame_ids = []
1079 
1080  for fid, frame in enumerate(self.model.frames):
1081  if frame_ids is None or fid in frame_ids:
1082  frame_viz_name = f"{self.viewerFramesGroupName}/{frame.name}"
1083  self.viewer[frame_viz_name].set_object(
1084  mg.LineSegments(
1085  mg.PointsGeometry(
1086  position=axis_length * FRAME_AXIS_POSITIONS,
1087  color=FRAME_AXIS_COLORS,
1088  ),
1089  mg.LineBasicMaterial(
1090  linewidth=axis_width,
1091  vertexColors=True,
1092  ),
1093  )
1094  )
1095  self.frame_ids.append(fid)
1096 
1097  def updateFrames(self):
1098  """
1099  Updates the frame visualizations with the latest transforms from model data.
1100  """
1101  pin.updateFramePlacements(self.model, self.data)
1102  for fid in self.frame_ids:
1103  frame_name = self.model.frames[fid].name
1104  frame_viz_name = f"{self.viewerFramesGroupName}/{frame_name}"
1105  self.viewer[frame_viz_name].set_transform(self.data.oMf[fid].homogeneous)
1106 
1107  def drawFrameVelocities(self, frame_id: int, v_scale=0.2, color=FRAME_VEL_COLOR):
1108  pin.updateFramePlacement(self.model, self.data, frame_id)
1109  vFr = pin.getFrameVelocity(
1110  self.model, self.data, frame_id, pin.LOCAL_WORLD_ALIGNED
1111  )
1112  line_group_name = f"ee_vel/{frame_id}"
1114  [v_scale * vFr.linear], [frame_id], [line_group_name], [color]
1115  )
1116 
1118  self,
1119  vecs: list[np.ndarray],
1120  frame_ids: list[int],
1121  vec_names: list[str],
1122  colors: list[int],
1123  ):
1124  """Draw vectors extending from given frames."""
1125  import meshcat.geometry as mg
1126 
1127  if len(vecs) != len(frame_ids) or len(vecs) != len(vec_names):
1128  return ValueError(
1129  "Number of vectors and frames IDs or names is inconsistent."
1130  )
1131  for i, (fid, v) in enumerate(zip(frame_ids, vecs)):
1132  frame_pos = self.data.oMf[fid].translation
1133  vertices = np.array([frame_pos, frame_pos + v]).astype(np.float32).T
1134  name = vec_names[i]
1135  geometry = mg.PointsGeometry(position=vertices)
1136  geom_object = mg.LineSegments(
1137  geometry, mg.LineBasicMaterial(color=colors[i])
1138  )
1139  prefix = self.viewerVisualGroupName + "/lines/" + name
1140  self.viewer[prefix].set_object(geom_object)
1141 
1142 
1143 __all__ = ["MeshcatVisualizer"]
pinocchio.visualize.meshcat_visualizer.Plane.widthSegments
widthSegments
Definition: meshcat_visualizer.py:208
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.clean
def clean(self)
Definition: meshcat_visualizer.py:963
common_symbols.type
type
Definition: common_symbols.py:34
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer._node_default_cam
_node_default_cam
Definition: meshcat_visualizer.py:647
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer._check_meshcat_has_get_image
def _check_meshcat_has_get_image(self)
Definition: meshcat_visualizer.py:1027
pinocchio::updateGeometryPlacements
void updateGeometryPlacements(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const GeometryModel &geom_model, GeometryData &geom_data)
Update the placement of the geometry objects according to the current joint placements contained in d...
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.setCameraTarget
def setCameraTarget(self, np.ndarray target)
Definition: meshcat_visualizer.py:682
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.setCameraPreset
def setCameraPreset(self, str preset_key)
Definition: meshcat_visualizer.py:688
pinocchio.visualize.meshcat_visualizer.DaeMeshGeometry.path
path
Definition: meshcat_visualizer.py:128
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.displayFrames
def displayFrames(self, visibility, frame_ids=None, axis_length=0.2, axis_width=2)
Definition: meshcat_visualizer.py:1066
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.captureImage
def captureImage(self, w=None, h=None)
Definition: meshcat_visualizer.py:1034
pinocchio.visualize.meshcat_visualizer.getColor
def getColor(color)
Definition: meshcat_visualizer.py:57
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.loadViewerGeometryObject
def loadViewerGeometryObject(self, geometry_object, geometry_type, color=None)
Definition: meshcat_visualizer.py:804
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.displayVisuals
def displayVisuals(self, visibility)
Definition: meshcat_visualizer.py:1055
pinocchio.visualize.meshcat_visualizer.DaeMeshGeometry.__init__
None __init__(self, str dae_path, set[str]|None cache=None)
Definition: meshcat_visualizer.py:117
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer._rot_cam_key
_rot_cam_key
Definition: meshcat_visualizer.py:649
pinocchio.visualize.meshcat_visualizer.Plane.height
height
Definition: meshcat_visualizer.py:207
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.viewerVisualGroupName
viewerVisualGroupName
Definition: meshcat_visualizer.py:930
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.loadPrimitive
def loadPrimitive(self, pin.GeometryObject geometry_object)
Definition: meshcat_visualizer.py:708
pinocchio.visualize.meshcat_visualizer.loadMesh
def loadMesh(mesh)
Definition: meshcat_visualizer.py:304
pinocchio.visualize.meshcat_visualizer.Cone.__init__
def __init__(self, float height, float radius, float radialSegments=32, bool openEnded=False)
Definition: meshcat_visualizer.py:93
pinocchio::forwardKinematics
void forwardKinematics(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const Eigen::MatrixBase< ConfigVectorType > &q, const Eigen::MatrixBase< TangentVectorType1 > &v, const Eigen::MatrixBase< TangentVectorType2 > &a)
Update the joint placements, spatial velocities and spatial accelerations according to the current jo...
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.initViewer
def initViewer(self, viewer=None, open=False, loadModel=False, zmq_url=None)
Definition: meshcat_visualizer.py:638
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.frame_ids
frame_ids
Definition: meshcat_visualizer.py:1078
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.reload
def reload(self, new_geometry_object, geometry_type=None)
Definition: meshcat_visualizer.py:948
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.display_collisions
display_collisions
Definition: meshcat_visualizer.py:1047
pinocchio.visualize.meshcat_visualizer.DaeMeshGeometry
Definition: meshcat_visualizer.py:116
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.viewer
viewer
Definition: meshcat_visualizer.py:645
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.__init__
def __init__(self, model=pin.Model(), collision_model=None, visual_model=None, copy_models=False, data=None, collision_data=None, visual_data=None)
Definition: meshcat_visualizer.py:602
pinocchio.visualize.meshcat_visualizer.Cone.radialSegments
radialSegments
Definition: meshcat_visualizer.py:97
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer._draw_vectors_from_frame
def _draw_vectors_from_frame(self, list[np.ndarray] vecs, list[int] frame_ids, list[str] vec_names, list[int] colors)
Definition: meshcat_visualizer.py:1117
pinocchio.visualize.meshcat_visualizer.Plane.heightSegments
heightSegments
Definition: meshcat_visualizer.py:209
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.addGeometryObject
def addGeometryObject(self, pin.GeometryObject obj, color=None)
Definition: meshcat_visualizer.py:1022
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.viewerCollisionGroupName
viewerCollisionGroupName
Definition: meshcat_visualizer.py:920
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.displayCollisions
def displayCollisions(self, visibility)
Definition: meshcat_visualizer.py:1044
pinocchio::getFrameVelocity
MotionTpl< Scalar, Options > getFrameVelocity(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, const DataTpl< Scalar, Options, JointCollectionTpl > &data, const FrameIndex frame_id, const ReferenceFrame rf=LOCAL)
Returns the spatial velocity of the Frame expressed in the desired reference frame....
Definition: frames.hpp:107
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.initializeFrames
def initializeFrames(self, frame_ids=None, axis_length=0.2, axis_width=2)
Definition: meshcat_visualizer.py:1073
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.viewerRootNodeName
viewerRootNodeName
Definition: meshcat_visualizer.py:917
pinocchio::updateFramePlacements
void updateFramePlacements(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data)
Updates the position of each frame contained in the model.
pinocchio.visualize.meshcat_visualizer.Plane
Definition: meshcat_visualizer.py:201
pinocchio.visualize.meshcat_visualizer.loadPrimitive
def loadPrimitive(geometry_object)
Definition: meshcat_visualizer.py:444
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.display_frames
display_frames
Definition: meshcat_visualizer.py:1068
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.updatePlacements
def updatePlacements(self, geometry_type)
Definition: meshcat_visualizer.py:986
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.static_objects
static_objects
Definition: meshcat_visualizer.py:620
pinocchio.visualize.meshcat_visualizer.DaeMeshGeometry.lower
dict[str, Any] lower(self)
Definition: meshcat_visualizer.py:171
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.drawFrameVelocities
def drawFrameVelocities(self, int frame_id, v_scale=0.2, color=FRAME_VEL_COLOR)
Definition: meshcat_visualizer.py:1107
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.setCameraPose
def setCameraPose(self, pose)
Definition: meshcat_visualizer.py:699
pinocchio.visualize.meshcat_visualizer.Cone.height
height
Definition: meshcat_visualizer.py:96
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.viewerFramesGroupName
viewerFramesGroupName
Definition: meshcat_visualizer.py:939
pinocchio.visualize.meshcat_visualizer.DaeMeshGeometry.material
material
Definition: meshcat_visualizer.py:129
pinocchio.visualize.meshcat_visualizer.loadOctree
def loadOctree(hppfcl.OcTree octree)
Definition: meshcat_visualizer.py:234
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.display
def display(self, q=None)
Definition: meshcat_visualizer.py:970
pinocchio.visualize.meshcat_visualizer.Plane.lower
MsgType lower(self, Any object_data)
Definition: meshcat_visualizer.py:217
pinocchio.visualize.meshcat_visualizer.applyScalingOnHomegeneousTransform
np.ndarray applyScalingOnHomegeneousTransform(np.ndarray homogeneous_transform, np.ndarray scale)
Definition: meshcat_visualizer.py:76
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.loadMeshFromFile
def loadMeshFromFile(self, geometry_object)
Definition: meshcat_visualizer.py:779
pinocchio::toRotationMatrix
void toRotationMatrix(const Eigen::MatrixBase< Vector3 > &axis, const Scalar &cos_value, const Scalar &sin_value, const Eigen::MatrixBase< Matrix3 > &res)
Computes a rotation matrix from a vector and values of sin and cos orientations values.
Definition: rotation.hpp:26
pinocchio.utils.npToTuple
def npToTuple(M)
Definition: bindings/python/pinocchio/utils.py:22
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.display_visuals
display_visuals
Definition: meshcat_visualizer.py:1058
pinocchio.visualize.meshcat_visualizer.DaeMeshGeometry.intrinsic_transform
intrinsic_transform
Definition: meshcat_visualizer.py:130
pinocchio.visualize.meshcat_visualizer.Plane.__init__
def __init__(self, float width, float height, float widthSegments=1, float heightSegments=1)
Definition: meshcat_visualizer.py:204
pinocchio::GeometryPhongMaterial
Definition: multibody/geometry-object.hpp:41
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer
Definition: meshcat_visualizer.py:580
pinocchio.visualize.meshcat_visualizer.createCapsule
def createCapsule(length, radius, radial_resolution=30, cap_resolution=10)
Definition: meshcat_visualizer.py:486
append-urdf-model-with-another-model.open
open
Definition: append-urdf-model-with-another-model.py:78
pinocchio.visualize.meshcat_visualizer.Cone.lower
MsgType lower(self, Any object_data)
Definition: meshcat_visualizer.py:106
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.setBackgroundColor
def setBackgroundColor(self, str preset_name="gray", col_top=None, col_bot=None)
Definition: meshcat_visualizer.py:671
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.setCameraZoom
def setCameraZoom(self, float zoom)
Definition: meshcat_visualizer.py:695
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.disableCameraControl
def disableCameraControl(self)
Definition: meshcat_visualizer.py:702
boost::fusion::append
result_of::push_front< V const, T >::type append(T const &t, V const &v)
Append the element T at the front of boost fusion vector V.
Definition: fusion.hpp:32
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.getViewerNodeName
def getViewerNodeName(self, geometry_object, geometry_type)
Definition: meshcat_visualizer.py:631
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.loadViewerModel
def loadViewerModel(self, rootNodeName="pinocchio", color=None, collision_color=None, visual_color=None)
Definition: meshcat_visualizer.py:891
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.delete
def delete(self, geometry_object, geometry_type)
Definition: meshcat_visualizer.py:966
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.enableCameraControl
def enableCameraControl(self)
Definition: meshcat_visualizer.py:705
pinocchio::updateFramePlacement
const DataTpl< Scalar, Options, JointCollectionTpl >::SE3 & updateFramePlacement(const ModelTpl< Scalar, Options, JointCollectionTpl > &model, DataTpl< Scalar, Options, JointCollectionTpl > &data, const FrameIndex frame_id)
Updates the placement of the given frame.
pinocchio.visualize.meshcat_visualizer.Plane.width
width
Definition: meshcat_visualizer.py:206
pinocchio.visualize.meshcat_visualizer.hasMeshFileInfo
def hasMeshFileInfo(geometry_object)
Definition: meshcat_visualizer.py:64
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer._node_background
_node_background
Definition: meshcat_visualizer.py:648
pinocchio.visualize.meshcat_visualizer.Cone.openEnded
openEnded
Definition: meshcat_visualizer.py:98
pinocchio.visualize.meshcat_visualizer.DaeMeshGeometry.dae_raw
dae_raw
Definition: meshcat_visualizer.py:135
CppAD::max
AD< Scalar > max(const AD< Scalar > &x, const AD< Scalar > &y)
Definition: autodiff/cppad.hpp:181
pinocchio.visualize.meshcat_visualizer.Cone.radius
radius
Definition: meshcat_visualizer.py:95
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.reset
def reset(self)
Definition: meshcat_visualizer.py:667
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.setCameraPosition
def setCameraPosition(self, np.ndarray position)
Definition: meshcat_visualizer.py:685
pinocchio.visualize.meshcat_visualizer.MeshcatVisualizer.updateFrames
def updateFrames(self)
Definition: meshcat_visualizer.py:1097
pinocchio.visualize.meshcat_visualizer.DaeMeshGeometry.set_scale
None set_scale(self, scale)
Definition: meshcat_visualizer.py:196
pinocchio.visualize.meshcat_visualizer.Cone
Definition: meshcat_visualizer.py:88
pinocchio::CartesianAxis
Definition: cartesian-axis.hpp:14


pinocchio
Author(s):
autogenerated on Tue Apr 22 2025 02:41:19