Module: facetSRPDynamicEffector

Executive Summary

This dynamic effector module uses a faceted spacecraft model to calculate the force and torque acting on a spacecraft due to solar radiation pressure (SRP). The force and torque are calculated about the spacecraft body frame origin point \(B\). The module can be configured for either a static spacecraft or a spacecraft with any number of articulating facets. For example, a spacecraft with two articulating solar arrays can be configured using 4 articulating facets. The unit test for this module shows how to set up this particular configuration.

Message Connection Descriptions

The following table lists all the module input and output messages. The module msg connection is set by the user from python. The msg type contains a link to the message structure definition, while the description provides information on what this message is used for.

Module I/O Messages

Msg Variable Name

Msg Type

Description

sunInMsg

SpicePlanetStateMsgPayload

Input msg with the Sun state information

articulatedFacetDataInMsgs

HingedRigidBodyMsgPayload

(Optional) Input message with facet articulation angle information

Detailed Module Description

Mathematical Modeling

The spacecraft is represented as a collection of \(N\) total facets with negligible thickness. Each facet is characterized by an area \(A\), a unit vector normal to its surface \(\boldsymbol{\hat{n}}\) expressed in \(\mathcal{B}\) frame components, a position vector from the spacecraft body frame origin point \(B\) to the facet center of pressure \(\boldsymbol{r}_{COP/B}\) expressed in \(\mathcal{B}\) frame components, an optional unit vector expressed in \(\mathcal{B}\) frame components representing the articulation axis of any additional articulating facets, and three optical coefficients representing the interaction of impinging photons with the facet surface. The fraction of specularly reflected, diffusely scattered, and absorbed photons are represented using the coefficients \(\delta, \rho,\) and \(\alpha\), respectively.

For each articulating facet, the current facet normal vector is computed using the facet articulation axis \(\boldsymbol{\hat{a}}\) and the corresponding facet articulation angle \(\phi\). The facet articulation angle is obtained from the articulatedFacetDataInMsgs input message data. The direction cosine matrix (DCM) required to rotate the given facet normal vector through the current facet articulation angle is obtained using a principal rotation vector (PRV) transformation where:

\[[\mathcal{B}_0\mathcal{B}] = \text{PRV2C}(\phi, \boldsymbol{\hat{a}})\]

and

\[{}^\mathcal{B} \boldsymbol{\hat{n}} = [\mathcal{B}\mathcal{B}_0] {}^{\mathcal{B}_0} \boldsymbol{\hat{n}}\]

Using the spacecraft facet information and spacecraft Sun-relative position vector \(\boldsymbol{r}_{\text{sc} / \odot }\), the estimated SRP force acting on the spacecraft is calculated by summing the SRP force contribution from all \(N\) facets:

\[\boldsymbol{F}_{\text{SRP}} = \sum_{i = 1}^{N} \boldsymbol{F}_{\text{SRP}_i} = -P(|\boldsymbol{r}_{\text{sc} / \odot }|) \sum_{i = 1}^{N} A_i \cos(\theta_i) \left [ (1 - \delta_i) \boldsymbol{\hat{s}} + 2 \left ( \frac{\rho_i}{3} + \delta_i \cos(\theta_i) \right ) \boldsymbol{\hat{n}}_{i}\right ]\]

Where \(\theta\) is defined as the incidence angle between each facet normal vector and the Sun-direction vector, and \(P(|\boldsymbol{r}_{\text{sc}/ \odot\ }|)\) is the pressure acting on the spacecraft scaled by the spacecraft heliocentric distance. Because the Sun and spacecraft inertial positions are given in inertial frame components, the current spacecraft attitude \(\sigma_{\mathcal{B} / \mathcal{N}}\) is used to determine the current DCM of the spacecraft body frame relative to the inertial frame, \([\mathcal{BN}]\). Note that all vector quantities must be expressed in the spacecraft body frame for the SRP force calculation. \(\boldsymbol{\hat{s}}\) is the unit direction vector pointing radially towards the Sun from the spacecraft body frame origin point \(B\). This vector is found by subtracting the current spacecraft inertial position from the Sun position given from the Sun Spice input message:

\[{}^\mathcal{B} \boldsymbol{\hat{s}} = [\mathcal{BN}] ( {}^\mathcal{N} \boldsymbol{r}_{\odot / N} - {}^\mathcal{N} \boldsymbol{r}_{\text{sc} / N})\]

The total torque acting on the spacecraft about point \(B\) due to SRP is calculated by summing the torque contributions over all \(N\) facets:

\[\boldsymbol{L}_{\text{SRP},B} = \sum_{i = 1}^{N} \boldsymbol{L}_{{\text{SRP},B}_i} = \sum_{i = 1}^{N} \boldsymbol{r}_{{COP_i}/B} \times \boldsymbol{F}_{\text{SRP}_i}\]

Module Testing

The unit test for this module ensures that the calculated SRP force and torque acting on the spacecraft about the body-fixed point B is properly computed for either a static spacecraft or a spacecraft with any number of articulating facets. The spacecraft geometry defined in the test consists of a cubic hub and two circular solar arrays. Six static square facets represent the cubic hub and four articulated circular facets describe the articulating solar arrays. To validate the module functionality, the final SRP force simulation value is checked with the true value computed in python.

User Guide

The following steps are required to set up the faceted SRP dynamic effector in python using Basilisk. Be sure to include the Sun as a gravitational body in the simulation to use this module.

  1. First import the facetSRPDynamicEffector class:

    from Basilisk.simulation import facetSRPDynamicEffector
    
  2. Next, create an instantiation of the SRP dynamic effector:

    SRPEffector = facetSRPDynamicEffector.FacetSRPDynamicEffector()
    SRPEffector.ModelTag = "SRPEffector"
    
  3. The user is required to set the total number of spacecraft facets and the number of articulated facets. For example, if the user wants to create a spacecraft with 10 total facets, four of which articulate; the user would set these module variables to:

    SRPEffector.numFacets = 10
    SRPEffector.numArticulatedFacets = 4
    
  4. If the spacecraft contains articulated facets, a HingedRigidBodyMsgPayload articulation angle message must be configured for each articulated facet. An example using two constant stand-alone messages is provided below:

    facetRotAngle1 = macros.D2R * 10.0  # [rad]
    facetRotAngle2 = macros.D2R * -10.0  # [rad]
    
    facetRotAngle1MessageData = messaging.HingedRigidBodyMsgPayload()
    facetRotAngle1MessageData.theta = facetRotAngle1
    facetRotAngle1MessageData.thetaDot = 0.0
    facetRotAngle1Message = messaging.HingedRigidBodyMsg().write(facetRotAngle1MessageData)
    
    facetRotAngle2MessageData = messaging.HingedRigidBodyMsgPayload()
    facetRotAngle2MessageData.theta = facetRotAngle2
    facetRotAngle2MessageData.thetaDot = 0.0
    facetRotAngle2Message = messaging.HingedRigidBodyMsg().write(facetRotAngle2MessageData)
    
  5. For articulating facets, the user must configure the module’s optional articulatedFacetDataInMsgs input message by calling the addArticulatedFacet() method with each facet’s HingedRigidBodyMsgPayload articulation angle input message:

    srpEffector.addArticulatedFacet(facetRotAngle1Message)
    srpEffector.addArticulatedFacet(facetRotAngle1Message)
    srpEffector.addArticulatedFacet(facetRotAngle2Message)
    srpEffector.addArticulatedFacet(facetRotAngle2Message)
    
  6. Next, define the spacecraft facet geometry information that is contained in the module’s FacetedSRPSpacecraftGeometryData structure:

    # Define facet areas
    area1 = 1.5 * 1.5
    area2 = np.pi * (0.5 * 7.5) * (0.5 * 7.5)
    facetAreas = [area1, area1, area1, area1, area1, area1, area2, area2, area2, area2]
    
    # Define the facet normal vectors in B frame components
    facetNormals_B = [np.array([1.0, 0.0, 0.0]),
                          np.array([0.0, 1.0, 0.0]),
                          np.array([-1.0, 0.0, 0.0]),
                          np.array([0.0, -1.0, 0.0]),
                          np.array([0.0, 0.0, 1.0]),
                          np.array([0.0, 0.0, -1.0]),
                          np.array([0.0, 1.0, 0.0]),
                          np.array([0.0, -1.0, 0.0]),
                          np.array([0.0, 1.0, 0.0]),
                          np.array([0.0, -1.0, 0.0])]
    
    # Define facet center of pressure locations relative to point B
    locationsPntB_B = [np.array([0.75, 0.0, 0.0]),
                       np.array([0.0, 0.75, 0.0]),
                       np.array([-0.75, 0.0, 0.0]),
                       np.array([0.0, -0.75, 0.0]),
                       np.array([0.0, 0.0, 0.75]),
                       np.array([0.0, 0.0, -0.75]),
                       np.array([4.5, 0.0, 0.75]),
                       np.array([4.5, 0.0, 0.75]),
                       np.array([-4.5, 0.0, 0.75]),
                       np.array([-4.5, 0.0, 0.75])]
    
    # Define facet articulation axes in B frame components
    rotAxes_B = [np.array([0.0, 0.0, 0.0]),
                 np.array([0.0, 0.0, 0.0]),
                 np.array([0.0, 0.0, 0.0]),
                 np.array([0.0, 0.0, 0.0]),
                 np.array([0.0, 0.0, 0.0]),
                 np.array([0.0, 0.0, 0.0]),
                 np.array([1.0, 0.0, 0.0]),
                 np.array([1.0, 0.0, 0.0]),
                 np.array([-1.0, 0.0, 0.0]),
                 np.array([-1.0, 0.0, 0.0])]
    
    # Define facet optical coefficients
    specCoeff = np.array([0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9])
    diffCoeff = np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
    

Important

Note that in order to use this module, the facet articulation axes must always be configured regardless of whether articulated facets are considered. For all static facets, the articulation axes must be set to zero. Ensure that the specified number of articulated facets matches the number of nonzero articulation axes.

Important

The module requires the articulated facet data to be added at the end of the facet data vectors.

  1. Populate the module’s FacetedSRPSpacecraftGeometryData structure with the spacecraft facet information using the addFacet() method:

    for i in range(numFacets)):
        SRPEffector.addFacet(facetAreas[i], specCoeff[i], diffCoeff[i], facetNormals_B[i], locationsPntB_B[i], rotAxes_B[i])
    
  2. Connect the Sun’s ephemeris message to the SRP module:

    SRPEffector.sunInMsg.subscribeTo(sunMsg)
    
  3. Add the SRP dynamic effector to the spacecraft:

    scObject.addDynamicEffector(SRPEffector)
    

    See Module: spacecraft documentation on how to set up a spacecraft object.

  4. Finally, add the SRP effector module to the task list:

    unitTestSim.AddModelToTask(unitTaskName, SRPEffector)
    

Note

See the example script scenarioSepMomentumManagement, which illustrates how to set up a spacecraft with articulated panels for SRP calculation.


struct FacetedSRPSpacecraftGeometryData
#include <facetSRPDynamicEffector.h>

Spacecraft Geometry Data.

Public Members

std::vector<double> facetAreas

[m^2] Vector of facet areas

std::vector<double> facetSpecCoeffs

Vector of facet spectral reflection optical coefficients.

std::vector<double> facetDiffCoeffs

Vector of facet diffuse reflection optical coefficients.

std::vector<Eigen::Vector3d> facetNormals_B

Vector of facet normals expressed in B frame components.

std::vector<Eigen::Vector3d> facetLocationsPntB_B

[m] Vector of facet COP locations wrt point B expressed in B frame components

std::vector<Eigen::Vector3d> facetRotAxes_B

[m] Vector of facet rotation axes expressed in B frame components

class FacetSRPDynamicEffector : public SysModel, public DynamicEffector
#include <facetSRPDynamicEffector.h>

Faceted Solar Radiation Pressure Dynamic Effector.

Public Functions

FacetSRPDynamicEffector()

The module constructor.

The constructor

~FacetSRPDynamicEffector()

The module destructor.

The destructor

void linkInStates(DynParamManager &states) override

Method for giving the effector access to the hub states.

This method is used to link the faceted SRP effector to the hub attitude and position, which are required for calculating SRP forces and torques

Parameters

states – Dynamic parameter states

Returns

void

void computeForceTorque(double callTime, double timeStep) override

Method for computing the SRP force and torque about point B.

This method computes the srp force and torque acting about the hub point B in B frame components

Parameters
  • callTime – [s] Time the method is called

  • timeStep – [s] Simulation time step

Returns

void

void Reset(uint64_t currentSimNanos) override

Reset method.

The reset method

Parameters

currentSimNanos – [ns] Time the method is called

Returns

void

void addFacet(double area, double specCoeff, double diffCoeff, Eigen::Vector3d normal_B, Eigen::Vector3d locationPntB_B, Eigen::Vector3d rotAxis_B)

Method for adding facets to the spacecraft geometry structure.

This method populates the spacecraft facet geometry structure with user-input facet information

Parameters
  • area – [m^2] Facet area

  • specCoeff – Facet spectral reflection optical coefficient

  • diffCoeff – Facet diffuse reflection optical coefficient

  • normal_B – Facet normal expressed in B frame components

  • locationPntB_B – [m] Facet location wrt point B expressed in B frame components

  • rotAxis_B – Facet articulation axis expressed in B frame components

Returns

void

void addArticulatedFacet(Message<HingedRigidBodyMsgPayload> *tmpMsg)

This method subscribes the articulated facet angle input messages to the module articulatedFacetDataInMsgs input message

Parameters

tmpMsg – hingedRigidBody input message containing facet articulation angle data

Returns

void

void ReadMessages()

This method reads the Sun state input message. If time-varying facet articulations are considered, the articulation angle messages are also read

Returns

void

Public Members

uint64_t numFacets

Total number of spacecraft facets.

uint64_t numArticulatedFacets

Number of articulated facets.

ReadFunctor<SpicePlanetStateMsgPayload> sunInMsg

Sun spice ephemeris input message.

Private Members

std::vector<ReadFunctor<HingedRigidBodyMsgPayload>> articulatedFacetDataInMsgs

Articulated facet angle data input message.

std::vector<double> facetArticulationAngleList

[rad] Vector of facet rotation angles

FacetedSRPSpacecraftGeometryData scGeometry

Spacecraft facet data structure.

Eigen::Vector3d r_SN_N

[m] Sun inertial position vector

StateData *hubPosition

[m] Hub inertial position vector

StateData *hubSigma

Hub MRP inertial attitude.

bool facetAngleMsgRead

Boolean variable signaling that the facet articulation messages are read.