VR-Link API Documentation for DIS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
13.3 - Coordinate Conversions

Table of Contents

VR-Link supports several coordinate systems and provides classes and functions for converting locations, vectors, and orientations from one system to another.

13.3.1 Geocentric Coordinates

DIS and the RPR FOM in HLA specify that world locations, velocities, accelerations and orientations be represented with respect to a right-hand geocentric Cartesian coordinate system. The origin of this geocentric coordinate system is the center of the earth. The positive X-axis passes through the prime meridian at the equator; the positive Y-axis passes through 90 degrees east longitude at the equator; and the positive Z-axis passes though the north pole (as illustrated below.)

The DtVector class is typically used to represent locations and vectors in geocentric coordinates, while DtTaitBryan or DtDcm is used to represent orientation.

geocentriccoordinatesystem.png
Geocentric Coordinate System

13.3.2 Geodetic Coordinates

Geodetic coordinates are another means of specifying location in the world. VR-Link geodetic coordinates consist of latitude and longitude in radians, and altitude in meters above a certain reference ellipsoid, for example, the surface of the earth at sea level.

VR-Link uses the class DtGeodeticCoord (defined in geodeticCoord.h) to represent geodetic coordinates. A DtGeodeticCoord can be initialized from a latitude, longitude, and altitude. Negative latitudes are south latitudes; negative longitudes are west longitudes.

DtGeodeticCoord myLoc(DtDeg2Rad(45.0), DtDeg2Rad(30.0), 1000.0);

If the default constructor is used, the resulting object represents a latitude, longitude, and altitude of zero.

DtGeodeticCoord has the following inspectors and mutators to get and set values for the individual components of a geodetic coordinate:

DtGeodeticCoord also has member functions that enable you to convert to and from geocentric coordinates. DtGeodeticCoord::geocentric() returns the geocentric equivalent of a geodetic coordinate. For example:

DtGeodeticCoord geod(DtDeg2Rad(30.0), DtDeg2Rad(100.0), 1000.0);
DtVector geoc = geod.geocentric();

After these lines of code, geoc will contain the coordinate:

{-960122.075, 5445122.868, 3170873.735}

which represents the same point in space as 30 degrees north latitude, 100 degrees east longitude, 1000 meters altitude.

A similar function is DtGeodeticCoord::getGeocentric(), which, rather than returning a geocentric coordinate, sets the value of an existing DtVector, for example:

DtGeodeticCoord geod(DtDeg2Rad(30.0), DtDeg2Rad(100.0), 1000.0);
DtVector geoc;
geod.getGeocentric(geoc);

Going in the other direction, DtGeodeticCoord::setGeocentric() sets the value of a DtGeodeticCoord to the latitude/longitude/altitude equivalent of a given geocentric coordinate:

DtVector geoc(-960122.075, 5445122.868, 3170873.735);
geod.setGeocentric(geoc);

Also in geodeticCoord.h, are the C-style functions DtGeocToGeod() and DtGeocToGeod(), which you can use instead of the member functions described previously, to convert between geocentric and geodetic coordinates, although their use is discouraged in favor of the member functions.

13.3.2.1 Choosing a Reference Ellipsoid

The default reference ellipsoid used for geocentric to geodetic conversions is WGS84, but this is configurable through the function DtUseMapDatum(), declared in geodeticCoord.h. Any DtMapDatum can be passed to this function. DtMapDatum is defined as:

typedef struct DtSpheroid
{
DtFloat64 semiMajor; // semimajor axis of the ellipsoid, in meters
DtFloat64 semiMinor; // semiminor axis of the ellipsoid, in meters
typedef struct DtMapDatum
{
DtFloat64 datumShift[3]; // added to WGS84 to get GCC in this datum

VR-Link has the following DtMapDatums pre-defined in mapDatum.h:

If you want to use the ED50 reference, for example, try:

DtUseMapDatum(&DtED50);

13.3.3 Topographic Coordinates

VR-Link defines a topographic coordinate system as a right-handed Cartesian coordinate system whose X-Y plane is tangent to the earth's surface at the origin, with the positive X-axis pointing north, the positive Y-axis pointing east, and the positive Z-axis pointing down (as illustrated below). Obviously, there are an infinite number of topographic coordinate systems – one for each point on the earth's surface.

topographiccoordinatesystem.png
Topographic coordinate system

A DtVector is usually used in VR-Link to represent a topographic coordinate.

13.3.3.1 DtCoordTransform

The easiest way to convert between geocentric and topographic coordinates is by using a DtCoordTransform object (defined in LibMatrix.h). A DtCoordTransform is an object that can transform locations, vectors, or orientations from one Cartesian coordinate system to another.

In general, a DtCoordTransform can be constructed by passing to its constructor the origin of one system with respect to the other, and a rotation matrix that indicates the orientation of one system with respect to the other. However, in the case of a geocentric to topographic transformation, VR-Link provides the function DtGeocToTopoTransform() to initialize a DtCoordTransform for you. This function, declared in topoCoord.h, does the following:

  1. Takes the latitude and longitude of a point on the earth and computes the rotation matrix that expresses the orientation of the topographic system defined by that point.
  2. Initializes a DtCoordTransform using this matrix along with the geocentric representation of the chosen point.

For example, to create a DtCoordTransform that can convert between geocentric coordinates and the topographic coordinate system whose origin is at 30 degrees north latitude, 100 degrees east longitude, you can do the following:

DtCoordTransform geocToTopo;
&geocToTopo);

Now, this transform can be used to convert from geocentric to topographic coordinates. For example, if we have a geocentric location in a DtEntityStateRepository, and we want to convert it to our topographic frame, we can use DtCoordTransform::coordTrans():

DtVector topoLocation;
geocToTopo.coordTrans(esr->location(), topoLocation);

If we want to do the reverse, we can initialize a second DtCoordTransform to convert from topographic to geocentric using the member function setByInverse():

DtCoordTransform topoToGeoc;
topoToGeoc.setByInverse(geocToTopo);

Now, we can use topoToGeoc() to convert to geocentric, say, for filling in a locally simulated entity's entity state repository:

DtVector geocLocation;
topoToGeoc.coordTrans(topoLocation, geocLocation);
esr->setLocation(geocLocation);

In addition to coordTrans(), DtCoordTransform also has vecTrans() and eulerTrans() member functions for converting vectors (such as velocity and acceleration), and orientations (expressed as Euler angles) between two different Cartesian coordinate systems.

13.3.3.2 Heading, Pitch, and Roll

Converting Euler angles from geocentric to topographic coordinates (or vice versa) is often particularly useful, because topographic-referenced Euler angles correspond to heading, pitch and roll.

Using a DtCoordTransform that can convert from geocentric to topographic coordinates, we can obtain an entity's heading, pitch, and roll as follows:

DtTaitBryan topoEuler;
geocToTopo.eulerTrans(esr->orientation, &topoEuler);
double heading = topoEuler.psi();
double pitch = topoEuler.theta();
double roll = topoEuler.phi();

13.3.4 UTM Coordinates

Locations in the world can be specified using a UTM coordinate system. UTM coordinates are mapped to a reference ellipsoid approximating the surface of the earth using a Universal Transverse Mercator projection. The coordinates consist of easting and northing from an origin or reference location, and an altitude above a reference ellipsoid, all in meters.

In a true UTM coordinate system, the origin or reference point (0,0,0) is often a point on the equator at the center of a particular UTM zone. (The world is longitudinally divided into 60 UTM zones, each centered on an odd multiple of 3 degrees.) However, VR-Link lets you define an "offset UTM" coordinate system by passing any arbitrary reference point, to the function DtUtmInit().

You must call DtUtmInit() to establish the world location of the origin of your UTM attribute system before you use any of the UTM coordinate conversion functions. Currently, VR-Link supports the use of only one UTM reference point at a time. However, you can call DtUtmInit() multiple times in your application to define the UTM origin you want to use for the next set of conversions.

13.3.4.1 Using DtUtmInit()

The first two arguments to DtUtmInit() are DtDegMinSec structures, representing the latitude and longitude of the reference point. DtDegMinSec has the following definition:

typedef struct
{
double deg, min, sec;
DtPolarDirection direction;

The following code initializes VR-Link's UTM conversion routines so that they use 35° north latitude and 122° west longitude as the reference point:

DtDegMinSec latRef = {35.0, 0.0, 0.0, DtNorth};
DtDegMinSec lonRef = {122.0, 0.0, 0.0, DtWest};
DtUtmInit(latRef, lonRef, 0);

The optional (and rarely used) third argument to DtUtmInit() indicates that a particular convention should be used, whereby 500,000 meters are added to all easting values and 10,000,000 meters are added to all north values, in order to eliminate the use of negative numbers in UTM coordinates. Applications that need to use this convention should pass a value of 1 for this argument as opposed to the more common 0.

The optional fourth argument (not shown) sets the UTM Reference zone. If you do not specify this parameter, VR-Link chooses it for you.

A UTM coordinate is represented using DtUtmCoord (defined in utmCoord.h). You can construct a DtUtmCoord by passing its three components (in meters) to the constructor:

DtUtmCoord utmLoc(50.0, 100.0, 70.0);

Assuming that DtUtmInit() was called as above, this DtUtmCoord would represent a point of altitude 70 meters, that is 50 meters east and 100 meters north of the reference point of 35 degrees north by 122 degrees west.

The class has a copy constructor and assignment operator defined, and has the following inspectors and mutators to access the various components: east, setEast, north, setNorth, up, setUp.

DtUtmCoord also has member functions that enable you to convert to and from geocentric or geodetic coordinates. DtUtmCoord::geocentric() and DtUtmCoord::geodetic() return the geodetic and geocentric equivalents of a UTM coordinate respectively. For example:

DtUtmInit(...);
...
DtUtmCoord utm(50.0, 60.0, 70.0);
DtGeodeticCoord geod = utm.geodetic();

The member functions getGeocentric() and getGeodetic() work similarly, but fill in an existing object passed by reference to the function, rather than returning the desired object.

Alternatively, the C-style functions DtGeodToUtm(), DtUtmToGeod(), DtGeocToUtm(), and DtUtmToGeoc() can also convert locations in UTM coordinates to geocentric or geodetic coordinates, and vice-versa. However their use is discouraged in favor of the member functions.

13.3.5 Differences Between UTM and Topographic Coordinates

Trouble often arises when programmers do not understand the differences between a UTM coordinate system and a topographic coordinate system that share the same origin.

Although the coordinates of a point near the origin may be similar in the two systems, they are different in several ways.

13.3.6 Lower Level Coordinate Conversion Functions

If you want a greater level of control over your coordinate conversions than that offered by the DtCoordTransform class described in 13.3.3.1 DtCoordTransform, there are several lower-level functions that can help.

If you have a rotation matrix that expresses a rotation between two coordinate systems, you can multiply that matrix by a vector, such as velocity, or acceleration using DtDcmVecMul() in order to convert that vector between the coordinate systems.

For geocentric/topographic conversions, the needed rotation matrix can be obtained using DtLatLon_to_GeocToTopo() or DtLatLon_to_TopoToGeoc(), declared in topoCoord.h. These functions take a latitude and longitude and return rotation matrices to convert between the geocentric frame and the topographic frame defined by that point on earth.

For example:

DtGeodeticCoord myOriginInGeod(35.0, -122.0, 0.0);
// Obtain a rotation matrix for the topo frame in question
DtDcm geoc2Topo;
DtLatLon_to_GeocToTopo(myOriginInGeod, geoc2Topo);
DtVector topoVel;
// Perform the vector rotation, using the matrix.
DtDcmVecMul(geoc2Topo, esr->velocity(), topoVel);

You can also use a rotation matrix to rotate a set of Euler angles from one coordinate system to another, using the function DtEulerToEuler(), declared in Euler.h, for example:

DtTaitBryan topoOrient;
DtEulerToEuler(esr->orientation(), geoc2Topo, topoOrient);

But if your goal is to obtain an entity's orientation as topographic Euler angles (heading, pitch, and roll), a more efficient way would be:

  1. Use esr->bodyToGeoc() rather than orientation.
  2. Multiply this returned matrix by geoc2Topo or by a geocentric to topographic rotation matrix obtained using DtLatLon_to_GeocToTopo() as described in the example above.
  3. Convert the result to Euler angles using DtBodyToRef_to_Euler() as follows:

    DtDcm bodyToTopo;
    DtDcmDcmMul(geoc2Topo, esr->bodyToGeoc(), bodyToTopo);
    DtTaitBryan topoEuler;
    DtBodyToRef_to_Euler(bodyToTopo, topoEuler);

Coordinate locations cannot be transformed using only a rotation matrix. The translational offset between the two coordinate systems is also required. To transform from one cartesian system to another:

  1. Subtract the origin of the second system from the point being transformed.
  2. Perform the rotation as above.

For example, to transform a location from geocentric to a topographic coordinate:

// Find the local origin expressed in geocentric coordinates
DtVector myOriginInGeoc = myOriginInGeod.geocentric();
// Subtract the local origin from the point being transformed
DtVecSub(esr->location(), myOriginInGeoc, tmp);
// Rotate the result
DtVector topoLoc;
DtDcmVecMul(geoc2Topo, tmp, topoLoc);

[<< Orientation, Euler Angles, and DtTaitBryan] [Home] [Top of Page] [Creating Linked Lists with DtList >>]


Document ID: Generated on Thu Feb 22 04:26:36 EST 2018 from SVN revision 186468
Copyright © 2005-2016 VT MÄK. All Rights Reserved (www.mak.com)