Pointing Reference Frame

Revision History

Version

Date

Author

Purpose

1

August 2019

Gary Turner

Initial version

2

September 2025

Hirad Mirhashemi/Alexandre Masset

Refactored into new template, added mathematical formulation, and data verification procedures.

3

August 2026

Nino Tarantino

Converted to reStructuredText and updated coverage


Introduction

The Pointing Reference Frame model provides an additional reference frame defined by two pre-existing frames and the following rules:

  1. The origin of the new frame is at the origin of one of the two pre-existing frames, the Originating-Frame.

  2. The x-axis of the new frame is aligned with the vector from the origin of the originating-frame to the origin of the other pre-existing frame, the Target-Frame.

  3. The z-axis of the new frame is aligned with the angular momentum vector resulting from the relative linear motion of the target frame with respect to the originating frame.

  4. The y-axis of the new frame completes the right-handed coordinate system.

A common application of this type of implementation is in creating a synodic frame, a frame that is always oriented between two bodies as they move around one another. An example of such a frame is the Earth-Moon Rotating Reference Frame.

This model is does not inherit from the jeod::RefFrame class. However, it still largely relies on this class as the Pointing Reference Frame built is a jeod::RefFrame object. It is advised to be familiar with this class before using this model.


Nomenclature and Concepts

In this documentation, the Pointing Reference Frame uses the terms Originating-Frame and Target-Frame, which are defined as follows:

  • Originating-frame: The reference frame at the origin of the Pointing Reference Frame.

  • Target-frame: The reference frame whose position relative to the originating-frame determines the Pointing Reference Frame's orientation.

These definitions define the Pointing Reference Frame as a reference frame that is centered at the Originating-Frame and pointing from there to the Target-Frame.


Requirements

  1. The model shall provide a RefFrame object that defines a Pointing Reference Frame between two frames: an originating frame and a target frame.

    1. The x-axis shall be defined along the position vector from the originating frame to the target frame.

    2. The z-axis shall be defined along the vector resulting from the cross product of the pointing reference frame x-axis and the relative velocity between the originating frame and the target frame.

    3. The y-axis shall complete this set to define a right-hand coordinate frame.

    4. These vectors must be unit vectors when defined.

  2. The model shall handle limit cases when the relative position and the relative velocity are aligned.

  3. The model shall provide optional use of Ephemerides in the construction of the pointing reference frame, allowing a user to use external existing reference frames for the originating frame and the target frame.

    1. The model shall guarantee that the Ephemerides tree is updated prior to the pointing reference frame.


Model Specifications

Architectural Considerations

The model consists of the primary PointingRefFrame class and the specialized extension of it, EphemBasedPointingRefFrame. The PointingRefFrame class includes access to a reference frame instance as a class member, instead of directly inheriting from RefFrame to allow inheritance from SubscriptionBase for standard activation and deactivation of the model. The EphemBasedPointingRefFrame class inherits from PointingRefFrame for scenarios where at least one of the Originating-Frame or Target-Frame are frames managed by the jeod::EphemeridesManager. This extended class provides a reference to the jeod::EphemeridesManager to update the ephemerides alongside the PointingRefFrame behavior.

Model Structure

class PointingRefFrame : public SubscriptionBase
#include "models/dynamics/state_descriptors/pointing_ref_frame/include/pointing_ref_frame.hh"

Defines a reference frame (the Pointing Frame) based on two other reference frames: the Originating Frrame and the Target Frame

The Pointing Frame is then defined by:

  • origin at the origin of the Originating Frame

  • x axis: Along the line from the origin of the Originating Frame to the origin of the Target Frame.

  • y-axis: Completes the orthogonal basis.

  • z-axis: Aligned with the angular momentum vector resulting from the relative linear motion of the Target Frame with respect to the Originating Frame.

  • Attitude-rate will always be on the local z-axis with value necessary for the x-axis to track the motion of the Target Frame. The frame is typically used to describe a vehicle state relative to a line joining two bodies such as planets. A common application would be a Synodic Frame, such as the Earth-Moon rotating frame.

Assumptions:

  • Both the Originating Frame and Target Frame must be registered in the simulation's frame-manager to provide a mechanism for deriving the relative state between them.

Design Considerations:

  • Originating Frame and Target Frame are pointers rather than references to allow for assignment of the reference frames after construction.

  • The jeod::RefFrame instance is a class member (has-a) rather than making this class a derivation of jeod::RefFrame (is-a). This choice is driven by a desire to avoid conflict between the two competing subscription mechanisms found in CML and JEOD. It was considered preferable to use the CML subscription pattern for the class implementation and to trigger the JEOD subscription process from the CML subscription process.

Subclassed by EphemBasedPointingRefFrame

Public Functions

PointingRefFrame()

Constructor

Initializes the frame with zero vectors for the position and velocity. The angular velocity is set to a unit vector along the z-axis. The transformation matrix is initialized as the identity matrix, and the attitude quaternion is set to the identity quaternion.

PointingRefFrame(const PointingRefFrame&) = delete

Copy constructor deleted

PointingRefFrame &operator=(const PointingRefFrame&) = delete

Copy assignment operator deleted

void set_originating_frame(jeod::RefFrame *originating_frame)

Set the Originating Frame pointer

After calling SubscriptionBase::initialize, the Originating Frame may not be changed.

Parameters:

originating_frame -- Non-null pointer to the Originating Frame

void set_target_frame(jeod::RefFrame *target_frame)

Set the Target Frame pointer

After calling SubscriptionBase::initialize, the Target Frame may not be changed.

Parameters:

target_frame -- Non-null pointer to the Target Frame

virtual void update()

Update the state of the Pointing Frame

Note

Since the Pointing Frame is defined with its origin at co-located with the Originating Frame's origin, only the orientation and angular rate will change.

Public Members

jeod::RefFrame pointing_frame

The generated reference frame

Units:

--

jeod::RefFrameState target_wrt_originating_state

The state of the Target Frame with respect to the Originating Frame. Exists as a class member for logging purposes only, elements of this instance are used to define the state of the pointing-ref-frame itself.

Units:

--

Protected Functions

bool setup_frames()

Add the Pointing Frame as a child of the Originating Frame and ensure that the Originating Frame and Target Frame are valid and subscribed

virtual void activate() override

Activate the model

virtual void deactivate() override

Deactivate the model

Protected Attributes

jeod::RefFrame *originating_frame = {nullptr}

Pointer to the Originating Frame. Note this cannot be const due to subscribe/unsubscribe operations, but the PointingRefFrame class should not influence any other aspect of this RefFrame instance.

Units:

--

jeod::RefFrame *target_frame = {nullptr}

Pointer to the Target Frame. Note this cannot be const due to subscribe/unsubscribe operations, but the PointingRefFrame class should not influence any other aspect of this RefFrame instance.

Units:

--


class EphemBasedPointingRefFrame : public PointingRefFrame
#include "models/dynamics/state_descriptors/pointing_ref_frame/include/ephem_based_pointing_ref_frame.hh"

Extension of the PointingRefFrame for cases where the Originating Frame or Target Frame are ephemeris-based frames.

This version should be used when the states of either the Originating Frame or the Target Frame are known only by updates coming from the Ephemeris Manager.

Subclassed by EarthMoonRotatingFrame

Public Functions

inline EphemBasedPointingRefFrame(jeod::EphemeridesManager &mgr)

Constructor

Parameters:

mgr -- Reference to the JEOD Ephemeris Manager, which for most simulations will be the jeod::DynManager instance

EphemBasedPointingRefFrame(const EphemBasedPointingRefFrame&) = delete

Copy constructor deleted

EphemBasedPointingRefFrame &operator=(const EphemBasedPointingRefFrame&) = delete

Copy assignment operator deleted

inline virtual void initialize() override

Register the Pointing Frame with the dynamics/ephem manager so that it can be used to represent the state of a vehicle

Protected Functions

inline virtual void activate() override

Sets up reference frames and tells the JEOD Ephemeris Manager to update the ephemerides

Protected Attributes

jeod::EphemeridesManager &ephem_manager

Mathematical Formulation

Mathematical Nomenclature

In this formulation, the following notation is used:

  • Vectors and matrices are denoted in bold (e.g. \(\mathbf{\hat{x}}\)).

  • Subscripts are used to provide additional descriptions (e.g. \(\mathbf{R_{\mathit{rel}}}\) describes a relative position vector)

  • Superscripts are used to provide the reference frame in which the vector is expressed (e.g. \(\mathbf{R_{\mathit{rel}}^{B}}\) describes a relative position vector expressed in the B-frame).

  • Vectors provided in their vector form use subscripts to provide the reference frame in which they are expressed. For example: \(\begin{bmatrix}x \\y \\z \\\end{bmatrix}_{B}\)

  • Superscripts on derivative operators are used to provide the reference frame of observation (e.g. \(\frac{{}^{I}d}{\mathit{dt}}{(\mathbf{R})}\) denotes the inertial derivative of \(\mathbf{R}\), i.e. the time rate of change of \(\mathbf{R}\) as observed from the inertial frame).

Following this notation, the context for each expression is provided below:

  • \(\mathbf{R_{\mathit{rel}}}\) represents the position vector of the Target-Frame relative to the Originating-Frame, expressed in the inertial frame.

  • \(\mathbf{V_{\mathit{rel}}}\) represents the velocity vector of the Target-Frame relative to the Originating-Frame, expressed in the inertial frame.

  • \(\mathbf{\hat{x}}\) represents the first unit basis vector of the rotating frame, expressed in the inertial frame.

  • \(\mathbf{\hat{y}}\) represents the second unit basis vector of the rotating frame, expressed in the inertial frame.

  • \(\mathbf{\hat{z}}\) represents the third unit basis vector of the rotating frame, expressed in the inertial frame.

  • \(\mathbf{T_{\mathit{PRF}/I}}\) represents the transformation matrix from the inertial frame to the rotating frame.

  • \(\mathbf{\Omega_{\mathit{PRF}/I}^{\mathit{PRF}}}\) represents the angular velocity vector from the inertial frame to the rotating frame, expressed in the rotating frame.

  • \(\mathbf{R_{v}}\) represents the inertial position vector of the vehicle.

  • \(\mathbf{R_{\mathit{PRF}}}\) represents the inertial position vector of the rotating frame.

  • \(\mathbf{R_{v/\mathit{PRF}}}\) represents the position vector of the vehicle relative to the rotating frame.

  • \(\mathbf{V_{v}}\) represents the inertial velocity vector of the vehicle.

  • \(\mathbf{V_{\mathit{PRF}}}\) represents the inertial velocity vector of the rotating frame.

  • \(\mathbf{V_{v/\mathit{PRF}}}\) represents the velocity vector of the vehicle relative to the rotating frame, as seen from the rotating frame.

Pointing Reference Frame

The Pointing Reference Frame is constructed using the motion of the Target-Frame relative to the Originating-Frame to define the origin and orientation of the rotating coordinate system. The x-axis points from the Originating-Frame to the Target-Frame, the z-axis is normal to the orbital plane formed by the relative motion, and the y-axis completes the right-handed coordinate system. While it is possible to express some of these vectors in a different reference frame as long as a consistent frame is used, this model implementation specifically uses only inertial components to define the Pointing Reference Frame axes, which leads to the following expressions:

\begin{equation} \begin{aligned} \mathbf{\hat{x}} &= \frac{ \mathbf{R_{\mathit{rel}}} }{ \lvert \mathbf{R_{\mathit{rel}}} \rvert } \\ \mathbf{\hat{z}} &= \frac{ \mathbf{R_{\mathit{rel}}} \times \mathbf{V_{\mathit{rel}}} }{ \lvert \mathbf{R_{\mathit{rel}}} \times \mathbf{V_{\mathit{rel}}} \rvert } \\ \mathbf{\hat{y}} &= \mathbf{\hat{z}} \times \mathbf{\hat{x}} \end{aligned} \end{equation}

The orientation of the Pointing Reference Frame with respect to the inertial frame is then represented by the transformation matrix:

\begin{equation} \mathbf{T_{\mathit{PRF}/I}} = \begin{bmatrix} \mathbf{{\hat{x}}^{T}} \\ \mathbf{{\hat{y}}^{T}} \\ \mathbf{{\hat{z}}^{T}} \\ \end{bmatrix} \end{equation}

By definition, the Pointing Reference Frame is rotating uniformly about its z-axis. Its angular velocity vector relative to the inertial frame is expressed in the Pointing Reference Frame as:

\begin{equation} \mathbf{\Omega}^{PRF}_{PRF/\mathbf{I}} = \begin{bmatrix} 0 \\ 0 \\ \omega_z \end{bmatrix}_{PRF} \end{equation}

Where:

\begin{equation} \omega_z = \frac{\mathbf{V_{\mathit{rel}}} \cdot \mathbf{\hat{y}}} {\lvert \mathbf{R_{\mathit{rel}}} \rvert} \end{equation}
\[\]

Note that the calculation of \(\mathbf{\Omega_{\mathit{PRF}/I}^{\mathit{PRF}}}\) is independent of the reference frame used to express \(\mathbf{R_{\mathit{rel}}}\), \(\mathbf{V_{\mathit{rel}}}\), and \(\mathbf{\hat{y}}\). This is trivially shown by expressing the inner product with vector multiplication: \({{\mathbf{V_{\mathit{rel}}} \cdot \mathbf{\hat{y}}} = \mathbf{{V_{\mathit{rel}}}^{T}}}\mathbf{\hat{y}}\). However, they must be expressed in the same reference frame.

Singularities in PointingRefFrame Construction

Under nominal conditions, the Pointing Reference Frame is constructed as described in the Pointing Reference Frame section, using the relative position and velocity vectors of the Target-Frame with respect to the Originating-Frame to define the axes. However, certain configurations can lead to numerically undefined axes in this formulation. These configurations are handled as follows:

Zero Relative Position Vector

If the magnitude of \(\mathbf{R_{\mathit{rel}}}\) is zero (i.e. the Target- and Originating-Frames are coincident), the Pointing Reference Frame cannot be constructed meaningfully. In this case, the transformation matrix defining the orientation is not updated from its initialized state, maintaining it as the identity matrix. Additionally, the angular velocity is set to zero. This ensures the axes are well defined by fixing it to the inertial frame as there is no meaningful relative motion.

Aligned Relative Position and Velocity Vectors

If the relative position and velocity vectors are aligned or nearly aligned, the cross product used to define the z-axis becomes zero and numerically unstable, resulting in a poorly defined z-axis. To address this, two alternative solutions are formulated:

  1. Use Last Known Y-Axis (Alternative 1): If the cross product of the relative position and velocity vectors are near zero, the z-axis is computed by using the previous y-axis vector in place of the relative velocity vector:

    \begin{equation} \mathbf{\overrightarrow{z}} = \mathbf{R_{\mathit{rel}}} \times \mathbf{\hat{y}}_{prev} \end{equation}

    If the resulting vector has a non-zero magnitude, it is normalized and used as the new z-axis and an appropriate warning is broadcasted.

  2. Use Previous Z-Axis (Alternative 2): If Alternative 1 fails (i.e. the previous y-axis is also aligned with the current relative position vector), the z-axis is reconstructed using the previous z-axis and the current x-axis:

    \begin{equation} \mathbf{\overrightarrow{z}} = \mathbf{\hat{x}} \times (\mathbf{\hat{z}}_{prev} \times \mathbf{\hat{x}}) \end{equation}

    This is a vector triple product, which ensures that the resulting z-axis is orthogonal to the current x-axis (i.e. the relative position vector). This formulation cannot produce a zero vector, because the current x-axis is aligned with the previous y-axis (as established from failing Alternative 1), and the previous y- and z-axes are by nominal construction orthogonal. Therefore, the previous z-axis cannot be aligned with the current x-axis, ensuring that this cross product produces a defined z-axis.

These alternatives together are a robust fallback for defining the z-axis in all cases where the relative position and velocity vectors are aligned.

Relative Derived State

The RelativeDerivedState model belongs to JEOD and is independent of the formulation described above. This formulation will present the relative position and velocity which is implemented in the RelativeDerivedState, but is commonly used alongside the rotating frame model and formulation provided earlier. For more information about the RelativeDerivedState model, please refer to the JEOD documentation.

Once the Pointing Reference Frame is established, the position of a vehicle relative to this Pointing Reference Frame can be determined by translating its inertial position into the frame's origin and applying the transformation matrix from the inertial to the Pointing Reference Frame:

\begin{equation} \mathbf{R_{v/\mathit{PRF}}^{PRF}} = \mathbf{T_{\mathit{PRF}/I}} \left( \mathbf{R_{v}^{I}} - \mathbf{R_{\mathit{PRF}}^{I}} \right) \end{equation}

where \(\mathbf{R_{v}^{I}}\) and \(\mathbf{R_{\mathit{PRF}}^{I}}\) are the inertial position vectors for the vehicle and the origin of the Pointing Reference Frame, respectively, expressed in the inertial frame. As a result, \(\mathbf{R_{v/\mathit{PRF}}^{\mathit{PRF}}}\) is the relative position of the vehicle with respect to the origin of the pointing reference frame, expressed in the Pointing Reference Frame.

It is important to emphasize that relative velocity as seen from the Pointing Reference Frame, isn't simply:

\[\frac{{}^{\mathit{PRF}}d}{\mathit{dt}}{{(\mathbf{R_{v/\mathit{PRF}}})} \neq \mathbf{T_{\mathit{PRF}/I}}}\frac{{}^{I}d}{\mathit{dt}}{(\mathbf{R_{v/\mathit{PRF}}})}\]

Instead, the velocity of the vehicle as seen from the Pointing Reference Frame is computed using the transport theorem to account for the rotation of the Pointing Reference Frame with respect to the inertial. Let \(\mathbf{V_{v}} = \frac{{}^{I}d}{\mathit{dt}}{(\mathbf{R_{v}})}\) denote the inertial velocity of the vehicle, \(\mathbf{V_{\mathit{PRF}}} = \frac{{}^{I}d}{\mathit{dt}}{(\mathbf{R_{\mathit{PRF}}})}\) denote the inertial velocity of the origin of the Pointing Reference Frame, and \(\mathbf{V_{v/\mathit{PRF}}} = \frac{{}^{\mathit{PRF}}d}{\mathit{dt}}{(\mathbf{R_{v/\mathit{PRF}}})}\) denote the vehicle velocity with respect to the origin of the Pointing Reference Frame as seen from the Pointing Reference Frame. Applying transport theorem, this relative velocity of the vehicle can be expressed as:

\[\mathbf{V_{v/\mathit{PRF}}} = \frac{{}^{I}d}{\mathit{dt}}{{(\mathbf{R_{v/\mathit{PRF}}})} - {\mathbf{\Omega_{\mathit{PRF}/I}} \times \mathbf{R_{v/\mathit{PRF}}}}}\]

Substituting the inertial velocities of the vehicle and the Pointing Reference Frame origin, this becomes:

\[\mathbf{V_{v/\mathit{PRF}}} = {{({\mathbf{V_{v}} - \mathbf{V_{\mathit{PRF}}}})} - {\mathbf{\Omega_{\mathit{PRF}/I}} \times \mathbf{R_{v/\mathit{PRF}}}}}\]

Finally, expressing the terms in a common Pointing Reference Frame yields:

\begin{equation} \mathbf{V_{v/\mathit{PRF}}^{PRF}} = \mathbf{T_{\mathit{PRF}/I}} ({\mathbf{V_{v}^{I}} - \mathbf{V_{\mathit{PRF}}^{I}}}) - \mathbf{\Omega_{\mathit{PRF}/I}^{PRF}} \times \mathbf{R_{v/\mathit{PRF}}^{PRF}} \end{equation}

where \(\mathbf{V_{v}^{I}}\) and \(\mathbf{V_{\mathit{PRF}}^{I}}\) are the inertial velocity vectors for the vehicle and the origin of the rotating frame, respectively.


User's Guide

Implementation

See the Model Structure section for include paths for the PointingRefFrame and EphemBasedPointingRefFrame classes.

Initialization

The non-ephemerides PointingRefFrame has a default constructor that takes no arguments. The ephemerides Pointing Reference Frame constructor takes a reference to the Ephemerides Manager. This is often provided as a reference to the jeod::DynManager, which is a derivative of the Ephemerides Manager:

PointingRefFrame non_ephem_rotating_frame;
EphemBasedPointingRefFrame ephem_rotating_frame(dyn_manager);

For both Pointing Reference Frames, set the Originating-Frame and Target-Frame, and a name for the Pointing Reference Frame like:

non_ephem_rotating_frame.set_originating_frame(vehicleA.composite_body);
non_ephem_rotating_frame.set_target_frame(vehicleB.composite_body);
non_ephem_rotating_frame.pointing_frame.set_name("VehicleAB-rotating-frame");

ephem_rotating_frame.set_originating_frame(earth.planet.inertial);
ephem_rotating_frame.set_target_frame(sun.planet.inertial);
ephem_rotating_frame.pointing_frame.set_name("EarthSun-rotating-frame");

For the non-ephemerides Pointing Reference Frame, you will need to add the frame to the Dynamics Manager:

dyn_manager.add_ref_frame(non_ephem_rotating_frame.pointing_frame);

The ephemerides Pointing Reference Frame does not require this step, as the model handles it internally with the reference to the Ephemerides Manager.

The method to schedule for initialization of the model:

P_ENV ("initialization") non_ephem_rotating_frame.initialize();

P_DYN ("initialization") ephem_rotating_frame.initialize();

The initialization of the non-ephemerides Pointing Reference Frame can occur as early as the reference frame initialization in P_ENV or later. However, the ephemerides pointing reference frame should occur quite late in the initialization sequence as it should be after the Ephemeris initialization, so P_DYN or later.

Routine Execution

The method to schedule for updates to the model:

P_ENV (DYNAMICS, "environment") non_ephem_rotating_frame.update();

P_DYN (DYNAMICS, "environment") ephem_rotating_frame.update();

Configuration

The model is inactive by default. To activate it, you could call the subscribe() method:

non_ephem_rotating_frame.subscribe();

ephem_rotating_frame.subscribe();

Relative Derived State

One of the most common uses of this frame is for expressing the state of a vehicle. The model itself provides only the frame, the state relative to that frame can be described using an instance of JEOD's jeod::RelativeDerivedState model. See the JEOD documentation for information on configuring this relative state.

Of particular relevance to this model, the configuration of a jeod::RelativeDerivedState requires specification of the Subject-Frame and the Target-Frame. Typically, the Subject-Frame is the vehicle frame of interest and the Target-Frame is the Pointing Reference Frame defined by this model. To set the Target-Frame, it is necessary to know the name of the Pointing Reference Frame, which is set in the initialization steps.

For example, to get the relative state of the vehicle to the Earth-Sun Pointing Reference Frame:

jeod::RelativeDerivedState veh_wrt_prf;

veh_wrt_prf.subject_frame_name = "test_vehicle.composite_body";
veh_wrt_prf.target_frame_name = "EarthSun-rotating-frame";

Logging

Typically, the desired output is the state of some vehicle with respect to the pointing frame, for example:

relative_derived_state_instance.rel_state.trans.position

The pointing frame itself also has a state. The position and velocity of the frame are not of interest because they are locked to the Originating-Frame, so both position and velocity are zero. However, the orientation and angular rate are occasionally useful. These are represented as follows:

  • Transformation matrix from the parent planet-inertial state to the pointing frame (3x3 matrix).

    rotating_frame_instance.pointing_frame.state.rot.T_parent_this
    
  • Left-handed transformation quaternion describing the transformation from the parent Originating-Frame state to the pointing frame, expressed as a scalar and a 3-element vector.

    rotating_frame_instance.pointing_frame.state.rot.Q_parent_this.scalar
    rotating_frame_instance.pointing_frame.state.rot.Q_parent_this.vector
    
  • Angular rate of the rotating frame relative to the parent Originating-Frame state, expressed in the rotating frame as a 3-element vector. By definition of the rotating frame, the x- and y-components are identically zero.

    rotating_frame_instance.pointing_frame.state.rot.ang_vel_this
    

Verification

Code Coverage

------------------------------------------------------------------------------
                        GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines     Exec  Cover   Missing
------------------------------------------------------------------------------
models/dynamics/state_descriptors/pointing_ref_frame/include/ephem_based_pointing_ref_frame.hh
                                              14       14   100%
models/dynamics/state_descriptors/pointing_ref_frame/src/pointing_ref_frame.cc
                                              87       87   100%
------------------------------------------------------------------------------
TOTAL                                        101      101   100%
------------------------------------------------------------------------------

Exceptions

N/A

Simulation Configurations

SIM_verif

This verification simulation tests the geometry and vector operations used in defining the pointing reference frame using two arbitrary reference frames A and B corresponding to the Originating-Frame and the Target-Frame, respectively. Additionally, a subject vehicle is used to verify the relative velocity of the body to the Pointing Reference Frame, as seen from the pointing reference frame.


RUN_01_Geometric

This test verifies that the Pointing Reference Frame is properly constructed with the correct orientation and angular velocity throughout a variety of configurations, and that the relative position and velocity of the subject vehicle with respect to the Pointing Reference Frame is correct.

The default setup for these unit tests includes these states in the inertial axes (+X, +Y, +Z):

  • Originating-Frame is at rest at the origin: \(\mathbf{R_{O}^{I}} = \begin{bmatrix}0 & 0 & 0\end{bmatrix}\), \(\mathbf{V_{O}^{I}} = \begin{bmatrix}0 & 0 & 0\end{bmatrix}\).

  • Target-Frame is located at \(\mathbf{R_{T}^{I}} = \begin{bmatrix}10 & 0 & 0\end{bmatrix}\) and moving in \(\mathbf{V_{T}^{I}} = \begin{bmatrix}0 & 5 & 0\end{bmatrix}\).

  • vehicle is located at \(\mathbf{R_{v}^{I}} = \begin{bmatrix}10 & 0 & 0\end{bmatrix}\) and moving in \(\mathbf{V_{v}^{I}} = \begin{bmatrix}0 & 0 & 0\end{bmatrix}\).

All references to the vehicle relative position and velocity are with respect to the origin of the Pointing Reference Frame and are expressed in the Pointing Reference Frame axes. The relative velocity is also observed from the perspective of the Pointing Reference Frame.

Default Configuration

Setup: All input states are in the default configuration.

Expected Results: Pointing frame aligns with +X (Target-Frame direction), +Y (Target-Frame velocity), +Z (angular momentum direction). Vehicle lies on pointing frame x-axis and its relative velocity opposes the Target-Frame motion.

Results:

Time (s)

\(\mathbf{R}_{v/\mathit{PRF}}^{\mathit{PRF}}\)

\(\mathbf{V}_{v/\mathit{PRF}}^{\mathit{PRF}}\)

\(\omega_{z}\)

\(\mathbf{\hat{x}}^{T}\)

\(\mathbf{\hat{y}}^{T}\)

\(\mathbf{\hat{z}}^{T}\)

0

[10,0,0]

[0,-5,0]

0.5

[1,0,0]

[0,1,0]

[0,0,1]

Offset Positions in 3D

Setup: Originating-, Target-Frames, and vehicle positions are all offset by [5,5,5] to maintain same relative position and motion.

Expected Results: Same pointing frame and vehicle relative state as default configuration.

Results:

1

[10,0,0]

[0,-5,0]

0.5

[1,0,0]

[0,1,0]

[0,0,1]

Vehicle Diagonally Located in 3D

Setup: Vehicle position is diagonally offset in the YZ-plane to be located at [10,-10,10].

Expected Results: Same pointing frame as default configuration. Vehicle relative position is the same as the vehicle inertial position, and it moves in the pointing frame x- and y-axes.

Results:

2

[10,-10,10]

[-5,-5,0]

0.5

[1,0,0]

[0,1,0]

[0,0,1]

Vehicle Moving in +X

Setup: Vehicle now has velocity of [10,0,0] (along +X), while the Target-Frame still moves in +Y with the same velocity [0,5,0].

Expected Results: Same pointing frame and vehicle relative position as default configuration. Vehicle relative velocity now reflects the vehicle inertial motion along the pointing frame x-axis, in addition to the previous opposing Target-Frame motion in the pointing frame y-axis.

Results:

3

[10,0,0]

[10,-5,0]

0.5

[1,0,0]

[0,1,0]

[0,0,1]

Vehicle Moving in +X, -Y, and +Z

Setup: Vehicle now has velocity of [10,-10,10], while the Target-Frame still moves in +Y with the same velocity [0,5,0].

Expected Results: Same pointing frame and vehicle relative position as default configuration. Vehicle relative velocity now reflects the vehicle inertial motion along the pointing frame x-, y-, and z-axes, in addition to the previous opposing Target-Frame motion in the pointing frame y-axis.

Results:

4

[10,0,0]

[10,-15,10]

0.5

[1,0,0]

[0,1,0]

[0,0,1]

Target Moving in -Y

Setup: Target-Frame now moves in opposite direction (along -Y) with velocity [0,-5,0].

Expected Results: Same pointing frame x-axis and vehicle relative state as default configuration. Pointing frame y- and z-axes are in the opposite direction.

Results:

5

[10,0,0]

[0,-5,0]

0.5

[1,0,0]

[0,-1,0]

[0,0,-1]

Target Moving in +Z

Setup: Target-Frame now moves in +Z with velocity [0,0,5] instead of +Y.

Expected Results: Same pointing frame x-axis and vehicle relative state as default configuration. With the Target-Frame moving in +Z, the pointing frame z-axis (angular momentum vector) shifts to -Y, aligning the pointing frame y-axis with +Z to maintain a right-handed frame.

Results:

6

[10,0,0]

[0,-5,0]

0.5

[1,0,0]

[0,0,1]

[0,-1,0]

Target in +Y, Moving in +X

Setup: Target-Frame lies along +Y at position [0,10,0] and moves in +X with velocity [5,0,0].

Expected Results: Pointing frame x-axis aligns with +Y (Target-Frame direction), y-axis with +X (Target-Frame velocity), and z-axis with -Z (angular momentum direction). Vehicle relative position lies on pointing frame y-axis and it moves in the direction of the pointing frame x-axis.

Results:

7

[0,10,0]

[5,0,0]

0.5

[0,1,0]

[1,0,0]

[0,0,-1]

Target in +Y, Moving in +Z

Setup: Target-Frame lies along +Y at position [0,10,0] and moves in +Z with velocity [0,0,5].

Expected Results: Pointing frame x-axis aligns with +Y (Target-Frame direction), y-axis with +Z (Target-Frame velocity), and z-axis with +X (angular momentum direction). Vehicle relative position lies on pointing frame z-axis with zero velocity.

Results:

8

[0,0,10]

[0,0,0]

0.5

[0,1,0]

[0,0,1]

[1,0,0]

Target in +Z, Moving in +X

Setup: Target-Frame lies along +Z at position [0,0,10] and moves in +X with velocity [5,0,0].

Expected Results: Pointing frame x-axis aligns with +Z (Target-Frame direction), y-axis with +X (Target-Frame velocity), and z-axis with +Y (angular momentum direction). Vehicle lies on pointing frame y-axis and it moves in the direction of the pointing frame x-axis.

Results:

9

[0,10,0]

[5,0,0]

0.5

[0,0,1]

[1,0,0]

[0,1,0]

Target in +Z, Moving in +Y

Setup: Target-Frame lies along +Z at position [0,0,10] and moves in +Y with velocity [0,5,0].

Expected Results: Pointing frame x-axis aligns with +Z (Target-Frame direction), y-axis with +Y (Target-Frame velocity), and z-axis with -X (angular momentum direction). Vehicle lies on pointing frame opposite z-axis with zero velocity.

Results:

10

[0,0,-10]

[0,0,0]

0.5

[0,0,1]

[0,1,0]

[-1,0,0]

Target Moving Diagonally in XY

Setup: Target-Frame and vehicle located at position [10,10,0], and the Target-Frame moves diagonally with velocity [-5,5,0].

Expected Results: Pointing frame x-axis aligns with the diagonal Target-Frame position vector in XY-plane, y-axis with diagonal Target-Frame velocity in XY-plane, and z-axis remains aligned with +Z (angular momentum direction). Vehicle lies on pointing frame x-axis and it moves in the direction opposite of the pointing-frame y-axis.

Results:

11

[14.14,0,0]

[0,-7.07,0]

0.5

[0.707,0.707,0]

[-0.707,0.707,0]

[0,0,1]

Target and Vehicle in 3D

Setup: Target-Frame and vehicle located at position [5,5,5], and the Target-Frame moves in +Z with velocity [0,0,5].

Expected Results: Pointing frame x-axis points diagonally in 3D (Target-Frame direction). The Target-Frame velocity in +Z produces an angular momentum vector in the XY-plane, pointing the pointing frame z-axis diagonal in-plane. The y-axis completes the right-handed frame and will be diagonal in 3D. Vehicle lies on the pointing frame x-axis and it moves in the direction opposite of the pointing frame y-axis. The angular velocity about the pointing frame z-axis should be lower than the other cases, because the Target-Frame velocity is less orthogonal to the position vector.

Results:

12

[8.66,0,0]

[0,-4.082,0]

0.471

[0.577,0.577,0.577]

[-0.408,-0.408,0.816]

[0.707,-0.707,0]

Origin Moving in -Y

Setup: Originating-Frame now moves in -Y with velocity [0,-5,0], the opposite of the previous Target-Frame motion.

Expected Results: Same pointing frame axes and vehicle relative state as default configuration. The angular velocity around the pointing frame z-axis will double compared to the default configuration results.

Results:

13

[10,0,0]

[0,-5,0]

1.0

[1,0,0]

[0,1,0]

[0,0,1]


ERROR_bad_frames

This test verifies the errors that result from incorrect configurations and warnings from cases where the Pointing Reference Frame axes aren't well defined and need to be alternatively handled using the methodology described in the Singularities section.

Configuration Frames are NULL

If the Originating-Frame or the Target-Frame are set to a NULL value during intialization, the model will broadcast a respective error.

***************************************************************
Set originating frame to NULL
***************************************************************

Non-critical Error detected at
Trick Sim-time: 0
File: /nobackup2/ataranti/cml/models/dynamics/state_descriptors/pointing_ref_frame/src/pointing_ref_frame.cc
Line: 50
Message: Configuration error
Attempt to assign the originating-frame of PointingRefFrame PointingFrame to be NULL.
This is not a valid setting.
Attempt failed.

***************************************************************
Set target frame to NULL
***************************************************************

Non-critical Error detected at
Trick Sim-time: 0
File: /nobackup2/ataranti/cml/models/dynamics/state_descriptors/pointing_ref_frame/src/pointing_ref_frame.cc
Line: 72
Message: Configuration error
Attempt to assign the target-frame of PointingRefFrame PointingFrame to be NULL.
This is not a valid setting.
Attempt failed.
Changing Configuration after Model Activation

If the Pointing Reference Frame model is already activated through its subscribe() method, any attempt to change the Originating-Frame or Target-Frame will result in the model broadcasting a respective error.

***************************************************************
t=0.0 Reset originating frame specification
***************************************************************

Non-critical Error detected at
Trick Sim-time: 0
File: /nobackup2/ataranti/cml/models/dynamics/state_descriptors/pointing_ref_frame/src/pointing_ref_frame.cc
Line: 43
Message: Reconfiguration error
Once activated, the PointingRefFrame PointingFrame cannot change its originating frame.
Originating-frame remains at its current setting.

***************************************************************
t=0.0 Reset target frame specification
***************************************************************

Non-critical Error detected at
Trick Sim-time: 0
File: /nobackup2/ataranti/cml/models/dynamics/state_descriptors/pointing_ref_frame/src/pointing_ref_frame.cc
Line: 65
Message: Reconfiguration error
Once activated, the PointingRefFrame PointingFrame cannot change its target frame.
Originating-frame remains at its current setting.
Relative Position Vector is Zero (Proximity Warning)

When the Pointing Reference Frame encounters a situation where the Originating-Frame and Target-Frame are very close to each other, the relative position vector between the frames will result in a zero vector, producing an undefined x-axis. The Pointing Reference Frame will result to retaining its orientation, and making the angular velocity zero.

Setup: At t=0, a nominal configuration is defined, but at t=1 both the Originating-Frame and Target-Frame are positioned at [0,0,0].

Expected Results: At t=1, the orientation from t=0 is retained and the frame has an angular velocity of zero.

Results:

Time (s)

\(\mathbf{R}_{v/\mathit{PRF}}^{\mathit{PRF}}\)

\(\mathbf{V}_{v/\mathit{PRF}}^{\mathit{PRF}}\)

\(\omega_{z}\)

\(\mathbf{\hat{x}}^{T}\)

\(\mathbf{\hat{y}}^{T}\)

\(\mathbf{\hat{z}}^{T}\)

0

[3,2,-1]

[8,2,-4]

1

[0,0,1]

[0,1,0]

[-1,0,0]

1

[3,2,-1]

[6,5,-4]

0

[0,0,1]

[0,1,0]

[-1,0,0]

Relative Position and Velocity Vectors are Aligned (Alternative 1)

When the Pointing Reference Frame encounters a situation where the relative position and velocity vectors between the Originating-Frame and Target-Frame are very close to being aligned, the cross product of these vectors will result in a zero vector, producing an undefined z-axis. In the case where the relative position vector is not aligned with the previous y-axis, the cross product of these vectors produces the new z-axis. Ultimately, this results in the y-axis being retained from the previous iteration.

Setup: At t=2, a nominal configuration is defined, but at t=3 the Originating-Frame and Target-Frame are positioned at [0,0,0] and [0,0,-1], respectively, and are moving at velocities [0,0,0] and [0,0,1], respectively.

Expected Results: At t=3, the relative position and velocity vectors are aligned, causing the z-axis to be computed using the relative position vector from t=3 and y-axis from t=2, thus preserving the previous y-axis orientation from t=2.

Results:

2

[0,0,-1]

[6,5,-4]

1

[0,0,1]

[0,1,0]

[-1,0,0]

3

[0,0,1]

[-6,5,4]

0

[0,0,-1]

[0,1,0]

[1,0,0]

Relative Position and Velocity Vectors are Aligned (Alternative 2)

Similar to the previous test, when the relative position and velocity vectors are very close to being aligned, the cross product of these vectors will produce an undefined z-axis. In the off-chance where the relative position vector is also aligned with the previous y-axis, the formulation from alternative 1 produces another undefined z-axis. In this case, the z-axis is defined as the result of a triple cross product of the x-axis and the previous z-axis. Ultimately, this results in the z-axis being retained from the previous iteration.

Setup: At t=3, the Pointing Reference Frame axes is fully defined using alternative 1, but at t=4 the Originating-Frame and Target-Frame are positioned at [0,0,0] and [0,1,0], respectively, and are moving at velocities [0,0,0] and [0,1,0], respectively. The relative position and velocity vectors at t=4 are different from those at t=3.

Expected Results: At t=4, the relative position is aligned with the relative velocity vector and the previous y-axis, causing the z-axis to be computed as the result of a triple cross product of the x-axis from t=4 and z-axis from t=3, thus preserving the previous z-axis orientation from t=3.

Results:

3

[0,0,1]

[-6,5,4]

0

[0,0,-1]

[0,1,0]

[1,0,0]

4

[0,0,1]

[5,6,4]

0

[0,1,0]

[0,0,1]

[1,0,0]


FAIL_unassigned_frames

This test verifies that when the model is initialized without specifying the Target-Frame and/or Originating-Frame, an error is broadcast, the model is stopped and returns the boolean false.

Non-critical Error detected at
Trick Sim-time: 0
File: /nobackup2/ataranti/cml/models/dynamics/state_descriptors/pointing_ref_frame/src/pointing_ref_frame.cc
Line: 209
Message: Incomplete specification
The target-frame and/or originating-frame of the
Pointing_Reference-Frame have not been assigned.
The Pointing-Reference-Frame PointingFrame cannot be activated.


Non-critical Error detected at
Trick Sim-time: 0
File: /nobackup2/ataranti/cml/models/utilities/subscriptions/src/subscriptions.cc
Line: 133
Message: Failure During Initialization.
The SubscriptionBase initialization for 'unnamed-instance' failed when the model
attempted to activate during initialization:
- activation sequence executed due to having pending subscriptions.
Model has been neither initialized nor activated
but pending subscriptions have been retained per setting of
configuration flag initialize_on_failed_activation.
Rerun <model>.initialize() to apply pending subscriptions and activate the model.

SIM_Ephem

This verification simulation tests the functionality of the EphemBasedPointingRefFrame class and is limited to the very small differences between this class and its base class, PointingRefFrame. It illustrates the potential pitfalls of using a PointingRefFrame instance rather than an EphemBasedPointingRefFrame instance when either the Target-Frame and/or Originating-Frame are managed by the Ephemerides Manager. See FAIL_noephem_only and FAIL_noephem_with_subscriptions for easy mistakes to avoid.

All the runs in this simulation define the Pointing Reference Frames to track the Earth and Sun relative positions and motion, with an individual subject vehicle fixed on the Earth-Sun vector to enable verification of the relative state of the vehicle with respect to the pointing reference frame.

Since the PointingRefFrame was already geometrically verified in SIM_verif, the purpose of logging data in this simulation is to determine which frame, EphemBasedPointingRefFrame or PointingRefFrame is actively driving the relative state updates, and whether the inertial positions of the Earth and Sun are being updated via the EphemeridesManager.


RUN_01_ephem_only

This test demonstrates the recommended implementation for a Pointing Reference Frame that depends on frames managed by the Ephemerides Manager.

Setup: Run only the EphemBasedPointingRefFrame and its associated relative state.

Expected Results: Only the EphemBasedPointingRefFrame instance and its relative vehicle state are updated, not the PointingRefFrame instance. The inertial positions of the Earth and Sun are also updated through the EphemBasedPointingRefFrame connection to the Ephemerides Manager.

Results: Results match expected.


RUN_02_both

This test demontrates that since EphemBasedPointingRefFrame can add its Ephemeris-based frames to the Ephemeris tree through the Ephemerides Manager, PointingRefFrame can indirectly track those same frames despite not having a connection to the Ephemerides Manager. The effect of this hidden dependency becomes evident in the FAIL_noephem_only test, where removing the EphemBasedPointingRefFrame causes the base PointingRefFrame to lose access to the Ephemeris-based frames.

Setup: Runs both the EphemBasedPointingRefFrame, the base PointingRefFrame, and their associated relative states.

Expected Results: Both the EphemBasedPointingRefFrame and the PointingRefFrame instances are updated with their associated relative vehicle states. The inertial positions of the Earth and Sun are also updated through the EphemBasedPointingRefFrame connection to the Ephemerides Manager.

Results: Results match expected.


RUN_03_ephem_only_resubscribe

This test is similar to RUN_01_ephem_only, in that only the EphemBasedPointingRefFrame and its associated relative-state are computed. However, this test highlights the expected behavior when the model is initially deactivated and later reactivated successfully, in constrast with FAIL_noephem_with_subscriptions, where reactivation fails. It serves to verify that the EphemBasedPointingRefFrame can correctly resume updating relative states and ephemeris-driven positions after being re-subscribed mid-simulation.

Setup: Run only the EphemBasedPointingRefFrame and its associated relative state. Model is initially deactivated and later reactivated during the simulation at t=300000.

Expected Results: The EphemBasedPointingRefFrame instance and its relative vehicle state are initialized at t=0 and not updated anymore until after t=300000. Similarly, the Sun inertial reference frame state won't be updated until that point as it is deactivated through EphemBasedPointingRefFrame's Target-Frame. However, the Earth inertial reference frame state continues updating as it is used as the integration frame for the subject vehicle.

Results: Results match expected.


FAIL_noephem_only

This test runs only the base PointingRefFrame and its associated relative state while still using Ephemeris-based frames like the Earth inertial and Sun inertial as the Originating-Frame and Target-Frame. The PointingRefFrame doesn't have access to the Ephemerides Manager unlike EphemBasedPointingRefFrame, which causes the test to fail as the Ephemeris reference frame tree was not built.

*********************************************************
Terminal error.  Ephem tree has not been built.
Sun.inertial and Earth.inertial are not the same tree
*********************************************************

FAIL_noephem_with_subscriptions

This test is similar to FAIL_noephem_only in that only the base PointingRefFrame and its associated relative state are computed while still using Ephemeris-based frames. However, this test specifically highlights the behavior that happens when a separate model, one dependent on either the Originating-Frame or Target-Frame, activates and deactivates those same Ephemeris-based frames internally without rebuilding the Ephemeris reference frame tree. These actions could interfere with the assumption that the frames will be simply activated and apart of the Ephemeris tree at initialization.

In this test, the input file acts as a "lurking model" that also depends on the Sun inertial frame. At the start of the simulation, this lurking model adds the Sun inertial frame to the Ephemeris tree and activates the frame. Although this setup is intended for the lurking model's own functionality, it incidentally enables the PointingRefFrame to initialize successfully, since the required frame is present in the Ephemeris tree at that time. After initialization, the lurking model deactivates the Sun inertial frame, removing it from the Ephemeris tree. To avoid failure at this point, the PointingRefFrame is also deactivated. Later in the simulation (at t=300000), the lurking model reactivates the Sun inertial frame, and the PointingRefFrame is re-enabled to test its functionality using that frame. However, the simulation fails at this point, because the Ephemeris tree is not automatically rebuilt upon reactivation of the Sun inertial frame or PointingRefFrame, unlike the EphemBasedPointingRefFrame. As a result, the Earth inertial and Sun inertial frame remain disconnected in the Ephemeris tree, failing at the computation of the relative state between the two frames. In conclusion, when using Ephemeris-based frames without the EphemBasedPointingRefFrame, the Ephemeris tree must be rebuilt everytime the model is re-subscribed to ensure the Originating-Frame and Target-Frame are dynamically connected (though the recommended approach is to use EphemBasedPointingRefFrame, which handles this automatically).

*********************************************************************
Terminal error.  Sun.inertial is not in tree.
Even though sun.inertial is newly active, the Ephemeris tree has not
been rebuilt, so the frame does not exist in the tree.
*********************************************************************