-
Notifications
You must be signed in to change notification settings - Fork 10
Nested components, as-built joints, MJCF joint ranges, and more #9
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
base: main
Are you sure you want to change the base?
Conversation
@@ -134,9 +138,6 @@ def run(): | |||
constants.set_text_palette(textPalette) | |||
|
|||
try: | |||
# Set design type into do not capture design history | |||
design.designType = adsk.fusion.DesignTypes.DirectDesignType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I can tell, this shouldn't be necessary. I kept the design history enabled for my model and everything was okay.
ui.messageBox("Finished exporting URDF for Gazebo.", msg_box_title) | ||
|
||
elif simulator == "PyBullet": | ||
elif simulator in ["Gazebo", "PyBullet", "MuJoCo"]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the code in each condition was nearly identical, I combined them into a single block.
self.joint = joint | ||
self.name = joint.name | ||
self.parent = joint.occurrenceTwo # parent link of joint | ||
self.child = joint.occurrenceOne | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In some cases, like when creating a rigid joint to an origin (i.e. lock to world), fetching the occurrences throws an exception.
@@ -144,7 +163,9 @@ def get_sdf_origin(self): | |||
# I guess using child joint origin works just because they coincide together for all the text examples | |||
|
|||
# get parent joint origin as the child joint | |||
if self.joint.geometryOrOriginTwo == adsk.fusion.JointOrigin: | |||
if hasattr(self.joint, 'geometry'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Necessary for an as-built joint
@@ -182,17 +203,24 @@ def get_joint_frame(self) -> adsk.core.Matrix3D: | |||
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() | |||
if hasattr(self.joint, 'geometry'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As-built joint origin geometry.
@@ -69,18 +69,14 @@ def get_parent_joint(self) -> adsk.fusion.Joint: | |||
# TODO: in closed loop mechanism, there exits one assembly method that | |||
# make one link have two parent joint, write a instruction or fix this bug | |||
# text_palette = constants.get_text_palette() | |||
joint_list: adsk.fusion.JointList = self.link.joints |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In some cases, when there are nested components, retrieving link.joints
will throw the exception: "RuntimeError: 3 : object does not belong to the occurrence's component"
The solution is to fetch all the joints in the design and perform the same logic.
@@ -161,6 +161,13 @@ def get_mjcf_joint(joint: Joint) -> Element: | |||
joint_ele.attrib = {"name": name_att, "type": joint_type, | |||
"axis": "{} {} {}".format(axis[0], axis[1], axis[2]), | |||
"pos": "{} {} {}".format(pose[0], pose[1], pose[2])} | |||
|
|||
|
|||
limits = joint.get_limits() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add joint limits to mjcf
all_occs = root_comp.allOccurrences | ||
|
||
joints = [j for j in root_comp.allJoints] + [j for j in root_comp.allAsBuiltJoints] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Include as-built joints in mjcf
@@ -236,6 +244,8 @@ def add_body_element(parent: adsk.fusion.Occurrence, parent_body_ele: Element) - | |||
|
|||
# traverse all the occs for body elements | |||
for occ in all_occs: | |||
if not occ.isLightBulbOn or not utils.component_has_bodies(occ.component): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ignore components that don't directly have bodies or that are not visible.
@@ -283,44 +283,6 @@ def get_joint_type(joint: Joint) -> str: | |||
pass | |||
return sdf_joint_type | |||
|
|||
def get_joint_pose(joint: Joint) -> list[float]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looked to be the same code as joint.get_sdf_origin
@@ -539,7 +548,7 @@ def get_link_inertial_origin(link: Link) -> list[float]: | |||
unit: m, radian | |||
""" | |||
# the link is the first link so called base-link | |||
if link.get_parent_joint() is None: | |||
if not joint_has_geometry(link.get_parent_joint()): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
joint_has_geometry
will return false if there is no parent joint, or if it's an as-built rigid joint.
link_frame: adsk.core.Matrix3D = link.pose | ||
from_origin, from_xAxis, from_yAxis, from_zAxis = parent_joint_frame.getAsCoordinateSystem() | ||
to_origin, to_xAsix, to_yAxis, to_zAxis = link_frame.getAsCoordinateSystem() | ||
if joint.has_origin(): | ||
parent_joint_frame: adsk.core.Matrix3D = joint.get_joint_frame() | ||
transform = math_op.coordinate_transform(parent_joint_frame, link.pose) | ||
mesh_origin = math_op.matrix3d_2_pose(transform) | ||
else: | ||
mesh_origin = math_op.matrix3d_2_pose(link.pose) | ||
|
||
transform = adsk.core.Matrix3D.create() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These variables weren't being used
Thanks for this great Fusion 360 Add In. I'd like to contribute the following updates:
As-Built Joints
These can be useful for some robots. The biggest challenge I ran into was that rigid as-built joints do not have parent origin geometry. In these cases, using the parent origin seems sufficient.
Test model
Here's a simple model I used to test these changes: https://a360.co/4kr0hsC