For more information on how to create an URDF, visit
our website. '
1294 | #tab3ChildInputs.addTextBoxCommandInput('fullWidth_textBox', '', message, 1, True)
1295 |
1296 | ##create thing that shows tree of links and joints
1297 | tab3ChildInputs.addBoolValueInput('createtree','Create tree', False,'', True)
1298 |
1299 | # Create a message that spans the entire width of the dialog by leaving out the "name" argument.
1300 | messaged = ''
1301 | tab3ChildInputs.addTextBoxCommandInput('debugbox', '', messaged, 10, True)
1302 |
1303 | # add group for link stuff
1304 | mylinkgroup = tab3ChildInputs.addGroupCommandInput('linkgroup', 'Link stuff' )
1305 | mylinkgroup.isVisible = False
1306 |
1307 | # Create a selection input.
1308 | selectionInput1 = mylinkgroup.children.addSelectionInput('linkselection', 'Select Link Components', 'Basic select command input')
1309 | selectionInput1.addSelectionFilter('Occurrences')
1310 | selectionInput1.setSelectionLimits(0)
1311 |
1312 | # add group for link stuff
1313 | myjointgroup = tab3ChildInputs.addGroupCommandInput('jointgroup', 'Joint stuff' )
1314 | myjointgroup.isVisible = False
1315 |
1316 | #global jtctrl
1317 | jtctrl = myjointgroup.children
1318 | allvisible = True
1319 | allenabled = False
1320 |
1321 | jtctrl.addBoolValueInput('setjoint','Set Joint', False,'', True)
1322 |
1323 | distanceValueInput = jtctrl.addDistanceValueCommandInput('distanceValueX', 'X', adsk.core.ValueInput.createByReal(0))#self.x+epsilon))
1324 | distanceValueInput.setManipulator(adsk.core.Point3D.create(0, 0, 0), adsk.core.Vector3D.create(1, 0, 0))
1325 | #return
1326 | distanceValueInput.hasMinimumValue = False
1327 | distanceValueInput.hasMaximumValue = False
1328 | distanceValueInput.isVisible = allvisible
1329 | distanceValueInput.isEnabled = allenabled
1330 |
1331 | # Create distance value input 2.
1332 | distanceValueInput2 = jtctrl.addDistanceValueCommandInput('distanceValueY', 'Y', adsk.core.ValueInput.createByReal(0))#self.y+epsilon))
1333 | distanceValueInput2.setManipulator(adsk.core.Point3D.create(0, 0, 0), adsk.core.Vector3D.create(0, 1, 0))
1334 | distanceValueInput2.hasMinimumValue = False
1335 | distanceValueInput2.hasMaximumValue = False
1336 | distanceValueInput2.isVisible = allvisible
1337 | distanceValueInput2.isEnabled = allenabled
1338 |
1339 | # Create distance value input 3.
1340 | distanceValueInput3 = jtctrl.addDistanceValueCommandInput('distanceValueZ', 'Z', adsk.core.ValueInput.createByReal(0))#self.z+epsilon))
1341 | distanceValueInput3.setManipulator(adsk.core.Point3D.create(0, 0, 0), adsk.core.Vector3D.create(0, 0, 1))
1342 | distanceValueInput3.hasMinimumValue = False
1343 | distanceValueInput3.hasMaximumValue = False
1344 | distanceValueInput3.isVisible = allvisible
1345 | distanceValueInput3.isEnabled = allenabled
1346 |
1347 | # Create angle value input 1.
1348 | angleValueInput = jtctrl.addAngleValueCommandInput('angleValueRoll', 'Roll', adsk.core.ValueInput.createByReal(0))#self.r+epsilon))
1349 | angleValueInput.setManipulator(adsk.core.Point3D.create(0, 0, 0), adsk.core.Vector3D.create(0, 1, 0), adsk.core.Vector3D.create(0, 0, 1))
1350 | angleValueInput.hasMinimumValue = False
1351 | angleValueInput.hasMaximumValue = False
1352 | angleValueInput.isVisible = allvisible
1353 | angleValueInput.isEnabled = allenabled
1354 |
1355 | # Create angle value input 2.
1356 | angleValueInput2 = jtctrl.addAngleValueCommandInput('angleValuePitch', 'Pitch', adsk.core.ValueInput.createByReal(0))#self.p+epsilon))
1357 | angleValueInput2.setManipulator(adsk.core.Point3D.create(0, 0, 0), adsk.core.Vector3D.create(0, 0, 1), adsk.core.Vector3D.create(1, 0, 0))
1358 | angleValueInput2.hasMinimumValue = False
1359 | angleValueInput2.hasMaximumValue = False
1360 | angleValueInput2.isVisible = allvisible
1361 | angleValueInput2.isEnabled = allenabled
1362 |
1363 | # Create angle value input 3.
1364 | angleValueInput3 = jtctrl.addAngleValueCommandInput('angleValueYaw', 'Yaw', adsk.core.ValueInput.createByReal(0))#self.yaw+epsilon))
1365 | angleValueInput3.setManipulator(adsk.core.Point3D.create(0, 0, 0), adsk.core.Vector3D.create(1, 0, 0), adsk.core.Vector3D.create(0, 1, 0))
1366 | angleValueInput3.hasMinimumValue = False
1367 | angleValueInput3.hasMaximumValue = False
1368 | angleValueInput3.isVisibile = allvisible
1369 | angleValueInput3.isEnabled = allenabled
1370 |
1371 |
1372 | # Create a selection input.
1373 | selectionInput2 =myjointgroup.children.addSelectionInput('jointselection', 'Select Joint', 'Basic select command input')
1374 | selectionInput2.addSelectionFilter('Joints')
1375 | selectionInput2.setSelectionLimits(1)
1376 | selectionInput2.isEnabled = False
1377 |
1378 | # Create a string value input.
1379 | parentlinkin = myjointgroup.children.addDropDownCommandInput('parentlinkname', 'Name of parent link', 1)
1380 |
1381 | childlinkin = myjointgroup.children.addDropDownCommandInput('childlinkname', 'Name of child link', 1)
1382 |
1383 |
1384 |
1385 | except:
1386 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
1387 |
1388 |
1389 | def createpaths(_ms_packagename):
1390 | folderDlg = _ui.createFolderDialog()
1391 | folderDlg.title = 'Choose location to save your URDF new package'
1392 | folderDlg.initialDirectory = os.path.join(os.path.expanduser("~"),'Documents')
1393 | dlgResult = folderDlg.showDialog()
1394 | if dlgResult != adsk.core.DialogResults.DialogOK:
1395 | _ui.messageBox('you need to select a folder!')
1396 | raise ValueError('Directory not selected. cannot continue.')
1397 | outputdir = os.path.join(folderDlg.folder,_ms_packagename)
1398 | thisscriptpath = os.path.dirname(os.path.realpath(__file__))
1399 | base_directory = os.path.abspath(outputdir)
1400 | _ui.messageBox(base_directory)
1401 | if not os.path.exists(base_directory):
1402 | os.makedirs(base_directory)
1403 | meshes_directory = os.path.join(base_directory, "meshes/")
1404 | _ui.messageBox( meshes_directory)
1405 | components_directory = os.path.join(base_directory, "components/")
1406 | _ui.messageBox(components_directory)
1407 | if not os.path.exists(meshes_directory):
1408 | os.makedirs(meshes_directory)
1409 | if not os.path.exists(components_directory):
1410 | os.makedirs(components_directory)
1411 |
1412 | filestochange = ['display.launch', 'urdf_.rviz', 'package.xml', 'CMakeLists.txt' ] ##actually urdf.rviz is the same, but i didnt want to make another method just to copy. when i have more files i need to copy i will do it.
1413 | #myfilename = 'display.launch'
1414 | for myfilename in filestochange:
1415 | # Read in the file
1416 | #_ui.messageBox(thisscriptpath)
1417 | with open( os.path.join(thisscriptpath,'resources/', myfilename), 'r') as file :
1418 | filedata = file.read()
1419 |
1420 | # Replace the target string
1421 | filedata = filedata.replace('somepackage', _ms_packagename)
1422 |
1423 | # Write the file out again
1424 | with open( os.path.join(base_directory, myfilename), 'w') as file:
1425 | file.write(filedata)
1426 | return base_directory, meshes_directory, components_directory
1427 |
1428 | thisdocsunits = ''
1429 |
1430 | class GenSTLCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
1431 | def __init__(self):
1432 | super().__init__()
1433 | def notify(self, args):
1434 | try:
1435 | global _ui, _design
1436 | _app = adsk.core.Application.get()
1437 | #_ui = _app.userInterface
1438 | product = _app.activeProduct
1439 | _design = adsk.fusion.Design.cast(product)
1440 | # # Get the command that was created.
1441 | # cmd = adsk.core.Command.cast(args.command)
1442 | #
1443 | # # Connect to the command destroyed event.
1444 | # onDestroy = GenSTLCommandDestroyHandler()
1445 | # cmd.destroy.add(onDestroy)
1446 | # _handlers.append(onDestroy)
1447 | #
1448 | # # Connect to the input changed event.
1449 | # onInputChanged = GenSTLCommandInputChangedHandler()
1450 | # cmd.inputChanged.add(onInputChanged)
1451 | # _handlers.append(onInputChanged)
1452 | #
1453 | # onExecute = GenSTLCommandExecuteHandler()
1454 | # cmd.execute.add(onExecute)
1455 | # _handlers.append(onExecute)
1456 |
1457 |
1458 |
1459 | logging.debug('starting genSTL')
1460 | # Get the root component of the active design
1461 | rootComp = _design.rootComponent
1462 |
1463 | # Create two new components under root component
1464 | allOccs = rootComp.allOccurrences
1465 |
1466 | # create a single exportManager instance
1467 | exportMgr = _design.exportManager
1468 |
1469 |
1470 | fileDlg = _ui.createFileDialog()
1471 | fileDlg.isMultiSelectEnabled = False
1472 | fileDlg.title = 'Choose location to save your STL '
1473 | fileDlg.filter = '*.stl'
1474 | fileDlg.initialDirectory = os.path.join(os.path.expanduser("~"),'Documents')
1475 | dlgResult = fileDlg.showSave()
1476 | if dlgResult != adsk.core.DialogResults.DialogOK:
1477 | _ui.messageBox('you need to select a folder!')
1478 | return
1479 |
1480 | # export the root component to printer utility
1481 | stlRootOptions = exportMgr.createSTLExportOptions(rootComp, fileDlg.filename)
1482 |
1483 | # get all available print utilities
1484 | #printUtils = stlRootOptions.availablePrintUtilities
1485 |
1486 | # export the root component to the print utility, instead of a specified file
1487 | #for printUtil in printUtils:
1488 | # stlRootOptions.sendToPrintUtility = True
1489 | # stlRootOptions.printUtility = printUtil
1490 | stlRootOptions.sendToPrintUtility = False
1491 | logging.info('saving STL file: '+ fileDlg.filename)
1492 | exportMgr.execute(stlRootOptions)
1493 | _ui.messageBox('file {} saved successfully'.format(fileDlg.filename))
1494 |
1495 | except:
1496 | logging.error('Failed:\n{}'.format(traceback.format_exc()))
1497 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
1498 |
1499 | def run(context):
1500 | try:
1501 | global _app, _ui, _design, _ms, thisdocsunits
1502 | _app = adsk.core.Application.get()
1503 | _ui = _app.userInterface
1504 | product = _app.activeProduct
1505 | _design = adsk.fusion.Design.cast(product)
1506 |
1507 | #createpaths('batatas')
1508 | thisdocsunits = _design.unitsManager.defaultLengthUnits
1509 |
1510 | #if thisdocsunits != 'm':
1511 | # _ui.messageBox('So, funny thing, I have no idea on how to set default units and set them back using this API. As far as I am aware, it is currently(18-08-2018) impossible. So you need to change this documents units to meters and also make meters default for the URDF to be generated the right way - I have to create new documents, so if you don''t change the default, it won''t work\n. Once Autodesk either responds my forum question, or fixes ExportManager or allows for non-uniform affine transformations, this will no longer be necessary. ')
1512 | # return
1513 | #a = adsk.core.Matrix3D.create()
1514 |
1515 | for handler in logging.root.handlers[:]:
1516 | logging.root.removeHandler(handler)
1517 | FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(levelname)s: %(message)s"
1518 | logging.basicConfig(filename=os.path.join(os.path.expanduser("~"),'urdfgen.log'),level=logging.DEBUG,format=FORMAT)
1519 |
1520 | workSpace = _ui.workspaces.itemById('FusionSolidEnvironment')
1521 | tbPanels = workSpace.toolbarPanels
1522 |
1523 | # global tbPanel
1524 | tbPanel = tbPanels.itemById('SolidScriptsAddinsPanel')
1525 | # if tbPanel:
1526 | # tbPanel.deleteMe()
1527 | # tbPanel = tbPanels.add('NewPanel', 'New Panel', 'SolidScriptsAddinsPanel', False)
1528 |
1529 |
1530 | # Get the existing command definition or create it if it doesn't already exist.
1531 | addlinkcmdDef = _ui.commandDefinitions.itemById('cmdInputsAddLink')
1532 | if not addlinkcmdDef:
1533 | addlinkcmdDef = _ui.commandDefinitions.addButtonDefinition('cmdInputsAddLink', 'Make URDF', 'My attempt to make an URDF.')
1534 | else:
1535 | pass
1536 |
1537 | genSTLcmdDef = _ui.commandDefinitions.itemById('cmdInputsgenSTL')
1538 | if not genSTLcmdDef:
1539 | genSTLcmdDef = _ui.commandDefinitions.addButtonDefinition('cmdInputsgenSTL', 'Generate STL', 'Generate single STL (in case some of them are incorrect/changed)')
1540 | else:
1541 | pass
1542 |
1543 | # Connect to the command created event.
1544 | onCommandCreated = AddLinkCommandCreatedHandler()
1545 | addlinkcmdDef.commandCreated.add(onCommandCreated)
1546 | _handlers.append(onCommandCreated)
1547 |
1548 | on2CommandCreated = GenSTLCommandCreatedHandler()
1549 | genSTLcmdDef.commandCreated.add(on2CommandCreated)
1550 | _handlers.append(on2CommandCreated)
1551 | #_ms.thistree = UrdfTree()
1552 | if runfrommenu:
1553 |
1554 | # will try to create a button for this guy
1555 | # but first morruca
1556 | while tbPanel.controls.itemById('cmdInputsAddLink'):
1557 | a = tbPanel.controls.itemById('cmdInputsAddLink')
1558 | a.deleteMe()
1559 |
1560 | while tbPanel.controls.itemById('cmdInputsgenSTL'):
1561 | a = tbPanel.controls.itemById('cmdInputsgenSTL')
1562 | a.deleteMe()
1563 |
1564 | tbPanel.controls.addCommand(addlinkcmdDef)
1565 | tbPanel.controls.addCommand(genSTLcmdDef)
1566 |
1567 | else:
1568 | # _ms = MotherShip()
1569 | # Execute the command definition.
1570 | addlinkcmdDef.execute()
1571 |
1572 | # Prevent this module from being terminated when the script returns, because we are waiting for event handlers to fire.
1573 | #adsk.autoTerminate(False)
1574 |
1575 | except:
1576 | #i need to close and destroy stuff otherwise Fusion crashes...
1577 | try:
1578 | logging.info("shutting down from failure or debugquit.")
1579 | # When the command is done, terminate the script
1580 | # This will release all globals which will remove all event handlers
1581 | if runfrommenu:
1582 | for handler in logging.root.handlers[:]:
1583 | handler.close()
1584 | logging.root.removeHandler(handler)
1585 |
1586 | del(_ms)
1587 | _ms = []
1588 | if runfrommenu:
1589 | pass
1590 | #adsk.terminate()
1591 | except:
1592 | _ui.messageBox('Failed in shutdown sequence!:\n{}'.format(traceback.format_exc()))
1593 | if _ui:
1594 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
1595 |
1596 | def stop(context):
1597 | global _ui,_app,_design,_handlers,_ms,runfrommenu
1598 | logging.info("stopping addin urdfgen")
1599 |
1600 | try:
1601 | workSpace = _ui.workspaces.itemById('FusionSolidEnvironment')
1602 | tbPanels = workSpace.toolbarPanels
1603 |
1604 | tbPanel = tbPanels.itemById('SolidScriptsAddinsPanel')
1605 |
1606 | #genSTLcmdDef = _ui.commandDefinitions.itemById('cmdInputsgenSTL')
1607 | #addlinkcmdDef = _ui.commandDefinitions.itemById('cmdInputsAddLink')
1608 | logging.info("stopping addin2")
1609 | if runfrommenu:
1610 | while tbPanel.controls.itemById('cmdInputsAddLink'):
1611 | logging.info("stopping addin3")
1612 | a = tbPanel.controls.itemById('cmdInputsAddLink')
1613 | a.deleteMe()
1614 |
1615 | while tbPanel.controls.itemById('cmdInputsgenSTL'):
1616 | logging.info("stopping addin4")
1617 | a = tbPanel.controls.itemById('cmdInputsgenSTL')
1618 | a.deleteMe()
1619 | logging.info("stopping addin5")
1620 | _ui.messageBox('Stop addin urdfgen')
1621 | #_app = None
1622 | #_ui = None
1623 | #_design = None
1624 |
1625 | #
1626 |
1627 | # Global set of event handlers to keep them referenced for the duration of the command
1628 | _handlers = []
1629 | _ms = []
1630 | #del(_ui,_app,_design,_handlers,_ms,runfrommenu)
1631 | #adsk.terminate()
1632 | logging.info("stopping addin6")
1633 | except:
1634 | logging.error('Failed hard while stopping:\n{}'.format(traceback.format_exc()))
1635 | if _ui:
1636 | _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
--------------------------------------------------------------------------------