Skip to content

Commit a5a6c83

Browse files
committed
Add support for remote skeletons
1 parent 06a7a6e commit a5a6c83

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed

aitviewer/remote/message.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Message(enum.Enum):
1313
ARROWS = 5
1414
RIGID_BODIES = 6
1515
SMPL = 10
16+
SKELETONS = 11
1617

1718
# Messages used to modify existing nodes on the remote viewer.
1819
DELETE = 100
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright (C) 2023 ETH Zurich, Manuel Kaufmann, Velko Vechev, Dario Mylonopoulos
2+
from ..message import Message
3+
from ..node import RemoteNode
4+
5+
6+
class RemoteSkeletons(RemoteNode):
7+
MESSAGE_TYPE = Message.SKELETONS
8+
9+
def __init__(self, viewer, joint_positions, joint_connections, **kwargs):
10+
"""
11+
This initializer takes a RemoteViewer object and all other arguments are forwarded
12+
to the Spheres constructor on the remote Viewer.
13+
See the Spheres class for more information about parameters.
14+
15+
:param viewer: a RemoteViewer object that will be used to send this node.
16+
:param joint_positions: A np array of shape (F, J, 3) containing J joint positions over F many time steps.
17+
:param joint_connections: The definition of the skeleton as a numpy array of shape (N_LINES, 2) where each row
18+
defines one connection between joints. The max entry in this array must be < J.
19+
"""
20+
super().__init__(
21+
viewer,
22+
joint_positions=joint_positions,
23+
joint_connections=joint_connections,
24+
**kwargs,
25+
)
26+
27+
def add_frames(self, joint_positions):
28+
"""
29+
Add frames to the remote Spheres node by adding new sphere positions.
30+
31+
:param joint_positions: A np array of shape (N, J, 3) or (J, 3) containing J joint positions.
32+
"""
33+
return super().add_frames(joint_positions=joint_positions)
34+
35+
def update_frames(self, joint_positions, frames):
36+
"""
37+
Update frames of the remote Spheres node by updating the sphere positions.
38+
39+
:param joint_positions: A np array of shape (N, J, 3) containing J joint positions.
40+
:param frames: a list of integer frame indices of size N or a single integer frame index.
41+
"""
42+
return super().update_frames(joint_positions=joint_positions, frames=frames)

aitviewer/renderables/skeletons.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,19 @@ def color(self, color):
136136
self.material.color = color
137137
self.spheres.color = color
138138
self.lines.color = color
139+
140+
def update_frames(self, joint_positions, frames):
141+
self.joint_positions[frames] = joint_positions
142+
self.redraw()
143+
144+
def add_frames(self, joint_positions):
145+
if len(joint_positions.shape) == 2:
146+
joint_positions = joint_positions[np.newaxis]
147+
148+
self.joint_positions = np.append(self.joint_positions, joint_positions, axis=0)
149+
self.spheres.add_frames(self.joint_positions)
150+
self.lines.add_frames(self.joint_positions[:, self.skeleton].reshape(len(self), -1, 3))
151+
152+
def remove_frames(self, frames):
153+
self.joint_positions = np.delete(self.joint_positions, frames, axis=0)
154+
self.redraw()

aitviewer/server.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from aitviewer.renderables.lines import Lines
1414
from aitviewer.renderables.meshes import Meshes
1515
from aitviewer.renderables.rigid_bodies import RigidBodies
16+
from aitviewer.renderables.skeletons import Skeletons
1617
from aitviewer.renderables.smpl import SMPLSequence
1718
from aitviewer.renderables.spheres import Spheres
1819
from aitviewer.scene.node import Node
@@ -118,6 +119,9 @@ def add(client, remote_uid, args, kwargs, type):
118119
elif type == Message.RIGID_BODIES:
119120
add(client, remote_uid, args, kwargs, RigidBodies)
120121

122+
elif type == Message.SKELETONS:
123+
add(client, remote_uid, args, kwargs, Skeletons)
124+
121125
elif type == Message.SMPL:
122126
layer_arg_names = {"model_type", "gender", "num_betas"}
123127
layer_kwargs = {k: v for k, v in kwargs.items() if k in layer_arg_names}

0 commit comments

Comments
 (0)