Skip to content

TRN Quick Start Guide : libtrnav use and configuration

At it's core, TRN is relatively simple to use. The quick start guide takes you through the basic steps:

- Building libtrnav
- Creating a TRN instance
- Setting TRN configuration options
- Understanding TRN Parameters
- Providing TRN input : using PoseT and MeasT data structures
- Interpreting TRN output (position estimates)

An example application, trn-player, is included.

Contents

Building libtrnav

Dependencies

  • libnetcdf
  • mframe (MBARI internal repo, git@bitbucket.org:mbari/mframe.git)
  • libpthread
  • libm
  • libcurl (for some versions of NetCDF)
  • libhdf5 (for some versions of NetCDF)
  • librt (some linux builds)

libtrnav may be built with either cmake or gnu make. cmake is the preferred build system.

In the following sections the following convention is used:

  • $TRN_BUILD : directory containing libtrnav (and mframe) repo(s)
  • $LIBTRNAV : path to the libtrnav repo
  • $MFRAME : path to the mframe repo
  • $SANDBOX : path to directory containing libtrnav installation and libtrnav-data

These environment variables are used only to create a consistent frame of reference in the documentation and examples; they are not required for TRN or referenced by any of the software.

Build Sandboxed Installation for trn-player Example

libtrnav includes a script, opt/examples/trn-player/pkg/trnplayer-sandbox.sh that generates a sandboxed build for the trn-player example:

$LIBTRNAV/opt/examples/trn-player/pkg/trnplayer-sandbox.sh -v

The script is also available in the Appendices.

creates directory trnplayer-<id> (TRN_BUILD) containing the sandbox directory (SANDBOX). If the -k option is used, the libtrnav and mframe directories are preserved; otherwise, they are deleted from trnplayer-<id>.

Alternatively, mframe and libtrnav may be built manually (installed to trnplayer/sandbox) as follows:

# create TRN_BUILD directory, go there
mkdir trnplayer
cd trnplayer
export TRN_BUILD=$PWD

# build mframe
cd $TRN_BUILD
git clone git@bitbucket.org:mbari/mframe.git
cd mframe
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=$PWD/pkg ..
cmake --build .
cmake --install .

# build libtrnav, install to TRN_BUILD/sandbox
cd $TRN_BUILD
git clone git@bitbucket.org:mbari/libtrnav.git
cd libtrnav
mkdir build
cmake -DCMAKE_INSTALL_PREFIX=$TRN_BUILD/sandbox ..
cmake --build .
cmake --install .

# set SANDBOX environment variable
cd $TRN_BUILD/sandbox
export SANDBOX=$PWD

# install libtrnav-data (optional, to run trn-player examples)
cd $SANDBOX
git clone git@bitbucket.org:mbari/libtrnav-data.git

General Build and Installation

It is recommended to build libtrnav using cmake. The general build instruction are similar to the sandboxed example, except that libtrnav is installed to the default location (/usr/local) or another directory:

# build libtrnav
cd $TRN_BUILD
git clone git@bitbucket.org:mbari/libtrnav.git
cd libtrnav
mkdir build
cmake ..
cmake --build .
cmake --install .

Use option -DCMAKE_INSTALL_PREFIX=<path> when configuring libtrnav to install to another directory (e.g. as in the sandboxed build).

All cmake build output goes to the build directory.

If mframe is not installed to one of the default locations:

  • /usr/local
  • TRN_BUILD/mframe/build/pkg

the MFRAME_PKG option must be specified when building libtrnav :

cmake -DMFRAME_PKG_PATH=<path> [options...] ..

cmake build options

cmake options include

buildOptROV=ON|OFF     Enable build of opt/rov libraries and applications
buildTrnNoRand=ON|OFF  Disable TRN random seed generation
buildTrnLog=ON|OFF     Disable binary TRN log
buildTrnLogEst=ON|OFF  Disable binary TRN estimate log
buildTrnCEPCorr=ON|OFF Enable CEP correction (deprecated, don't use)

enable during cmake configuring using

cmake -D<option>=<value>...

The install path for cmake may be configured using

cmake -DCMAKE_INSTALL_PREFIX=<path>...

or during install using

cmake --install . --prefix=\<path\>

In both cases, the install path should be absolute.

Build with gnu make (deprecated)

The core libraries are built using

make
sudo make install

components that require libmframe are built with the trnc target.

make trnc

for a full list of targets (including application-specific), use

make help

The install path for gnu make is generally set using the environment variable PREFIX. The environment variable DESTDIR may also be used for greater flexibility:

${DESTDIR}${PREFIX}/...

Note that DESTDIR should include a trailing slash, PREFIX should not.

gnu make output goes to the libtranav/bin and libtrnav/build. The build directory contains intermediate files, bin contains libraries and executables.

tar.gz distribution

The top level Makefile includes a dist target that builds a tar.gz distribution, libtrnav-\<version>.tar.gz

The opt/sentry directory includes a script for packaging libtrnav and libmframe, along with scripting to configure and install them using either cmake or gnu make. This is used to distribute libtrnav for the WHOI Sentry vehicle. This is a convenient way to distribute the code and build stand-alone installations in a test directory.
Details are provided in opt/sentry/README-trndev-build.md.

Build Doxygen doc

The libtrnav doc directory contains a Doxygen configuration file; while the code does not consistently include doxygen markup, Doxygen generates a fairly sensible package that is convenient to navigate. It may be built using the gnu make doc target:

make doc

Output will be written to doc/doxygen.out

libtrnav Contents

See the Software Guide for a list of libtrnav applications and libraries.

Creating a TRN instance

The C++ API has a number of constructors with different configuration information, for example:


// minimal constructors
TerrainNav();

// commonly used 
TerrainNav(char *mapName, char *vehicleSpecs,
             const int &filterType, const int &mapType);

TerrainNav(char *mapName, char *vehicleSpecs,
             const int &filterType, const int &mapType, char *directory);

TerrainNav(char* mapName, char* vehicleSpecs, char* particles,
             const int& filterType, const int& mapType, char* directory);

The C API constructor takes a trn_cfg_t structure. The structure members are used to invoke a C++ constructor.

wtnav_t *wtnav_new(trn_cfg_t *cfg);

The C++ TRN constructor arguments are described in the following section.

In the quick start section, we'll reference the C++ API; the basic steps are similar for the C API, in which the trn_cfg_t structure replaces the constructor arguments.

It's worth noting that TRN may be run as a TCP/IP server using the trn-server application. trn-server enables applications to perform TRN functions via TCP using TrnClient (or it's base class TerrainNavClient). trn-server configuration is essentially the same as for a TRN instance constructed in an application.

Configuring TRN

Consider the parameters passed to the TRN C++ constructor, summarized in the following table and explained below.

Parameter Description
mapName map file name; format should match type specified by mapType argument
(path is specified using TRN_MAPFILES environment variable)
vehicleSpecs Vehicle specs file name; contents defined below
(path is specified using TRN_CONFIGDIR environment variable)
filterType An integer (enumeration) indicating a TRN filter variant. While several experiment filter types exist, filter type 2 (TRN_FT_PARTICLE, a particle filter) is used almost exclusively.
mapType An integer (enumeration) indicating a TRN map format:
1 : TRN_MAP_DEM Digital Elevation Map (.GRD)
2 : TRN_MAP_BO Binary Octree Map (.BO)
directory directory in which to save TRN logs and store copies of config files
particles particle file name (logs particle file information; optional (a lot of data)

Applications typically use a configuration file and environment variables to obtain values used to construct TerrainNav and/or initialize utility classes TNavConfig or TrnAttr that are used to manage configuration values. TrnAttr is used to parse and use key/value pairs primarily used for terrainAid.cfg.


Fig: TRN configuration

The map files, configuration files, and environment variables are described in greater detail in the following sections.

Application Configuration Files

There are three files strictly required to configure TRN:

File Description
Map file Contains TRN map data in one of two supported formats
Vehicle specification file Enumerates bathymetry sensors used by TRN and describes mounting geometry
Sensor specification file(s) Describes sensor beam geometry and other TRN parameters
referenced by the vehicle specification file.

The format and content of these is described below.

Though each application is different, most use a configuration file and environment variables to specify TRN configuration parameters, though it is not strictly required.

terrainAid.cfg

Some applications use a file called terrainAid.cfg to load configuration values; it is convenient, but not required. The trn-player example app also includes a configuration file parser that supports terrainAid.cfg syntax.

terrainAid.cfg is a text file with key/value entries using the format:

// comment...
key = value;

Commonly used parameters include:

Parameter Description
mapFileName map file name (path specified by TRN_MAPFILES)
map_type Numeric map type value (1: DEM/GRD 2: BO)
vehicleCfgName vehicle specification file
resonCfgName Reson multibeam sonar sensor specification
dvlCfgName DVL sensor specification file
filterType type of TRN filter (usually 2: particle filter)
terrainNavServer TRN server IP address
applies only to trn-server (TRN via TCP/IP)
terrainNavServer TRN server IP port
applies only to trn-server (TRN via TCP/IP)
allowFilterReinits enable TRN filter reinitialization if true

These values are used primarily by the replay application (libtrnav/opt/dorado):

Parameter Description
samplePeriod for DVL, used to skip lines with timestamps inside previous sample
useMbTrnData Use the MbTrn data format (MbTrn.log) if true, otherwise use TerrainAid.log
lrauvDvlFilename use lrauv log data
useIDTData use Imagenex DeltaT data
maxNorthingCov convergence criteria
maxEastingCov convergence criteriay
maxNorthingError convergence criteriay
maxEastingError convergence criteria

Other parameters that are experimental or used for debug may generally be excluded or commented out; these include

Parameter Description
particlesName name of particles file (logs particle state information).
IO/storage intensive; generally for debugging
useModifiedWeighting select one of several alternative particle weighting schemes.
forceLowGradeFilter deprecated?

In practice, applications like replay populate a (singleton) TNavConfig instance or TrnAttr using the contents of a configuration file. The TrnAttr struct contains a set of elements associated with terrainAid.cfg, a config file used by Dorado and some other applications. The TrnClient uses TrnAttr, and replay has code for parsing terrainAid.cfg into TRN_attr. TrnAttr should be used for new applications that use terrainAid.cfg keys.

In contrast, the TrnPlayer example in the Quick Start Guide does not require a configuration file. It uses the TrnPlayerCtx to parse options passed on the command line. The context class contains configuration values and instance variables. This pattern helps to support multiple instances concurrently. TrnPlayer does support an extended terrainAid.cfg syntax, and TrnPlayerCtx includes parsing code.

The ROV TRN implementation (libtrnav/opt/rov) uses a similar context base approach; it's trnxpp_ctx context class supports both command line and configuration files.

Environment Variables

Several environment variables may be used to set the paths file arguments, though it is not required by TRN per se. This is done to enable use cases in which TRN configuration parameters are passed remotely, e.g. to a TRN server instance, whose host environment may differ from the callers.

Core Environment variables are summarized in the following table; additional variables are described in later sections.

Environment Description
TRN_LOGFILES Output directory for TRN logs and config file copies
TRN_DATAFILES Input directory for TRN config files (e.g. vehicle specs, sensor specs)
TRN_MAPFILES Path to TRN map files

Map Files

As indicated above, TRN supports two map file formats: digital elevation maps (.GRD) or binary octree files. Binary octrees are typically used, and though a single monolithic map file may be used, they are often sub-divided into smaller tiles that reduce memory use. Tools exist in the libtrnav repository to generate tiled GRD and BO maps.

When tiled maps are used, they must be stored in the same directory, along with a tiles.csv file defining the tile boundaries.

The name of the map directory or single map file is passed to the TRN constructor, and the TRN_MAPFILES environment variable set accordingly.

Vehicle and Sensor Spec Files

There are two types of configuration files associated with libtrnav: the vehicle specification file and one or more sensor specification files. These are required by TRN.

The vehicle spec file specify some TRN parameters, and enumerates the sensors that will be used by TRN, and describes mounting orientation. Each of the sensors is defined in a separate sensor spec file, and defines additional sensor-specific TRN parameters, e.g. beam geometry. These are described in detail below, with examples.

With these files, TRN supports processing bathymetry (beams) from several types of commonly used sensors - e.g. DVLs and multibeam sonars; the parameters they describe are primarily about describing the sensor geometry and orientation with respect to the platform. TRN is able to apply the appropriate geometry calculations to bathymetry inputs for the given navigation and attitude.

There are use cases that don't fit typical fixed sensors, for example, in a system in which a bathymetry sensor is on a rotating platform, the mounting angles change dynamically. In such cases, the application may set the relevant configuration file parameters to zero, and geometry calculations for TRN inputs will need to be computed by the application.

Vehicle Specification File

The vehicle specification file is a text file containing a list of sensor config files, sensor mounting geometries, and a process noise parameter. It's format is rigid; it uses a naming convention <NAME>_spec.cfg, and its contents are arranged as follows:

# comments...

NAME:<config file name (w/o _spec.cfg)>
NUMSENSORS:<number of sensor entries (integer)>
DRIFTRATE:<process noise figure (floating point)>

SENSORNAME:<sensor spec file name (w/o _spec.cfg)>
DR:<phi>,<theta>,<psi>
DT:<x>,<y>,<z>
...

Example: Vehicle Spec File

# Vehicle specification sheet
#----------------------------
NAME:mappingAUV
NUMSENSORS:3
DRIFTRATE:1.5

SENSORNAME:rdiDVL
DR:0,0,0
DT:0,0,0

SENSORNAME:resonSeabat8101
DR:0,0,0
DT:0,0,0

SENSORNAME:imagenexdeltat
DR:0,0,0
DT:0,0,0

The parameters are described as follows:

Name Description/th>
NAME Configuration name (matches file name, w/o _spec.cfg suffix)
NUMSENSORS Number of sensor entries to follow
DRIFTRATE Somewhat of a misnomer, represents TRN process noise, typically 1.5/2
depends on terrain, instruments, etc.
SENSORNAME name of sensor spec file (w/o _spec.cfg suffix)
DR sensor orientation, NED Euler angles in vehicle frame (degrees)
DT sensor mounting location, distance from vehicle cente (meters)

Mounting geometry parameters DR and DT describe the location and orientation of the sensor with respect to the origin in the vehicle frame of references; typically this is X/FWD, Y/STBD, Z/DOWN, i.e. NED.

DT is the XYZ distance from the vehicle center, in meters. DR are NED Euler angles (phi, theta, psi) with respect to FWD, STBD, DOWN.

Sensor Specification File

The sensor specification files, referenced by the vehicle spec file, are text files containing a bathymetry sensor configuration information. A number of different sensors are supported. It's format is rigid; it uses a naming convention <NAME>_spec.cfg, and their contents are arranged as follows:

# comments...
NAME:<sensor name (matches file, w/o _spec.cfg suffix)>
TYPE: <sensor type (integer)>
NUMBEAMS: <number of beams>
PERCENTRANGEERROR: <range error, %>
BEAMWIDTH: <beam width (deprecated)>

# optional fields, type-dependent
PITCH ANGLES:<comma separated list of pitch angles>
DELTA_PITCH:<pitch angle increment>
INIT_YAW ANGLE:<comma separated list of yaw angles>
DELTA_YAW: <yaw angle increment>
INIT_PITCH ANGLES|starting pitch angle(s) in sensor frame, decimal degrees|
Name Description
NAME Configuration name (matches file name, w/o _spec.cfg suffix)
TYPE Sensor type enumeration value
Value Type
1 : TRN_SENSOR_DVL DVL
2 : TRN_SENSOR_MB Multibeam
3 : TRN_SENSOR_PENCIL Single Beam
4 : TRN_SENSOR_HOMER Homer Relative Measurement
5 : TRN_SENSOR_DELTAT Imagenex multibeam
NUMBEAMS number of beams
PERCENTRANGEERROR estimated range error (% of range)
BEAMWIDTH width of beams, m (deprecated)
PITCH ANGLES sensor beam geometry: pitch angles in sensor frame, decimal degrees
used for non-multibeam types
DELTA_PITCH sensor beam geometry: pitch angle increment, decimal degrees
used for non-multibeam types
YAW ANGLES sensor beam geometry: yaw angles in sensor frame, decimal degrees
used for non-multibeam type
DELTA_YAW sensor beam geometry:yaw angle increment, decimal degrees
used for non-multibeam types

The sensor beam geometry parameters assume that bathymetry sensors have beams that arranged in an angular or radial array at uniform angular intervals, which is true of all currently used TRN sensors.

Multibeam sensors are assumed to extend radially from the sensor origin, i.e. subtending an arc with a specified swath angle, typically 90-120 degrees.

Non-multibeam sensors (e.g. DVLs) are assumed to be arranged in a radial array around the sensor origin, with azimuth YAW ANGLE (relative to E) separated by DELTA_YAW. The beams are pitched downward at PITCH ANGLE, optionally incrementing by DELTA_PITCH. DVLs typically have 4 beams, separated by 90 degrees, oriented at an outward angle with respect to vertical.

For both types of sensors,

Example: multibeam sensor spec file

# Sensor specification sheet
#----------------------------
NAME: resonSeabat8101
TYPE: 2
NUMBEAMS: 20
PERCENTRANGEERROR: 4
BEAMWIDTH: 1.5

PITCH ANGLES: 0
DELTA_PITCH: 0
INIT_YAW ANGLE: 0
DELTA_YAW: 0

Example: DVL sensor spec file

# Sensor specification sheet
#----------------------------
NAME: rdiDVL
TYPE: 1
NUMBEAMS: 4
PERCENTRANGEERROR: 4
BEAMWIDTH: 3.9

PITCH ANGLES:30, 30, 30, 30
YAW ANGLES: -45, 135, 45, -135

#----------------------------------------------------------------
# Sensor beam configuration diagram:
#
# Beam numbering convention, looking down on Dvl from above.  
# x and y are the vehicle axes. x points to port, y to starboard.               
#                                                                        
#                  x                                                     
#                  ^                                                          
#                  |                                                     
#                1 | 3                                                   
#                  |------> y                                            
#                4   2                                                   
#                                                                        
# Each beam is spaced 45 degrees from the horizontal/vertical.            
# The inclination angle is 30 degrees.        

Relevant files in the repository include:

terrain-nav/TerrainNav.h,cpp
terrain-nav/structDefs.h
trnw/trn_msg.h

Other TRN Configuration: run-time and compilation options

To recap, we've looked at TRN inputs and parameters required to create a TRN instance:

  • configuration file (e.g. terrainAid.cfg)
  • map file
  • vehicle spec file
    • Number of sensors
    • Navigation drift rate
    • Bathymetry sensor specification list and mounting geometry
  • sensor spec file(s)
    • sensor name and type
    • estimated range error
    • beam geometry

Run time TRN Configuration

The following table summarizes TRN parameters that may be set at run-time:

Parameter File Description
setVehicleDriftRate(double &driftRate) terrain-nav/TerrainNav.h Sets the vehicle inertial drift rate parameter.
The driftRate parameter is given in units of % drift in meters/sec.
Default : value in vehicle specification sheet.
setFilterReinit(bool allow) terrain-nav/TerrainNav.h Enable TRN filter reinitialization.
Default: false
void setEstNavOffset(double offset_x, double offset_y, double offset_z) terrain-nav/TerrainNav.h This function sets the x, y, z values of the estNavOffset structure that holds the prior offset estimate. This function is used prior to a particle filter reinit callvin order to force the reinit to be centered on a particular offset value rather than the actual last offset estimate. This capability was created for use by the MB-System program mbtrnpp so that reinit could, if necessary, be forced to be centered on a zero offset or a prior very good offset estimate if that is known. Resetting the prior offset estimate addresses the occasional tendency of TRN to converge on similar topoography far from the actual location - when this occurs convergence will soon be lost, but the reinit should be centered on a more likely position if that is known external to TRN.
setInitStdDevXYZ(double sdev_x, double sdev_y, double sdev_z) terrain-nav/TerrainNav.h Values potentially used in reinitFilter and estimatePose Replaces _initVars member variable, use NULL to reset to defaults Using the method except immediately before filter reinitialization (i.e. on a running filter) may give undefined output.

Compile time options

In addition, there are a number of TRN parameters that may be set when compiling libtrnav, described in the table below. This list is not comprehensive; the code contains a number of parameters introduced over time to try out experimental features for research; these are generally disabled and should remain so. Note that these are rarely modified; change only if you know what you are doing.

Parameter File Description
TRN_MAX_BEAMS terrain-nav/structDefs.h Maximum number of bathymetry beams
Default: 120
TRN_MSG_SIZE terrain-nav/structDefs.h Maximum TRN server (commsT) message length (bytes)
Default: 8000
N_COVAR terrain-nav/structDefs.h covariance matrix size for TRN estimates
Default: 45
MAX_PARTICLES particleFilterDefs.h maximum number of particles; note this has a potentially large impact on computational load and TRN performance
Default: 10000
MAX_NIS_VALUE terrain-nav/TerrainNav.h Maximum allowable NIS Windowed Average (used by TerrainNav) Default: 1.4
NIS_WINDOW_LENGTH terrain-nav/genFilterDefs.h Length of NIS window (used by filter) Default: 29
MAX_RANGE terrain-nav/genFilterDefs.h Maximum allowable sonar range Default: 220
MAP_NOISE_MULTIPLIER terrain-nav/genFilterDefs.h Multiplier on map noise in particle filter should be 1.0 usually
MOTION_NOISE_MULTIPLIER terrain-nav/genFilterDefs.h Multiplier on motion noise stdev in particle filter should be 2.0 usually
[XYZ]_STDDEV_INIT terrain-nav/genFilterDefs.h FILTER INITIALIZATION PARAMETERS [XYZ]_STDDEV_INIT values establish a map search area; values have units of meters, and are application-specific. If the distribution is uniform, these comprise a box (see initDistribType, TNavFilter.h). If set incorrectly, TRN may fail to initialize correctly, resulting in errors, e.g.
TerrainNav::Filter not initialized - vehicle is currently within a non-valid region of the reference map

TerrainNav::Cannot compute pose estimate; motion has not been initialized.

Typical values include:
[XY]_STDDEV_INIT
60.0 Portuguese Ledge/Dorado
600.0 Axial/Sentry
[Z]_STDDEV_INIT
5.0 Portuguese Ledge/Dorado, Axial/Sentry
10.0 ?

Providing TRN Input: PoseT, MeasT

Once a TRN instance is configured, it is provided with bathymetry and navigation inputs that it uses to update the particle filter state. Updates are periodically passed to TrN using in an appropriate data structure (poseT, measT) via TRN's input methods: motionUpdate and measUpdate.


Fig: TRN cycle

motionUpdate is used to update vehicle navigation and attitude information. It requiers a poseT structure, and must be called first; calls made to measUpdate before motionUpdate has successfully completed will fail.

measUpdate is used to provide bathymetry at a specified location and attitude to TRN, and requires a measT structure and sensor type.

estimatePose accepts a poseT reference and an estimate type. It returns the current TRN position estimate of the specified type along uncertainties (array of covariances).

The C++ API calls are as follows:

void TerrainNav::motionUpdate(poseT* incomingNav)
void TerrainNav::measUpdate(measT* incomingMeas, const int& type)
void TerrainNav::estimatePose(poseT* estimate, const int &type)

PoseT and MeasT are defined in terrain-nav/structDefs.h.

The C API uses wmeast_t and wposet_t, which are thin C wrappers around PoseT and MeasT objects. wposet_t and wmeast_t are defined in trnw/trnw.h

poseT

The PoseT structure is used for both input and output to TRN.

For input (motionUpdate), most applications populate only a subset of these fields for input:

Parameter Description
time Time in posix epoch seconds (seconds since 1970-01-01T00:00:00)
x,y,z bathymetry sensor origin, world frame (e.g. UTM) (meters)
vx,vy,vz velocity in x,y,z direction (m/s)
phi,theta,psi vehicle pitch, roll, heading, world frame (radians)
dvlValid true if DVL input is valid
gpsValid true if GPS input is valid
bottomLock true if DVL has bottom lock

vx is strictly required for TRN input; vy, vz are optional. The complete structure is shown below.

To fully initialize, TRN requires that a motion update be received with vx (along-track velocity) not equal to zero, which indicates forward motion. Until that happens, TRN emits an error message indicating that TRN has not been initialized when measurement updates are received. Once motion has been established, motion and measurement updates may occur in any order.

vx is used for most configurations to indicate motion, and its value is not critical, but must be != 0 in order for TRN to initialize.

In general, TRN does not require velocity to operate, but in some contexts, velocity may be integrated to determine position, in which case it is needed.

For output (estimatePose), a PoseT instance is passed into estimatePose, which populates these fields:

Parameter Description
time Time in posix epoch seconds (seconds since 1970-01-01T00:00:00)
x,y,z position estimate, world frame (e.g. UTM) (meters)
covariance position estimate uncertainty array:
index description
0 x/N covariance
2 y/E covariance
5 z/D covariance
1 XY covariance

The remaining fields are somewhat application-specific, and may be used in some TRN configurations. The complete poseT structure appears below.

struct poseT {

    double x, y, z;                // North, East, Down position (m)
    double vx, vy, vz, ve;         // Vehicle velocity wrto terrain (m/s) [1]
    double vw_x, vw_y, vw_z;       // Vehicle velocity wrto water (m/s) [1]
    double vn_x, vn_y, vn_z;       // Vehicle velocity wrto an inertial frame (m/s) [1]
    double wx, wy, wz;             // Vehicle angular velocity wrto an inertial frame (rad/s) [1]
    double ax, ay, az;             // Vehicle aceleration wrto an inertial frame (m/s^2) [1]
    double phi, theta, psi;        // 3-2-1 Euler angles relating Body frame to  
                                   // an inertial NED frame (rad).
    double psi_berg, psi_dot_berg; // TRN states

    double time;                   // Time (seconds since 01-01-1970T00:00:00)

    bool dvlValid;                 // DVL measurement valid flag
    bool gpsValid;                 // GPS measurement valid flag
    bool bottomLock;               // DVL bottom lock valid flag

    double covariance[N_COVAR];    // Covariances: XYZ, phi, theta, psi, wy, wz  
                                   // (passively stable in roll) (see above units)

    // [1] coordinates in Body Frame

    poseT();
    poseT& operator=(const poseT& rhs);
    poseT& operator-=(const poseT& rhs);
    poseT& operator+=(const poseT& rhs);

    int   serialize(char *buf, int buflen);
    int unserialize(char *buf, int buflen);
};

measT

The measT structure is used for measurement update (bathymetry) input. In libtrnav, measurements are often referred to as beams; this stems from the fact that TRN bathymetry sensors are historically acoustic instruments, i.e. sonars and DVLs. They could, however, include LIDAR or other sensors. Here, measurement and beams are used interchangeably.

struct measT {
    double time;              // Measurement time (s)
    int dataType;             // Sensor type [1]
    double phi, theta, psi;   // 3-2-1 Euler angles relating Body frame to 
                              // an inertial NED frame (rad).
    double x, y, z;           // North, East, Down position (m)

    double* covariance;       // covariance array [2]
    double* ranges;           // beam ranges [2]
    double* crossTrack;       // beam component perpendiclar to velocity [2]
    double* alongTrack;       // beam component parallel to velocity [2]
    double* altitudes;        // beam component downward [2]
    double* alphas;           // alpha values [2]
    bool* measStatus;         // beam measurement valid flag [2]
    unsigned int ping_number; // measurement number
    int numMeas;              // number of beams
    int* beamNums;            // beam numbers (for sensors w/ variable beams) [2]

    // [1] sensor type enumerations  
    //      1: DVL  
    //      2: Multibeam  
    //      3: Single Beam  
    //      4: Homer Relative Measurement  
    //      5: Imagenex multibeam   
    //      6: Side-looking DVL  
    // [2] array with dimension numMeas

    measT();
    measT(unsigned int nummeas, int datatype);
    ~measT();
    void clean();
    measT& operator=(const measT& rhs);

    int   serialize(char *buf, int buflen);
    int unserialize(char *buf, int buflen);
};  

On input, measT is passed into measUpdate, with these fields populated:

Parameter Description
time Time in posix epoch seconds (seconds since 1970-01-01T00:00:00)
time Time in posix epoch seconds (seconds since 1970-01-01T00:00:00)
x,y,z bathymetry sensor origin, world frame (e.g. UTM) (meters)
phi,theta,psi vehicle pitch, roll, heading, world frame (radians)
dataType sensor type
Value Type
1 : TRN_SENSOR_DVL DVL
2 : TRN_SENSOR_MB Multibeam
3 : TRN_SENSOR_PENCIL Single Beam
4 : TRN_SENSOR_HOMER Homer Relative Measurement
5 : TRN_SENSOR_DELTAT Imagenex multibeam
ranges Beam range (length) array (meters)
numMeas number of beams (size of arrays ranges, crossTrack, etc.)
crossTrack beam range component perpindicular to direction or travel (m)
alongTrack beam range component in direction or travel (m)
altitudes beam range component down (m)
measStatus beam valid flag array (true if valid)
ping_number_ Bathymetry measurement sequence number (assumed to increase monotonically, > 0)
beamNums Beam numbers of ranges and components

To recap, the TRN computation cycle is shown again below, in which TRN is provided with periodic motion and measurement updates (in that order), followed by a call to estimatePose to request a position estimate with uncertainties.


Fig: TRN cycle

The call to estimatePose requires a poseT (to contain the return value), and a measurement type:

void estimatePose(poseT* estimate, const int &type);

The measurement type argument is described below; in general, the MMSE value is used.

Type Description
1: MLE Maximum Likelihood Estimator, which maximizes the probability of observed data
2: MMSE minimum mean square error, which minimizes the expected squared difference between the estimated value and the true value

In other words, MLE is more a peak (best single match), which is potentially an incorrect local maximum. MSE is the best/closest, across the range of estimates.

The covariance array returned has N_COVAR elements, the most commonly used of which are:

Index Description
0 x/N covariance
2 y/E covariance
5 z/D covariance
1 XY covariance

Input streams may be decimated (sub-sampled) as needed. Sensor data streams are typically at different rates. Bathymetry inputs should correspond to the location and attitude associated with them. If data are buffered, be aware that updates should not use data that is too old, or for which there is significant temporal skew between motion and measurement updates.

Example TRN application: trn-player

A reference TRN application called trn-player is included in the libtrnav repository (libtrnav/opt/examples/trn-player).

trn-player provides a minimal demonstration of TRN:

  • Configures a TRN instance
  • Reads bathymetry, navigation, and attitude data from a log file
  • Passes poseT and measT data structures to motionUpdate and measUpdate
  • Calls estimatePose and sends TRN output to the console in CSV format (convenient for plotting), and to log files.

The contents are as follows:

File Description
opt/examples/trn-player/TrnPlayer.hpp,h
opt/examples/trn-player/TrnPlayer.cpp,h
opt/examples/trn-player/TrnPlayerCtx.hpp,h
opt/examples/trn-player/trn-player.cpp,h
terrain-nav/TerrainNav.cpp,h
trn-player source code
opt/examples/trn-player/pkg/trnplayer-sandbox.sh generates sandboxed build for trn-player example

Data and configuration files may be obtained from the libtrnav-data repository: https://bitbucket.org/mbari/libtrnav-data

File Description
libtrnav-data/trn-player/data/csv
libtrnav-data/trn-player/data/mbtrn
libtrnav-data/trn-player/data/tnav
TRN configuration files and data using different log formats.
libtrnav-data/trn-player/maps/PortTiles Binary octree map
libtrnav-data/trn-player/trnplayer.cfg trn-player configuration file

The trn-player example builds with libtrnav; see build instructions above and/or use the trnplayer-sandbox.sh script to build the sandboxed version used below.

In this example, the following conventions are used:

  • $TRN_BUILD : directory containing libtrnav (and mframe) repo(s)
  • $LIBTRNAV : path to the libtrnav repo
  • $MFRAME : path to the mframe repo
  • $SANDBOX : path to directory containing libtrnav installation and libtrnav-data

These environment variables are used only to create a consistent frame of reference in the documentation and examples; they are not required for TRN or referenced by any of the software.

Running trn-player

These instructions show how to use trn-player using sample data that is available in the libtrnav-data repo. This example shows how to run mbtrn, one of several sets in libtrnav-data.

Clone the sample data repo into the $SANDBOX directory, if you haven't already done so:

cd $SANDBOX
git clone git@bitbucket.org:mbari/libtrnav-data.git

The $SANDBOX directory should contain:

bin
include
lib
share
libtrnav-data

Run TRN player using the example configuration file included with libtrnav-data:

cd $SANDBOX

# run trn-player using default settings and verbose output
./bin/trn-player --config=libtrnav-data/trn-player/trnplayer.cfg -v

# for help and other options use
./bin/trn-player -h

The default used above runs a data set from an MbTrn.log; the sample data also includes data from TerrainNav.log, TerrainAid.log, and CSV files (DVL, IDT, and multibeam formats).

To run other other data sets from the example config file, edit the config file, commenting out all but the selected configuration, then run again as above.

To process your own data, use the example configuration file and config file reference ($LIBTRNAV/sandbox/share/README-config.md) to create a new configuration file that references your data, maps, and configuration files, then run as above.

The trn-player default location for maps and data are ./maps and ./data; configuration files are assumed to be located in the data directory. the -c option specifies the config directory.

Alternatively, these methods may be used to reference trn-player inputs:

# Option 1: use data and map symlinks
Make symbolic links to the sample data maps and data:

ln -s libtrnav-data/trn-player/data/mbtrn data
ln -s libtrnav-data/trn-player/maps maps

# Option 2: use the trn-player options to set 
# config (-c), data (-d), and map (-m) directories:

-c "libtrnav-data/trn-player/data/mbtrn" 
-d "libtrnav-data/trn-player/data/mbtrn" 
-m "libtrnav-data/trn-player/maps" 

# Option 3: copy/rename the map, data directories to your directory 

cp -R libtrnav-data/trn-player/maps maps
cp -R libtrnav-data/trn-player/data/mbtrn data

Example: process tnav example data without configuration files

The example data set in libtrnav-data/trn-player/tnav uses the TerrainNav.log and has a different vehicle specs file; if configuration file is not used, options must be passed on the command line to configure trn-player.

Using command line options only:

cd $SANDBOX

./bin/trn-player \
-d "libtrnav-data/trn-player/data/tnav" \
-c "libtrnav-data/trn-player/data/tnav" \
-m "libtrnav-data/trn-player/maps" \
-V "RDIequippedAUV_specs.cfg" \
-s 1 -l 1 -F -v 

# -V : vehicle specs file name
# -s : sensor type DVL
# -l : log type TerrainNav.log
# -F : force beam status flags valid
# -v : verbose output

Or, assuming that symlinks are being used to point to maps and data, the tnav example data may be run by replacing the data symlink to point to the tnav directory and passing the appropriate options on the trn-player command line:

# from the build-trn-player sandbox
cd $SANDBOX

# change the data symlink to point to the tnav data set
rm data
ln -s libtrnav-data/trn-player/data/tnav data

# run with options to set the sensor type, log type
# and vehicle specs name. The -F option forces the 
# beam status flags to valid.
./bin/trn-player -v -s 1 -l 1 -V "RDIequippedAUV_specs.cfg" -F 

Though not strictly required, configuration files can simplify use in command line or scripted contexts.

The trn-player app supports configuration files consisting of key = value pairs, where keys are trn-player long options. In addition, legacy terrainAid.cfg syntax and options are also valid. terrainAid.cfg syntax requires lines to be terminated with semicolons; they are optional for trn-player. There is limited support for using environment variables in config files. A syntax summary is provided libtrnav share directory.

terrainAid.cfg options may be specified as long options to trn-player, e.g. --allowFilterReinits=true.

The following table summarizes trn-player options:

trn-player terrainAid.cfg Argument Description
-c, --cdir - directory string config directory
-C, --config - path string config file path
-d, --ddir - directory string data directory
--dperiod samplePeriod long int msec decimation period (msec)
>0 : Decimates records to match specified input period as nearly as possible
<=0 : Disabled (use all records)
-D, --debug - integer ≥ 0 debug output
-e, --eofile - file name (w/o path) estimate output file name
-f, --ftype filter_type 0: TRN_FT_NONE
1: TRN_FT_POINTMASS
2: TRN_FT_PARTICLE (default)
3: TRN_FT_BANK
values other then 2 are experimental
filter type
-F, --fstat - - force beam status true
(TerrainNav.log input format)
-G, --oflags - flags string (one or more)
p: pretty
m: measurement CSV
e: estimate CSV
q: quiet
S: output MMSE
L: output MLE
B: output both MLE, MMSE
output control flags
-h, --help - - print help message
--interp map_interp 0: nearest-neighbor (none)
1: bilinear
2: bicubic
3: spline
map interpolation method
(DEM maps only)
-i, --iformat - Types and default names
0: MbTrn.log
1: TerrainNav.log
2: TerrainAid.log
3: dvl.csv [1]
4: idt.csv [1]
5: mb.csv [1]

[1] implies moformat = iformat
input file format
-I, --ifile - file name (w/o path) input file name
(override lookup based on input format)
-m, --mdir - directory string map directory
-M, --mfile mapFileName file name (w/o path) map file name
-N, --nfile file name (w/o path) navigation log file name
Only used w/ TerrainAid.log
Note: terrainAid.cfg boolean option useDVLSide sets to dvlSide.log
-o, --odir - directory string TRN output log directory
-O, --mofile - file name (w/o path) measurement output file name
--pfomode - integer enum:
0: HISTOGRAM (distribution summary)
1: PARTICLES (all particles; large data volume)
2: NONE
writes to odir/filterDistrib.txt
log full particle states or a histogram
Note: generates a large volume of data
-P, --pfile particlesName file name (w/o path) particles file name
-r, --reinit allowFilterReinits boolean 0/1, N/Y, false/true Allow TRN particle filter reinits
-s, --stype - integer enum
0 : UNDEFINED
1 : TRN_SENSOR_DVL DVL
2 : TRN_SENSOR_MB Multibeam/Generic
3 : TRN_SENSOR_PENCIL Single Beam
4 : TRN_SENSOR_HOMER Homer Relative Measurement
5 : TRN_SENSOR_DELTAT Imagenex DeltaT
Bathymetry data format passed to
measurement update

May differ from sensor of origin

Corresponds to terrainAid.cfg sensor_type
-v, --verbose - boolean 0/1, N/Y, false/true Enable verbose output
-V, --vfile vehicleCfgName file name (w/o path) vehicle spec file name
-w, --mweight - integer enum
0 : No weighting modifications
1 : Shandor's original alpha modification
2 : Crossbeam with Shandor's weighting
3 : Subcloud with Shandor's original
4 : Subcloud with modified NIS always on
set modified weighting scheme
-x , --mtype map_type 0 : UNDEFINED
1 : TRN_MAP_DEM Digital Elevation Map (.GRD)
2 : TRN_MAP_BO Binary Octree Map (.BO)
map file format
-Z ,
--moformat
- integer enum
3: DVL CSV]
4: IDT CSV
5: MB/Generic CSV
measurement output CSV file format (input file format enum)
Use -Z, --moformat to override default (== iformat)
i.e. to convert DVL, IDT to MB/Generic format

No default name

Use -Z, --mofile to enable measurement output, set file name
- forceLowGradeFilter boolean 0/1, N/Y, false/true use low grade particle filter
(rarely use/deprecated)
- dvlCfgName
resonCfgName
lrauvDvlFilename
terrainNavServer
terrainNavPort
maxNorthingCov
maxNorthingError
maxEastingCov
maxEastingError
RollOffset
useIDTData
useMbTrnData
useMbTrnServer
terrainAidCfg parameters not used in TrnPlayer

CSV Formats and Output Flags Details

trn-player output is sent to the console (stdout). Debug and error information is directed to stderr.

CSV file output is supported for measurements or estimates. Setting the measurement output file name (using -O, --mofile) and/or the estimated output file name (-E, --eofile) enables file output. If the input file uses a CSV format, the output format defaults to the same format; the output format may be overridden using -Z, --moformat, though not all conversions are supported. Any input format may be written to the multibeam/generic format. The format details are described below.

CSV file output may also be captured to a file using redirection, e.g.

trn-player [options...] -G e > path/to/file.csv

CSV estimate output format

When a TRN estimate output file is named (-E, --eofile), TRN estimates are written to the specifed file in the output directory.
The CSV field format is as follows:

 field indices
 [  1] mse time (epoch sec, double)
 [  2] mse N (m)
 [  3] mse E (m)
 [  4] mse D (m)
 [  5] mse vx (m/s)
 [  6] mse vy (m/s)
 [  7] mse vz (m/s)
 [  8] mse roll (phi) (rad)
 [  9] mse pitch (theta) (rad)
 [ 10] mse rheading (psi) (rad)
 [ 11] nav (pt) time (epoch sec, double)
 [ 12] nav N (m)
 [ 13] nav E (m)
 [ 14] nav D (m)
 [ 15] nav roll (phi) (rad)
 [ 16] nav pitch (theta) (rad)
 [ 17] nav rheading (psi) (rad)
 [ 18] offset N (mse - pt) (m)
 [ 19] offset E (mse - pt) (m)
 [ 20] offset D (mse - pt) (m)
 [ 21] covariance N (m)
 [ 22] covariance E (m)
 [ 23] covariance D (m)
 [ 24] covariance magnitude (m)

CSV File Formats

Three CSV output formats are supported for input and output: DVL, IDT, and MB (multibeam/generic).

DVL CSV fields

 field indices
 [  1] = time           decimal epoch seconds
 [  2] = auvN           northing (m)
 [  3] = auvE           easting (m)
 [  4] = depth          depth (m)
 [  5] = yaw            heading/psi (rad)
 [  6] = pitch          pitch/theta (rad)
 [  7] = roll           roll/phi (rad)
 [  8] = 0              flag(0)
 [  9] = 0              flag(0)
 [ 10] = 0              flag(0)
 [ 11] = vx             velocity x (m/s)
 [ 12] = vy             velocity y (m/s)
 [ 13] = vz             velocity z (m/s)
 [ 14] = dvlvalid       dvl valid (1: valid)
 [ 15] = bottomlock     has bottomlock (1: valid)
 [ 16] = numbeams       number of beams (4)
 [ 17] = beam_number[i] beam number
 [ 18] = beamStatus[i]  beam valid (1:valid)
 [ 19] = range[i]       beam range (m)
 ...
 (fixed number of beams (4), 3 fields per beam)
 ```

_IDT CSV Fields_

field indices [ 1] = time decimal epoch seconds [ 2] = auvN northing (m) [ 3] = auvE easting (m) [ 4] = depth depth (m) [ 5] = yaw heading/psi (rad) [ 6] = pitch pitch/theta (rad) [ 7] = roll roll/phi (rad) [ 8] = 0; flag(0) [ 9] = 0; flag(0) [ 10] = 0; flag(0) [ 11] = vx velocity x (m/s) [ 12] = vy velocity y (m/s) [ 13] = vz velocity z (m/s) [ 14] = dvlvalid dvl valid (1: valid) [ 15] = bottomlock has bottomlock (1: valid) [ 16] = numbeams number of beams (120) [ 17] = beam_number[i] beam number [ 18] = beamStatus[i] beam valid (1:valid) [ 19] = range[i] beam range (m) ... (fixed number of beams (120), 3 fields per beam) ```

MB CSV Fields

 field indices
 [  1] = time           decimal epoch seconds
 [  2] = auvN           northing (m)
 [  3] = auvE           easting (m)
 [  4] = depth          depth (m)
 [  5] = yaw            heading/psi (rad)
 [  6] = pitch          pitch/theta (rad)
 [  7] = roll           roll/phi (rad)
 [  8] = 0              flag(0)
 [  9] = 0              flag(0)
 [ 10] = 0              flag(0)
 [ 11] = vx             velocity x (m/s)
 [ 12] = vy             velocity y (m/s)
 [ 13] = vz             velocity z (m/s)
 [ 14] = dvlvalid       dvl valid (1: valid)
 [ 15] = bottomlock     has bottomlock (1: valid)
 [ 16] = numbeams       number of beams
 [ 17] = beam_number[i] beam number
 [ 18] = beamStatus[i]  beam valid (1:valid)
 [ 19] = range[i]       beam range (m)
 [ 20] = alongTrack[i]  along track (m)
 [ 21] = crossTrack[i]  across track (m)
 [ 22] = altitudes[i]   down (m)
 ...
 (variable number of beams, 6 fields per beam)
 ```

#### oflags Description

The oflags parameter is a character string used to control
console output content and format. If multiple are specified, they may be interleaved on the console.

Defaults are 'pS' (pretty output with MMSE)

_p: pretty_

Formatted console output:

MMSE [t,x,y,z,s] : 63898130419.000, 4061708.231, 594373.492, 67.741, 1 OFS [x,y,z] : +39.921, +40.644, +25.505 COV [x,y,z,m] : 1.646, 1.675, 1.622, 2.855


_m: measurement CSV_

Measurement (TRN inputs) in CSV format specified by -Z, --moformat.
If unspecified, the input format is used for CSV types.

Example: --moformat=1 (DVL) 

63898130270.000,4061675.360,594219.527,16.263,0.167,-0.192,0.396,0,0,0,0.100,0.000,0.000,1,1,4,0,1,115.917969,1,1,70.320312,2,1,77.679688,3,1,96.435547


_e: estimate CSV_

TRN Estimate in CSV format

Format fields: mse time (epoch sec, double) mse N,E,D (m) mse vx, vy, vz (m/s) mse roll, pitch, heading (phi, theta, psi) (rad) nav (pt) time (epoch sec, double) nav N,E,D (m) nav roll, pitch, heading (phi, theta, psi) (rad) offset (mse - pt) x, y, z (m) covariance x,y,z,magnitude (m)


_S: output MMSE in pretty output_

_L: output MLE in pretty output_

_B: output both MLE, MMSE in pretty output_

An undefined value (e.g. '?') may be used to suppress console output.

__About trn-player output__  

Each time trn-player is run, TRN creates a directory, trn-player-TRN[.N] where N is an integer that is incremented for each session. Logs produced by the TRN session are stored there.

By default, trn-player outputs a TRN summary each time estimatePose is called:    

MMSE [t,x,y,z] : 63898130388.000, 4061606.865, 594335.044, 44.745 OFS [x,y,z] : -58.695, +30.902, +6.336 COV [x,y,z,m] : 2.176, 2.542, 0.710, 3.420


TrnPlayerCtx has a number of flags that control output content and format, set with the -O option. For example, there are a couple of CSV formats that make plotting easier.  
Use the -h option for a description of all trn-player options. 

trn-player output is directed to stderr; TerrainNav also directs some output to stderr, e.g. when map tiles change. 

#### trn-player Code Highlights

Configuring and running TRN is relatively simple, as shown in the code below.

In trn-player, a TrnPlayerCtx instance is used to hold configuration values (command line options are parsed to override defaults) and some shared variables. Apart from vehicle and sensor spec files, no environment variables or special configuration files are required to use TRN.

The TrnPlayer::configure() method captures the steps needed to configure a TRN instance:

```cpp
// Parse input from command line or config file
// configure TRN instance
// Replaces both ctx and trn

int TrnPlayer::configure(int argc, char **argv)
{
    if(ctx != NULL)
        delete ctx;

    ctx = new TrnPlayerCtx();

    // load command line options
    int test = TrnPlayerCtx::parse(argc, argv, ctx);

    if(ctx->verbose) {
        show();
    }

    if(ctx->is_help_set) {
        // show help and exit
        ctx->show_help(basename(argv[0]));
        return -1;
    }

    if(test != 0)
        return test;

    if(trn != NULL)
        delete trn;

    // configure a TRN instance
    try {
        if(ctx->is_particles_set == 0) {
            trn = new TerrainNav(ctx->mpath, ctx->vpath, ctx->filter_type, ctx->map_type, ctx->odir);
        } else {
            trn = new TerrainNav(ctx->mpath, ctx->vpath, ctx->ppath, ctx->filter_type, ctx->map_type, ctx->odir);
        }
    } catch(...) {
        fprintf(stderr, "%s ERR TerrainNav failed; check input directories and file names; use -v\n", __func__);
        return -1;
    }

    // copy config file to output directory
    copy_config();

    trn->setFilterReinit(ctx->reinit_en);
    trn->setModifiedWeighting(ctx->mod_weight);
    trn->setMapInterpMethod(ctx->map_interp);
    if(ctx->force_lgf)
        trn->useLowGradeFilter();
    else {
        trn->useHighGradeFilter();
    }

    if(ctx->pf_omode != PFO_NONE)
        trn->tNavFilter->setDistribToSave(ctx->pf_omode);

    getSensorGeometry();

    return 0;
}

The TrnPlayer::run() method demonstrates the TRN update and output cycle:

// main application logic:
// - configure a TRN instance
// - iterate over log records
// - fill in poseT, measT from log records
// - update TRN state using motionUpdate, measUpdate
// - get TRN estimate using estimatePose
// - output estimate

int TrnPlayer::run(int argc, char **argv)
{
    // configure if needed
    if(trn == NULL) {
        int test = configure(argc, argv);
        // return on error/help request
        if(test != 0)
            return test;
    }

    if(trn == NULL || ctx == NULL) {
        // configuration error
        fprintf(stderr, "%s - ERR trn (%p) or ctx (%p) NULL; call configure or pass options\n", __func__, trn, ctx);
        return -1;
    }

    // open IO files
    init_io();

    // poseT, measT structs for TRN IO
    poseT pt, mse, mle;
    measT mt;
    poseT *pt_set[3] = {&pt, &mse, &mle};
    measT *mt_set[1] = {&mt};

    // init measT (may be changed by record reader)
    mt.dataType   = ctx->sensor_type;
    mt.numMeas    = 4;
    mt.ranges     = (double *) malloc(mt.numMeas * sizeof(double));
    mt.crossTrack = (double *) malloc(mt.numMeas * sizeof(double));
    mt.alongTrack = (double *) malloc(mt.numMeas * sizeof(double));
    mt.altitudes  = (double *) malloc(mt.numMeas * sizeof(double));
    mt.alphas     = (double *) malloc(mt.numMeas * sizeof(double));
    mt.covariance = (double *) malloc(mt.numMeas * sizeof(double));
    mt.beamNums   = (int *) malloc(mt.numMeas * sizeof(int));
    mt.measStatus = (bool *) malloc(mt.numMeas * sizeof(bool));

    // iterate over data records
    // until EOF or error limit exceeded
    do {

        // ----- Read bathymetry and navigation data -----
        // populate poseT, measT
        status = getNextRecord(&pt, &mt);
        rec_n++;

        if(status == 0) {
            // read valid
            val_n++;

            // udpate range stats
            if(mt.ping_number < ctx->ping_range[0])
                ctx->ping_range[0] = mt.ping_number;
            if(mt.ping_number > ctx->ping_range[1])
                ctx->ping_range[1] = mt.ping_number;
            if(mt.time < ctx->time_range[0])
                ctx->time_range[0] = mt.time;
            if(mt.time > ctx->time_range[1])
                ctx->time_range[1] = mt.time;

            // ----- Update TRN -----
            // call motionUpdate, measUpdate
            // ensure motionUpdate valid before measUpdate
            trn->motionUpdate(&pt);
            trn->measUpdate(&mt, ctx->sensor_type);

            // ----- TRN estimate -----
            trn->estimatePose(&mse, TRN_EST_MMSE);
            trn->estimatePose(&mle, TRN_EST_MLE);

            // ----- do something with TRN -----
            if( (ctx->last_meas = trn->lastMeasSuccessful())) {
                // estimate valid
                est_n++;

                if (NULL != ctx->part_out) {
                    // write particle states
                    trn->tNavFilter->saveCurrDistrib(*ctx->part_out);
                }
            }

            // write output
            write_output(pt, mt, mse, mle);

            reset_pt(pt_set, 3);
            reset_mt(mt_set, 1);

        } else {
            // record read invalid
            if(status < 0)
                err_n++;
            if(status == RI_DEC)
                dec_n++;
        }

    } while(err_n <= MAX_ERRS && status != 1);

    if(ctx->verbose) {
        show_summary();
    }

    // release memory resources
    delete trn;
    trn = NULL;

    mt.clean();

    return (err_n >= MAX_ERRS ? -1 : 0);
}

Core TrnPlayerCtx data members

    // Filter Type
    // 0 : TRN_FT_NONE
    // 1 : TRN_FT_POINTMASS
    // 2 : TRN_FT_PARTICLE (always use 2)
    // 3 : TRN_FT_BANK
    int filter_type;

    // Map Type
    // 0 : UNDEFINED
    // 1 : TRN_MAP_DEM Digital Elevation Map (.GRD)
    // 2 : TRN_MAP_BO  Binary Octree Map (.BO)
    int map_type;

    // Sensor Type
    // 0 : UNDEFINED
    // 1 : TRN_SENSOR_DVL    DVL
    // 2 : TRN_SENSOR_MB     Multibeam
    // 3 : TRN_SENSOR_PENCIL Single Beam
    // 4 : TRN_SENSOR_HOMER  Homer Relative Measurement
    // 5 : TRN_SENSOR_DELTAT Imagenex multibeamconst int sensor_type=2;
    int sensor_type;

    // Use modified weigting
    // 0 : TRN_WT_NONE No modification
    // 1 : TRN_WT_NORM  Shandor's original alpha modification
    // 2 : TRN_WT_XBEAM Crossbeam with original
    // 3 : TRN_WT_SUBCL Subcloud with original
    // 4 : TRN_FORCE_SUBCL Force Subcloud every measurement
    // 5 : TRN_WT_INVAL invalid
    int mod_weight;

    // allow filter reinitialization
    bool reinit_en;

    // Map interpolation method
    // 0 : nearest-neighbor (no interpolation, default)
    // 1 : bilinear
    // 2 : bicubic
    // 3 : spline
    int map_interp;

    // force low grade filter if true (use high grade otherwise)
    bool force_lgf;

    // Input Log
    // 0 : MbTrn.log
    // 1 : TerrainNav.log
    // 2 : TerrainAid.log
    // 3 : trn.csv
    int log_type;

    // CSV format
    // 0 : CSV_DVL
    // 1 : CSV_IDT
    // 2 : CSV_MB
    int csv_itype;
    int csv_otype;

    // Hack to force beam status valid
    // for TerrainNav.log on LRAUV w/ RDI
    bool force_status;

    // mounting geometry parameters
    // for input sensor_type, defined in vfile (vehicle spec)
    // dr: euler angles phi,theta,psi (pitch,roll,yaw) (deg)
    // dt: translation (x,y,z) (m)
    double geo_dr[3];
    double geo_dt[3];

    // Output control flags (bitfield)
    // -- Format Flags --
    // OUT_PRETTY   0x1
    // OUT_EST_CSV  0x2
    // OUT_MEAS_CSV 0x4
    // -- Content Flags --
    // OUT_MMSE     0x100 (OUT_PRETTY)
    // OUT_MLE      0x200 (OUT_PRETTY)
    unsigned int oflags;

    // Bathymetry log reader
    DataLogReader *trn_log;

    // Navigation log reader
    DataLogReader *nav_log;
...

Note that only a few are needed to configure a TRN instance:

// configure a TRN instance
TerrainNav *trn = new TerrainNav(ctx->map, ctx->vspec, ctx->filter_type, ctx->map_type, ctx->odir);

Interpreting TRN Output: Estimates and Convergence

The poseT structure returned by estimatePose contains both an position estimate (position on the map, in world frame) and a covariance array that provides estimated uncertainties, as described above.

When uncertainty is low, it is said that TRN is converged, i.e. that there is some degree of confidence that it's position estimate is correct. There are common conditions under which uncertainties are very low and the location estimate is incorrect.

What conditions cause poor or invalid convergence?

TRN has an critical requirement that each update consists of independent observations. When overlapping TRN inputs are provided, the measurements potentially become correlated, which violates the requirement and potentially leads to invalid output.

As a guideline, TRN inputs should be spaced by at least ~3 m. For example, if a platform is moving at 1 m/s and using a sonar pinging at 3 Hz, there are 3 samples/m; every 9th sample would be ~3m apart. TRN implementation choices need to take into account vehicle speed, sensor sampling rates, and the information content of the terrain. Terrain that is flat or contains few distinguishing features contains less information that TRN can use to identify a unique location on the map.

Configuration, especially sensor and mounting geometry, ara another common source of issues with TRN. Ensure that offset parameters and rotations (DT, DR) are correct, and that the beam components have the correct sign and are on the correct axes.

Consistent failures in measUpdates are sometimes seen as errors in the TRN syslog indication that motion has not been initiated. This usually means that a valid motionUpdate has not occurred. There may be a number of reasons for this, and can mean that vx value is provided to motionUpdate is always zero.

How is it possible to tell whether TRN is converged, and the estimate is valid?

In typical applications, we are interested in determining a navigation offset (difference between estimated location and the location reported by navigation sensors), rather than an absolute location.

When TRN is converged, the offset is expected to be reasonable small (a few 10s of meters at most) and relatively stable (i.e., not highly variable in magnitude or sign). The covariances are also expected to relatively be small and stable, but not vanishingly small or constant.

What can be done if TRH is reporting false positives?

Instantaneous values are not generally reliable indicators of convergence. Instead, a common strategy is to track offset and covariance magnitude over a window, and only accept it as valid when convergence criteria have been within an acceptable range for a number of measurements, for example covariance magnitude 0.1 < x < 4.0 for 200 measurements.

Common issues and troubleshooting strategies

Issue Diagnostics
Not converging (in information-dense terrain) Check mounting geometry (TD,TR) and signs
Check beam component magnitude, sign, directions
Assess convergence criteria
Ensure that TRN update rates are not too frequent or infrequent.
Ensure that measurements are independent.
Converges quickly with suspiciously small covariances and/or high stability Reinitialize TRN
Assess convergence criteria
Ensure that TRN update rates are not too frequent or infrequent.
Offset magnitude sign opposite expected value Check mounting geometry (TD,TR) and signs
Check beam component magnitude, sign, directions
TRN segfaults Check trn-log
Ensure that number of TRN_MAX_BEAMS and TRN_MSG_SIZE are adequate.

Log files

TRN produces several log files that are especially useful for resolving issues.

TRN generates log files that include a message logs for debugging, and data logs containing input and output.

Log File Format Contents
trn.log.nnnn text TRN message log (segmented, 0000-9999)
TrnIO.log binary TRN data log (multiple record types)
TerrainNav.log binary TRN data log (single record type, legacy)
TNavPFLog.log binary TRN particle state log (a lot of data)

The TRN message log (trn-log) is a text file that provides a useful first line of diagnostic information. Though loosely structured, it provides a chronological output stream, and is easily read and searched.

The TrnIO log may contain multiple record types, identified with IDs:

MOTN_IN = motion update input
MEAS_IN = measurement update input
MSE_OUT = MMSE output
MLE_OUT = MLE output

TrnIO record types are dynamically sized, and contain minimal record headers and sync patterns, making them efficient in terms of storage and straightforward to search and parse, even if corrupted. The trnLog-player utility may be used to replay the TrnIO log, and produces a content summary along with output compatible with tlp-plot (also in libtrnav). The tlp-plot utility generates PDF plots of TRN output and performance.

The TerrainNav log uses a single record type to record (MLE, MMSE) outputs and inputs, which is less efficient; it writes all fields, including arrays (which are statically sized to TRN_MAX_BEAMS), whether they are used or not. Also, record type is ambiguous, and do not contain any sync patterns.

Logs are written to the directory passed to TerrainNav constructor, along with configuraton files used to configure the TRN instance.