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 specific NodeIndex, ObjectIndex, …
You can create any item index, e.g., using ni = NodeIndex(42) or oi = 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., NodeIndex ni into an integer number using int(ni) of ni.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 a int 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, use ni.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.