9 from urdf_parser_py
import urdf
as URDF
11 import robowflex_visualization
as rv
36 def __init__(self, name, urdf, make_pretty = True):
39 self.
collectioncollection = rv.utils.get_collection(name)
41 self.
collectioncollection = rv.utils.make_collection(name)
57 self.
urdf_pathurdf_path = rv.utils.resolve_path(urdf)
58 xml_output = os.path.join(
"/tmp",
59 os.path.basename(self.
urdf_pathurdf_path) +
".xml")
60 dae_output = os.path.join(
"/tmp",
61 os.path.basename(self.
urdf_pathurdf_path) +
".dae")
63 subprocess.check_output([
72 self.
urdf_xmlurdf_xml = open(xml_output,
'r').read()
77 if not os.path.exists(dae_output):
78 subprocess.check_output([
87 bpy.ops.wm.collada_import(filepath = dae_output)
88 rv.utils.move_selected_to_collection(self.
namename)
89 rv.utils.deselect_all()
96 return rv.utils.find_object_in_collection(self.
namename, link_name)
103 for link
in self.
robotrobot.links:
104 if link.name == link_name:
114 for joint
in self.
robotrobot.joints:
115 if joint.name == joint_name:
131 def set_joint(self, joint_name, value, interpolate = True):
133 parent_xml = self.
get_link_xmlget_link_xml(joint_xml.parent)
134 link_xml = self.
get_link_xmlget_link_xml(joint_xml.child)
135 link = self.
get_linkget_link(joint_xml.child)
137 link.rotation_mode =
"QUATERNION"
139 parent_l = mathutils.Matrix.Identity(4)
140 if parent_xml.visual:
141 parent_l = rv.utils.get_tf_origin_xml(parent_xml.visual)
142 parent_l = parent_l.inverted()
144 origin_l = mathutils.Matrix.Identity(4)
146 origin_l = rv.utils.get_tf_origin_xml(link_xml.visual)
148 origin_j = rv.utils.get_tf_origin_xml(joint_xml)
150 if joint_xml.type ==
"prismatic":
151 rm = mathutils.Matrix.Translation(
152 mathutils.Vector(joint_xml.axis) * value)
155 rotation = mathutils.Quaternion(joint_xml.axis, value)
156 rm = rotation.to_matrix()
159 output = parent_l @ origin_j @ rm @ origin_l
161 prior = link.rotation_quaternion.copy()
163 link.location = output.to_translation()
164 link.rotation_quaternion = output.to_quaternion()
167 link.rotation_quaternion.make_compatible(prior)
184 if joint_name ==
"virtual_joint":
190 link_xml = self.
get_link_xmlget_link_xml(joint_xml.child)
191 link = self.
get_linkget_link(joint_xml.child)
193 link.rotation_mode =
"QUATERNION"
194 link.location = tf[
'translation']
196 q = mathutils.Quaternion([tf[
'rotation'][3]] + tf[
'rotation'][:3])
198 q.make_compatible(link.rotation_quaternion)
200 link.rotation_quaternion = q
213 if joint_name ==
"virtual_joint":
219 link_xml = self.
get_link_xmlget_link_xml(joint_xml.child)
220 link = self.
get_linkget_link(joint_xml.child)
222 link.keyframe_insert(data_path =
"location", frame = frame)
223 link.keyframe_insert(data_path =
"rotation_quaternion", frame = frame)
238 interpolate = False):
239 path = rv.utils.read_YAML_data(path_file)
241 trajectory = path[
"joint_trajectory"]
242 names = trajectory[
"joint_names"]
244 if "multi_dof_joint_trajectory" in path:
245 mdof_trajectory = path[
"multi_dof_joint_trajectory"]
246 mdof_names = mdof_trajectory[
"joint_names"]
248 last_time = float(trajectory[
"points"][-1][
"time_from_start"])
255 for i
in range(len(trajectory[
"points"])):
256 point = trajectory[
"points"][i]
258 time = float(point[
"time_from_start"])
260 time = last_time - time
262 frame = start + time * fps
263 if frame > last_frame:
266 for value, name
in zip(point[
"positions"], names):
267 self.
set_jointset_joint(name, value, interpolate
or i > 0)
270 if "multi_dof_joint_trajectory" in path:
271 mdof_point = mdof_trajectory[
"points"][i]
272 for tf, name
in zip(mdof_point[
"transforms"], mdof_names):
273 self.
set_joint_tfset_joint_tf(name, tf, interpolate
or i > 0)
276 return math.ceil(last_frame)
282 state = rv.utils.read_YAML_data(state_file)
283 joint_state = state[
"joint_state"]
285 names = joint_state[
"name"]
286 position = joint_state[
"position"]
288 for name, value
in zip(names, position):
298 rv.utils.parent_object(self.
get_linkget_link(link_name), item, frame)
308 rv.utils.unparent_object(self.
get_linkget_link(link_name), item, frame)
314 for link_xml
in self.
robotrobot.links:
318 link = self.
get_linkget_link(link_xml.name)
319 rv.utils.remove_doubles(link)
321 rv.utils.apply_edge_split(link)
322 rv.utils.apply_smooth_shade(link)
335 name = self.
namename +
"_temp"
336 collection = rv.utils.make_collection(name)
339 visual = link_xml.visuals[0]
340 geometry = visual.geometry
343 if hasattr(geometry,
'filename')
and ".dae" in geometry.filename:
344 meshes, top = rv.primitives.add_mesh(
345 {
"resource": geometry.filename})
347 rv.utils.deselect_all()
348 bpy.context.view_layer.objects.active = meshes[0]
350 mesh.select_set(
True)
351 bpy.ops.object.join()
352 rv.utils.move_selected_to_collection(name)
353 rv.utils.deselect_all()
355 old = self.
get_linkget_link(link_name)
356 old.data = meshes[0].data
358 rv.utils.remove_collection(name)
362 for link_xml
in self.
robotrobot.links:
363 link = self.
get_linkget_link(link_xml.name)
365 link.animation_data_clear()
370 for joint
in self.
robotrobot.joints:
372 children.append(xml.child)
374 for link
in self.
robotrobot.links:
375 if link.name
not in children:
Controllable URDF described robot.
def set_joint(self, joint_name, value, interpolate=True)
Set the value of a 1-DoF joint in the URDF.
def set_state(self, state_file)
Sets the robot's state from a file with a moveit_msgs::RobotState.
def get_joint_xml(self, joint_name)
Get the XML description in the URDF of a joint.
def get_root(self)
Get the root link of this robot.
def detach_object(self, link_name, item, frame)
Detaches an object to a link of the robot.
def clear_animation_data(self)
Clear all animation data for this robot.
def get_link(self, link_name)
Gets a Blender object corresponding to a link on the robot.
def add_keyframe(self, joint_name, frame)
Adds a keyframe to a joint in the URDF at a frame in the animation timeline.
def __init__(self, name, urdf, make_pretty=True)
Constructor.
def prettify(self)
Cleans up robot mesh geometry and applies modifiers to improve rendering aesthetics.
def set_joint_tf(self, joint_name, tf, interpolate=True)
Set the value of a 6-DoF joint in the URDF.
def get_link_xml(self, link_name)
Get the XML description in the URDF of a link.
name
Name of Robot and Blender collection.
def load_link_mesh(self, link_name)
Loads the mesh data for a specific link on the robot.
def load_urdf(self, urdf, load=True)
Loads the URDF as a COLLADA mesh, as well as loading the XML.
def attach_object(self, link_name, item, frame)
Attaches an object to a link of the robot.
def animate_path(self, path_file, fps=60., start=30, reverse=False, interpolate=False)
Adds keyframes to animate a moveit_msgs::RobotTrajectoryMsg.
collection
Blender collection containing loaded robot geometry.