Skip to content

Enhancement: Proper Handling of Component Occurrences in URDF Export #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
.vscode
.vscode
Add-IN/ACDC4Robot/.env
1 change: 0 additions & 1 deletion Add-IN/ACDC4Robot/.env

This file was deleted.

31 changes: 21 additions & 10 deletions Add-IN/ACDC4Robot/commands/ACDC4Robot/acdc4robot.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def get_link_joint_list(design: adsk.fusion.Design):

return link_list, joint_list

def export_stl(design: adsk.fusion.Design, save_dir: str, links: list[Link]):
def export_stl(design: adsk.fusion.Design, save_dir: str, links: list[Link], rdf: str):
"""
export each component's stl file into "save_dir/mesh"

Expand All @@ -66,6 +66,8 @@ def export_stl(design: adsk.fusion.Design, save_dir: str, links: list[Link]):
current active design
save_dir: str
the directory to store the export stl file
rdf: str
robot description format
"""
# create a single exportManager instance
export_manager = design.exportManager
Expand All @@ -77,9 +79,14 @@ def export_stl(design: adsk.fusion.Design, save_dir: str, links: list[Link]):
for link in links:
visual_body: adsk.fusion.BRepBody = link.get_visual_body()
col_body: adsk.fusion.BRepBody = link.get_collision_body()
if rdf == "URDF":
mesh_name = mesh_dir + "/" + link.link.component.name
else :
mesh_name = mesh_dir + "/" + link.get_name()
if (visual_body is None) and (col_body is None):
# export the whole occurrence
mesh_name = mesh_dir + "/" + link.get_name()
if os.path.isfile(mesh_name) :
continue
occ = link.get_link_occ()
# obj_export_options = export_manager.createOBJExportOptions(occ, mesh_name)
# obj_export_options.unitType = adsk.fusion.DistanceUnits.MillimeterDistanceUnits # set unit to mm
Expand All @@ -92,14 +99,18 @@ def export_stl(design: adsk.fusion.Design, save_dir: str, links: list[Link]):
export_manager.execute(stl_export_options)
elif (visual_body is not None) and (col_body is not None):
# export visual and collision geometry seperately
visual_mesh_name = mesh_dir + "/" + link.get_name() + "_visual"
visual_mesh_name = mesh_name + "_visual"
if os.path.isfile(visual_mesh_name) :
continue
visual_exp_options = export_manager.createSTLExportOptions(visual_body, visual_mesh_name)
visual_exp_options.sendToPrintUtility = False
visual_exp_options.isBinaryFormat = True
visual_exp_options.meshRefinement = adsk.fusion.MeshRefinementSettings.MeshRefinementLow
export_manager.execute(visual_exp_options)

col_mesh_name = mesh_dir + "/" + link.get_name() + "_collision"
col_mesh_name = mesh_name + "_collision"
if os.path.isfile(col_mesh_name) :
continue
col_exp_options = export_manager.createSTLExportOptions(col_body, col_mesh_name)
col_exp_options.sendToPrintUtility = False
col_exp_options.isBinaryFormat = True
Expand Down Expand Up @@ -181,14 +192,14 @@ def run():
# write to .urdf file
write.write_urdf(link_list, joint_list, save_folder, robot_name)
# export mesh files
export_stl(design, save_folder, link_list)
export_stl(design, save_folder, link_list, rdf)
ui.messageBox("Finished exporting URDF for Gazebo.", msg_box_title)

elif simulator == "PyBullet":
# write to .urdf file
write.write_urdf(link_list, joint_list, save_folder, robot_name)
# export mesh files
export_stl(design, save_folder, link_list)
export_stl(design, save_folder, link_list, rdf)
# generate pybullet script
write.write_hello_pybullet(rdf, robot_name, save_folder)
ui.messageBox("Finished exporting URDF for PyBullet.", msg_box_title)
Expand All @@ -197,7 +208,7 @@ def run():
# write to .urdf file
write.write_urdf(link_list, joint_list, save_folder, robot_name)
# export mesh files
export_stl(design, save_folder, link_list)
export_stl(design, save_folder, link_list, rdf)

ui.messageBox("Finished exporting URDF for MuJoCo.", msg_box_title)

Expand All @@ -213,13 +224,13 @@ def run():
des = constants.get_model_description()
write.write_sdf_config(save_folder, robot_name, author, des)
# export stl files
export_stl(design, save_folder, link_list)
export_stl(design, save_folder, link_list, rdf)
ui.messageBox("Finished exporting SDFormat for Gazebo.", msg_box_title)
elif simulator == "PyBullet":
# write to .sdf file
write.write_sdf(link_list, joint_list, save_folder, robot_name)
# export stl files
export_stl(design, save_folder, link_list)
export_stl(design, save_folder, link_list, rdf)
# generate pybullet script
write.write_hello_pybullet(rdf,robot_name, save_folder)
ui.messageBox("Finished exporting SDFormat for PyBullet.", msg_box_title)
Expand All @@ -242,7 +253,7 @@ def run():
# write to .xml file
write.write_mjcf(root, robot_name, save_folder)
# export stl files
export_stl(design, save_folder, link_list)
export_stl(design, save_folder, link_list, rdf)
time.sleep(0.1)
ui.messageBox("Finished exporting MJCF for MuJoCo.", msg_box_title)

Expand Down
18 changes: 6 additions & 12 deletions Add-IN/ACDC4Robot/core/joint.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,20 +181,14 @@ def get_joint_frame(self) -> adsk.core.Matrix3D:
a homogeneous matrix represents joint frame J in world frame W
translation unit: cm
"""
# get parent joint origin's coordinate w.r.t world frame
if self.joint.geometryOrOriginTwo == adsk.fusion.JointOrigin:
w_P_J = self.joint.geometryOrOriginTwo.geometry.origin.asArray()
else:
w_P_J = self.joint.geometryOrOriginTwo.origin.asArray()
geometry_two_transform = self.joint.geometryTwoTransform
matrix_array = geometry_two_transform.asArray()

w_P_J = [round(i, 6) for i in w_P_J]

# no matter jointGeometry or jointOrigin object, both have these properties
zAxis: adsk.core.Vector3D = self.joint.geometryOrOriginTwo.primaryAxisVector
xAxis: adsk.core.Vector3D = self.joint.geometryOrOriginTwo.secondaryAxisVector
yAxis: adsk.core.Vector3D = self.joint.geometryOrOriginTwo.thirdAxisVector
origin = adsk.core.Point3D.create(matrix_array[3], matrix_array[7], matrix_array[11])

origin = adsk.core.Point3D.create(w_P_J[0], w_P_J[1], w_P_J[2])
xAxis = adsk.core.Vector3D.create(matrix_array[0], matrix_array[1], matrix_array[2])
yAxis = adsk.core.Vector3D.create(matrix_array[4], matrix_array[5], matrix_array[6])
zAxis = adsk.core.Vector3D.create(matrix_array[8], matrix_array[9], matrix_array[10])

joint_frame = adsk.core.Matrix3D.create()
joint_frame.setWithCoordinateSystem(origin, xAxis, yAxis, zAxis)
Expand Down
16 changes: 8 additions & 8 deletions Add-IN/ACDC4Robot/core/urdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -710,19 +710,19 @@ def get_link_visual_geo(link: Link) -> str:
col_body = link.get_collision_body()
if (visual_body is None) and (col_body is None):
# visual and collision geometry is same
mesh_loc = "meshes/" + link.get_name() + ".stl"
mesh_loc = "meshes/" + link.link.component.name + ".stl"
return mesh_loc
elif (visual_body is not None) and (col_body is not None):
mesh_loc = "meshes/" + link.get_name() + "_visual.stl"
mesh_loc = "meshes/" + link.link.component.name + "_visual.stl"
return mesh_loc
elif (visual_body is None) and (col_body is not None):
error_message = "Please set two bodies, one for visual and one for collision. \n"
error_message = error_message + link.get_name() + " body for visual missing."
error_message = error_message + link.link.component.name + " body for visual missing."
utils.error_box(error_message)
utils.terminate_box()
elif (visual_body is not None) and (col_body is None):
error_message = "Please set two bodies, one for visual and one for collision. \n"
error_message = error_message + link.get_name() + " body for collision missing."
error_message = error_message + link.link.component.name + " body for collision missing."
utils.error_box(error_message)
utils.terminate_box()

Expand All @@ -737,19 +737,19 @@ def get_link_collision_geo(link: Link) -> str:
visual_body = link.get_visual_body()
col_body = link.get_collision_body()
if (visual_body is None) and (col_body is None):
mesh_loc = "meshes/" + link.get_name() + ".stl"
mesh_loc = "meshes/" + link.link.component.name + ".stl"
return mesh_loc
elif (visual_body is not None) and (col_body is not None):
mesh_loc = "meshes/" + link.get_name() + "_collision.stl"
mesh_loc = "meshes/" + link.link.component.name + "_collision.stl"
return mesh_loc
elif (visual_body is None) and (col_body is not None):
error_message = "Please set two bodies, one for visual and one for collision. \n"
error_message = error_message + link.get_name() + " body for visual missing."
error_message = error_message + link.link.component.name + " body for visual missing."
utils.error_box(error_message)
utils.terminate_box()
elif (visual_body is not None) and (col_body is None):
error_message = "Please set two bodies, one for visual and one for collision. \n"
error_message = error_message + link.get_name() + " body for collision missing."
error_message = error_message + link.link.component.name + " body for collision missing."
utils.error_box(error_message)
utils.terminate_box()

Expand Down
10 changes: 6 additions & 4 deletions Add-IN/ACDC4Robot/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ def get_valid_filename(s):
>>> get_valid_filename("john's portrait in 2004.jpg")
'johns_portrait_in_2004.jpg'
"""
# Replace the number `:#+` by `-`
s = re.sub(r':.*?\+', '_', s)
# Remove the number at the end of the full path name
s = re.sub(r':.*$', '', s)

# Several body for the composant so keep the number id
# Replace `:` by `-`
s = re.sub(r':', '-', s)
# Replace `+` by `_`
s = re.sub(r'\+', '_', s)

s = str(s).strip().replace(' ', '-')
return re.sub(r'(?u)[^-\w.]', '', s)
Expand Down