Skip to content

Commit f5af4d6

Browse files
authored
Merge pull request #1211 from robotology/add_meshcat_animation
Add the possibility to generate animation in MeshcatVisualizer
2 parents 5fe4cf9 + 48452b2 commit f5af4d6

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

bindings/python/visualize/meshcat_visualizer.py

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,22 @@ def __init__(self, zmq_url=None):
6666
self.primitive_geometries_names = []
6767
self.arrow_names = []
6868
self.link_visuals = dict()
69+
self._animation = None
70+
self._current_frame = 0
71+
72+
def start_recording_animation(self):
73+
from meshcat.animation import Animation
74+
self._animation = Animation()
75+
76+
def stop_recording_animation(self):
77+
self._animation = None
78+
79+
def set_animation_frame(self, frame_number):
80+
self._current_frame = frame_number
81+
82+
def publish_animation(self):
83+
if self._animation is not None:
84+
self.viewer.set_animation(self._animation)
6985

7086
@staticmethod
7187
def __is_mesh(geometry_object: idyn.SolidShape) -> bool:
@@ -174,7 +190,11 @@ def __apply_transform_to_primitive_geomety(
174190
world_H_geometry_scaled = np.array(world_H_geometry)
175191

176192
# Update viewer configuration.
177-
self.viewer[viewer_name].set_transform(world_H_geometry_scaled)
193+
if self._animation is None:
194+
self.viewer[viewer_name].set_transform(world_H_geometry_scaled)
195+
else:
196+
with self._animation.at_frame(self.viewer, self._current_frame) as frame:
197+
frame[viewer_name].set_transform(world_H_geometry_scaled)
178198

179199
def __apply_transform(self, world_H_frame, solid_shape, viewer_name):
180200
world_H_geometry = (
@@ -187,7 +207,11 @@ def __apply_transform(self, world_H_frame, solid_shape, viewer_name):
187207
world_H_geometry_scaled = np.array(world_H_geometry).dot(extended_scale)
188208

189209
# Update viewer configuration.
190-
self.viewer[viewer_name].set_transform(world_H_geometry_scaled)
210+
if self._animation is None:
211+
self.viewer[viewer_name].set_transform(world_H_geometry_scaled)
212+
else:
213+
with self._animation.at_frame(self.viewer, self._current_frame) as frame:
214+
frame[viewer_name].set_transform(world_H_geometry_scaled)
191215

192216
def __model_exists(self, model_name):
193217
return (
@@ -509,7 +533,11 @@ def set_primitive_geometry_transform(
509533
transform[0:3, 0:3] = rotation
510534
transform[0:3, 3] = position
511535
transform[3, 3] = 1
512-
self.viewer[shape_name].set_transform(transform)
536+
if self._animation is None:
537+
self.viewer[shape_name].set_transform(transform)
538+
else:
539+
with self._animation.at_frame(self.viewer, self._current_frame) as frame:
540+
frame[shape_name].set_transform(transform)
513541

514542
def set_arrow_transform(self, origin, vector, shape_name="iDynTree"):
515543
if not self.__arrow_exists(shape_name):
@@ -523,7 +551,11 @@ def set_arrow_transform(self, origin, vector, shape_name="iDynTree"):
523551
transform[3, 3] = 1
524552

525553
if np.linalg.norm(vector) < 1e-6:
526-
self.viewer[shape_name].set_transform(transform)
554+
if self._animation is None:
555+
self.viewer[shape_name].set_transform(transform)
556+
else:
557+
with self._animation.at_frame(self.viewer, self._current_frame) as frame:
558+
frame[shape_name].set_transform(transform)
527559
return
528560

529561
# extract rotation matrix from a normalized vector
@@ -543,7 +575,11 @@ def set_arrow_transform(self, origin, vector, shape_name="iDynTree"):
543575
R = np.eye(3) + skew_symmetric_matrix + np.dot(skew_symmetric_matrix, skew_symmetric_matrix) * ((1 - c) / (s ** 2))
544576

545577
transform[0:3, 0:3] = R @ S
546-
self.viewer[shape_name].set_transform(transform)
578+
if self._animation is None:
579+
self.viewer[shape_name].set_transform(transform)
580+
else:
581+
with self._animation.at_frame(self.viewer, self._current_frame) as frame:
582+
frame[shape_name].set_transform(transform)
547583

548584
def load_model_from_file(
549585
self, model_path: str, considered_joints=None, model_name="iDynTree", color=None

0 commit comments

Comments
 (0)