C++ Module: facetedSRPEffector

Executive Summary

The faceted spacecraft solar radiation pressure (SRP) module computes the aggregate force and torque acting on the spacecraft due to impinging photons from the Sun. The inertial Sun state information must be subscribed to the module SpicePlanetStateMsgPayload input message. The module assumes the spacecraft is modeled as a collection of facets, where the facet geometry information is passed as a vector of FacetElementBodyMsgPayload input messages to the module. The facet geometry information is required to be provided in the spacecraft body frame. This SRP module does not make any assumptions regarding whether the facets are rigid or articulate. The C++ Module: facetedSpacecraftModel module can be connected upstream and used to transform the facet geometry data from the facet frames to the spacecraft body frame. This upstream module can also be used to configure articulating facets. Finally, this SRP module also requires the sunlit area of all facets to be pre-computed and connected to the module vector of ProjectedAreaMsgPayload input messages. This information can be passed to the SRP module by connecting the facet geometry information to the C++ Module: facetedSpacecraftProjectedArea module upstream.

Important

The total number of facets must be set using setNumFacets() before connecting the facet input message vectors.

Important

All facet geometry and projected area input message vectors must have lengths equal to numFacets.

Note

Unlike the C++ Module: facetSRPDynamicEffector module, this module does not internally compute the facet projected areas or manipulate facet information. The facets are general in this module. Articulating facets can be configured upstream using the C++ Module: facetedSpacecraftModel module. The C++ Module: facetSRPDynamicEffector module can be used to quickly set up a simulation where all facet information is computed internally.

Message Connection Descriptions

The following table lists all module input messages. The module msg connections are set by the user from Python. The msg type contains a link to the message structure definition, while the description provides information on what each message is used for.

facetedSRPEffector module input and output messages

Module I/O Messages

Msg Variable Name

Msg Type

Description

sunStateInMsg

SpicePlanetStateMsgPayload

Input message containing the Sun inertial state.

facetElementBodyInMsgs

FacetElementBodyMsgPayload

Input message vector containing facet element data expressed in body-frame components.

facetProjectedAreaInMsgs

ProjectedAreaMsgPayload

Input message vector containing pre-computed per-facet projected areas.

sunEclipseInMsg

EclipseMsgPayload

(Optional) Input msg for the Sun eclipse data. If connected, the SRP force and torque are scaled by the illumination factor (0 = full shadow, 1 = full sunlight).

Module Functions

Below is a list of functions this simulation module performs:

  • Reads the Sun inertial position and computes the Sun direction vector in spacecraft body-frame components

  • Reads facet body-frame geometry and optical coefficients for each facet

  • Reads per-facet projected areas for each facet

  • Computes SRP pressure scaled by spacecraft heliocentric distance

  • Computes and sums per-facet SRP force and torque contributions

  • Writes total SRP force and torque to the dynamic effector base-class outputs forceExternal_B and torqueExternalPntB_B

Module Assumptions and Limitations

  • The user must call setNumFacets() before connecting message vectors

  • This module assumes facet normals and center-of-pressure vectors are already expressed in the spacecraft body frame

  • This module expects projected areas to be provided externally; it does not compute projected area internally

  • This module does not read articulation-angle messages directly

  • Facets with non-positive projected area contribute zero SRP force and torque

Test Description and Success Criteria

The unit test for this module is located in test_facetedSRPEffector. The test verifies that the module correctly computes the aggregate SRP force and torque acting on the spacecraft due to impinging photons from the Sun. The test sets up a simulation with a faceted spacecraft modeled as a cubic hub with two attached circular solar arrays. Six square facets represent the cubic hub and four circular facets represent the two solar arrays. The test varies the initial state information of the spacecraft, the initial state information of the Sun, and the Sun illumination factor. Specifically, the test parameterizes:

  • Spacecraft initial inertial position

  • Sun inertial position

  • Spacecraft initial attitude

  • Spacecraft initial angular velocity

  • Sun visibility (illumination) factor

The test checks that the computed SRP forces and torques at each timestep match the values output from the module.

User Guide

The following steps are required to set up the facetedSRPEffector module in Python.

Note

A common setup is to connect facetedSpacecraftModel upstream to provide body-frame facet geometry and connect facetedSpacecraftProjectedArea upstream to provide per-facet projected areas.

  1. Import the required BSK modules:

    import numpy as np
    from Basilisk.utilities import SimulationBaseClass
    from Basilisk.utilities import simIncludeGravBody
    from Basilisk.simulation import facetedSpacecraftProjectedArea
    from Basilisk.simulation import facetedSRPEffector
    from Basilisk.simulation import spacecraft
    from Basilisk.architecture import messaging
    
  2. Create the spacecraft object and set its initial states:

    sc_object = spacecraft.Spacecraft()
    sc_object.ModelTag = "scObject"
    sc_object.hub.mHub = 750.0  # [kg]
    sc_object.hub.r_BcB_B = [[0.0], [0.0], [1.0]]  # [m]
    sc_object.hub.IHubPntBc_B = [[900.0, 0.0, 0.0], [0.0, 800.0, 0.0], [0.0, 0.0, 600.0]]  # [kg m^2]
    sc_object.hub.r_CN_NInit = [[-4020338.690396649], [7490566.741852513], [5248299.211589362]]  # [m]
    sc_object.hub.v_CN_NInit = [[-5199.77710904224], [-3436.681645356935], [1041.576797498721]]  # [m/s]
    sc_object.hub.sigma_BNInit = [0.0, 0.0, 0.0]  # [-]
    sc_object.hub.omega_BN_BInit = [0.0, 0.0, 0.0]  # [rad/s]
    
  3. Create the SRP module and set the number of facets:

    faceted_srp_effector = facetedSRPEffector.FacetedSRPEffector()
    faceted_srp_effector.ModelTag = "facetedSRPEffector"
    faceted_srp_effector.setNumFacets(2)
    
  4. Create the sun and connect the Sun inertial state message:

    sun_state_message_data = messaging.SpicePlanetStateMsgPayload()
    sun_state_message_data.PositionVector = [0.0, 0.0, 0.0]  # [m]
    sun_state_message_data.VelocityVector = [0.0, 0.0, 0.0]  # [m/s]
    sun_state_message = messaging.SpicePlanetStateMsg().write(sun_state_message_data)
    
    grav_factory = simIncludeGravBody.gravBodyFactory()
    sun = grav_factory.createSun()
    sun.isCentralBody = True
    grav_factory.gravBodies['sun'].planetBodyInMsg.subscribeTo(sun_state_message)
    faceted_srp_effector.sunStateInMsg.subscribeTo(sun_state_message)
    
  5. Create a FacetElementBodyMsgPayload facet geometry input message for each facet:

    facet_area_list = [0.5, 1.0]  # [m^2]
    facet_r_CopB_B_list = [np.array([-0.1, 0.1, -0.1]),
                           np.array([0.1, -0.1, -0.1])]  # [m]
    facet_nHat_B_list = [np.array([1.0, 0.0, 0.0]),
                         np.array([0.0, 1.0, 0.0])]
    facet_rotHat_B_list = [np.array([0.0, 1.0, 0.0]),
                           np.array([1.0, 0.0, 0.0])]
    facet_diffuse_coeff_list = [0.1, 0.1]
    facet_specular_coeff_list = [0.9, 0.9]
    
    facet_1_message_data = messaging.FacetElementBodyMsgPayload(
        area = facet_area_list[0],
        r_CopB_B = facet_r_CopB_B_list[0],
        nHat_B = facet_nHat_B_list[0],
        rotHat_B = facet_rotHat_B_list[0],
        c_diffuse = facet_diffuse_coeff_list[0],
        c_specular = facet_specular_coeff_list[0],
    )
    facet_2_message_data = messaging.FacetElementBodyMsgPayload(
        area = facet_area_list[1],
        r_CopB_B = facet_r_CopB_B_list[1],
        nHat_B = facet_nHat_B_list[1],
        rotHat_B = facet_rotHat_B_list[1],
        c_diffuse = facet_diffuse_coeff_list[1],
        c_specular = facet_specular_coeff_list[1],
    )
    facet_1_message = messaging.FacetElementBodyMsg().write(facet_1_message_data)
    facet_2_message = messaging.FacetElementBodyMsg().write(facet_2_message_data)
    
  6. Subscribe the facet geometry input messages to the SRP module facetElementBodyInMsgs input message vector:

    faceted_srp_effector.facetElementBodyInMsgs[0].subscribeTo(facet_1_message)
    faceted_srp_effector.facetElementBodyInMsgs[1].subscribeTo(facet_2_message)
    
  7. Create the faceted spacecraft projected area module and set the total number of facets:

    faceted_sc_projected_area = facetedSpacecraftProjectedArea.FacetedSpacecraftProjectedArea()
    faceted_sc_projected_area.ModelTag = "facetedSpacecraftProjectedArea"
    faceted_sc_projected_area.setNumFacets(2)
    
  8. Subscribe the facet geometry input messages to the projected area module facetElementBodyInMsgs input message vector:

    faceted_sc_projected_area.facetElementBodyInMsgs[0].subscribeTo(facet_1_message)
    faceted_sc_projected_area.facetElementBodyInMsgs[1].subscribeTo(facet_2_message)
    
  9. Subscribe the projected area module facetProjectedAreaOutMsgs output message vector to the SRP module facetProjectedAreaInMsgs input message vector:

    faceted_srp_effector.facetProjectedAreaInMsgs[0].subscribeTo(faceted_sc_projected_area.facetProjectedAreaOutMsgs[0])
    faceted_srp_effector.facetProjectedAreaInMsgs[1].subscribeTo(faceted_sc_projected_area.facetProjectedAreaOutMsgs[1])
    
  10. Subscribe other required messages to the projected area module:

    faceted_sc_projected_area.sunStateInMsg.subscribeTo(sun_state_message)
    faceted_sc_projected_area.spacecraftStateInMsg.subscribeTo(sc_object.scStateOutMsg)
    
  11. Optionally, connect an eclipse message to account for shadow conditions. If connected, the computed SRP force and torque are scaled by the illumination factor (0.0 = full shadow, 1.0 = full sunlight):

    faceted_srp_effector.sunEclipseInMsg.subscribeTo(eclipse_msg)
    
  12. Add the SRP effector to the spacecraft:

    sc_object.addDynamicEffector(faceted_srp_effector)
    
  13. Add each module to a task:

    test_sim.AddModelToTask(task_name, faceted_sc_projected_area)
    test_sim.AddModelToTask(task_name, sc_object)
    test_sim.AddModelToTask(task_name, faceted_srp_effector)
    

Note

Add the spacecraft object to the task after the projected area module to ensure the SRP effector has valid input message data at the first integration timestep.


class FacetedSRPEffector : public SysModel, public DynamicEffector
#include <facetedSRPEffector.h>

Faceted solar radiation pressure dynamic effector.

Public Functions

FacetedSRPEffector() = default

Constructor.

~FacetedSRPEffector() = default

Destructor.

void linkInStates(DynParamManager &states) override

Method for giving the effector access to the hub states.

This method gives the module access to the hub inertial attitude and position.

Parameters:

states – Dynamic parameter states

void computeForceTorque(double callTime, double timeStep) override

Method for computing the total 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

void Reset(uint64_t currentSimNanos) override

Reset method.

This method resets required module variables and checks the input messages to ensure they are linked.

Parameters:

currentSimNanos – [ns] Time the method is called

void setNumFacets(const uint64_t numFacets)

Setter method for total number of spacecraft facets.

Setter method for the total number of spacecraft facets.

Parameters:

numFacets – [-]

const uint64_t getNumFacets() const

Getter method for total number of spacecraft facets.

Getter method for the total number of spacecraft facets.

Returns:

const uint64_t

Public Members

std::vector<ReadFunctor<FacetElementBodyMsgPayload>> facetElementBodyInMsgs

List of facet geometry input data (Expressed in hub B frame).

std::vector<ReadFunctor<ProjectedAreaMsgPayload>> facetProjectedAreaInMsgs

List of facet projected area input messages.

ReadFunctor<SpicePlanetStateMsgPayload> sunStateInMsg

Sun spice ephemeris input message.

ReadFunctor<EclipseMsgPayload> sunEclipseInMsg

(optional) Sun eclipse input message

Private Members

std::vector<double> facetAreaList

[m^2] List of facet areas

std::vector<double> facetProjectedAreaList

[m^2] List of facet projected areas

std::vector<Eigen::Vector3d> facetR_CopB_BList

[m] List of facet center of pressure locations wrt point B expressed in B frame components

std::vector<Eigen::Vector3d> facetNHat_BList

[-] List of facet normal vectors expressed in hub B frame components

std::vector<double> facetDiffuseCoeffList

[-] List of facet diffuse reflection optical coefficient list

std::vector<double> facetSpecularCoeffList

[-] List of facet specular reflection optical coefficient list

uint64_t numFacets = {}

Number of spacecraft facets.

StateData *hubPosition = nullptr

[m] Hub inertial position vector

StateData *hubSigma = nullptr

Hub MRP inertial attitude.

double sunVisibilityFactor = 1.0

Sun visibility factor (0 = full shadow, 1 = full sunlight).