# -*- coding: utf-8 -*- """ Export Link infos to XML from Fusion 360 @syuntoku @yanshil """ import adsk, re from xml.etree.ElementTree import Element, SubElement from ..utils import utils class Link: def __init__(self, name, xyz, center_of_mass, repo, mass, inertia_tensor): """ Parameters ---------- name: str name of the link xyz: [x, y, z] coordinate for the visual and collision center_of_mass: [x, y, z] coordinate for the center of mass link_xml: str generated xml describing about the link repo: str the name of the repository to save the xml file mass: float mass of the link inertia_tensor: [ixx, iyy, izz, ixy, iyz, ixz] tensor of the inertia """ self.name = name # xyz for visual self.xyz = [-_ for _ in xyz] # reverse the sign of xyz # xyz for center of mass self.center_of_mass = center_of_mass self.link_xml = None self.repo = repo self.mass = mass self.inertia_tensor = inertia_tensor def make_link_xml(self): """ Generate the link_xml and hold it by self.link_xml """ link = Element('link') link.attrib = {'name':self.name} #inertial inertial = SubElement(link, 'inertial') origin_i = SubElement(inertial, 'origin') origin_i.attrib = {'xyz':' '.join([str(_) for _ in self.center_of_mass]), 'rpy':'0 0 0'} mass = SubElement(inertial, 'mass') mass.attrib = {'value':str(self.mass)} inertia = SubElement(inertial, 'inertia') inertia.attrib = \ {'ixx':str(self.inertia_tensor[0]), 'iyy':str(self.inertia_tensor[1]),\ 'izz':str(self.inertia_tensor[2]), 'ixy':str(self.inertia_tensor[3]),\ 'iyz':str(self.inertia_tensor[4]), 'ixz':str(self.inertia_tensor[5])} # visual visual = SubElement(link, 'visual') origin_v = SubElement(visual, 'origin') origin_v.attrib = {'xyz':' '.join([str(_) for _ in self.xyz]), 'rpy':'0 0 0'} geometry_v = SubElement(visual, 'geometry') mesh_v = SubElement(geometry_v, 'mesh') mesh_v.attrib = {'filename': self.repo + self.name + '.stl','scale':'0.001 0.001 0.001'} ## scale = 0.001 means mm to m. Modify it according if using another unit material = SubElement(visual, 'material') material.attrib = {'name':'silver'} # collision collision = SubElement(link, 'collision') origin_c = SubElement(collision, 'origin') origin_c.attrib = {'xyz':' '.join([str(_) for _ in self.xyz]), 'rpy':'0 0 0'} geometry_c = SubElement(collision, 'geometry') mesh_c = SubElement(geometry_c, 'mesh') mesh_c.attrib = {'filename': self.repo + self.name + '.stl','scale':'0.001 0.001 0.001'} ## scale = 0.001 means mm to m. Modify it according if using another unit material = SubElement(visual, 'material') # print("\n".join(utils.prettify(link).split("\n")[1:])) self.link_xml = "\n".join(utils.prettify(link).split("\n")[1:]) def make_inertial_dict(root, msg): """ Parameters ---------- root: adsk.fusion.Design.cast(product) Root component msg: str Tell the status Returns ---------- inertial_dict: {name:{mass, inertia, center_of_mass}} msg: str Tell the status """ # Get component properties. allOccs = root.occurrences inertial_dict = {} for occs in allOccs: # Skip the root component. occs_dict = {} prop = occs.getPhysicalProperties(adsk.fusion.CalculationAccuracy.VeryHighCalculationAccuracy) occs_dict['name'] = re.sub('[ :()]', '_', occs.name) mass = prop.mass # kg occs_dict['mass'] = mass center_of_mass = [_/100.0 for _ in prop.centerOfMass.asArray()] ## cm to m occs_dict['center_of_mass'] = center_of_mass # https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-ce341ee6-4490-11e5-b25b-f8b156d7cd97 (_, xx, yy, zz, xy, yz, xz) = prop.getXYZMomentsOfInertia() moment_inertia_world = [_ / 10000.0 for _ in [xx, yy, zz, xy, yz, xz] ] ## kg / cm^2 -> kg/m^2 occs_dict['inertia'] = utils.origin2center_of_mass(moment_inertia_world, center_of_mass, mass) if 'base_link' in occs.component.name: inertial_dict['base_link'] = occs_dict else: inertial_dict[re.sub('[ :()]', '_', occs.name)] = occs_dict return inertial_dict, msg # def make_inertial_dict(root, msg): # """ # Parameters # ---------- # root: adsk.fusion.Design.cast(product) # Root component # msg: str # Tell the status # Returns # ---------- # inertial_dict: {name:{mass, inertia, center_of_mass}} # msg: str # Tell the status # """ # # Get ALL component properties. # allOccs = root.allOccurrences # inertial_dict = {} # for occs in allOccs: # # Skip the root component. # occs_dict = {} # prop = occs.getPhysicalProperties(adsk.fusion.CalculationAccuracy.VeryHighCalculationAccuracy) # mass = prop.mass # kg # occs_dict['mass'] = mass # center_of_mass = [_/100.0 for _ in prop.centerOfMass.asArray()] ## cm to m # occs_dict['center_of_mass'] = center_of_mass # # https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-ce341ee6-4490-11e5-b25b-f8b156d7cd97 # (_, xx, yy, zz, xy, yz, xz) = prop.getXYZMomentsOfInertia() # moment_inertia_world = [_ / 10000.0 for _ in [xx, yy, zz, xy, yz, xz] ] ## kg / cm^2 -> kg/m^2 # occs_dict['inertia'] = utils.origin2center_of_mass(moment_inertia_world, center_of_mass, mass) # # if occs.component.name == 'base_link': # # occs_dict['name'] = 'base_link' # # inertial_dict['base_link'] = occs_dict # # # print("Processing Base Link") # if 'base_link' in occs.component.name: # inertial_dict['base_link'] = occs_dict # else: # # occs_dict['name'] = re.sub('[ :()]', '_', occs.name) # key = utils.get_valid_filename(occs.fullPathName) # occs_dict['name'] = key # inertial_dict[key] = occs_dict # # print("Exporting link {}".format(occs_dict['name'])) # return inertial_dict, msg