Developer Notes

Development History

PyMbs started off as a tool to generate the equations of motions of multibody system for external tools, such as MATLAB or Modelica. This is still at the core of PyMbs. Initially, sympy was used to generate these equations. This turned out to be inadequate in terms of performance for larger systems, so a dedicated symbolic computation module has been written in C++. Over time, a graphical user interface with the ability to simulate the model has been added, as well the ability to define sensors and kinematic loops. Recently, the ability to influence the behaviour of your system by use of a controller has been implemented.

Structure of the Repository

To get a feel for the project and where a particular peace of code is residing, here is a quick rundown of the most commonly used files and directories.

setup.py is the starting point for building, distributing and installing a Python module, this goes for PyMbs as well.

builder.py handles the extra steps required to build the symbolics module from C++ using CMake. It is called from setup.py when necessary.

common/ contains the base classes for bodies, frames, etc.

doc/ contains the Sphinx documentation for PyMbs.

examples/ contains various examples of PyMbs models. Take a look at examples/controlled for models using a controller. Under examples/misc you’ll find old examples that may or may not work with current versions of PyMbs.

Graphics/ includes all the code responsible for creating the graphical user interface.

input/ is the main module that defines the user interface of PyMbs scripting. In particular, input/mbs_system.py is the starting point in all PyMbs scripts. Start here if you want to find out how a particular feature is implemented.

processing/ the code for Loads (Forces and Torques), Sensors, Kinematic Loops, etc. resides here.

symbolics/ all of the “heavy lifting” is done in this C++ module. If you want to change the output for a code generator, you’ll have to modify the respective file in symbolics/writer/.

test/ contains the unittests. Some of them are obsolete, others need expansion. Writing new tests is a great way to get started on improving PyMbs!

Building PyMbs under Windows

To build PyMbs under Windows, you need CMake and Visual Studio (Express). Once you have VS installed, start a Visual Studio command prompt (the normal windows command prompt will not work, take a look under Visual Studio in the Start Menu), cd to your PyMbs source directory and execute:

python setup.py install

This should generate all the files necessary and copy them to the appropriate locations. Alternatively, you can use the CMake GUI and generate a Visual Studio project file which you can then build using the Visual Studio IDE.

Running the Tests

There are a couple of files containing unittests. Running each of these commands should result in no error:

python test/test_symbolics.py
python test/test_input.py
python symbolics/test_symbolics.py
python examples/test_examples.py

Working on the Documentation

A very good, short introduction to the Sphinx syntax can be found at Documenting Your Project Using Sphinx.

Building the Documentation

The documentation at Read the Docs is automatically build on every commit.

For building a local copy of the HTML documentation, you can call Sphinx like this:

sphinx-build <documentation-directory> <target-directory>

Commonly, if you are in the PyMbs source directory, you would call:

sphinx-build doc doc/.build

To then take a look at your newly built documentation, direct your browser to doc/.build/index.html.

If you want to build the PDF documentation, you need to have LaTeX installed as well. Then you need to call Sphinx with the option -b latex to select the LaTeX builder, e.g.:

sphinx-build -b latex doc doc/.latex

This generates all the necessary .tex files, but does not execute PDF generation. To do this, go to the target directory (doc/.latex) and call make. This will call pdflatex a number of times and result in a file called PyMbs.pdf in that directory.

Sphinx Hints

In some cases it has been necessary to use some of the more obscure features of Sphinx. These are documented here.


Avoid substitutions in autodoced function definitions

The autodoc extension will execute some of your Python code as it imports your module/class. In some cases, this will lead to unwanted results. Consider this example code:

x = 3
def my_function(foo_bar=x):
    pass

This would be rendered as

my_function(foo_bar=3)

by autodoc. If you want to circumvent this, you have to duplicate the function definition in the first line of the docstrings, i.e.:

x = 3
def my_function2(foo_bar=x):
    """
    my_function2(foo_bar=x)
    """
    pass

which now renders as intended

my_function2(foo_bar=x)

In PyMbs, this has been used to document e.g. pymbs.input.MbsSystem.addFrame().


Document instance variables

Autodoc extracts the docstrings of your classes and methods to build parts of the documentation, in our case most of the Command Reference section. Variables and instance variables usually don’t have docstrings though. However, we expose the interfaces to Loads (Forces and Torques), Kinematic Loops, Sensors, etc. using instance variables. To document these entities, precede them with Python comments, followed by a colon. For example, the interface PyMbs.Input.MbsSystem.addLoad has been documented like this:

#: addLoad contains a :class:`PyMbs.Input.MbsSystem.AddLoad` instance,
#: see :ref:`loads` for the different load types available
#:
#: >>> world.addLoad.PtPForce(F, body_one, body_two)
self.addLoad = AddLoad(self)

Alternativly use can add an ivar (instance variable) info field to the docstring of the class. However, these can not be linked to and should therefore be using sparingly.


Animation in HTML output, static image in PDF

The examples have a small animation of the simulation attached to them. They are in the form of .gif files; however, they can’t be included in the LaTeX version of the documentation. Because of this, a different file is to be included depending on the builder:

.. only:: html

    .. image:: simple_pendulum.gif

.. only:: latex

    .. image:: simple_pendulum.jpg            :scale: 50 %

Source code from Examples

The Examples are documented by including the actual source code from <pymbs-root>/examples with the literalinclude directive, e.g.:

.. literalinclude:: ../../examples/simple_pendulum.py
    :lines: 29-31

This includes the lines 29 through 31 in the documentation.

Warning

When you change the example .py files in <pymbs-root>/examples, make sure you also change the line numbers in the documentation accordingly!