UNC Magnetic Tracker Calibration Research
Magnetic tracker calibration data and code
This data, code, and
configuration file set was used to generate the results
in the Presence article and the AR snapshots on these web pages. The format
of the data files is as follows.
Each file has a given number of "samples." Each sample consists of a
given number of readings from the magnetic tracker (FOB), then a given
number of readings from the mechanical tracker (Faro), and then the
time that elapsed (in seconds) between the first reading (from either)
and the last reading (from either). A reading consists of seven
numbers (in this order): the x, y, and z position
measurements (in meters), and the x, y, z, and
w components of a quaternion. All numbers are IEEE standard
double-precision floating point values in big-endian byte order.
Associated with each file is a set of auxiliary transformations.
These transformations close the loop involving the two trackers, as
described in the paper. A set of auxiliary transformations can be
associated with more than one data set, as is the case below.
The files are given by their name and by the compressed name. Only
one link per file will be a valid link at a given time, but I don't want to
promise which one. There is no difference in the data stored, only in
whether or not the file is compressed (with gzip).
The number of readings is indeed the same for all files. There are 11
from the magnetic tracker and 3 from the mechanical tracker. The
readings constitute the transformations (respectively) from the
magnetic tracker's sensor to the magnetic field transmitter and from
the Faro tracker's tip to the origin of the Faro's coordinate system.
The transformations in the auxiliary transformations file are derived
from the configuration of our lab and equipment and are explained
- A 4x4 homogeneous transformation matrix from the Faro coordinate
system to the world coordinate system (denoted by a wooden frame,
hence the name "faro2fram" in the transformation file).
- A 4x4 homogeneous transformation matrix from the world to the FOB
transmitter's coordinate system (fram2asce).
- An xyz-quaternion pair that transforms to the Faro tip's space
(a plastic rod, hence the name "rrod") from a corrected version
of the tip coordinate system ("rrodc2rrodu") that places and
aligns it where we wanted it to be but couldn't determine an easy
calibration method to align it with the Faro's automatic tip
calibration method. This basically sets up the tip-to-sensor
transformation, described below. Note the punctuation in this
- A 4x4 homogenous transformation matrix from the corrected tip
system to the sensor's computed coordinate system ("rrodc2srod")
see the FOB manual and the paper).
The paper makes reference to a number of parameters that can be set to
change the calibration table that results. Here are the values that I
- Position noise metric maxima (FOB, Faro) = 0.020, 0.0075 meters
- Orientation noise metric maxima (FOB, Faro) = 0.050, 0.018 meters
- Minimum number of points used to build a grid point = 2 (though
sometimes I allowed 1 under certain conditions to avoid cutting
the table down in places I did not want to cut it - this is
necessary with the extents below).
- Minimum cumulative Gaussian weight to build a grid point = 0.010
- Maximum allowed distance of center of gravity of points used to
build a grid point from the grid point = 0.015 meters
- Gaussian kernel cutoff radius = 0.15 meters
- Gaussian kernel sigma = 0.05 meters
Extents of the table I built:
The following is a list of the code modules that you need and a brief
description of what each one does. There is also a archive of all the code
files in GNU tar format, code.tar.gz.
- Makefile - GNU Makefile, has targets for which
code is not included, and are unnecessary for computing the calibration.
The most interesting of the code not included is the flythrough of the
data (Makefile target: disptable) which was used to generate the
visualizations in the paper. For compiling on an SGI, you should use
an argument of opt=-D__SGI (two underscores) or else you will
get undefined symbols.
- points.c - main program for resampling the
unstructured data into a regular look-up table
- tabletest.c - main program to test the table,
i.e. correct the samples and see what the a posteriori error is.
- file.c, file.h - module for
low-level reading of the data files
- data.c, data.h - module for
higher-level reading and low-level analyzing of the data
- config.c, config.h - module
for reading configuration input files. Sample files are below.
- svd.c, svd.h - C wrapper for
NetLib ForTran code for SVD decomposition of matrices
- svdF.f, blas.f - NetLib ForTran
code for SVD decomposition of matrices
- quatext.c, quatext.h -
module of high-level quaternion, matrix, and vector operations
- cog.c, cog.h - module for moving
the grid point closer to its intended location (use of this does not make
much difference, as noted in the article)
- stax.c, stax.h - module for
computing statistical quantities on the fly: minimum, maximum, average,
and standard deviation
- time.c, time.h - an old version
of the SGI-specific time module, which memory-maps the free-running
hardware timer. A more recent version is available on
my web page, but the
version here may be necessary to get the code to compile and run
- table.c, table.h - module to
read in the table and correct samples in real time
You will also need to have the quaternion library
that was developed based on Ken Shoemake's 1985 SIGGRAPH paper (specifically,
the code in the Appendix) that does basic operations involving quaternions.
Various UNC students have added to it over the years. This code is public
domain, but please give credit to both Ken Shoemake and to the UNC Graphics
Lab if you pass it along.
NOTE: There is one catch with this library, however. It was modified
since I used it with the code in question. It should still work, but
if it doesn't, then let me know. The best test is to run the code first on my
data and see if you get my numbers. If not, something is different.
NOTE: Much of this code has code commented out with #if 0 and
other compiler directives (e.g. #ifdef). Most of these are options
that are discussed in the paper and make little difference in the performance.
You are encouraged to try these options and see if the performance you get is
significantly different. I would very much like to hear of results that change
greatly with different options enabled for, say, the averaging method for
rotations used in table look-up, center of gravity correction, et al.
Finally, you will need sample configuration files. Here are the three files
that I used to build the most recent table and to test it, although some of
the numbers may have been changed. I believe the list on this page (above) is
correct. What this file will tell you is which data files I used. You will
have to correct the pathnames given to the data files listed within the
If anything here is unlcear or you have trouble downloading something,
feel free to send me mail.
This work is part of the UNC
Ultrasound Visualization project.
Last Modified: 15 May 98 by Mark A. Livingston