Python external function examples: Externally calculated vessel motion

This topic is intended to be read in conjunction with the main external function documentation, and the example source code.

This ZIP file contains all of the Python external function examples, with each example contained in the appropriately named sub-folder.

External functions that calculate vessel primary motion must return the vessel motion in info.StructValue instead of info.Value. When used for vessel motion, this StructValue is an instance of ExternallyCalculatedImposedMotion.

This example comprises the ExternallyCalculatedVesselMotion.py example, OrcaFlex model ExternallyCalculatedVesselMotion.dat and OrcaFlex workspace file ExternallyCalculatedVesselMotion_default.wrk. Open that model, run the simulation and open the default workspace file to see the imposed motion.

Orientation matrices

One attribute of the imposed motion struct is an orientation matrix. Orientation matrices define the directions of the child frame axes with respect to some parent frame axes directions. For a vessel motion struct, the rows of the orientation matrix are the unit vectors in the vessel local axes directions, expressed as components with respect to global axes directions.

For the sake of an example, consider the attributes Orientation and Velocity. Referring to the finer details in the C++ documentation, we note that the velocity vector is expressed with respect to global axes directions. We add a suffix to include the reference frame in the variable name, writing VelocityWrtGlobal in our example code.

Now suppose we wish to express the velocity with respect to the vessel axes directions. This is achieved by pre-multiplying the vector by the orientation matrix. In pseudo-code:

VelocityWrtGlobal = Velocity
VesselWrtGlobal = Orientation
VelocityWrtVessel = VesselWrtGlobal × VelocityWrtGlobal

In this equation we treat both vectors as column vectors.

To perform such a re-orientation in Python we would typically use the numpy module. The code to do so could look like this:

import numpy

VelocityWrtGlobal = numpy.array(Velocity)
VesselWrtGlobal = numpy.array(Orientation)
VelocityWrtVessel = VesselWrtGlobal @ VelocityWrtGlobal

Now suppose that you wished to perform the re-orientation in the opposite direction. That is to re-orient a vector with respect to child axes directions to a vector with respect to parent axes directions. So, for example, consider the attribute named AngularVelocity. In order to express this vector with respect to global axes directions we post-multiply with the orientation:

AngularVelocityWrtVessel = AngularVelocity
VesselWrtGlobal = Orientation
AngularVelocityWrtGlobal = AngularVelocityWrtVessel × VesselWrtGlobal

In this equation we treat both angular velocity vectors as row vectors.

The equivalent code in Python is this:

import numpy

AngularVelocityWrtVessel = numpy.array(AngularVelocity)
VesselWrtGlobal = numpy.array(Orientation)
AngularVelocityWrtGlobal = AngularVelocityWrtVessel @ VesselWrtGlobal