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


pinocchio
Author(s):
autogenerated on Thu Dec 19 2024 03:41:31