Python and Catia V5 Defining axis for volumic operations - python

I am trying to do Catia V5 automation using python. I managed to create my baseline sketch without any problem however, I am unable to set axis for volumic operations. Here is a simple example that (should) create a round ball by revolving around the global Z axis :
import os
from win32com.client import Dispatch
CATIA = Dispatch('CATIA.Application')
CATIA.Visible = True
from pathlib import Path
# Creating the part and the sketch
partDocument1 = CATIA.Documents.Add("Part")
part1 = partDocument1.Part
bodies1 = part1.Bodies
body1 = bodies1.Item("PartBody")
sketches1 = body1.Sketches
originElements1 = part1.OriginElements
reference1 = originElements1.PlaneYZ
sketch1 = sketches1.Add(reference1)
# Creating the baseline sketch
sketch1.OpenEdition()
geometricElements1 = sketch1.GeometricElements
axis2D1 = geometricElements1.Item("AbsoluteAxis")
circle2D1 = sketch1.Factory2D.CreateCircle(0.000000, 0.000000, 100, 1.570796, 4.712389)
# Volumic operation
shapeFactory1 = part1.ShapeFactory
reference8 = part1.CreateReferenceFromName("")
shaft1 = shapeFactory1.AddNewShaftFromRef(reference8)
reference9 = part1.CreateReferenceFromObject(sketch1)
shaft1.SetProfileElement(reference9)
hybridShapes1 = body1.HybridShapes
hybridShapeLineExplicit1 = hybridShapes1.Item("Z Axis")
reference10 = part1.CreateReferenceFromObject(hybridShapeLineExplicit1)
shaft1.RevoluteAxis = reference10
part1.UpdateObject(shaft1)
part1.Update()
And here is the traceback :
hybridShapeLineExplicit1 = hybridShapes1.Item("Z Axis")
File "<COMObject <unknown>>", line 2, in Item
I think my problem comes from the fact that this axis is located "outside" the sketch used for the shaft. I dont know how to define an axis in this python "vba-like" code.
Could you help me ?
Thank you very much !

Related

Pydrake: Creating a Trajectory Source for RigidTransformations

I've been trying to create a TrajectorySource for RigidTransforms to pass into a DifferentialInverseKinematicsIntegrator which only takes in RigidTransforms in its input port.
def createTraj(time, pose):
times = []
poses = []
for step in time:
times.append(time[step])
poses.append(pose[step])
return PiecewisePose.MakeLinear(times, poses)
Initially, I tried to directly pass in the output from createTraj above into TrajectorySource but ran into the issue of my trajectory having more than one columns: Failure at systems/primitives/trajectory_source.cc:21 in TrajectorySource(): condition 'trajectory.cols() == 1' failed.
import matplotlib.pyplot as plt, mpld3
class DexterTest():
# Output from createTraj is passed as parameter: traj into constructor
def __init__(self, traj):
builder = DiagramBuilder()
self.station = DexterPPStation(1e-4, "/opt/drake/share/drake/manipulation/models/final_dexter_description/urdf/dexter.urdf")
self.station.CreateBins("/opt/drake/share/drake/examples/manipulation_station/models/bin.sdf", RigidTransform(np.array([0.5,0,0])), RigidTransform(np.array([0,0.5,0])))
self.station.CreateRandomPickingObjects(3)
self.station.AddDexter()
builder.AddSystem(self.station)
self.station.Finalize()
self.diff_ik = DifferentialInverseKinematicsIntegrator(self.station.controller_plant, self.station.plant.GetFrameByName("link6", self.station.dexter["instance"]), self.station.time_step, DifferentialInverseKinematicsParameters(7,7))
builder.AddSystem(self.diff_ik)
#=========================================== Likely Source of Error ===========================================
pose = builder.AddSystem(PoseSystem())
p_G_source = builder.AddSystem(TrajectorySource(traj.get_position_trajectory()))
w_G_source = builder.AddSystem(TrajectorySource(traj.get_orientation_trajectory()))
builder.Connect(p_G_source.get_output_port(), pose.GetInputPort("p_G"))
builder.Connect(w_G_source.get_output_port(), pose.GetInputPort("r_G"))
builder.Connect(pose.get_output_port(), self.diff_ik.get_input_port())
#======================================================================================
MeshcatVisualizerCpp.AddToBuilder(builder, self.station.GetOutputPort("query_object"), meshcat)
self.diagram = builder.Build()
self.simulator = Simulator(self.diagram)
self.diagram_context = self.simulator.get_mutable_context()
self.station_context = self.station.GetMyMutableContextFromRoot(self.diagram_context)
self.plant_context = self.station.GetSubsystemContext(self.station.plant, self.station_context)
self.station.SetRandomPoses(self.plant_context)
builder.Connect(self.diff_ik.get_output_port(), self.station.GetInputPort("dexter_position"))
def run(self):
self.simulator.set_target_realtime_rate(2.0)
self.simulator.AdvanceTo(1)
class PoseSystem(LeafSystem):
def __init__(self):
LeafSystem.__init__(self)
self.p_G = self.DeclareVectorInputPort("p_G", BasicVector(3))
self.r_G = self.DeclareVectorInputPort("r_G", BasicVector(4))
self.DeclareAbstractOutputPort("X_G", Value[RigidTransform], self.CalcOutput)
def CalcOutput(self, context, output):
pose = RigidTransform(Quaternion(self.r_G.Eval(context)), self.p_G.Eval(context))
output.set_value(pose)
Instead, I tried to break up my trajectory into its orientation and position parts, add them to the input ports of a custom system, and then reconstruct them together in the output port. However, this gives me the following RuntimeError once the run method is called: RuntimeError: This multibody element does not belong to the supplied MultibodyTree.
Any help would be greatly appreciated!
I think you are very close. The PoseSystem looks like it should be a solution to the problem you've articulated in your post. (The error about MultibodyTree must be coming from the other part of your code.
You don't actually need to break the RigidTransform up into orientation / translation to create your PoseSystem, your CalcOutput could just call output.set_value(poses.Eval(t)) if poses is a PiecewisePose trajectory.
I have an example of doing this in the PickAndPlaceTrajectory class in this notebook: https://github.com/RussTedrake/manipulation/blob/008cec6343dd39063705287e6664a3fee71a43b8/pose.ipynb

How to Access WorkPlanes of Occurrences in Assemblies using the Inventor API with Python

I want to add constraints between the planes of the base-coordinate systems of components in an Inventor assmbly using the Inventor API with Python. The placement of the components works. My issue is, that i cannot access WorkPlanes in the Definition of my individual Occurrences.
My Code looks like this:
import win32com.client as win32
project_folder = "C:\\Users\\User_1\\210608_project\\"
#initialization
inv = win32.gencache.EnsureDispatch('Inventor.Application')
inv.Visible = True
#Open a new assembly
inv.Documents.Add(win32.constants.kAssemblyDocumentObject, "", True)
invActDoc = inv.ActiveDocument
invAssDoc = win32.CastTo(invActDoc, 'AssemblyDocument')
#Create the transient matrices
oTG = inv.TransientGeometry
oMatrix = oTG.CreateMatrix()
#Add component to assembly
invAssDocDef = invAssDoc.ComponentDefinition
invAssOcc = invAssDocDef.Occurrences
occ1 = invAssOcc.Add(project_folder + 'generic_part_1.ipt', oMatrix)
occ2 = invAssOcc.Add(project_folder + 'generic_part_2.ipt', oMatrix)
#create constraints
#get the Planes of the Base-Coordinate-System of Part 1
wp_YZ_1 = occ1.Definition.WorkPlanes.Item(1)
wp_XZ_1 = occ1.Definition.WorkPlanes.Item(2)
wp_XY_1 = occ1.Definition.WorkPlanes.Item(3)
#get the Planes of the Base-Coordinate-System of Part 2
wp_YZ_2 = occ2.Definition.WorkPlanes.Item(1)
wp_XZ_2 = occ2.Definition.WorkPlanes.Item(2)
wp_XY_2 = occ2.Definition.WorkPlanes.Item(3)
#Add the constraints
AssCons = invAssDoc.ComponentDefinition.Constraints
AssCons.AddFlushConstraint(wp_YZ_1, wp_YZ_2, 0)
AssCons.AddFlushConstraint(wp_XZ_1, wp_XZ_2, 0)
AssCons.AddFlushConstraint(wp_XY_1, wp_XY_2, 0)
It breaks when i try to get the WorkPlanes:
Traceback (most recent call last):
File "C:/Users/User1/210608_projekt/how_to_constrain_components_in_assemblies.py", line 27, in <module>
wp1 = occ1.Definition.WorkPlanes.Item(1)
File "C:\Program Files\Python37\lib\site-packages\win32com\client\__init__.py", line 473, in __getattr__
raise AttributeError("'%s' object has no attribute '%s'" % (repr(self), attr))
AttributeError: '<win32com.gen_py.Autodesk Inventor Object Library.ComponentDefinition instance at 0x2748634277928>' object has no attribute 'WorkPlanes'
This happens to everything that I tried, that is inside of Occurrence.Item(i).Definition.
If i open the same assembly in a VBA script, everything is where it should be. Am I missing something about working with occurrences using the API?
You need to create WorkPlaneProxy object of the WorkPlane. It means representation of workplane defined in part in context of specific occurrence in the assembly
Here is part of VB.NET code
'Define variables for workplane proxy
Dim wp_YZ_1_proxy As WorkPlaneProxy
Dim wp_YZ_2_proxy As WorkPlaneProxy
'You need to pass result variable as argument
' ByRef in VB.NET, out in C#
'I don't know how to do in Python
occ1.CreateGeometryProxy(wp_YZ_1, wp_YZ_1_proxy)
occ2.CreateGeometryProxy(wp_YZ_2, wp_YZ_2_proxy)
Dim AssCons As AssemblyConstraints = asm.Constraints
'Use this proxies for constraint creation
AssCons.AddFlushConstraint(wp_YZ_1_proxy, wp_YZ_2_proxy, 0)
So this is how the solution/replacement of the last 3 blocks looks like:
#cast the definitions to PartComponentDefinition
occ1_def = win32.CastTo(occ1.Definition, 'PartComponentDefinition')
occ2_def = win32.CastTo(occ2.Definition, 'PartComponentDefinition')
#create constraints
#get the Planes of the Base-Coordinate-System of Part 1
wp_YZ_1 = occ1_def.WorkPlanes.Item(1)
wp_XZ_1 = occ1_def.WorkPlanes.Item(2)
wp_XY_1 = occ1_def.WorkPlanes.Item(3)
#create Geometry-Proxys for Workplanes of Comp1
wp_YZ_1_proxy = occ1.CreateGeometryProxy(wp_YZ_1)
wp_XZ_1_proxy = occ1.CreateGeometryProxy(wp_XZ_1)
wp_XY_1_proxy = occ1.CreateGeometryProxy(wp_XY_1)
#get the Planes of the Base-Coordinate-System of Part 2
wp_YZ_2 = occ2_def.WorkPlanes.Item(1)
wp_XZ_2 = occ2_def.WorkPlanes.Item(2)
wp_XY_2 = occ2_def.WorkPlanes.Item(3)
#create Geometry-Proxys for Workplanes of Comp2
wp_YZ_2_proxy = occ2.CreateGeometryProxy(wp_YZ_2)
wp_XZ_2_proxy = occ2.CreateGeometryProxy(wp_XZ_2)
wp_XY_2_proxy = occ2.CreateGeometryProxy(wp_XY_2)
#Add the constraints
AssCons = invAssDoc.ComponentDefinition.Constraints
AssCons.AddFlushConstraint(wp_YZ_1_proxy, wp_YZ_2_proxy, 0)
AssCons.AddFlushConstraint(wp_XZ_1_proxy, wp_XZ_2_proxy, 0)
AssCons.AddFlushConstraint(wp_XY_1_proxy, wp_XY_2_proxy, 0)

How to work around GMSH and Calculix GUI in FreeCAD to automate Finite Element Analysis using Macro?

I created a macro (python script) in FreeCAD that generates a cantilever beam, creates an Analysis, selects a material, and applies constraints to the body.
How do I now extend the script, so I can generate the mesh (using GMSH) and run the analysis with Calculix all in the same script?
Please see below my code:
import FreeCAD
import PartDesign
import PartDesignGui
import Sketcher
import FemGui
import ObjectsFem
import Fem
# Open new Document
exec(open('/usr/share/freecad/Mod/Start/StartPage/LoadNew.py').read())
App.setActiveDocument("Unnamed")
App.ActiveDocument=App.getDocument("Unnamed")
#
# generate cantilever beam
#
# Start new part design
App.activeDocument().addObject('PartDesign::Body','Body')
App.activeDocument().Body.newObject('Sketcher::SketchObject','Sketch')
App.activeDocument().Sketch.Support = (App.activeDocument().XY_Plane, [''])
App.activeDocument().Sketch.MapMode = 'FlatFace'
App.ActiveDocument.recompute()
# create cross section sketch
geoList = []
geoList.append(Part.LineSegment(App.Vector(-10, 9,0),App.Vector( 10, 9,0)))
geoList.append(Part.LineSegment(App.Vector( 10, 9,0),App.Vector( 10,-10,0)))
geoList.append(Part.LineSegment(App.Vector( 10,-10,0),App.Vector(-10,-10,0)))
geoList.append(Part.LineSegment(App.Vector(-10,-10,0),App.Vector(-10, 9,0)))
App.ActiveDocument.Sketch.addGeometry(geoList,False)
conList = []
conList.append(Sketcher.Constraint('Coincident',0,2,1,1))
conList.append(Sketcher.Constraint('Coincident',1,2,2,1))
conList.append(Sketcher.Constraint('Coincident',2,2,3,1))
conList.append(Sketcher.Constraint('Coincident',3,2,0,1))
conList.append(Sketcher.Constraint('Horizontal',0))
conList.append(Sketcher.Constraint('Horizontal',2))
conList.append(Sketcher.Constraint('Vertical',1))
conList.append(Sketcher.Constraint('Vertical',3))
App.ActiveDocument.Sketch.addConstraint(conList)
# Pad the cross section to create beam
App.getDocument('Unnamed').recompute()
App.activeDocument().Body.newObject("PartDesign::Pad","Pad")
App.activeDocument().Pad.Profile = App.activeDocument().Sketch
App.activeDocument().Pad.Length = 10.0
App.ActiveDocument.recompute()
App.ActiveDocument.recompute()
App.ActiveDocument.Pad.Length = 200.000000
App.ActiveDocument.Pad.Length2 = 100.000000
App.ActiveDocument.Pad.Type = 0
App.ActiveDocument.Pad.UpToFace = None
App.ActiveDocument.Pad.Reversed = 0
App.ActiveDocument.Pad.Midplane = 0
App.ActiveDocument.Pad.Offset = 0.000000
App.ActiveDocument.recompute()
#
# Start FEM process
#
# make analysis
ObjectsFem.makeAnalysis(FreeCAD.ActiveDocument, 'Analysis')
FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.ActiveObject)
ObjectsFem.makeSolverCalculixCcxTools(FreeCAD.ActiveDocument)
FemGui.getActiveAnalysis().addObject(FreeCAD.ActiveDocument.ActiveObject)
# Select Material
FemGui.getActiveAnalysis().addObject(ObjectsFem.makeMaterialSolid(FreeCAD.ActiveDocument, 'SolidMaterial'))
FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)
# Add Fixed Constraint
App.activeDocument().addObject("Fem::ConstraintFixed","FemConstraintFixed")
App.activeDocument().FemConstraintFixed.Scale = 1
App.activeDocument().Analysis.addObject(App.activeDocument().FemConstraintFixed)
for amesh in App.activeDocument().Objects:
if "FemConstraintFixed" == amesh.Name:
amesh.ViewObject.Visibility = True
elif "Mesh" in amesh.TypeId:
aparttoshow = amesh.Name.replace("_Mesh","")
for apart in App.activeDocument().Objects:
if aparttoshow == apart.Name:
apart.ViewObject.Visibility = True
amesh.ViewObject.Visibility = False
App.ActiveDocument.recompute()
App.ActiveDocument.FemConstraintFixed.Scale = 1
App.ActiveDocument.FemConstraintFixed.References = [(App.ActiveDocument.Pad,"Face5")]
App.ActiveDocument.recompute()
# Add Force Constraint
App.activeDocument().addObject("Fem::ConstraintForce","FemConstraintForce")
App.activeDocument().FemConstraintForce.Force = 1.0
App.activeDocument().FemConstraintForce.Reversed = False
App.activeDocument().FemConstraintForce.Scale = 1
App.activeDocument().Analysis.addObject(App.activeDocument().FemConstraintForce)
for amesh in App.activeDocument().Objects:
if "FemConstraintForce" == amesh.Name:
amesh.ViewObject.Visibility = True
elif "Mesh" in amesh.TypeId:
aparttoshow = amesh.Name.replace("_Mesh","")
for apart in App.activeDocument().Objects:
if aparttoshow == apart.Name:
apart.ViewObject.Visibility = True
amesh.ViewObject.Visibility = False
App.ActiveDocument.recompute()
App.ActiveDocument.FemConstraintForce.Force = 1
App.ActiveDocument.FemConstraintForce.Direction = None
App.ActiveDocument.FemConstraintForce.Reversed = False
App.ActiveDocument.FemConstraintForce.Scale = 1
App.ActiveDocument.FemConstraintForce.References = [(App.ActiveDocument.Pad,"Face6")]
App.ActiveDocument.recompute()
# Generate Mesh
ObjectsFem.makeMeshGmsh(FreeCAD.ActiveDocument, 'FEMMeshGmsh')
FreeCAD.ActiveDocument.ActiveObject.Part = FreeCAD.ActiveDocument.Pad
FemGui.getActiveAnalysis().addObject(FreeCAD.ActiveDocument.ActiveObject)
FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)
When I run my code, I get the fully setup analysis with constraints applied and material select. FreeCAD shows me the "FEM mesh by Gmsh" view, where I can select parameters and press a button to generate the mesh file. I would like to push that button in code.
Similarly, I can double click on my Calculix Solver and get the "Mechanical Analysis" view, which allows me to select an analysis type, generate the .inp file, and run the analysis. How do I perform these steps in code.
I am open to calling other script files from within my python file that are written in other languages. But I need it to be automatable, s.t. I could run through various analyses in a for-loop.

Python: correct format on input to datagridview

I want to add rows to a datagridview "manually". I tried converting the following code to python: https://learn.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-manipulate-rows-in-the-windows-forms-datagridview-control
However, I struggle with adding rows. The following doesn't work:
for j in range(len(signals)):
self._dataGridView1.Rows.Add(signals[j])
The following code does work, but is not dynamically enough as I don't know how many elements there will be:
for j in range(len(signals)):
self._dataGridView1.Rows.Add(signals[j][0], signals[j][1], signals[j][2], signals[j][3])
How should I fix this? I tried tuple, but the result were a tuple with all the info shown in the first cell instead of spread over the columns.
I would not like to add packages, as this is to be run within revid dynamo among several users, and I cannot convince everyone to install packages.
full code for context:
import clr
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
clr.AddReference('System.Data')
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import TaskDialog
from System.Windows.Forms import *
from System.Drawing import (
Point, Size,
Font, FontStyle,
GraphicsUnit
)
from System.Data import DataSet
from System.Data.Odbc import OdbcConnection, OdbcDataAdapter
msgBox = TaskDialog
headers = IN[0]
signals = IN[1]
class DataGridViewQueryForm(Form):
def __init__(self):
self.Text = 'Signals'
self.ClientSize = Size(942, 255)
self.MinimumSize = Size(500, 200)
self.setupDataGridView()
def setupDataGridView(self):
self._dataGridView1 = DataGridView()
self._dataGridView1.AllowUserToOrderColumns = True
self._dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize
self._dataGridView1.Dock = DockStyle.Fill
self._dataGridView1.Location = Point(0, 111)
self._dataGridView1.Size = Size(506, 273)
self._dataGridView1.TabIndex = 3
self._dataGridView1.ColumnCount = len(headers)
self._dataGridView1.ColumnHeadersVisible = True
for i in range(len(headers)):
self._dataGridView1.Columns[i].Name = headers[i]
for j in range(len(signals)):
self._dataGridView1.Rows.Add(signals[j][0], signals[j][1], signals[j][2], signals[j][3])
self.Controls.Add(self._dataGridView1)
Application.Run(DataGridViewQueryForm())
Figured it out. Had to use System.Array.
from System import Array
code changes:
array_str = Array.CreateInstance(str, len(headers))
for j in range(len(signals)):
for k in range(len(headers)):
array_str[k] = signals[j][k]
self._dataGridView1.Rows.Add(array_str)

Optimize output of a script by varying input parameters

I have a written a script that uses the code below and I would like to optimize rsi_high and rsi_low to get the best sharpe_ratio:
#
import numpy
import talib as ta
global rsi_high, rsi_low
rsi_high = 63
rsi_low = 41
def myTradingSystem(DATE, OPEN, HIGH, LOW, CLOSE, VOL, exposure, equity, settings):
''' This system uses trend following techniques to allocate capital into the desired equities'''
nMarkets = CLOSE.shape[1] # SHAPE OF NUMPY ARRAY
result, rsi_pos = numpy.apply_along_axis(rsicalc, axis=0, arr=CLOSE)
pos = numpy.asarray(rsi_pos, dtype=numpy.float64)
return pos, settings
def rsicalc(num):
# print rsi_high
try:
rsival = ta.RSI(numpy.array(num,dtype='f8'),timeperiod=14)
if rsival[14] > rsi_high: pos_rsi = 1
elif rsival[14] < rsi_low: pos_rsi = -1
else: pos_rsi = 0
except:
rsival = 0
pos_rsi = 0
return rsival, pos_rsi
def mySettings():
''' Define your trading system settings here '''
settings = {}
# Futures Contracts
settings['markets'] = ['CASH','F_AD', 'F_BO', 'F_BP', 'F_C', 'F_CC', 'F_CD',
'F_CL', 'F_CT', 'F_DX', 'F_EC', 'F_ED', 'F_ES', 'F_FC', 'F_FV', 'F_GC',
'F_HG', 'F_HO', 'F_JY', 'F_KC', 'F_LB', 'F_LC', 'F_LN', 'F_MD', 'F_MP',
'F_NG', 'F_NQ', 'F_NR', 'F_O', 'F_OJ', 'F_PA', 'F_PL', 'F_RB', 'F_RU',
'F_S', 'F_SB', 'F_SF', 'F_SI', 'F_SM', 'F_TU', 'F_TY', 'F_US', 'F_W',
'F_XX', 'F_YM']
settings['slippage'] = 0.05
settings['budget'] = 1000000
settings['beginInSample'] = '19900101'
settings['endInSample'] = '19931231'
settings['lookback'] = 504
return settings
# Evaluate trading system defined in current file.
if __name__ == '__main__':
import quantiacsToolbox
results = quantiacsToolbox.runts(__file__, plotEquity=False)
sharpe_ratio = results['stats']['sharpe']
I suspect that using something like scipy minimize function would do the trick, but I am having trouble understanding how to package my script so that it can be in a usable form.
I have tried putting everything in a function and then running all the code through a number of loops, each time incrementing values but there must be a more elegant way of doing this.
Apologies for posting all my code but I thought it would help if the responder wanted to reproduce my setup and for anyone who is new to quantiacs to see a real example who is faced with the same issue.
Thanks for your help in advance!

Categories