Skip to content

Commit

Permalink
Utilize Fusion's Unit Manager [AARD-1773] (#1101)
Browse files Browse the repository at this point in the history
  • Loading branch information
BrandonPacewic authored Aug 22, 2024
2 parents 1da19af + ae6e78f commit a6e0219
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 200 deletions.
6 changes: 1 addition & 5 deletions exporter/SynthesisFusionAddin/src/Parser/ExporterOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
Joint,
ModelHierarchy,
PhysicalDepth,
PreferredUnits,
Wheel,
encodeNestedObjects,
makeObjectFromJson,
Expand All @@ -43,10 +42,7 @@ class ExporterOptions:
wheels: list[Wheel] = field(default_factory=list)
joints: list[Joint] = field(default_factory=list)
gamepieces: list[Gamepiece] = field(default_factory=list)
preferredUnits: PreferredUnits = field(default=PreferredUnits.IMPERIAL)

# Always stored in kg regardless of 'preferredUnits'
robotWeight: KG = field(default=0.0)
robotWeight: KG = field(default=KG(0.0))
autoCalcRobotWeight: bool = field(default=False)
autoCalcGamepieceWeight: bool = field(default=False)

Expand Down
Binary file not shown.
Binary file not shown.
24 changes: 12 additions & 12 deletions exporter/SynthesisFusionAddin/src/Types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,24 @@
from enum import Enum, EnumType
from typing import Any, TypeAlias, get_args, get_origin

import adsk.fusion

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

WheelType = Enum("WheelType", ["STANDARD", "OMNI", "MECANUM"])
SignalType = Enum("SignalType", ["PWM", "CAN", "PASSIVE"])
ExportMode = Enum("ExportMode", ["ROBOT", "FIELD"]) # Dynamic / Static export
PreferredUnits = Enum("PreferredUnits", ["METRIC", "IMPERIAL"])
ExportLocation = Enum("ExportLocation", ["UPLOAD", "DOWNLOAD"])
UnitSystem = Enum("UnitSystem", ["METRIC", "IMPERIAL"])

FUSION_UNIT_SYSTEM: dict[int, UnitSystem] = {
adsk.fusion.DistanceUnits.MillimeterDistanceUnits: UnitSystem.METRIC,
adsk.fusion.DistanceUnits.CentimeterDistanceUnits: UnitSystem.METRIC,
adsk.fusion.DistanceUnits.MeterDistanceUnits: UnitSystem.METRIC,
adsk.fusion.DistanceUnits.InchDistanceUnits: UnitSystem.IMPERIAL,
adsk.fusion.DistanceUnits.FootDistanceUnits: UnitSystem.IMPERIAL,
}


@dataclass
Expand Down Expand Up @@ -72,18 +82,8 @@ class ModelHierarchy(Enum):
SingleMesh = 3


LBS: TypeAlias = float
KG: TypeAlias = float


def toLbs(kgs: KG) -> LBS:
return LBS(round(kgs * 2.2062, 2))


def toKg(pounds: LBS) -> KG:
return KG(round(pounds / 2.2062, 2))


LBS: TypeAlias = float
PRIMITIVES = (bool, str, int, float, type(None))


Expand Down
7 changes: 0 additions & 7 deletions exporter/SynthesisFusionAddin/src/UI/ConfigCommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,12 +331,6 @@ def notify(self, args: adsk.core.CommandEventArgs) -> None:
selectedJoints, selectedWheels = jointConfigTab.getSelectedJointsAndWheels()
selectedGamepieces = gamepieceConfigTab.getGamepieces()

if generalConfigTab.exportMode == ExportMode.ROBOT:
units = generalConfigTab.selectedUnits
else:
assert generalConfigTab.exportMode == ExportMode.FIELD
units = gamepieceConfigTab.selectedUnits

exporterOptions = ExporterOptions(
str(savepath),
name,
Expand All @@ -345,7 +339,6 @@ def notify(self, args: adsk.core.CommandEventArgs) -> None:
joints=selectedJoints,
wheels=selectedWheels,
gamepieces=selectedGamepieces,
preferredUnits=units,
robotWeight=generalConfigTab.robotWeight,
autoCalcRobotWeight=generalConfigTab.autoCalculateWeight,
autoCalcGamepieceWeight=gamepieceConfigTab.autoCalculateWeight,
Expand Down
78 changes: 15 additions & 63 deletions exporter/SynthesisFusionAddin/src/UI/GamepieceConfigTab.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

from src.Logging import logFailure
from src.Parser.ExporterOptions import ExporterOptions
from src.Types import Gamepiece, PreferredUnits, toKg, toLbs
from src.UI import IconPaths
from src.Types import Gamepiece, UnitSystem
from src.UI.CreateCommandInputsHelper import (
createBooleanInput,
createTableInput,
createTextBoxInput,
)
from src.Util import convertMassUnitsFrom, convertMassUnitsTo, getFusionUnitSystem


class GamepieceConfigTab:
Expand All @@ -19,7 +19,6 @@ class GamepieceConfigTab:
gamepieceTable: adsk.core.TableCommandInput
previousAutoCalcWeightCheckboxState: bool
previousSelectedUnitDropdownIndex: int
currentUnits: PreferredUnits

@logFailure
def __init__(self, args: adsk.core.CommandCreatedEventArgs, exporterOptions: ExporterOptions) -> None:
Expand All @@ -37,20 +36,6 @@ def __init__(self, args: adsk.core.CommandCreatedEventArgs, exporterOptions: Exp
)
self.previousAutoCalcWeightCheckboxState = exporterOptions.autoCalcGamepieceWeight

self.currentUnits = exporterOptions.preferredUnits
imperialUnits = self.currentUnits == PreferredUnits.IMPERIAL
weightUnitTable = gamepieceTabInputs.addDropDownCommandInput(
"gamepieceWeightUnit", "Unit of Mass", adsk.core.DropDownStyles.LabeledIconDropDownStyle
)

# Invisible white space characters are required in the list item name field to make this work.
# I have no idea why, Fusion API needs some special education help - Brandon
weightUnitTable.listItems.add("‎", imperialUnits, IconPaths.massIcons["LBS"])
weightUnitTable.listItems.add("‎", not imperialUnits, IconPaths.massIcons["KG"])
weightUnitTable.tooltip = "Unit of mass"
weightUnitTable.tooltipDescription = "<hr>Configure the unit of mass for for the weight calculation."
self.previousSelectedUnitDropdownIndex = int(not imperialUnits)

self.gamepieceTable = createTableInput(
"gamepieceTable",
"Gamepiece",
Expand All @@ -62,8 +47,17 @@ def __init__(self, args: adsk.core.CommandCreatedEventArgs, exporterOptions: Exp
self.gamepieceTable.addCommandInput(
createTextBoxInput("gamepieceNameHeader", "Name", gamepieceTabInputs, "Name", bold=False), 0, 0
)
fusUnitSystem = getFusionUnitSystem()
self.gamepieceTable.addCommandInput(
createTextBoxInput("gamepieceWeightHeader", "Weight", gamepieceTabInputs, "Weight", bold=False), 0, 1
createTextBoxInput(
"gamepieceWeightHeader",
"Weight",
gamepieceTabInputs,
f"Weight {'(lbs)' if fusUnitSystem is UnitSystem.IMPERIAL else '(kg)'}",
bold=False,
),
0,
1,
)
self.gamepieceTable.addCommandInput(
createTextBoxInput(
Expand Down Expand Up @@ -112,10 +106,6 @@ def isVisible(self, value: bool) -> None:
def isActive(self) -> bool:
return self.gamepieceConfigTab.isActive or False

@property
def selectedUnits(self) -> PreferredUnits:
return self.currentUnits

@property
def autoCalculateWeight(self) -> bool:
autoCalcWeightButton: adsk.core.BoolValueCommandInput = self.gamepieceConfigTab.children.itemById(
Expand Down Expand Up @@ -168,26 +158,13 @@ def addChildOccurrences(childOccurrences: adsk.fusion.OccurrenceList) -> None:
frictionCoefficient.valueOne = 0.5

physical = gamepiece.component.getPhysicalProperties(adsk.fusion.CalculationAccuracy.LowCalculationAccuracy)
if self.currentUnits == PreferredUnits.IMPERIAL:
gamepieceMass = toLbs(physical.mass)
else:
gamepieceMass = round(physical.mass, 2)

gamepieceMass = round(convertMassUnitsFrom(physical.mass), 2)
weight = commandInputs.addValueInput(
"gamepieceWeight", "Weight Input", "", adsk.core.ValueInput.createByString(str(gamepieceMass))
)
weight.tooltip = "Weight of field element"
weight.isEnabled = not self.previousAutoCalcWeightCheckboxState

weightUnitDropdown: adsk.core.DropDownCommandInput = self.gamepieceConfigTab.children.itemById(
"gamepieceWeightUnit"
)
if weightUnitDropdown.selectedItem.index == 0:
weight.tooltipDescription = "<tt>(in pounds)</tt>"
else:
assert weightUnitDropdown.selectedItem.index == 1
weight.tooltipDescription = "<tt>(in kilograms)</tt>"

row = self.gamepieceTable.rowCount
self.gamepieceTable.addCommandInput(gamepieceName, row, 0)
self.gamepieceTable.addCommandInput(weight, row, 1)
Expand Down Expand Up @@ -222,7 +199,7 @@ def getGamepieces(self) -> list[Gamepiece]:
gamepieces: list[Gamepiece] = []
for row in range(1, self.gamepieceTable.rowCount): # Row is 1 indexed
gamepieceEntityToken = self.selectedGamepieceList[row - 1].entityToken
gamepieceWeight = self.gamepieceTable.getInputAtPosition(row, 1).value
gamepieceWeight = convertMassUnitsTo(self.gamepieceTable.getInputAtPosition(row, 1).value)
gamepieceFrictionCoefficient = self.gamepieceTable.getInputAtPosition(row, 2).valueOne
gamepieces.append(Gamepiece(gamepieceEntityToken, gamepieceWeight, gamepieceFrictionCoefficient))

Expand All @@ -232,25 +209,14 @@ def reset(self) -> None:
self.selectedGamepieceEntityIDs.clear()
self.selectedGamepieceList.clear()

@logFailure
def updateWeightTableToUnits(self, units: PreferredUnits) -> None:
assert units in {PreferredUnits.METRIC, PreferredUnits.IMPERIAL}
conversionFunc = toKg if units == PreferredUnits.METRIC else toLbs
for row in range(1, self.gamepieceTable.rowCount): # Row is 1 indexed
weightInput: adsk.core.ValueCommandInput = self.gamepieceTable.getInputAtPosition(row, 1)
weightInput.value = conversionFunc(weightInput.value)

@logFailure
def calcGamepieceWeights(self) -> None:
for row in range(1, self.gamepieceTable.rowCount): # Row is 1 indexed
weightInput: adsk.core.ValueCommandInput = self.gamepieceTable.getInputAtPosition(row, 1)
physical = self.selectedGamepieceList[row - 1].component.getPhysicalProperties(
adsk.fusion.CalculationAccuracy.LowCalculationAccuracy
)
if self.currentUnits == PreferredUnits.IMPERIAL:
weightInput.value = toLbs(physical.mass)
else:
weightInput.value = round(physical.mass, 2)
weightInput.value = round(convertMassUnitsFrom(physical.mass), 2)

@logFailure
def handleInputChanged(
Expand Down Expand Up @@ -283,20 +249,6 @@ def handleInputChanged(

self.previousAutoCalcWeightCheckboxState = autoCalcWeightButton.value

elif commandInput.id == "gamepieceWeightUnit":
weightUnitDropdown = adsk.core.DropDownCommandInput.cast(commandInput)
if weightUnitDropdown.selectedItem.index == self.previousSelectedUnitDropdownIndex:
return

if weightUnitDropdown.selectedItem.index == 0:
self.currentUnits = PreferredUnits.IMPERIAL
else:
assert weightUnitDropdown.selectedItem.index == 1
self.currentUnits = PreferredUnits.METRIC

self.updateWeightTableToUnits(self.currentUnits)
self.previousSelectedUnitDropdownIndex = weightUnitDropdown.selectedItem.index

elif commandInput.id == "gamepieceAddButton":
gamepieceSelection.isVisible = gamepieceSelection.isEnabled = True
gamepieceSelection.clearSelection()
Expand Down
Loading

0 comments on commit a6e0219

Please sign in to comment.