Введение
Примеры построения сборки:
As-Built Joint
RevoluteJointMotion
SliderJointMotion
CylindricalJointMotion
Введение
Один из наиболее важных аспектов построения сборки – соединение подвижных компонентов. Fusion 360 позволяет легко определить соединения (Joints), совмещая геометрические элементы деталей и задавая определенные степени свободы в перемещениях. В зависимости от разновидностей совмещения и перемещений различают семь типов соединений:
«Rigid» (неподвижное) фиксирует все степени свободы, т.е., два компонента неподвижно прикрепляются друг к другу (см. пример реализации через API).
«Revolute» (шарнир) имеет одну степень свободы – вращение вокруг оси. В качестве оси вращения могут быть выбраны оси X, Y и Z или любое ребро в модели. См. пример реализации через API.
«Slider» (ползун) имеет одну поступательную степень свободы. В качестве направления движения могут быть выбраны оси X, Y и Z или любое ребро в модели. См. пример реализации через API.
«Сylindrical» (цилиндрическое) имеет две степени свободы – поступательное и вращательное движения, причем одна и та же ось используется как для перемещения так и для вращения. См. пример реализации через API.
«Pin Slot» (штифт и паз) также имеет две степени свободы – поступательное и вращательное движения, но в этом случае оси могут быть различными.
«Planar» (плоское) имеет три степени свободы – поступательное в 2-х измерениях плоскости и вращательное вокруг оси, перпендикулярной этой плоскости. Пример такого соединения – хоккейная шайба, которая скользит по льду
«Ball» (шар) имеет две степени свободы вращения – вокруг взаимно перпендикулярных осей.
Примеры построения сборки
As-Built Joint
Ниже Python код демонстрирует создание простой сборки из 2х цилиндрических деталей, которые создаются в разных компонентах и неподвижно прикрепляются друг к другу (соединение «Rigid»). Последовательность работы программы отражена на рисунках.
import adsk.core, adsk.fusion, traceback def run(context): ui = None try: app = adsk.core.Application.get() ui = app.userInterface # Create a document. doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) product = app.activeProduct design = adsk.fusion.Design.cast(product) # Get the root component of the active design rootComp = design.rootComponent # Create two new components under root component allOccs = rootComp.occurrences transform = adsk.core.Matrix3D.create() subOcc0 = allOccs.addNewComponent(transform) # Create sketch 1 in sub component 1 subComp0 = subOcc0.component sketches0 = subComp0.sketches sketch0 = sketches0.add(subComp0.xZConstructionPlane) sketchCircles0 = sketch0.sketchCurves.sketchCircles centerPoint = adsk.core.Point3D.create(0, 0, 0) sketchCircles0.addByCenterRadius(centerPoint, 2.5) # Get the profile defined by the circle prof0 = sketch0.profiles.item(0) # Create an extrude input and make sure it's in the new component extrudes0 = subComp0.features.extrudeFeatures extInput0 = extrudes0.createInput(prof0, adsk.fusion.FeatureOperations.NewBodyFeatureOperation) # Set the extrude input distance0 = adsk.core.ValueInput.createByString("5 mm") extInput0.setDistanceExtent(False, distance0) extInput0.isSolid = True # Create the extrude extrude0 = extrudes0.add(extInput0) # Get the end face of the created extrude endFaceOfExtrude0 = extrude0.endFaces.item(0) # Create a construction plane for extrude 2 constructionPlanes = subComp0.constructionPlanes constructionPlaneInput = constructionPlanes.createInput() constructionPlaneInput.setByOffset(endFaceOfExtrude0, adsk.core.ValueInput.createByString("20 mm")) constructionPlane = constructionPlanes.add(constructionPlaneInput) constructionPlaneProxy = constructionPlane.createForAssemblyContext(subOcc0) # Create sketch 2 in sub component 2 subOcc1 = allOccs.addNewComponent(transform) subComp1 = subOcc1.component sketches1 = subComp1.sketches sketch1 = sketches1.add(constructionPlaneProxy) sketchCircles1 = sketch1.sketchCurves.sketchCircles sketchCircles1.addByCenterRadius(centerPoint, 0.5) # Get the profile defined by the circle prof1 = sketch1.profiles.item(0) # Create an extrude input and make sure it's in the new component extrudes1 = subComp1.features.extrudeFeatures extInput1 = extrudes1.createInput(prof1, adsk.fusion.FeatureOperations.NewBodyFeatureOperation) # Set the extrude input distance1 = adsk.core.ValueInput.createByString("50 mm") extInput1.setDistanceExtent(False, distance1) extInput1.isSolid = False # Create the extrude extrudes1.add(extInput1) # Create the AsBuiltJointInput asBuiltJoints_ = rootComp.asBuiltJoints asBuiltJointInput = asBuiltJoints_.createInput(subOcc0, subOcc1, None) # Create the AsBuiltJoint asBuiltJoints_.add(asBuiltJointInput) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Для создания сборки в программе были выполнены следующие действия:
- Создается component 1 в корневом компоненте, а в нем цилиндрическое тело – выдавливанием.
- Верхняя грань 1-го цилиндра ( extrude feature обеспечивает EndFaces ) используется для конструкционной плоскости constructionPlaneProxy, в которой будет создаваться эскиз и профиль для выдавливания другого цилиндра.
- Создается component 2 в корневом компоненте, а в нем – второй цилиндр.
- Создается соединение (AsBuiltJoint) между 2-я вхождениями (subOcc0 и subOcc1) .
RevoluteJointMotion
Ниже Python код демонстрирует создание соединения «Revolute» (шарнир) для цилиндра. Цилиндр имеет одну степень свободы – вращение вокруг горизонтальной оси.
Последовательность работы программы отражена на рисунках.
import adsk.core, adsk.fusion, traceback def run(context): ui = None try: app = adsk.core.Application.get() ui = app.userInterface # Create a document. doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) product = app.activeProduct design = adsk.fusion.Design.cast(product) # Get the root component of the active design rootComp = design.rootComponent # Create sketch in root component sketches = rootComp.sketches sketch = sketches.add(rootComp.xZConstructionPlane) sketchCircles = sketch.sketchCurves.sketchCircles centerPoint0 = adsk.core.Point3D.create(0, 0, 0) circle0 = sketchCircles.addByCenterRadius(centerPoint0, 5.0) centerPoint1 = adsk.core.Point3D.create(10, 10, 0) circle1 = sketchCircles.addByCenterRadius(centerPoint1, 5.0) # Get the profile defined by the circle prof0 = sketch.profiles.item(0) prof1 = sketch.profiles.item(1) # Create an extrusion input and make sure it's in a new component extrudes = rootComp.features.extrudeFeatures extInput = extrudes.createInput(prof0, adsk.fusion.FeatureOperations.NewComponentFeatureOperation) # Set the extrusion input distance = adsk.core.ValueInput.createByReal(5) extInput.setDistanceExtent(True, distance) extInput.isSolid = True # Create the extrusion ext = extrudes.add(extInput) # Get the side face of the created extrusion body sideFace = ext.sideFaces.item(0) # Create the first joint geometry with the side face geo0 = adsk.fusion.JointGeometry.createByNonPlanarFace(sideFace, adsk.fusion.JointKeyPointTypes.StartKeyPoint) # Create the second joint geometry with prof1 geo1 = adsk.fusion.JointGeometry.createByProfile(prof1, circle1, adsk.fusion.JointKeyPointTypes.CenterKeyPoint) # Create joint input joints = rootComp.joints jointInput = joints.createInput(geo0, geo1) # Set the joint input angle = adsk.core.ValueInput.createByString('90 deg') jointInput.angle = angle offset = adsk.core.ValueInput.createByString('1 cm') jointInput.offset = offset jointInput.isFlipped = True jointInput.setAsRevoluteJointMotion(adsk.fusion.JointDirections.YAxisJointDirection) # Create the joint joint = joints.add(jointInput) revoluteMotion = joint.jointMotion limits = revoluteMotion.rotationLimits limits.isMinimumValueEnabled = True limits.minimumValue = 3.14 / 3 limits.isMaximumValueEnabled = True limits.maximumValue = 3.14 / 3 * 2 except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Для создания сборки в программе были выполнены следующие действия:
- Создается эскиз с 2-я окружностями в плоскости XZ корневого компонента.
- Профиль одной из окружностей (prof0) используется для выдавливания цилиндра и создания тела в новом компоненте.
- Ось боковой поверхности цилиндра (sideFace) с началом (StartKeyPoint)используется для создания первой соединительной геометрии (geo0).
- Центр (CenterKeyPoint) второй окружности (prof1, circle1) используем для создания второй joint геометрии (geo1).
- Создается соединение в соответствии с joint input данными – угол (90 deg ), параллельное смещение (1 см) и ось вращения.
- Устанавливаются параметры соединения – минимальный и максимальный углы поворота цилиндра.
SliderJointMotion
Ниже Python код демонстрирует создание соединения «Slider» для цилиндра. Цилиндр имеет одну степень свободы – перемещение вдоль вертикальной оси от заданной точки. Последовательность работы программы отражена на рисунках.
import adsk.core, adsk.fusion, traceback def run(context): ui = None try: app = adsk.core.Application.get() ui = app.userInterface # Create a document. doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) product = app.activeProduct design = adsk.fusion.Design.cast(product) # Get the root component of the active design rootComp = design.rootComponent # Create sketch in root component sketches = rootComp.sketches sketch = sketches.add(rootComp.xZConstructionPlane) sketchPts = sketch.sketchPoints point = adsk.core.Point3D.create(1, 0, 1) sketchPt = sketchPts.add(point) sketchCircles = sketch.sketchCurves.sketchCircles centerPoint = adsk.core.Point3D.create(0, 0, 0) circle = sketchCircles.addByCenterRadius(centerPoint, 5.0) # Get the profile defined by the circle prof = sketch.profiles.item(0) # Create an extrusion input and make sure it's in a new component extrudes = rootComp.features.extrudeFeatures extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewComponentFeatureOperation) # Set the extrusion input distance = adsk.core.ValueInput.createByReal(5) extInput.setDistanceExtent(True, distance) extInput.isSolid = True # Create the extrusion ext = extrudes.add(extInput) # Get the end face of the created extrusion body endFace = ext.endFaces.item(0) # Get the occurrence of the new component occ = rootComp.occurrences.item(0) # Create a new sketch in the occurrence sketchInOcc = sketches.add(endFace, occ) # Get the sketch curve projected to the sketch curve = sketchInOcc.sketchCurves.item(0) # Create the first joint geometry with the sketch curve geo0 = adsk.fusion.JointGeometry.createByCurve(curve, adsk.fusion.JointKeyPointTypes.CenterKeyPoint) # Create the second joint geometry with sketch point geo1 = adsk.fusion.JointGeometry.createByPoint(sketchPt) # Create joint input joints = rootComp.joints jointInput = joints.createInput(geo0, geo1) # Set the joint input jointInput.setAsSliderJointMotion(adsk.fusion.JointDirections.ZAxisJointDirection) # Create the joint joint = joints.add(jointInput) sliderMotion = joint.jointMotion limits = sliderMotion.slideLimits limits.isRestValueEnabled = True limits.restValue = 1.0 except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Для создания сборки в программе были выполнены следующие действия:
- Создается эскиз в плоскости XZ корневого компонента. В нем отображаются точка sketchPt и окружность circle, из которой получаем профиль.
- Создается новый компонент, а в нем – тело цилиндра, полученное выдавливанием профиля окружности.
- Получаем верхнюю грань цилиндра endFace и вхождение нового компонента occ. Используя грань endFace, создаем эскиз sketchInOcc во вхождении occ. Получаем эскиз curve, в который проецируется окружность на эскизе sketchInOcc.
- Создаются объекты geo0 и geo1 (JointGeometry), в которых задаются элементы для совмещения. При создании соединения центр окружности curve совместится с точкой sketchPt .
- Подготавливаются другие jointInput данные. В качестве направления движения выбрана вертикальная ось. Создается объект joint (соединение) и устанавливаются его параметры.
CylindricalJointMotion
Ниже Python код демонстрирует создание соединения «Cylindrical». Последовательность работы программы отражена на рисунках.
import adsk.core, adsk.fusion, traceback def run(context): ui = None try: app = adsk.core.Application.get() ui = app.userInterface # Create a document. doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) product = app.activeProduct design = adsk.fusion.Design.cast(product) # Get the root component of the active design rootComp = design.rootComponent # Create sketch in root component sketches = rootComp.sketches sketch = sketches.add(rootComp.xZConstructionPlane) sketchPts = sketch.sketchPoints point = adsk.core.Point3D.create(1, 0, 1) sketchPt = sketchPts.add(point) sketchLines = sketch.sketchCurves.sketchLines point1 = adsk.core.Point3D.create(1, 0, 2) point2 = adsk.core.Point3D.create(2, 0, 1) point1SketchSpace = sketch.modelToSketchSpace(point1) point2SketchSpace = sketch.modelToSketchSpace(point2) lines = sketchLines.addTwoPointRectangle(point1SketchSpace, point2SketchSpace) # Get the profile defined by the circle prof = sketch.profiles.item(0) # Create an extrusion input and make sure it's in a new component extrudes = rootComp.features.extrudeFeatures extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewComponentFeatureOperation) # Set the extrusion input distance = adsk.core.ValueInput.createByReal(5) extInput.setDistanceExtent(True, distance) extInput.isSolid = True # Create the extrusion ext = extrudes.add(extInput) # Get the end face of the created extrusion body endFace = ext.endFaces.item(0) # Get the occurrence of the new component occ = rootComp.occurrences.item(0) # Create a new sketch in the occurrence sketchInOcc = sketches.add(endFace, occ) # Get the sketch curve projected to the sketch curve = sketchInOcc.sketchCurves.item(0) # Create the first joint geometry with the sketch curve geo0 = adsk.fusion.JointGeometry.createByCurve(curve, adsk.fusion.JointKeyPointTypes.StartKeyPoint) # Create the second joint geometry with sketch point geo1 = adsk.fusion.JointGeometry.createByPoint(sketchPt) # Create joint input joints = rootComp.joints jointInput = joints.createInput(geo0, geo1) # Set the joint input jointInput.setAsCylindricalJointMotion(adsk.fusion.JointDirections.CustomJointDirection,curve.createForAssemblyContext(occ)) # Create the joint joint = joints.add(jointInput) cylindricalMotion = joint.jointMotion rotLimits = cylindricalMotion.rotationLimits rotLimits.isRestValueEnabled = True rotLimits.restValue = 3.14 / 3 slideLimits = cylindricalMotion.slideLimits slideLimits.isMinimumValueEnabled = True slideLimits.minimumValue = 0.1 except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Для создания соединения в программе были выполнены следующие действия:
- Создается эскиз в плоскость XZ корневого компонента. В нем отображается точка sketchPt и прямоугольник lines, из которого получаем профиль prof.
- Создается новый компонент, а в нем – тело параллелепипеда, полученное выдавливанием профиля prof.
- Получаем верхнюю грань параллелепипеда endFace и вхождение нового компонента occ. Используя грань endFace, создаем эскиз sketchInOcc во вхождении occ. Получаем эскиз curve, в который проецируется параллелепипед на эскизе sketchInOcc.
- Создаются объекты geo0 и geo1 (JointGeometry), в которых задаются элементы для совмещения. При создании соединения стартовая точка curve совместится с точкой sketchPt .
- Подготавливаются другие jointInput данные. В качестве направления движения и вращения выбрана вертикальная ось. Создается объект joint (соединение) и устанавливаются его параметры.
Контрольные задания
Задание 1
Разработать Python приложение для создания модели тележки с амортизацией колес. Вращение колес обеспечивается относительно нижних горизонтальных ребер параллелепипеда. Амортизация колес обеспечивается вдоль боковых вертикальных ребер.
Задание 2
Модифицировать Python приложение «Модель тележки» (см. задание 1) в приложение «Модель самоходной артиллерийской установки (САУ)» либо в «Модель танка»:
- В САУ верхняя часть корпуса неподвижно прикреплена к основанию (см. соединение «Rigid»). У танка верхняя часть корпуса (башня) вращается относительно вертикальной оси по центру корпусных деталей (см. соединение «Revolute»).
- В САУ ствол поворачивается в горизонтальной и вертикальной плоскостях (см. соединение «Ball»). У танка ствол поворачивается только в вертикальной плоскости (см. соединение «Revolute»).
- Колеса вращаются на цилиндрической оси (см. соединение «Revolute»), при этом ось амортизирует (см. соединение «Slider») вдоль вертикальных ребер основания. Схема зависимой подвески показана на рисунке:
- Усложненный вариант задания — использовать в сборке схему независимой подвески, самостоятельно изменив форму основания и подобрав необходимые детали и типы соединений между ними.
Порядок выполнения заданий 1 и 2
Корпус моделируется параллелепипедом – создается выдавливанием прямоугольника в корневом компоненте. Из параллелепипеда через B-Rep моделирование получаем геометрию для соединения с дисками колес — боковую грань и нижнее ребро на ней
В корневом компоненте создается компонент 1, а в нем моделируется диск колеса.
Между геометрией диска компонента 1 и геометрией параллелепипеда устанавливается соединение SliderJointMotion.
В корневом компоненте создается новое вхождение компонента 1. Из диска вхождения через B-Rep моделирование получаем геометрию для соединения. Между геометрией диска вхождения компонента 1 и геометрией параллелепипеда устанавливается соединение SliderJointMotion.
В компоненте 1 создается компонент 2, а в нем колесо. Из диска и колеса через B-Rep моделирование получаем геометрию для соединения — цилиндрические поверхности колес. Между геометрией диска и колеса устанавливается соединение RevoluteJointMotion в компоненте 1.
Ниже приводится приложение, которое создает модель тележки с 2-я колесами. Доработать это приложение, чтобы создавалась модель тележки с 4-я колесами, а затем перейти к моделированию САУ или танка.
import adsk.core, adsk.fusion, adsk.cam, traceback def run(context): ui = None try: app = adsk.core.Application.get() ui = app.userInterface # Create a document. doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) product = app.activeProduct design = adsk.fusion.Design.cast(product) # Get the root component of the active design rootComp = design.rootComponent # Create sketch in root component sketch_root = rootComp.sketches.add(rootComp.xYConstructionPlane) sketchLines = sketch_root.sketchCurves.sketchLines centerPoint = adsk.core.Point3D.create(0, 0, 0) conerPoint = adsk.core.Point3D.create(20, 10,0) rect = sketchLines.addCenterPointRectangle(centerPoint, conerPoint) # Get the profile defined by the rectangle prof_rect = sketch_root.profiles.item(0) features = rootComp.features extrudes = features.extrudeFeatures extInput = extrudes.createInput(prof_rect,adsk.fusion.FeatureOperations.NewBodyFeatureOperation) # Set the extrusion input distance = adsk.core.ValueInput.createByReal(5) extInput.setDistanceExtent(True, distance) extInput.isSolid = True # Create the extrusion. ext = extrudes.add(extInput) # Create joint geometry with body body1 = ext.bodies.item(0) face = body1.faces.item(5) edge = face.edges.item(3) geo0 = adsk.fusion.JointGeometry.createByPlanarFace(face, edge, adsk.fusion.JointKeyPointTypes.EndKeyPoint) geo01 = adsk.fusion.JointGeometry.createByPlanarFace(face, edge, adsk.fusion.JointKeyPointTypes.StartKeyPoint) # Create component 1 in root component trans = adsk.core.Matrix3D.create(); # Create component #1 Comp1 = rootComp.occurrences.addNewComponent(trans).component # Create a sketch in component #1 sketch1 = Comp1.sketches.add(Comp1.xYConstructionPlane) sketchCircles = sketch1.sketchCurves.sketchCircles centerPoint = adsk.core.Point3D.create(0, 0, 0) circle = sketchCircles.addByCenterRadius(centerPoint, 5.0) # Get the profile defined by the circle prof_circle = sketch1.profiles.item(0) # Create an extrusion input extrudes = Comp1.features.extrudeFeatures extInput = extrudes.createInput(prof_circle, adsk.fusion.FeatureOperations.NewBodyFeatureOperation) # Set the extrusion input distance = adsk.core.ValueInput.createByReal(1) extInput.setDistanceExtent(True, distance) extInput.isSolid = True # Create the extrusion ext = extrudes.add(extInput) # Get the side face of the created extrusion body sideFace = ext.sideFaces.item(0) # Create joint geometry with wheel geo_cil = adsk.fusion.JointGeometry.createByNonPlanarFace(sideFace, adsk.fusion.JointKeyPointTypes.StartKeyPoint) # Create joint wheel and body jointInput = rootComp.joints.createInput(geo_cil, geo0) jointInput.setAsSliderJointMotion(adsk.fusion.JointDirections.XAxisJointDirection) # Create the joint rootComp.joints.add(jointInput) # Create a new occurrence for the component #1 newOcc = rootComp.occurrences.addExistingComponent(Comp1, trans) body = newOcc.bRepBodies.item(0) sideFace = body.faces.item(1) # Create joint wheel and body geo_cil_new = adsk.fusion.JointGeometry.createByNonPlanarFace(sideFace, adsk.fusion.JointKeyPointTypes.StartKeyPoint) jointInput = rootComp.joints.createInput(geo_cil_new, geo01) #jointInput.setAsRevoluteJointMotion(adsk.fusion.JointDirections.ZAxisJointDirection) jointInput.setAsSliderJointMotion(adsk.fusion.JointDirections.XAxisJointDirection) # Create the joint rootComp.joints.add(jointInput) # Create component #2 in component #1 Comp2 = Comp1.occurrences.addNewComponent(trans).component # Create a sketch in component #2 sketch1 = Comp2.sketches.add(Comp1.xYConstructionPlane) sketchCircles = sketch1.sketchCurves.sketchCircles centerPoint = adsk.core.Point3D.create(0, 0, 0) circle = sketchCircles.addByCenterRadius(centerPoint, 7.0) # Get the profile defined by the circle prof_circle = sketch1.profiles.item(0) # Create an extrusion input and make sure it's in a new component extrudes = Comp2.features.extrudeFeatures extInput = extrudes.createInput(prof_circle, adsk.fusion.FeatureOperations.NewBodyFeatureOperation) # Set the extrusion input distance = adsk.core.ValueInput.createByReal(1) extInput.setDistanceExtent(True, distance) extInput.isSolid = True # Create the extrusion ext = extrudes.add(extInput) # Get the side face of the created extrusion body sideFace = ext.sideFaces.item(0) # Create the first joint geometry with wheel geo_cil1 = adsk.fusion.JointGeometry.createByNonPlanarFace(sideFace, adsk.fusion.JointKeyPointTypes.StartKeyPoint) jointInput = Comp1.joints.createInput(geo_cil, geo_cil1) jointInput.setAsRevoluteJointMotion(adsk.fusion.JointDirections.ZAxisJointDirection) # Create the joint Comp1.joints.add(jointInput) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Задание на олимпиаду по САПР
См. пример моделирования задачи автоматизированного проектирования многодисковой фрикционной муфты
Автор: Николай Свирневский