base_visualizer.py
Go to the documentation of this file.
1 from .. import pinocchio_pywrap as pin
2 from ..shortcuts import buildModelsFromUrdf, createDatas
3 
4 import time
5 import numpy as np
6 import os.path as osp
7 
8 
9 try:
10  import imageio
11  IMAGEIO_SUPPORT = True
12 except ImportError:
13  IMAGEIO_SUPPORT = False
14 
15 
16 class BaseVisualizer(object):
17  """Pinocchio visualizers are employed to easily display a model at a given configuration.
18  BaseVisualizer is not meant to be directly employed, but only to provide a uniform interface and a few common methods.
19  New visualizers should extend this class and override its methods as neeeded.
20  """
21 
22  _video_writer = None
23 
24  def __init__(
25  self,
26  model=pin.Model(),
27  collision_model=None,
28  visual_model=None,
29  copy_models=False,
30  data=None,
31  collision_data=None,
32  visual_data=None,
33  ):
34  """Construct a display from the given model, collision model, and visual model.
35  If copy_models is True, the models are copied. Otherwise, they are simply kept as a reference."""
36 
37  if copy_models:
38  self.model = model.copy()
39  self.collision_model = collision_model.copy()
40  self.visual_model = visual_model.copy()
41  else:
42  self.model = model
43  self.collision_model = collision_model
44  self.visual_model = visual_model
45 
46  if data is None:
47  self.data = self.model.createData()
48  else:
49  self.data = data
50 
51  if collision_data is None and self.collision_model is not None:
53  else:
54  self.collision_data = collision_data
55 
56  if visual_data is None and self.visual_model is not None:
58  else:
59  self.visual_data = visual_data
60 
61  def rebuildData(self):
62  """Re-build the data objects. Needed if the models were modified.
63  Warning: this will delete any information stored in all data objects."""
64  self.data, self.collision_data, self.visual_data = createDatas(
65  self.model, self.collision_model, self.visual_model
66  )
67 
68  def getViewerNodeName(self, geometry_object, geometry_type):
69  """Return the name of the geometry object inside the viewer."""
70  pass
71 
72  def initViewer(self, *args, **kwargs):
73  """Init the viewer by loading the gui and creating a window."""
74  pass
75 
76  def loadViewerModel(self, *args, **kwargs):
77  """Create the scene displaying the robot meshes in the viewer"""
78  pass
79 
80  def reload(self, new_geometry_object, geometry_type=None):
81  """Reload a geometry_object given by its type"""
82  pass
83 
84  def clean(self):
85  """Delete all the objects from the whole scene"""
86  pass
87 
88  def display(self, q=None):
89  """Display the robot at configuration q or refresh the rendering
90  from the current placements contained in data by placing all the bodies in the viewer."""
91  pass
92 
93  def displayCollisions(self, visibility):
94  """Set whether to display collision objects or not."""
95  pass
96 
97  def displayVisuals(self, visibility):
98  """Set whether to display visual objects or not."""
99  raise NotImplementedError()
100 
101  def setBackgroundColor(self, *args, **kwargs):
102  """Set the visualizer background color."""
103  raise NotImplementedError()
104 
105  def setCameraTarget(self, target):
106  """Set the camera target."""
107  raise NotImplementedError()
108 
109  def setCameraPosition(self, position):
110  """Set the camera's 3D position."""
111  raise NotImplementedError()
112 
113  def setCameraZoom(self, zoom):
114  """Set camera zoom value."""
115  raise NotImplementedError()
116 
117  def setCameraPose(self, pose=np.eye(4)):
118  """Set camera 6D pose using a 4x4 matrix."""
119  raise NotImplementedError()
120 
121  def captureImage(self, w=None, h=None):
122  """Captures an image from the viewer and returns an RGB array."""
123  pass
124 
126  raise NotImplementedError()
127 
129  raise NotImplementedError()
130 
131  def drawFrameVelocities(self, *args, **kwargs):
132  """Draw current frame velocities."""
133  raise NotImplementedError()
134 
135  def sleep(self, dt):
136  time.sleep(dt)
137 
138  def has_video_writer(self):
139  return self._video_writer is not None
140 
141  def play(self, q_trajectory, dt=None, callback=None, capture=False, **kwargs):
142  """Play a trajectory with given time step. Optionally capture RGB images and returns them."""
143  nsteps = len(q_trajectory)
144  if not capture:
145  capture = self.has_video_writer()
146 
147  imgs = []
148  for i in range(nsteps):
149  t0 = time.time()
150  self.display(q_trajectory[i])
151  if callback is not None:
152  callback(i, **kwargs)
153  if capture:
154  img_arr = self.captureImage()
155  if not self.has_video_writer():
156  imgs.append(img_arr)
157  else:
158  self._video_writer.append_data(img_arr)
159  t1 = time.time()
160  elapsed_time = t1 - t0
161  if dt is not None and elapsed_time < dt:
162  self.sleep(dt - elapsed_time)
163  if capture and not self.has_video_writer():
164  return imgs
165 
166  def create_video_ctx(self, filename=None, fps=30, directory=None, **kwargs):
167  """Create a video recording context, generating the output filename if necessary.
168 
169  Code inspired from https://github.com/petrikvladimir/RoboMeshCat.
170  """
171  if not IMAGEIO_SUPPORT:
172  import warnings, contextlib
173  warnings.warn("Video context cannot be created because imageio is not available.", UserWarning)
174  return contextlib.nullcontext()
175  if filename is None:
176  if directory is None:
177  from tempfile import gettempdir
178 
179  directory = gettempdir()
180  f_fmt = "%Y%m%d_%H%M%S"
181  ext = "mp4"
182  filename = time.strftime("{}.{}".format(f_fmt, ext))
183  filename = osp.join(directory, filename)
184  return VideoContext(self, fps, filename)
185 
186 
188  def __init__(self, viz, fps, filename, **kwargs):
189  self.viz = viz
190  self.vid_writer = imageio.get_writer(filename, fps=fps, **kwargs)
191 
192  def __enter__(self):
193  print("[Entering video recording context]")
194  self.viz._video_writer = self.vid_writer
195 
196  def __exit__(self, *args):
197  self.vid_writer.close()
198  self.viz._video_writer = None
199 
200 
201 __all__ = ["BaseVisualizer"]
def getViewerNodeName(self, geometry_object, geometry_type)
JointDataTpl< Scalar, Options, JointCollectionTpl > createData(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through CreateData visitor to create a JointDataTpl.
def reload(self, new_geometry_object, geometry_type=None)
def createDatas(models)
Definition: shortcuts.py:56
def play(self, q_trajectory, dt=None, callback=None, capture=False, kwargs)
def __init__(self, model=pin.Model(), collision_model=None, visual_model=None, copy_models=False, data=None, collision_data=None, visual_data=None)
def create_video_ctx(self, filename=None, fps=30, directory=None, kwargs)
def __init__(self, viz, fps, filename, kwargs)


pinocchio
Author(s):
autogenerated on Fri Jun 23 2023 02:38:28