-
Notifications
You must be signed in to change notification settings - Fork 1
Naming convention and data formats
I decided to keep the API functions in their original names and naming style, so you can look up the corresponding function in the manual. All other scripts I wrote use a different naming format. This way, just by looking at the name of the function in question, you know whether to check details of it in this documentation or the API reference manual. Optionally, you can check the code itself where I wrote plenty of comments. So, to illustrate:
OptotrakFancyFunction()
is lifted directly from the API supplied by NDI, whereas
optotrak_fancy_function()
is something I wrote.
Sometimes, I had to add a little bit to an existing function so Matlab would be able to work with it, these functions are annotated like so:
OptotrakFancyFunction_with_a_twist()
.
OptotrakActivateMarkers()
and DataBufferStart()
are functions included in the API.
optotrak_plot_marker_status()
or optotrak_tell_me_what_went_wrong()
are convenience scripts and wrapper functions I had to write.
Sometimes, I had to use a mixed approach:
DataGetLatest3D()
is an API function, which returns the coordinates as a structure array, but since Matlab's shared library support doesn't handle structure arrays very well, I had to write DataGetLatest3D_as_array()
, which does the structure array - 2D array conversion before returning the data to Matlab.
The toolbox saves data in a format that is more convenient for Matlab users.
Generally 2D arrays are used, where each row is a frame of captured data, and three columns are used for each entry. All data arrays must have a multiple of 3 columns. The data is converted to Matlab's double-precision floating-point, from C's float
type.
In each row, a marker's coordinates are stored in X-Y-Z triplets. For example, where there are M frames and N markers:
coorindate_array = [
frame1_marker1_X, frame1_marker1_Y, frame1_marker1_Z, frame1_marker2_X, frame1_marker2_Y, frame1_marker2_Z, ..., frame1_markerN_X, frame1_markerN_Y, frame1_markerN_Z;
frame2_marker1_X, frame2_marker1_Y, frame2_marker1_Z, frame2_marker2_X, frame2_marker2_Y, frame2_marker2_Z, ..., frame2_markerN_X, frame2_markerN_Y, frame2_markerN_Z;
.
.
.
frameM_marker1_X, frameM_marker1_Y, frameM_marker1_Z, frameM_marker2_X, frameM_marker2_Y, frameM_marker2_Z,..., frameM_markerN_X, frameM_markerN_Y, frameM_markerN_Z;
When there is a rigid body defined, there are two arrays generated. The translation array tells where the calculated centroid object is with respect to the coordinate system, and the rotation array tells the orientation of the object with respect to the rigid body definition by default. Each row corresponds to a frame. If there is more than one rigid body defined, the C code generates more columns in the return array.
Translation is returned for each frame, with X-Y-Z triplets for each rigid body. For M frames and N rigid bodies, the array looks like this:
translation_array = [
frame1_rigidBody1_X, frame1_rigidBody1_Y, frame1_rigidBody1_Z, frame1_rigidBody2_X, frame1_rigidBody2_Y, frame1_rigidBody2_Z, ..., frame1_rigidBodyN_X, frame1_rigidBodyN_Y, frame1_rigidBodyN_Z;
frame2_rigidBody1_X, frame2_rigidBody1_Y, frame2_rigidBody1_Z, frame2_rigidBody2_X, frame2_rigidBody2_Y, frame2_rigidBody2_Z, ..., frame2_rigidBodyN_X, frame2_rigidBodyN_Y, frame2_rigidBodyN_Z;
.
.
.
frameM_rigidBody1_X, frameM_rigidBody1_Y, frameM_rigidBody1_Z, frameM_rigidBody2_X, frameM_rigidBody2_Y, frameM_rigidBody2_Z,..., frameM_rigidBodyN_X, frameM_rigidBodyN_Y, frameM_rigidBodyN_Z;
The orientation is stored in RADIANS, in roll-pitch-yaw triplets. For N rigid bodies and M frames:
rotation_array = [
frame1_rigidBody1_roll, frame1_rigidBody1_pitch, frame1_rigidBody1_yaw, frame1_rigidBody2_roll, frame1_rigidBody2_pitch, frame1_rigidBody2_yaw, ..., frame1_rigidBodyN_roll, frame1_rigidBodyN_pitch, frame1_rigidBodyN_yaw;
frame2_rigidBody1_roll, frame2_rigidBody1_pitch, frame2_rigidBody1_yaw, frame2_rigidBody2_roll, frame2_rigidBody2_pitch, frame2_rigidBody2_yaw, ..., frame2_rigidBodyN_roll, frame2_rigidBodyN_pitch, frame2_rigidBodyN_yaw;
.
.
.
frameM_rigidBody1_roll, frameM_rigidBody1_pitch, frameM_rigidBody1_yaw, frameM_rigidBody2_roll, frameM_rigidBody2_pitch, frameM_rigidBody2_yaw,..., frameM_rigidBodyN_roll, frameM_rigidBodyN_pitch, frameM_rigidBodyN_yaw;
By NDI's convention,
'ROLL' is when I spin the Z axis, so the angle is calculated from the X and Y coordinates.
'PITCH' is when I spin the Y axis, so the angle is calculated from the X and Z coordinates, but the angle has to be reversed when calculating this using coordinate data.
'YAW' is when I spin the X axis, so the angle is calculated from the Z and Y coordinates.