Frames

This documentation was generated with the assistance of AI. Please report any inaccuracies.

The com.irurueta.navigation.frames package (and its frames.converters sub-package) models the reference frames used throughout navigation mathematics — Earth-Centered Inertial (ECI), Earth-Centered Earth-Fixed (ECEF), North-East-Down (NED), and body frames — plus the converters that translate a position/velocity/attitude estimate from one frame to another. Every equation on this page, and the code that implements it, follows Groves, 2013 unless stated otherwise; see the bibliography for full citations.

Coordinate frames

Frame Definition

ECI (ECIFrame)

Origin at the Earth’s center of mass; axes fixed with respect to the stars (nonrotating). Cartesian position, velocity, and attitude are resolved in these axes. Inertial (Newtonian) navigation equations only hold in a frame like this one.

ECEF (ECEFFrame)

Origin at the Earth’s center of mass; axes rotate with the Earth (z-axis along the polar axis, x-axis through the prime meridian at the equator). Used for satellite/GNSS positions and as the pivot frame between ECI and NED.

NED / local navigation (NEDFrame)

A local frame whose origin follows the body, with axes pointing North, East, and Down (i.e., curvilinear latitude/longitude/height plus a locally-level attitude reference). This is the natural frame for expressing a vehicle’s position on the Earth’s surface and its heading/pitch/roll.

Body (CoordinateTransformation with FrameType.BODY_FRAME)

Axes fixed to the vehicle (typically x-forward, y-right, z-down). Attitude is expressed as the coordinate transformation between the body frame and one of the frames above.

FrameType enumerates these four frames plus FrameType.LOCAL_TANGENT_PLANE_FRAME (the Cartesian tangent-plane frame produced by converters.FrameToLocalTangentPlaneTransformationConverter, useful when a Euclidean approximation of a small area of the Earth’s surface is sufficient).

ECEFPosition/ECEFVelocity, NEDPosition/NEDVelocity, and ECEFPositionAndVelocity are plain data holders for the position/velocity half of a frame, used by the position/velocity-only converters below when attitude doesn’t need to be carried along.

Attitude: the coordinate transformation matrix

CoordinateTransformation holds the 3x3 rotation matrix, , that transforms a vector’s resolving axes from frame to frame :

Because it is orthonormal, its inverse is simply its transpose, (CoordinateTransformation.inverse()), and successive rotations compose by matrix multiplication:

CoordinateTransformation.setEulerAngles(roll, pitch, yaw) builds the matrix from Euler angles \$(\phi, \theta, \psi)\$ using (2.22):






var c = new CoordinateTransformation(
        Math.toRadians(2.0),   // roll
        Math.toRadians(-1.0),  // pitch
        Math.toRadians(45.0),  // yaw
        FrameType.BODY_FRAME, FrameType.LOCAL_NAVIGATION_FRAME);

var roll = c.getRollEulerAngle();
var pitch = c.getPitchEulerAngle();
var yaw = c.getYawEulerAngle();

var inverse = c.inverseAndReturnNew(); // NED -> body

API reference: CoordinateTransformation (javadoc, source)
FrameType (javadoc, source)

CoordinateTransformation.ecefToNedMatrix(latitude, longitude) builds the ECEF-to-NED rotation directly from geodetic latitude and longitude using (2.150):






Frame converters

Each converter in frames.converters implements one leg of the ECI/ECEF/NED position-velocity-attitude conversion, mirroring a MATLAB script from Groves' companion MATLAB code. FrameConverter<S, D> is the common interface; a *PositionVelocityConverter variant of each exists for when only position and velocity (no attitude) need to be converted.

Class Converts Key equations

ECEFtoNEDFrameConverter / ECEFtoNEDPositionVelocityConverter

ECEF (Cartesian) NED (curvilinear)

Borkowski closed-form position solution (see below), (2.73) velocity, (2.15) attitude

NEDtoECEFFrameConverter / NEDtoECEFPositionVelocityConverter

NED (curvilinear) ECEF (Cartesian)

(2.105) meridian radius of curvature, (2.112) position, (2.73) velocity, (2.15) attitude

ECEFtoECIFrameConverter

ECEF ECI, accounting for Earth rotation over a time interval

(2.145) rotation matrix, (2.146) position

ECItoECEFFrameConverter

ECI ECEF, accounting for Earth rotation over a time interval

(2.145) rotation matrix, (2.146) position, (2.15) attitude

FrameToLocalTangentPlaneTransformationConverter

ECEF frame EuclideanTransformation3D about a NED-based local tangent plane

Built from CoordinateTransformation (no new equations)

ECEF to NED: curvilinear position from Cartesian position

Converting a Cartesian ECEF position to curvilinear latitude/longitude/height is, in general, iterative — (2.113) in Groves, 2013 gives the standard iterative inverse, noting that the transverse radius of curvature itself depends on the (unknown) latitude:



ECEFtoNEDFrameConverter/ECEFtoNEDPositionVelocityConverter avoid the iteration by implementing Borkowski’s closed-form solution (Borkowski, 1989), referenced by Groves, 2013 as Appendix C, Section C.2.1, equations (C.29)-(C.38) — an appendix distributed only on the book’s companion DVD, not in the print/PDF edition. The chain of intermediate terms, following the code’s own derivation in ECEFtoNEDFrameConverter.java, is:







with height recovered from and . Longitude is simply — the same relation as in (2.113). Velocity is then rotated with (2.73), , and attitude with (2.15), .

var ecef = new ECEFFrame(x, y, z, vx, vy, vz);
var ned = ECEFtoNEDFrameConverter.convertECEFtoNEDAndReturnNew(ecef);

var latitude = ned.getLatitude();
var longitude = ned.getLongitude();
var height = ned.getHeight();

API reference: ECEFFrame (javadoc, source)
NEDFrame (javadoc, source)
ECEFtoNEDFrameConverter (javadoc, source)

NED to ECEF: Cartesian position from curvilinear position

The reverse direction is direct, not iterative. The meridian radius of curvature (used for the north-south rate of change of latitude) is (2.105):

and the transverse radius of curvature feeds directly into the Cartesian position (2.112):






var ned = new NEDFrame(Math.toRadians(41.3851), Math.toRadians(2.1734), 50.0);
var ecef = NEDtoECEFFrameConverter.convertNEDtoECEFAndReturnNew(ned);

var x = ecef.getX();
var y = ecef.getY();
var z = ecef.getZ();

API reference: NEDFrame (javadoc, source)
NEDtoECEFFrameConverter (javadoc, source)
ECEFFrame (javadoc, source)

ECEF and ECI: accounting for Earth rotation

ECI and ECEF share the same origin and z-axis, differing only by the Earth’s rotation angle accumulated over the propagation interval. CoordinateTransformation.ecefToEciMatrixFromAngle(angle) implements (2.145):






and position transforms with (2.146), (and its inverse for ECI ECEF).

var eci = new ECIFrame(x, y, z, vx, vy, vz);
var propagationInterval = new Time(1.0, TimeUnit.SECOND);
var ecef = ECItoECEFFrameConverter.convertECItoECEFAndReturnNew(eci, propagationInterval);

API reference: ECIFrame (javadoc, source)
ECItoECEFFrameConverter (javadoc, source)
ECEFFrame (javadoc, source)

An original diagram: frame axes at a glance

The figure below is an original illustration (not reproduced from Groves, 2013) sketching how ECEF, NED, and body axes relate at a point on the Earth’s surface — compare with Fig. 2.14/2.22 in the book for the publisher’s own artwork.

flowchart TB subgraph ECEF["ECEF frame (Earth-fixed)"] direction LR E1["x^e — through prime meridian"] --- E2["y^e — 90° E"] --- E3["z^e — polar axis"] end ECEF -->|"C(2.150): lat L_b, lon lambda_b"| NED["NED frame\nN / E / D at body b"] NED -->|"C^b_n: roll/pitch/yaw"| BODY["Body frame\nx-forward / y-right / z-down"]