Guidelines for developers
Code guidelines for data processing functions/algorithms
Data processing functions take input data, calculate something and return output data. This can range from simple quaternion multiplication to complex analysis frameworks that take inertial sensor data from a full kinematic chain, perform different calculations, and return a large number of output signals.
In general, there are three different kinds of implementations of data processing algorithms:
online: processes data sample-by-sample, immediately returns output for the current sample
vectorized: processes all data at once but could be implemented as an online algorithm
offline: processes all data at once and is impossible to implement as an online algorithm
Function naming and parameters
Functions are named using camelCase, starting with a small letter. Names should be descriptive and be similar to names used in existing functions. The same holds for names of input arguments and returned outputs.
The arguments of each function are first the inputs (i.e. data to be processed), then parameters (i.e. things that
influence how the data is processed), and then debug and plot flags which default to False. Parameters can
have default values.
Example:
def oriEstIMU(gyr, acc, mag, rate, tauAcc=1.0, tauMag=3.0, accRating=1.0, zeta=0.0, debug=False, plot=False):
# calculates quat based on inputs gyr, acc and mag with parameters rate, tauAcc, tauMag, accRating and zeta
if debug or plot:
debugData = dict(diagreement=disagreement, bias=bias)
if plot:
oriEstIMU_debugPlot(debugData, plot)
if debug:
return quat, debugData
return quat
If there are too many inputs, parameters, and/or outputs, they can be replaced by dicts called inputs, params
and outputs. If an outputs dict exists, the debug dict is returned as part of it. See the following example
that also shows how to use default parameters:
def oriEstIMU(inputs, params, debug=False):
defaults = dict(tauAcc=1.0, tauMag=3.0, accRating=1.0, zeta=0.0)
params.update((k, v) for k, v in defaults.items() if k not in params)
params = setDefaults(params, default, ['rate']) # rate is a non-optional parameter without a default value
outputs = {}
outputs['quat'] = # ...
if debug or plot:
debugData = dict(diagreement=disagreement, bias=bias)
if plot:
oriEstIMU_debugPlot(debugData, plot)
if debug:
outputs['debug'] = debugData
return outputs
Note
The usage of dicts is independent for inputs, parameters, and outputs. For this example function, only
params should probably be passed using a dict.
Note
In functions without an outputs dict, the debug flag changes the number of outputs! This makes simple
functions much more convenient to use, but can lead to unexpected behavior.
Plot functions
Each data processing function must be accompanied by a corresponding plot function called $functionname_debugPlot.
The function takes the debug dict of the processing function and an optional fig parameter containing a
matplotlib figure object (or a figs list if the function plots into multiple figures).
The plot function must use qmt.utils.plot.AutoFigure to create and show/save plots automatically as configured
with qmt.setupDebugPlots(). See the implementation of .:ref:qmult_plotFunction: for an example.
Online algorithms
For online data processing, the qmt.Block class should be used. An online data processing block typically has
a state and, given one input sample, calculates one output sample. Furthermore, processing can be adjusted with
parameters.
Other conventions
For time series, each row contains one sample. For example, a series of N quaternions is stored as an array with shape (N, 4) and not (4, N).
Scalar time series (e.g. time vectors, single angles, …) should be stored with shape (N,) and not (N, 1).
Functions that can be applied to a single sample or a time series (e.g.
qmt.qmult()) should apply both as input and return outputs of the same shape, e.g.qmult((4,), (4,))returns an output of shape (4,) whileqmult((1, 4), (1, 4))returns an output of shape (1, 4). If possible, numpy broadcasting should be used for input data.