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


pinocchio
Author(s):
autogenerated on Wed May 28 2025 02:41:20