Custom Estimates Extensions

Top  Previous  Next

A Custom Estimates FreeFlyer Extension allows you to hook into the FreeFlyer Orbit Determination system from an Extension to include additional estimable properties, or "solve-fors," in the state vector. This allows you to solve for physical properties that affect a custom force that's defined in a FreeFlyer Extension. Some examples include custom drag or list models, estimating force scaling factors, solving for Spacecraft object properties, and solving for CelestialObject properties.

 

Properties can be added to the state vector for orbit determination (OD)

Example: James Webb Space Telescope (JWST)

oEstimable Force Extension to vary SRP scaling factor

oExtension developed for accurate orbit determination

 

The Custom Estimates Extension provides a few additional features over a Custom Force Extension.

 

The EstimableProperty attribute

oThis attribute tells FreeFlyer that a given property can be included in the state vector for estimation.

oIt includes an optional argument indicating whether the Extension will provide validation checks for the state update associated with that state property.

The ICustomForceWithEstimablePropertyExtension interface

oThis provides additional interfaces that are needed to estimate components of the Custom Force. These include:

CalculateForceAndPartials interface: This is used instead of just CalculateForce for a normal Custom Force Extension

CalculateDataPriorToStep interface: This provides information about what properties of the Extension are in the state vector prior to taking an integration step

ValidateStateUpdate interface: This provides a mechanism to optionally have the Extension validate the computed state update before applying it

 

 

Creating a Custom Estimates Extension


The process to create a Custom Estimates Extension is similar to the creation of a Custom Force Extension, and requires only a few extra steps beyond those covered in the Anatomy of a FreeFlyer Extension guide.

 

Override the BaseTypeName Property

Override the BaseTypeName property and return AvailableBaseTypes.CustomForce:

 

public override string BaseTypeName

{

  get

  {

    return AvailableBaseTypes.CustomForce;

  }

}

 

Tag Properties Using the EstimablePropertyAttribute

FreeFlyer determines what properties are available for estimation through the EstimableProperty attribute. To make a property estimable, tag it with the attribute in the interface definition.

 

public interface IMyCustomEstimableForce

{

   [EstimableProperty()]

  double Mu { get; set; }

 

}

 

If you intend to do your own validation of the state update on the estimable property (via the ValidateStateUpdate interface) prior to its application, include the optional state validation constructor argument.

 

public interface IMyCustomEstimableForce

{

   [EstimableProperty(validateStateUpdate:true)]

  double Mu { get; set; }

 

}

 

Implement the ICustomForceWithEstimablePropertyExtension Interface

When estimating a property of an Extension, the ICustomForceWithEstimablePropertyExtension interface must be implemented instead of the ICustomForceExtension interface. For optimization reasons, this provides the CalculateForceAndPartials interface instead of the CalculateForce interface. Note that this interface is available as part of the version 2 FreeFlyer Extensions SDK. As a result you must also implement IFFObjectExtension as shown below.

 

public class EstimableCustomForceExtension : ExtensionBase,

                                             IFFObjectExtension,

                                             ICustomForceWithEstimablePropertyExtension,

                                             IMyCustomEstimableForce

{

 

Implement CalculateForceAndPartials

The CalculateForceAndPartials method must be implemented to provide FreeFlyer with the model for the custom force, as well as the acceleration partials.

 

public bool CalculateForceAndPartials(ISpacecraftIntegrationData integrationData, bool needToComputePartials, out double [] calculatedForces,

                                                                                                              out double [,] A, out double [,] B,

                                                                                                              out double [,] C)

{

    DenseVector scPosition = new DenseVector(3);

    double[] position      = new double[3];

    integrationData.GetPosition(out position);

 

    scPosition = position;

 

    double rMag = scPosition.Norm(2);

    double r2 = rMag * rMag;

    double r3 = r2 * rMag;

 

 

    DenseVector Force = new DenseVector(3);

 

    double forceMag = (-1.0*integrationData.Mass * _EarthMu / r3);

    Force = forceMag * scPosition;

 

    calculatedForces = new double[3];

    calculatedForces = Force.ToArray();

 

    A = B = C = null;

    if (needToComputePartials)

    {

    DenseMatrix A_mat = new DenseMatrix(3, 3);

    DenseMatrix B_mat = new DenseMatrix(3, 3);

 

    A_mat = (DenseMatrix)(-1.0 * DenseMatrix.CreateIdentity(3) * _EarthMu / r3);

    A_mat += (DenseMatrix)(3.0 * (_EarthMu / (r3 * r2)) * scPosition.ToColumnMatrix() * scPosition.ToRowMatrix());

    A_mat *= integrationData.Mass;

 

    B_mat = 0.0 * DenseMatrix.CreateIdentity(3);

 

    A = A_mat.ToArray();

    B = B_mat.ToArray();

 

    if (_NumberOfCMatrixColumns > 0)

    {

        DenseMatrix C_mat = new DenseMatrix(3, _NumberOfCMatrixColumns);

 

        C_mat = (DenseMatrix)(-1.0 * integrationData.Mass * scPosition.ToColumnMatrix() / r3);

        C = C_mat.ToArray();

    }

 

    }

 

    return true;

}

 

The needToComputePartials flag indicates whether the partials are needed in the particular stage of the estimation process. FreeFlyer sets this flag and it can be used in your Extension as an optimization, as the STM is not needed in all phases of integration in the estimation process. A Custom Estimates Extension works with the variational equations to determine the sensitivities between state elements through the state-transition-matrix (STM). The CalculateForceAndPartials method implementation must provide the A, B, and C matrices for use in the variational equations.  The A, B, and C matrices are defined as follows.

 

     

 

The N dimension of the C matrix is determined from the call to CalculateDatePriorToStep.

 

Implement CalculateDataPriorToStep

The CalculateDataPriorToStep method is called prior to each integration step. This method can be used to pre-compute values that will be constant through the phases of the integration process.

 

public bool CalculateDataPriorToStep(ISTMCalculationData data)

{

    // Get the number of columns in the C matrix:

    _NumberOfCMatrixColumns = data.NumberOfColumnsInCMatrix;

 

    // Get the index corresponding to the estimable property:

    data.GetCMatrixColumnForProperty("Mu"out _IndexOfMuInCMatrix);

 

    return true;

}

 

The ISTMCalculation interface provides a mechanism to determine what properties of the Custom Estimates Extension are in the C matrix and their corresponding column indices. This data should be stored as member data for use in the CalculateForceAndPartials method.

 

Implement ValidateStateUpdate

ValidateStateUpdate is called by FreeFlyer for properties that are tagged with the EstimableProperty attribute with the validateStateUpdate argument set to true.

 

public bool ValidateStateUpdate(string propertyName, double stateUpdate, out bool isValid)

{

    isValid = true;

    return true;

}

 

Setting isValid to false will terminate the estimation process at the stage of the estimation process where the state update is computed for the estimable property. This is a recoverable error, via the Try command in FreeFlyer script, which provides a mechanism to remedy the issue at the Mission Plan level. Note that if no properties are tagged with the EstimableProperty attribute with the validateStateUpdate argument set to true this method is not called. Regardless, it still must be implemented in order to fulfill the interface contract.

 

 

Using a Custom Estimates Extension


Once a Custom Estimates Extension has been built and registered for use with FreeFlyer, a Custom Force with an EstimableProperty is created in FreeFlyer script and added to the Spacecraft ForceModel like any other Custom Force.

 

CustomPointMassForce pmForce;

pmForce.Mu += 100;

 

Spacecraft mySpacecraft;

(mySpacecraft.Propagator AsType Integrator).ForceModel.AddForce(pmForce);

 

When a property is marked with the EstimableProperty attribute the AddForce method will create a new EstimableProperty object associated with that property and add it to the SpacecraftODProperties child object of the Spacecraft. To access the EstimableProperty object associated with the custom solve-for, use the SpacecraftODProperties.GetEstimableProperty() method.

 

// Create an Alias to make the script more readable:

Alias mu = mySpacecraft.OD.GetEstimableProperty("Mu");

 

// Set the Sigma, ProcessAction, and ProcessNoise

// of the EstimableProperty object:

mu.ProcessAction = 1; // 0 == Ignore

                      // 1 == Estimate

                      // 2 == Consider

mu.Sigma         = 1;

mu.ProcessNoiseRate  = 1e-5;

 

// ... perform estimation ...

 

// Report out estimation statistics:

Report mu.StateUpdate, mu.Sigma;

 

The GetEstimableProperty() method provides access to all the tuning and statistical properties of any other EstimableProperty native to FreeFlyer at the FreeFlyer script level.