Skip to content

Commit

Permalink
Working wheel and weight design save
Browse files Browse the repository at this point in the history
  • Loading branch information
BrandonPacewic committed Jun 20, 2024
1 parent 0cd2e39 commit 93baef6
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 72 deletions.
63 changes: 28 additions & 35 deletions exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
""" ParserOptions
- This module targets the creation of the parser used for actually parsing the data
- Since the parsing can be recursive you can pass a low overhead options construction into each function to detail the parsing
- Should have factory methods to convert from a given configuration possibly
- or maybe a configuration should replace this im not certain
- this is essentially a flat configuration file with non serializable objects
"""
Container for all options pertaining to the Fusion Exporter.
These options are saved per-design and are passed to the parser upon design export.
"""

import json
Expand All @@ -17,11 +13,13 @@

from ..strings import INTERNAL_ID

# Not 100% sure what this is for - Brandon
JointParentType = Enum("JointParentType", ["ROOT", "END"])

JointParentType = Enum("JointParentType", ["ROOT", "END"]) # Not 100% sure what this is for - Brandon
WheelType = Enum("WheelType", ["STANDARD", "OMNI"])
SignalType = Enum("SignalType", ["PWM", "CAN", "PASSIVE"])
ExportMode = Enum("ExportMode", ["ROBOT", "FIELD"]) # Dynamic / Static export
ExportMode = Enum("ExportMode", ["ROBOT", "FIELD"]) # Dynamic / Static export
PreferredUnits = Enum("PreferredUnits", ["METRIC", "IMPERIAL"])


@dataclass
Expand All @@ -38,7 +36,7 @@ class Joint:
signalType: SignalType = field(default=None)
speed: float = field(default=None)
force: float = field(default=None)


@dataclass
class Gamepiece:
Expand All @@ -48,39 +46,30 @@ class Gamepiece:


class PhysicalDepth(Enum):
"""
Depth at which the Physical Properties are generated and saved
This is mostly dictated by export type as flattening or any hierarchical modification takes precedence
"""

""" No Physical Properties are generated """
# No Physical Properties are generated
NoPhysical = 0

""" Only Body Physical Objects are generated """
# Only Body Physical Objects are generated
Body = 1

""" Only Occurrence that contain Bodies and Bodies have Physical Properties """
# Only Occurrence that contain Bodies and Bodies have Physical Properties
SurfaceOccurrence = 2

""" Every Single Occurrence has Physical Properties even if empty """
# Every Single Occurrence has Physical Properties even if empty
AllOccurrence = 3


class ModelHierarchy(Enum):
"""
Enum Class to describe how the model format should look on export to suit different needs
"""

""" Model exactly as it is shown in Fusion 360 in the model view tree """
# Model exactly as it is shown in Fusion 360 in the model view tree
FusionAssembly = 0

""" Flattened Assembly with all bodies as children of the root object """
# Flattened Assembly with all bodies as children of the root object
FlatAssembly = 1

""" A Model represented with parented objects that are part of a jointed tree """
# A Model represented with parented objects that are part of a jointed tree
PhysicalAssembly = 2

""" Generates the root assembly as a single mesh and stores the associated data """
# Generates the root assembly as a single mesh and stores the associated data
SingleMesh = 3


Expand All @@ -95,14 +84,19 @@ class ExporterOptions:
wheels: list[Wheel] = field(default=None)
joints: list[Joint] = field(default=None)
gamepieces: list[Gamepiece] = field(default=None)
robotWeight: float = field(default=0.0) # kg
preferredUnits: PreferredUnits = field(default=PreferredUnits.IMPERIAL)
robotWeight: float = field(default=0.0) # Always stored in kg regardless of 'preferredUnits'
compressOutput: bool = field(default=True)
exportAsPart: bool = field(default=False)

hierarchy: ModelHierarchy = field(default=ModelHierarchy.FusionAssembly)
visualQuality: TriangleMeshQualityOptions = field(default=TriangleMeshQualityOptions.LowQualityTriangleMesh)
visualQuality: TriangleMeshQualityOptions = field(
default=TriangleMeshQualityOptions.LowQualityTriangleMesh
)
physicalDepth: PhysicalDepth = field(default=PhysicalDepth.AllOccurrence)
physicalCalculationLevel: CalculationAccuracy = field(default=CalculationAccuracy.LowCalculationAccuracy)
physicalCalculationLevel: CalculationAccuracy = field(
default=CalculationAccuracy.LowCalculationAccuracy
)

def read(self) -> None:
designAttributes = adsk.core.Application.get().activeProduct.attributes
Expand Down Expand Up @@ -143,16 +137,15 @@ def write(self) -> None:
# TODO: There should be a way to clean this up - Brandon
def _makeObjectFromJson(self, objectType: type, data: any) -> any:
primitives = (bool, str, int, float, type(None))
if (
if isinstance(objectType, EnumType):
return objectType(data)
elif (
objectType in primitives or type(data) in primitives
): # Required to catch `fusion.TriangleMeshQualityOptions`
return data
elif isinstance(objectType, EnumType):
return objectType(data)
elif get_origin(objectType) is list:
return [
self._makeObjectFromJson(objectType.__args__[0], item)
for item in data
self._makeObjectFromJson(objectType.__args__[0], item) for item in data
]

newObject = objectType()
Expand Down
13 changes: 10 additions & 3 deletions exporter/SynthesisFusionAddin/src/Parser/SynthesisParser/Joints.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,19 @@ def populateJoints(

# really could just map the enum to a friggin string
if (
parse_joints.signalType != ExporterOptions.SignalType.PASSIVE
parse_joints.signalType
!= ExporterOptions.SignalType.PASSIVE
and assembly.dynamic
):
if parse_joints.signalType == ExporterOptions.SignalType.CAN:
if (
parse_joints.signalType
== ExporterOptions.SignalType.CAN
):
signal.device_type = signal_pb2.DeviceType.CANBUS
elif parse_joints.signalType == ExporterOptions.SignalType.PWM:
elif (
parse_joints.signalType
== ExporterOptions.SignalType.PWM
):
signal.device_type = signal_pb2.DeviceType.PWM

motor = joints.motor_definitions[joint.entityToken]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .Utilities import *
from .. import ExporterOptions


class Parser:
def __init__(self, options: ExporterOptions):
"""Creates a new parser with the supplied options
Expand All @@ -37,7 +38,9 @@ def export(self) -> bool:
)

# set int to 0 in dropdown selection for dynamic
assembly_out.dynamic = self.exporterOptions.exportMode == ExporterOptions.ExportMode.ROBOT
assembly_out.dynamic = (
self.exporterOptions.exportMode == ExporterOptions.ExportMode.ROBOT
)

# Physical Props here when ready

Expand Down
72 changes: 39 additions & 33 deletions exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
Joint,
Wheel,
JointParentType,
PreferredUnits,
)
from .Configuration.SerialCommand import SerialCommand

Expand Down Expand Up @@ -162,6 +163,7 @@ def __init__(self, configure):
def notify(self, args):
try:
exporterOptions = ExporterOptions().read()
# exporterOptions = ExporterOptions()

if not Helper.check_solid_open():
return
Expand All @@ -172,14 +174,6 @@ def notify(self, args):
NOTIFIED = True
write_configuration("analytics", "notified", "yes")

# Transition: AARD-1687
# designCompress = self.designAttrs.itemByName("SynthesisExporter", "compress")
# global compress
# if designCompress:
# compress = True if designCompress.value == "True" else False
# else:
# compress = True

if A_EP:
A_EP.send_view("export_panel")

Expand Down Expand Up @@ -226,9 +220,7 @@ def notify(self, args):
dropDownStyle=adsk.core.DropDownStyles.LabeledIconDropDownStyle,
)

# TODO
# dynamic = exporterOptions.exportMode == ExporterOptions.ExportMode.ROBOT
dynamic = True
dynamic = exporterOptions.exportMode == ExportMode.ROBOT
dropdownExportMode.listItems.add("Dynamic", dynamic)
dropdownExportMode.listItems.add("Static", not dynamic)

Expand Down Expand Up @@ -271,11 +263,18 @@ def notify(self, args):
auto_calc_weight.resourceFolder = IconPaths.stringIcons["calculate-enabled"]
auto_calc_weight.isFullWidth = True

imperialUnits = exporterOptions.preferredUnits == PreferredUnits.IMPERIAL
if imperialUnits:
# ExporterOptions always contains the metric value
displayWeight = exporterOptions.robotWeight * 2.2046226218
else:
displayWeight = exporterOptions.robotWeight

weight_input = inputs.addValueInput(
"weight_input",
"Weight Input",
"",
adsk.core.ValueInput.createByString("0.0"), # TODO
adsk.core.ValueInput.createByReal(displayWeight),
)
weight_input.tooltip = "Robot weight"
weight_input.tooltipDescription = """<tt>(in pounds)</tt><hr>This is the weight of the entire robot assembly."""
Expand All @@ -285,11 +284,12 @@ def notify(self, args):
"Weight Unit",
adsk.core.DropDownStyles.LabeledIconDropDownStyle,
)

weight_unit.listItems.add(
"‎", True, IconPaths.massIcons["LBS"]
"‎", imperialUnits, IconPaths.massIcons["LBS"]
) # add listdropdown mass options
weight_unit.listItems.add(
"‎", False, IconPaths.massIcons["KG"]
"‎", not imperialUnits, IconPaths.massIcons["KG"]
) # add listdropdown mass options
weight_unit.tooltip = "Unit of mass"
weight_unit.tooltipDescription = (
Expand Down Expand Up @@ -401,6 +401,11 @@ def notify(self, args):
3,
)

for wheel in exporterOptions.wheels:
wheelEntity = gm.app.activeDocument.design.findEntityByToken(wheel.jointToken)[0]
typeWheel = type(wheelEntity)
addWheelToTable(wheelEntity)

# ~~~~~~~~~~~~~~~~ JOINT CONFIGURATION ~~~~~~~~~~~~~~~~
"""
Joint configuration group. Container for joint selection table
Expand Down Expand Up @@ -530,6 +535,7 @@ def notify(self, args):
5,
)

# Fill the table with all joints in current design
for joint in list(
gm.app.activeDocument.design.rootComponent.allJoints
) + list(gm.app.activeDocument.design.rootComponent.allAsBuiltJoints):
Expand Down Expand Up @@ -710,7 +716,7 @@ def notify(self, args):
"compress",
"Compress Output",
exporter_settings,
checked=compress,
checked=exporterOptions.compressOutput,
tooltip="Compress the output file for a smaller file size.",
tooltipadvanced="<hr>Use the GZIP compression system to compress the resulting file which will be opened in the simulator, perfect if you want to share the file.<br>",
enabled=True,
Expand All @@ -720,7 +726,7 @@ def notify(self, args):
"export_as_part",
"Export As Part",
exporter_settings,
checked=False,
checked=exporterOptions.exportAsPart,
tooltip="Use to export as a part for Mix And Match",
enabled=True,
)
Expand Down Expand Up @@ -1078,10 +1084,6 @@ def notify(self, args):
.children.itemById("exporter_settings")
.children.itemById("export_as_part")
).value
# parserOptions.exportAsPart = export_as_part_boolean

# Transition: AARD-1687
# self.designAttrs.add("SynthesisExporter", "export_as_part", str(export_as_part_boolean.value))

processedFileName = gm.app.activeDocument.name.replace(" ", "_")
dropdownExportMode = INPUTS_ROOT.itemById("mode")
Expand All @@ -1090,9 +1092,6 @@ def notify(self, args):
elif dropdownExportMode.selectedItem.index == 1:
isRobot = False

# Transition: AARD-1687
# self.designAttrs.add("SynthesisExporter", "mode", str(isRobot))

if platform.system() == "Windows":
if isRobot:
if export_as_part_boolean:
Expand Down Expand Up @@ -1183,8 +1182,8 @@ def notify(self, args):
_exportWheels.append(
Wheel(
WheelListGlobal[row - 1].entityToken,
wheelTypeIndex,
signalTypeIndex,
wheelTypeIndex + 1, # TODO: More explicit conversion to 'enum' - Brandon
signalTypeIndex + 1, # TODO: More explicit conversion to 'enum' - Brandon
# onSelect.wheelJointList[row-1][0] # GUID of wheel joint. if no joint found, default to None
)
)
Expand Down Expand Up @@ -1220,7 +1219,7 @@ def notify(self, args):
Joint(
JointListGlobal[row - 1].entityToken,
JointParentType.ROOT,
signalTypeIndex, # index of selected signal in dropdown
signalTypeIndex + 1, # TODO: More explicit conversion to 'Enum' - Brandon
jointSpeed,
jointForce / 100.0,
) # parent joint GUID
Expand All @@ -1244,7 +1243,7 @@ def notify(self, args):
Joint(
JointListGlobal[row - 1].entityToken,
parentJointToken,
signalTypeIndex,
signalTypeIndex + 1, # TODO: More explicit conversion to 'Enum' - Brandon
jointSpeed,
jointForce,
)
Expand Down Expand Up @@ -1285,8 +1284,10 @@ def notify(self, args):
weight_unit = INPUTS_ROOT.itemById("weight_unit")

if weight_unit.selectedItem.index == 0:
selectedUnits = PreferredUnits.IMPERIAL
_robotWeight = float(weight_input.value) / 2.2046226218
else:
selectedUnits = PreferredUnits.METRIC
_robotWeight = float(weight_input.value)

"""
Expand All @@ -1305,9 +1306,6 @@ def notify(self, args):
.children.itemById("compress")
).value

# Transition: AARD-1687
# self.designAttrs.add("SynthesisExporter", "compress", str(compress))

exporterOptions = ExporterOptions(
savepath,
name,
Expand All @@ -1316,13 +1314,14 @@ def notify(self, args):
joints=_exportJoints,
wheels=_exportWheels,
gamepieces=_exportGamepieces,
preferredUnits=selectedUnits,
robotWeight=_robotWeight,
exportMode=_mode,
compressOutput=compress,
)
exporterOptions.write()

Parser(exporterOptions).export()
exporterOptions.write()
except:
if gm.ui:
gm.ui.messageBox("Failed:\n{}".format(traceback.format_exc()))
Expand Down Expand Up @@ -2347,7 +2346,15 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None:
wheel (adsk.fusion.Occurrence): wheel Occurrence object to be added.
"""
try:
onSelect = gm.handlers[3]
try:
onSelect = gm.handlers[3]
onSelect.allWheelPreselections.append(wheel.entityToken)
except IndexError:
# Not 100% sure what we need the select handler here for however it should not run when
# first populating the saved wheel configs. This will naturally throw a IndexError as
# we do this before the initialization of gm.handlers[]
pass

wheelTableInput = wheelTable()
# def addPreselections(child_occurrences):
# for occ in child_occurrences:
Expand All @@ -2359,7 +2366,6 @@ def addWheelToTable(wheel: adsk.fusion.Joint) -> None:
# if wheel.childOccurrences:
# addPreselections(wheel.childOccurrences)
# else:
onSelect.allWheelPreselections.append(wheel.entityToken)

WheelListGlobal.append(wheel)
cmdInputs = adsk.core.CommandInputs.cast(wheelTableInput.commandInputs)
Expand Down

0 comments on commit 93baef6

Please sign in to comment.