CPython 3, Apply loads to Load cases

CPython 3, Apply loads to Load cases

stefanyC6JZ7
Enthusiast Enthusiast
1,101 Views
8 Replies
Message 1 of 9

CPython 3, Apply loads to Load cases

stefanyC6JZ7
Enthusiast
Enthusiast

Hi all, 

We are trying to migrate our scripts from IronPython2 to CPython3.

I am trying to apply loads to the load case "GCW" as picture shows. The original script is attached, it was done with version IronPython2 and it works, however when turning to CPython 3, there are some errors. 

Warning: AttributeError : '__ComObject' object has no attribute 'Records' [' File "<string>", line 32, in <module>\n']

and I got problems with IRobotLoadRecordMngr.Count. Could you help me checking what is wrong with the script?

 

Thank you in advance. 

Files are attached.

Best regards, 

Stefany 

 

 

 

 

stefanyC6JZ7_2-1660749824498.png

 

stefanyC6JZ7_1-1660748175526.png

 

 

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

from System import Environment
user = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
sys.path.append(user+r"\Dynamo\Dynamo Core\2.11\packages\Structural Analysis for Dynamo\bin\RSA\Interop.RobotOM.dll")
clr.AddReference('interop.RobotOM')
#clr.AddReference(user+r"\Dynamo\Dynamo Core\2.11\packages\Structural Analysis for Dynamo\bin\RSA\Interop.RobotOM.dll")
from RobotOM import *
from System import Object

objects = IN[0]
LoadCaseID = IN[1]
ILRT = IN[2]
LoadPX = IN[3]
LoadPY = IN[4]
LoadPZ = IN[5]


application = RobotApplicationClass()
project = application.Project
structure = project.Structure
labels = structure.Labels
loads = structure.Cases

CreatedLoads = []
case = structure.Cases.Get(LoadCaseID)
simplecase = IRobotSimpleCase
simplecase = case
rec = IRobotLoadRecord
IRobotLoadRecordMngr = simplecase.Records
count = IRobotLoadRecordMngr.Count
for i in range(count+1)[::-1]:
	rec = simplecase.Records.Delete(i)
#for i in range(1,count+1,1):
#	rec = simplecase.Records.Delete(i)

for j in range(len(objects)):
	for k in range(len(objects[j])):
		Uniform = []
		Uniform.append(simplecase.Records.New(ILRT))
		LoadRecord = simplecase.Records.Get(Uniform[0])
		LoadRecord.SetValue(0,LoadPX)
		LoadRecord.SetValue(1,LoadPY)
		LoadRecord.SetValue(2,LoadPZ[j])
		LoadRecord.Objects.FromText(objects[j][k])
		CreatedLoads.append(LoadRecord.UniqueID)

application.Visible = True
application.Interactive = True
application.Project.ViewMngr.Refresh()

#Assign your output to the OUT variable.
OUT = CreatedLoads, count
0 Likes
Accepted solutions (1)
1,102 Views
8 Replies
Replies (8)
Message 2 of 9

1234eddie
Advocate
Advocate

Hi All,

 

Some of you may recognise these text from the script. @stefanyC6JZ7  is my colleague.

@JacquesGaudin @cool.stuff @chjpcoi 

 

Hope someone of you explain to us what is nessesary to get our scripts to Cpython3.

 

Thanks in advance.

Gr Edward

0 Likes
Message 3 of 9

JacquesGaudin
Advocate
Advocate

Try this?

 

 

 

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

from System import Environment
user = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
sys.path.append(user+r"\Dynamo\Dynamo Core\2.11\packages\Structural Analysis for Dynamo\bin\RSA\Interop.RobotOM.dll")
clr.AddReference('interop.RobotOM')
from System import Object

objects = IN[0]
LoadCaseID = IN[1]
ILRT = IN[2]
LoadPX = IN[3]
LoadPY = IN[4]
LoadPZ = IN[5]


application = RobotApplicationClass()
project = application.Project
structure = project.Structure
labels = structure.Labels
loads = structure.Cases

CreatedLoads = []
case = structure.Cases.Get(LoadCaseID)
simplecase = IRobotSimpleCase(case)
rec = IRobotLoadRecordMngr(simplecase.Records)
count = rec.Count
for i in range(count+1)[::-1]:
	rec.Delete(i)
#for i in range(1,count+1,1):
#	rec = simplecase.Records.Delete(i)

for j in range(len(objects)):
	for k in range(len(objects[j])):
		Uniform = []
		Uniform.append(rec.New(ILRT))
		LoadRecord = rec.Get(Uniform[0])
		LoadRecord.SetValue(0,LoadPX)
		LoadRecord.SetValue(1,LoadPY)
		LoadRecord.SetValue(2,LoadPZ[j])
		LoadRecord.Objects.FromText(objects[j][k])
		CreatedLoads.append(LoadRecord.UniqueID)

application.Visible = True
application.Interactive = True
application.Project.ViewMngr.Refresh()

#Assign your output to the OUT variable.
OUT = CreatedLoads, count

 

 

0 Likes
Message 4 of 9

stefanyC6JZ7
Enthusiast
Enthusiast

Hi @JacquesGaudin,

Thank you for your reply. I have tried the code you suggested, but it is not working completely. The first part of the script runs without a problem, at line 42 the set value does not correspond because of the com_object error, please see picture below. 

what could be a solution for this one?

stefanyC6JZ7_0-1660806409987.png

 

as a test i did turn line 42-46 off. the loop and everything then works.

 

Forum.PNG

 

Thank you in advance. 

 

Best regards, 

Stefany 

0 Likes
Message 5 of 9

1234eddie
Advocate
Advocate

@JacquesGaudin 

 

we still having problems with this one. i did a little dig in the api.

i think i know why this happens, but don't know how to solve it. 

Setvalue is part of Irobotloadrecord,

1234eddie_0-1660808835134.png

And our definition of loadrecord in the script is (if i'm right) part of IRobotLoadRecordMngr

1234eddie_1-1660808858949.png

could this be the problem.

 

Gr Edward

0 Likes
Message 6 of 9

JacquesGaudin
Advocate
Advocate

@1234eddie @stefanyC6JZ7 

 

You are right, the `SetValue` method is not available because `LoadRecord` is not recognised as a IRobotLoadRecord object but rather a generic COM object.

 

In general, when this happens, the solution is to just cast the object to the expected type:

LoadRecord = IRobotLoadRecord(rec.Get(Uniform[0]))

# This forces the result of the `Get` method to be cast to IRobotLoadRecord
# In general:
# my_obj = ExpectedType(object_server.Get(i))

 

This is due to the way PythonNet works and to the fact that there is no such things as interfaces in Python. 

 

IronPython was dealing with the interface types under the hood but PythonNet doesn't do that, leaving some objects with a generic COM object type. To gain access to the methods of the object, it is necessary to cast the object to the correct type.

 

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

from System import Environment
user = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
sys.path.append(user+r"\Dynamo\Dynamo Core\2.11\packages\Structural Analysis for Dynamo\bin\RSA\Interop.RobotOM.dll")
clr.AddReference('interop.RobotOM')
from System import Object

objects = IN[0]
LoadCaseID = IN[1]
ILRT = IN[2]
LoadPX = IN[3]
LoadPY = IN[4]
LoadPZ = IN[5]


application = RobotApplicationClass()
project = application.Project
structure = project.Structure
labels = structure.Labels
loads = structure.Cases

CreatedLoads = []
case = structure.Cases.Get(LoadCaseID)
simplecase = IRobotSimpleCase(case)
rec = IRobotLoadRecordMngr(simplecase.Records)
count = rec.Count
for i in range(count+1)[::-1]:
	rec.Delete(i)

for j in range(len(objects)):
	for k in range(len(objects[j])):
		Uniform = []
		Uniform.append(rec.New(ILRT))
		LoadRecord = IRobotLoadRecord(rec.Get(Uniform[0]))
		LoadRecord.SetValue(0,LoadPX)
		LoadRecord.SetValue(1,LoadPY)
		LoadRecord.SetValue(2,LoadPZ[j])
		LoadRecord.Objects.FromText(objects[j][k])
		CreatedLoads.append(LoadRecord.UniqueID)

application.Visible = True
application.Interactive = True
application.Project.ViewMngr.Refresh()

#Assign your output to the OUT variable.
OUT = CreatedLoads, count

 

Message 7 of 9

stefanyC6JZ7
Enthusiast
Enthusiast

Hi @JacquesGaudin

Thank you for your reply, and for your help. Now the code works better, loads are applied to the load case, see picture below. But, I got an error with lines 48 and 49. 

Warning: TypeError : No method matches given arguments for FromText: (<class 'int'>) [' File "<string>", line 48, in <module>\n']

Warning: AttributeError : 'IRobotLoadRecord' object has no attribute 'UniqueId' [' File "<string>", line 49, in <module>\n']

Could you help me to solve it?

stefanyC6JZ7_1-1660822446601.png

 

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

from System import Environment
user = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
#sys.path.append(user+r"\Dynamo\Dynamo Core\2.11\packages\Structural Analysis for Dynamo\bin\RSA\Interop.RobotOM.dll")
#clr.AddReference('interop.RobotOM')
clr.AddReference(user+r"\Dynamo\Dynamo Core\2.11\packages\Structural Analysis for Dynamo\bin\RSA\Interop.RobotOM.dll")
from RobotOM import *
from System import Object

objects = IN[0]
LoadCaseID = IN[1]
ILRT = IN[2]
LoadPX = IN[3]
LoadPY = IN[4]
LoadPZ = IN[5]


application = RobotApplicationClass()
project = application.Project
structure = project.Structure
labels = structure.Labels
loads = structure.Cases

CreatedLoads = []
case = structure.Cases.Get(LoadCaseID)
simplecase = IRobotSimpleCase(case)
rec = IRobotLoadRecordMngr(simplecase.Records)

#rec1 = IRobotLoadRecord(simplecase.Records)
count = rec.Count
for i in range(count+1)[::-1]:
	rec.Delete(i)
#for i in range(1,count+1,1):
#	rec = simplecase.Records.Delete(i)

for j in range(len(objects)):
	for k in range(len(objects[j])):
		Uniform = []
		Uniform.append(rec.New(ILRT))
		LoadRecord = IRobotLoadRecord(rec.Get(Uniform[0]))
		#LoadRecord.SetValue(LoadPZ[j])
		LoadRecord.SetValue(0,LoadPX)
		LoadRecord.SetValue(1,LoadPY)
		LoadRecord.SetValue(2,LoadPZ[j])
		LoadRecord.Objects.FromText(objects[j][k])
		CreatedLoads.append(LoadRecord.UniqueId)
		#selection_bars = structure.Bars.Get(objects[j][k])
		#LoadRecord.Objects.FromText(objects[j][k])
		#LoadRecord.Objects = '1'
		#LoadRecord.Objects.FromText(objects[j][k])
		

application.Visible = True
application.Interactive = True
application.Project.ViewMngr.Refresh()

#Assign your output to the OUT variable.
OUT = objects, selection_bars
#OUT = CreatedLoads, count

stefanyC6JZ7_0-1660822168430.png

Thank you in advance for you help. 

 

Best regards, 

Stefany 

 

 

 

0 Likes
Message 8 of 9

JacquesGaudin
Advocate
Advocate
Accepted solution

The first error is because the `FromText` method expects a string argument, not an integer. Just cast the integer to a string to fix it.

LoadRecord.Objects.FromText(str(objects[j][k]))

 

The second is because the IRobotLoadRecord interface doesn't provide `UniqueId` as an attribute. To access it you have to use an interface that derives from IRobotLoadRecord but is more specific. For a uniformly distributed load, it is IRobotLoadRecordLinear3D.

for j in range(len(objects)):
	for k in range(len(objects[j])):
		Uniform = []
		Uniform.append(rec.New(ILRT))
		LoadRecord = IRobotLoadRecordLinear3D(rec.Get(Uniform[0]))  # A more specific interface must be used
		LoadRecord.SetValue(0,LoadPX)
		LoadRecord.SetValue(1,LoadPY)
		LoadRecord.SetValue(2,LoadPZ[j])
		LoadRecord.Objects.FromText(str(objects[j][k]))  # Converts integer to str
		CreatedLoads.append(LoadRecord.UniqueId)
		

 

Note you could apply the same loads with this:

 

for obj_lst in objects:
	Uniform = []
	Uniform.append(rec.New(ILRT))
	LoadRecord = IRobotLoadRecordLinear3D(rec.Get(Uniform[0]))
	LoadRecord.SetValue(0,LoadPX)
	LoadRecord.SetValue(1,LoadPY)
	LoadRecord.SetValue(2,LoadPZ[j])
	LoadRecord.Objects.FromText(' '.join(str(el) for el in obj_lst)
	CreatedLoads.append(LoadRecord.UniqueId)
		
Message 9 of 9

stefanyC6JZ7
Enthusiast
Enthusiast

Hi @JacquesGaudin

Thank you very much for your help and patience with us while trying to fix the script. Now it is working, and I am happy to share the results below.

 

Have a nice day!

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

from System import Environment
user = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

clr.AddReference(user+r"\Dynamo\Dynamo Core\2.11\packages\Structural Analysis for Dynamo\bin\RSA\Interop.RobotOM.dll")
from RobotOM import *
from System import Object

objects = IN[0]
LoadCaseID = IN[1]
ILRT = IN[2]
LoadPX = IN[3]
LoadPY = IN[4]
LoadPZ = IN[5]

application = RobotApplicationClass()
project = application.Project
structure = project.Structure
labels = structure.Labels
loads = structure.Cases

case = structure.Cases.Get(LoadCaseID)
simplecase = IRobotSimpleCase(case)
rec = IRobotLoadRecordMngr(simplecase.Records)
count = rec.Count

for i in range(count+1)[::-1]:
	rec.Delete(i)

for j in range(len(objects)):
	for k in range(len(objects[j])):
		Uniform = []
		Uniform.append(rec.New(ILRT))
		LoadRecord = IRobotLoadRecord(rec.Get(Uniform[0])) 
		LoadRecord.SetValue(0,LoadPX)
		LoadRecord.SetValue(1,LoadPY)
		LoadRecord.SetValue(2,LoadPZ[j])
		LoadRecord.Objects.FromText(str(objects[j][k])) 
application.Visible = True
application.Interactive = True
application.Project.ViewMngr.Refresh()

OUT = objects

 

Best regards, 

Stefany