This chapter lists the basic interface functions which can be used to set up a Exudyn model in Python.
General information on Python-C++ interface
This chapter lists the basic interface functions which can be used to set up a Exudyn model in Python. Note that some functions or classes will be used in examples, which are explained in detail later on. In the following, some basic steps and concepts for usage are shown, references to all functions are placed hereafter:
To import the module, just include the Exudyn module in Python:
import exudyn as exu
For compatibility with examples and other users, we recommend to use the exu
abbreviation throughout. In addition, you may work with a convenient interface for your items, therefore also always include:
from exudyn.itemInterface import *
Note that including exudyn.utilities
will cover itemInterface
. Also note that from ... import *
is not recommended in general and it will not work in certain cases, e.g., if you like to compute on a cluster. However, it greatly simplifies life for smaller models and you may replace imports in your files afterwards by removing the star import.
The general hub to multibody dynamics models is provided by the classes SystemContainer
and MainSystem
, except for some very basic system functionality (which is inside the Exudyn module).
You can create a new SystemContainer
, which is a class that is initialized by assigning a system container to a variable, usually denoted as SC
:
SC = exu.SystemContainer()
Note that creating a second exu.SystemContainer()
will be independent of SC
and therefore makes no sense if you do not intend to work with two different containers.
To add a MainSystem to system container SC
and store as variable mbs
, write:
mbs = SC.AddSystem()
Furthermore, there are a couple of commands available directly in the exudyn
module, given in the following subsections. Regarding the (basic) module access, functions are related to the exudyn = exu
module, see these examples:
1# import exudyn module:
2import exudyn as exu
3# print detailed exudyn version, Python version (at which it is compiled):
4exu.GetVersionString(addDetails = True)
5# set precision of C++ output to console
6exu.SetOutputPrecision(numberOfDigits)
7# turn on/off output to console
8exu.SetWriteToConsole(False)
9# invalid index, may depend on compilation settings:
10nInvalid = exu.InvalidIndex() #the invalid index, depends on architecture and version
Understanding the usage of functions for python object SystemContainer
of the module exudyn
, the following examples might help:
1#import exudyn module:
2import exudyn as exu
3# import utilities (includes itemInterface, basicUtilities,
4# advancedUtilities, rigidBodyUtilities, graphics):
5from exudyn.utilities import *
6# create system container and store in SC:
7SC = exu.SystemContainer()
8# add a MainSystem (multibody system) to system container SC and store as mbs:
9mbs = SC.AddSystem()
10# add a second MainSystem to system container SC and store as mbs2:
11mbs2 = SC.AddSystem()
12# print number of systems available:
13nSys = SC.NumberOfSystems()
14exu.Print(nSys) #or just print(nSys)
15# delete reference to mbs and mbs2 (usually not necessary):
16del mbs, mbs2
17# reset system container (mbs becomes invalid):
18SC.Reset()
If you run a parameter variation (check Examples/parameterVariationExample.py
), you may reset or delete the created MainSystem
mbs
and the SystemContainer
SC
before creating new instances in order to avoid memory growth.
Item index
Many functions will work with node numbers (NodeIndex
), object numbers (ObjectIndex
),marker numbers (MarkerIndex
) and others. These numbers are special Python objects, which have been introduced in order to avoid mixing up, e.g., node and object numbers.
For example, the command mbs.AddNode(...)
returns a NodeIndex
. For these indices, the following rules apply:
mbs.Add[Node|Object|...](...)
returns a specificNodeIndex
,ObjectIndex
, …You can create any item index, e.g., usingni = NodeIndex(42)
oroi = ObjectIndex(42)
The benefit of these indices comes as they may not be mixed up, e.g., using an object index instead of a node index.You can convert any item index, e.g., NodeIndexni
into an integer number usingint(ni)
ofni.GetIndex()
Still, you can use integers as initialization for item numbers, e.g.:mbs.AddObject(MassPoint(nodeNumber=13, ...))
However, it must be a pure integer type.You can make integer calculations with such indices, e.g.,oi = 2*ObjectIndex(42)+1
restricing to addition, subtraction and multiplication. Currently, the result of such calculations is aint
type andoperating on mixed indices is not checked (but may raise exceptions in future).You can also print item indices, e.g.,print(ni)
as it converts to string by default.If you are unsure about the type of an index, useni.GetTypeString()
to show the index type.
Copying and referencing C++ objects
As a key concept to working with Exudyn , most data which is retrieved by C++ interface functions is copied.
Experienced Python users may know that it is a key concept to Python to often use references instead of copying, which is
sometimes error-prone but offers a computationally efficient behavior.
There are only a few very important cases where data is referenced in Exudyn , the main ones are
SystemContainer
,
MainSystem
,
VisualizationSettings
, and
SimulationSettings
which are always references to internal C++ classes.
The following code snippets and comments should explain this behavior:
1import copy #for real copying
2import exudyn as exu
3from exudyn.utilities import *
4#create system container, referenced from SC:
5SC = exu.SystemContainer()
6SC2 = SC #this will only put a reference to SC
7 #SC2 and SC represent the SAME C++ object
8#add a MainSystem (multibody system):
9mbs = SC.AddSystem() #get reference mbs to C++ system
10mbs2=mbs #again, mbs2 and mbs refer to the same C++ object
11og = mbs.AddObject(ObjectGround()) #copy data of ObjectGround() into C++
12o0 = mbs.GetObject(0) #get copy of internal data as dictionary
13
14mbsCopy=copy.copy(mbs) #mbsCopy is now a real copy of mbs; uses pickle; experimental!
15SC.Append(mbsCopy) #this is needed to work with mbsCopy
16
17del o0 #delete the local dictionary; C++ data not affected
18del mbs, mbs2 #references to mbs deleted (C++ data still available)
19del mbsCopy #now also copy of mbs destroyed
20del SC #references to SystemContainer deleted
21#at this point, mbs and SC are not available any more (data will be cleaned up by Python)
Exceptions and Error Messages
There are several levels of type and argument checks, leading to different types of errors and exceptions. The according error messages are non-unique, because they may be raised in Python modules or in C++, and they may be raised on different levels of the code. Error messages depend on Python version and on your iPython console. Very often the exception may be called ValueError
, but it mustnot mean that it is a wrong error, but it could also be, e.g., a wrong order of function calls.
As an example, a type conversion error is raised when providing wrong argument types, e.g., try exu.GetVersionString('abc')
:
1Traceback (most recent call last):
2
3File "C:\Users\username\AppData\Local\Temp\ipykernel_24988\2212168679.py", line 1, in <module>
4 exu.GetVersionString('abc')
5
6TypeError: GetVersionString(): incompatible function arguments. The following argument types are supported:
7 1. (addDetails: bool = False) -> str
8
9Invoked with: 'abc'
Note that your particular error message may be different.
Another error results from internal type and range checking, saying User ERROR, as it is due to a wrong input of the user. For this, we try
mbs.AddObject('abc')
Which results in an error message similar to:
1=========================================
2User ERROR [file 'C:\Users\username\AppData\Local\Temp\ipykernel_24988\2838049308.py', line 1]:
3Error in AddObject(...):
4Check your python code (negative indices, invalid or undefined parameters, ...)
5
6=========================================
7
8Traceback (most recent call last):
9
10 File "C:\Users\username\AppData\Local\Temp\ipykernel_24988\2838049308.py", line 1, in <module>
11 mbs.AddObject('abc')
12
13RuntimeError: Exudyn: parsing of Python file terminated due to Python (user) error
Finally, there may be system errors. They may be caused due to previous wrong input, but if there is no reason seen, it may be appropriate to report this error on github.com/jgerstmayr/EXUDYN/ .
Be careful in reading and interpreting such error messages. You should read them from top to bottom, as the cause may be in the beginning. Often files and line numbers of errors are provided (e.g., if you have a longer script). In the ultimate case, try to comment parts of your code or deactivate items to see where the error comes from. See also section on Trouble shooting and FAQ.