Skip to content

Commit 0c9c9c1

Browse files
committed
adds Item base class and the methods attach_meshes and draw_attached_meshes
1 parent bce3fbb commit 0c9c9c1

File tree

2 files changed

+60
-10
lines changed

2 files changed

+60
-10
lines changed

src/compas/robots/base_artist/_artist.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
'BaseRobotModelArtist'
1515
]
1616

17+
from compas.robots.model.link import Item
18+
1719

1820
class AbstractRobotModelArtist(object):
1921
def transform(self, geometry, transformation):
@@ -75,6 +77,7 @@ def __init__(self, model):
7577
self.create()
7678
self.scale_factor = 1.
7779
self.attached_tool_model = None
80+
self.attached_items = {}
7881

7982
def attach_tool_model(self, tool_model):
8083
"""Attach a tool to the robot artist.
@@ -114,6 +117,45 @@ def detach_tool_model(self):
114117
"""
115118
self.attached_tool_model = None
116119

120+
def attach_mesh(self, mesh, link=None):
121+
"""Rigidly attaches a compas mesh to a given link.
122+
123+
Parameters
124+
----------
125+
mesh : :class:`compas.datastructures.Mesh`
126+
The mesh to attach to the robot model.
127+
link : :class:`compas.robots.Link`
128+
The link within the robot model or tool model to attach the mesh to. Optional.
129+
Defaults to the model's end effector link.
130+
131+
Returns
132+
-------
133+
``None``
134+
"""
135+
if not link:
136+
link = self.model.get_end_effector_link()
137+
138+
frame = link.parent_joint.origin.copy()
139+
initial_transformation = Transformation.from_frame_to_frame(Frame.worldXY(), frame)
140+
141+
sample_geometry = link.collision[0] if link.collision else link.visual[0] if link.visual else None
142+
143+
if hasattr(sample_geometry, 'current_transformation'):
144+
relative_transformation = sample_geometry.current_transformation
145+
else:
146+
relative_transformation = Transformation()
147+
148+
transformation = relative_transformation.concatenated(initial_transformation)
149+
native_mesh = self.create_geometry(mesh)
150+
self.transform(native_mesh, transformation)
151+
152+
item = Item()
153+
item.native_geometry = [native_mesh]
154+
item.init_transformation = transformation # !!!
155+
item.current_transformation = Transformation() # !!!
156+
157+
self.attached_items.setdefault(link.name, []).append(item)
158+
117159
def create(self, link=None, context=None):
118160
"""Recursive function that triggers the drawing of the robot model's geometry.
119161
@@ -258,6 +300,8 @@ def _transform_link_geometry(self, link, transformation, collision=True):
258300
# some links have only collision geometry, not visual. These meshes have not been loaded.
259301
if item.native_geometry:
260302
self._apply_transformation_on_transformed_link(item, transformation)
303+
for item in self.attached_items.get(link.name, []):
304+
self._apply_transformation_on_transformed_link(item, transformation)
261305

262306
def update_tool(self, joint_state=None, visual=True, collision=True, transformation=None):
263307
"""Triggers the update of the robot geometry of the tool.
@@ -302,6 +346,13 @@ def draw_collision(self):
302346
for native_geometry in self._iter_geometry(self.attached_tool_model, 'collision'):
303347
yield native_geometry
304348

349+
def draw_attached_meshes(self):
350+
"""Draws all meshes attached to the robot model."""
351+
for items in self.attached_items.values():
352+
for item in items:
353+
for native_mesh in item.native_geometry:
354+
yield native_mesh
355+
305356
@staticmethod
306357
def _iter_geometry(model, geometry_type):
307358
for link in model.iter_links():

src/compas/robots/model/link.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,14 @@ def data(self, data):
168168
self.inertia = Inertia.from_data(data['inertia']) if data['inertia'] else None
169169

170170

171-
class Visual(Data):
171+
class Item(object):
172+
def __init__(self):
173+
self.init_transformation = None # to store the init transformation
174+
self.current_transformation = None # to store the current transformation
175+
self.native_geometry = None # to store the link's CAD native geometry
176+
177+
178+
class Visual(Item, Data):
172179
"""Visual description of a link.
173180
174181
Attributes
@@ -195,10 +202,6 @@ def __init__(self, geometry, origin=None, name=None, material=None, **kwargs):
195202
self.material = material
196203
self.attr = kwargs
197204

198-
self.init_transformation = None # to store the init transformation
199-
self.current_transformation = None # to store the current transformation
200-
self.native_geometry = None # to store the link's CAD native geometry
201-
202205
def get_urdf_element(self):
203206
attributes = {}
204207
if self.name is not None:
@@ -265,7 +268,7 @@ def from_primitive(cls, primitive, **kwargs):
265268
return cls(geometry, origin=origin, **kwargs)
266269

267270

268-
class Collision(Data):
271+
class Collision(Item, Data):
269272
"""Collidable description of a link.
270273
271274
Attributes
@@ -289,10 +292,6 @@ def __init__(self, geometry, origin=None, name=None, **kwargs):
289292
self.name = name
290293
self.attr = kwargs
291294

292-
self.init_transformation = None # to store the init transformation
293-
self.current_transformation = None # to store the current transformation
294-
self.native_geometry = None # to store the link's CAD native geometry
295-
296295
def get_urdf_element(self):
297296
attributes = {}
298297
if self.name is not None:

0 commit comments

Comments
 (0)