Difference between revisions of "Coordinate systems"

From biophysics
Jump to navigation Jump to search
Line 201: Line 201:
  
 
<pre>
 
<pre>
point = [1;0;0]
 
  
Rx = rotx(angle1)
+
In the biofysica toolbox you the function Rx, Ry and Rz. These functions generate rotation matrices.
Ry = roty(angle2)
+
Mx = Rx(angle1)
Rz = rotz(angle3)
+
My = Ry(angle2)
 +
Mz = Rz(angle3)
 +
 
 +
In case the rotations are small (say smaller than 1 degree) the order
 +
 
 +
M = Mz * My * Mx
 +
 
 +
When the rotation is done in multiple steps you have:
 +
 
 +
M_total = M(1) * M(2)  * .... * M(n-1) * M(n) for rotations in the device coordinates.
 +
M_total = M(n) * M(n-1) * .... * M(2)  * M(1) for rotations in the room coordinates.
 +
 
 +
--------------------------------------------------------------------------------------
 +
if you have the Aerospace Toolbox you can use rotx, roty and rotz (angles in degrees)
 +
Mx = rotx(angle1_deg)
 +
My = roty(angle2_deg)
 +
Mz = rotz(angle3_deg)
 +
--------------------------------------------------------------------------------------
  
rotatedPoint = Ry * point
 
  
N.B. angles in degrees
 
 
</pre>
 
</pre>
  

Revision as of 13:36, 30 April 2024

Introduction

In the three dimensions of our world you can define different coordinate systems. In our auditory labs a subject is placed with his head in the center of the speaker setup (a sphere or semi-circle). We define the coordinate systems in this situation with respect to the default position of the head of the subject.

Normally we are interested in the direction of a stimulus and we define the directions with the angles azimuth and elevation in a double polar coordinate system. This system is a non-conventional coordinate system that is not often used beyond auditory experiments.

  • Coordinates systems are defined with respect to the default gaze position in the experiment.
  • When stimulus positions are specified, the coordinates are expressed in double polar coordinates.
  • When we want to use a Cartesian coordinate system we will adopt the medical coordinate system "RAS".
  • Our EMF head tracking system uses three orthogonal axis: Horizontal, Frontal, Vertical. We refer to them as H, F and V.
  • Equipment with IMU's can have use different definitions for Cartesian coordinates. In case of head trackers they have to be converted to the medical coordinate system.
  • We will have no fixed Cartesian coordinate system referred to by X, Y and Z in our lab.
  • Our Gitkab\biofysica toolbox has classes and transformation functions for RAS, Double Polar and Spherical coordinate systems.
  • Use of coordinate systems and transformations between coordinates systems should be made explicit in all documentation and programs.

The Spherical Coordinate System is more standard and is widely used. When your are interested in the Spherical coordinate system you have to ask Wikipedia or other sources.

Medical Cartesian coordinates

For a body (or head) a medical notation is often adopted:

left (L) 
right (R)
anterior (A)
posterior (P)
superior (S)
inferior (I)

Cartesian coordinates in 3 dimensions are normally described by triples. For describing the position of the head of a person we will adopt the 'RAS'-convention:

R-axis: from left (-R) to right (+R)
A-axis: from back (-A) to front (+A)
S-axis: from bottom (-S) to top (+S)

The origin in this system is chosen right between the ears.

In terms of unit vectors: S-hat is the outer product of R-hat and A-hat.

Double Polar coordinates

The double polar coordinates are called azimuth , elevation and radius. The azimuth defines a semi-circle parallel to the AS plane. The elevation defines a circle parallel to the RA plane. The intersection of the azimuth circle and the elevation circle is the target point. Since there are two intersections (most of the time), the hemisphere of the intersection has to be specified in order to resolve the ambiguity.

azimuth

  • Azimuth is the angle with the AS plane.
  • pi/2 <= azimuth <= pi/2 (or -90° <= azimuth <= 90°)

elevation

  • Elevation is the angle with the RA plane
  • pi/2 <= elevation<= pi/2 (or -90° <= elevation <= 90°)

radius

  • Radius is the distance from the origin to a target point

hemisphere

  • Hemisphere is +1 for a point in the forward hemisphere.
  • Hemisphere is 0 for a point in the RS-plane (A=0).
  • Hemisphere is -1 for a point in the backward hemisphere.

consistency check

There is a constraint on azimuth and elevation:

azimuth + elevation <= pi (or azimuth_deg + elevation_deg <= 90°)

Transforming double polar to RAS coordinates

right    = radius * sin(azimuth)
superior = radius * sin(elevation)
anterior = hemisphere * sqrt(radius^2 - Right^2 - Superior^2)

Transforming Cartesian to double polar coordinates

In the origin we have by definition azimuth = 0 and elevation = 0.

radius     = norm([right,anterior,superior])
azimuth    = arcsin(right   /radius)    
elevation  = arcsin(superior/radius)
hemisphere = sign(anterior);

Matlab

Angles

Standard trigonometry functions in Matlab use radians as unit for angles. Inside your programs it is advised to use only radians in the code and convert to degrees when presenting values for angles on screen, or in an output file. When reading from screen or input file you should convert degrees to radians at the first assignment.

  • When variables use degrees they should have the suffix _deg in the name.
  • It is recommended to use the matlab conversion functions between radians and degrees:
angle     = deg2rad(angle_deg)
angle_deg = rad2deg(angle)

Trigonometric functions

Matlab has all kind of standard trigonometric functions working with radians or with degrees. When degrees are used it is recommendable to add the suffix "_deg" to your angle variables.

Standard trigonometric functions using radians:

x = sin(angle)
x = cos(angle)   
x = tan(angle)
angle = asin(x)
angle = acos(x)
angle = atan(x)
angle = atan2(y, x)

Standard trigoniometric functions using degrees:

x = sind(angle_deg)
x = cosd(angle_deg)   
x = tand(angle_deg)
angle_deg = asind(x)
angle_deg = acosd(x)
angle_deg = atand(x)
angle_deg = atan2d(y, x)

Coordinate system representations

In the Gitlab in biofysica\utilities\coordinates\RAS_DP_SPH there are classes for the coordinates

coordinates_DP.m
coordinates_DP_withID.m
coordinates_RAS.m
coordinates_RAS_withID.m
coordinates_SPH.m
coordinates_SPH_withID.m

The classes with suffix "_withID" are meant for relating coordinates to IDs of Leds or Speakers.

RAS coordinates is the standard for coordinates relative to body or head orientation. It has the following fields:

   - ID (optional)
   - right (in meters)
   - anterior (in meters)
   - superior (in meters)

In our auditory experiments the default head position is the reference orientation and the origin is taken between the ears of the subject.

Double Polar coordinates

   - ID (optional)
   - azimuth (in radians)
   - elevation (in radians)
   - radius (in meters)
   - hemisphere (+1, 0 or -1: stands for forward, in between or backward hemisphere)

Spherical coordinates

   - ID (optional)
   - azimuth (in radians: 0 to 2pi positive X-axis is 0)
   - elevation (in radians: -pi to pi positive Y-axis is 0)
   - radius (in meters)

Example code:

right    = 0.5; % in meters
anterior = 0.5; % in meters
superior = 0.5; % in meters

% create a stimulus position in RAS:
stimulusPos_RAS = coordinates_RAS(right, anterior, superior);

% transform the stimulus position from RAS to double polar:
stimulusPos_DP = transform_RAS2DP(stimulusPos_RAS);

Coordinate transformations

RAS <==> DP <==> SPH

The biofysica repository has the following transformation functions:

and conversion functions between coordinates:

transform_DP2RAS.m  (Double Polar to RAS)
transform_DP2SPH.m  (Double Polar to Spherical)
transform_RAS2DP.m  (RAS to Double Polar)
transform_RAS2SPH.m (RAS to Spherical)
transform_SPH2DP.m  (Spherical to Double Polar)
transform_SPH2RAS.m (Spherical to RAS)

They all have a single input parameter in the form of a struct or table and a single output parameter in the form of a table. Angles are always in radians.

  • HVF2DP_withNetCalibrationFile (Field coil reading to Double Polar)

The HVF2DP has an extra parameter NetCalibrationFile, that should contains the filename of the latest calibration.

XYZ ==> RAS

In order to transform XYZ to RAS coordinates you have to specify a 3x3 transformation matrix.

E.g. If the X-saxis is pointing to Superior, the Y-axis to Right and the Z-axis pointing to Anterior you get the following transformation matrix:

XYZ2RASdefinition = [0, 1, 0;
                     0, 0 ,1;
                     1, 0, 0];

You define the transformation matrix can use the transform function:

RAScoordinates = transform_XYZ2RAS(XYZcoordinates, XYZ2RASdefinition)

Build in Matlab functions for rotating Cartesian triples

For rotations of Cartesian coordinates Matlab uses a 3x3 matrix working on the XYZ row vector. For rotations around the axis there are functions that create these 3x3 matrices:


In the biofysica toolbox you the function Rx, Ry and Rz. These functions generate rotation matrices.
Mx = Rx(angle1)
My = Ry(angle2)
Mz = Rz(angle3)

In case the rotations are small (say smaller than 1 degree) the order 

M = Mz * My * Mx

When the rotation is done in multiple steps you have:

M_total = M(1) * M(2)   * .... * M(n-1) * M(n) for rotations in the device coordinates. 
M_total = M(n) * M(n-1) * .... * M(2)   * M(1) for rotations in the room coordinates. 

--------------------------------------------------------------------------------------
if you have the Aerospace Toolbox you can use rotx, roty and rotz (angles in degrees)
Mx = rotx(angle1_deg)
My = roty(angle2_deg)
Mz = rotz(angle3_deg)
--------------------------------------------------------------------------------------


Older biofysica functions

N.B. These are not recommended for new code.

Here are some earlier functions that are using different conventions are:

varargout = azel2cart(AZ,EL,R)
azel      = cart2azel(x,y,z)
azel      = xyz2azel(x,y,z)
[PostRotAZ,PostRotEL] = rotate2d(azimuth,elevation,Beta)
[X,Y,Z] = pitch(X,Y,Z,Angle)
[X,Y,Z] = yaw(X,Y,Z,Angle)

N.B. all angles are in degrees

Stimulus position lookup tables

Setups with different speaker and led positions have a lookup table for the stimulus positions in the form of an excel file. The excel file should have a sheet with the name 'DP' for data in double polar coordinates. The sheet should have five columns with the headers 'ID', 'azimuth', 'elevation', 'radius', 'hemisphere'.

stimulusPos = readtable(fname, 'sheet',  'DP');

The function 'readtable' outputs a table with the named column headers that are accessable in the same way as fields of a struct.

ID = stimulusPos.ID;
azimuth = stimulusPos.azimuth;
etc....

Head tracking

Field coil head tracking

Field coil head tracking is a method for movement detection. A pickup coil mounted on the head of the subject is picking up modulated magnetic fields. Three lock-in amplifiers splits the signal from the head coil into three components, horizontal, vertical and frontal. These components are measured as voltages.

The convention for head tracking directions (H,V,F) are related to body coordinates in the following way:

Horizontal: H = R positive signal when looking right
Vertical:   V = S positive signal when looking up
Frontal:    F = A positive signal when looking forward

In Gitlab biofysica\utilities\coordinates\RAS_DP_SPH there is a function 'transform_HVF2DP_withNetCalibration.m' that uses a netcalibration file in order to transform the (H,V,F)-voltages into double polar coordinates.

Head tracker with IMU

Each head tracker with an IMU has its own XYZ coordinate system. In order to transform this to RAS coordinates we have to use a device specific transformation matrix. In the biofysica toolbox there is a function for each device (definition_XYZ2RAS_<devicename>) that generates a struct with a description of the definition for the XYZ2RAS transformation and a transformation matrix. This struct can be readily used as the input for the function transform_XYZ2RAS.

Here is an example of a transformation of XYZ coordinates to RAS coordinates of a head tracking device:

%get X, Y and Z from the device (X, Y and Z can be column arrays)
X = get_X_fromTheDevice;
Y = get_Y_fromTheDevice;
Z = get_Z_fromTheDevice;

% create a XYZcoordinates object
XYZcoordinates = coordinates_XYZ(X,Y,Z);

% transform to RAS coordinates
RAScoordinates = transform_XYZ2RAS(XYZcoordinates, definition_XYZ2RAS_devicename);

% this is what you get
R = RAScoordinates.right
A = RAScoordinates.anterior
S = RAScoordinates.superior

Conventions for expressing angles in text

An angle is normally expressed in radians or degrees.

One radian corresponds to the angle for which the arc (s) on a circle equals the radius (r), thus 1 rad = s/r = 1. In the SI standard 1 rad = 1 per definition, so rad is dimensionless. Therefore it is not necessary to explicitly use it. Only when confusion is possible you should mention it as the unit behind a value.

The other convention for angles is the degree. The conversion between radians and degrees follows from the relation 360° = 2π rad. Note that the degree, with the symbol °, is not a unit of the SI. When expressing angles in degrees the use of the symbol ° is mandatory.

When using trigonometric formulae you have to be aware that by default these functions use radians. If you want to use constants expressed in degrees you have to use the degree symbol °. The following expression are equivalent:

X and L in meters, angle in radians

   X = L * sin(pi/2) 

is equivalent to: 

   X = L * sin(90°)

and

   angle = pi   + arcsin(Y/L) 

is equivalent to:
 
   angle = 180° + arcsin(Y/L)