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


pinocchio
Author(s):
autogenerated on Sat Sep 28 2024 02:41:21