Module: thrusterStateEffector

Executive Summary

This module provides an implementation of the behavior of thrusters. Thrusters are modeled dynamically using a first-order ordinary differential equation, which is compatible with variable time step integrators. With this module, there are now two different thruster implementations. See Module: thrusterDynamicEffector for the previous version, which implemented thrusters using on and off-ramps, although not compatible with variable time step integrators.

Message Connection Descriptions

The following table lists all the module input and output messages. The module msg variable name 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

cmdsInMsg

THRArrayOnTimeCmdMsgPayload

(optional) input message with thruster commands. If not connected the thruster commands are set to zero.

thrusterOutMsgs

THROutputMsgPayload

output message vector for thruster data

Detailed Module Description

Thruster Modeling

The functionalities of this thruster implementation are identical to the ones seen in Module: thrusterDynamicEffector. For a general description of the thruster implementation in Basilisk, namely how the forces and torques are computed, see that module’s documentation.

The main difference between the two thruster implementations comes from how the thrustFactor is computed and updated at each timestep. The thrustFactor is a parameter specific to each thruster and ranges from 0 to 1. It defines what the current magnitude of the thrust is: at 0 the thruster is off, and at 1 the thruster is at maxThrust. While the previous thruster module computed the thrustFactor using on and off-ramps at the beginning and end of the thrusting maneuver, respectively, with a constant steady-state value of 1 in-between, this module updates that value through a first-order ordinary differential equation.

The state variable used in this state effector is \(\kappa\), which is a vector of thrustFactors for each thruster. As with Module: thrusterDynamicEffector, the addThruster() method augments the vector of thruster inside the module. However, for this module the state vector \(\kappa\) is also augmented in this method.

Let \(\kappa_i\) correspond to the thrustFactor of the i-th thruster. It has two governing differential equations, depending on whether a thrust command is present or not. The differential equation when thrusting is given by

\[\dot{\kappa_i} = \omega(1-\kappa_i)\]

where \(\omega\), in rad/s, corresponds to the cutoff frequency of the first-order filter, and is thruster-specific. The differential equation when not thrusting is given by

\[\dot{\kappa_i} = -\omega\kappa_i\]

While the value of \(\kappa_i\) for each thruster is computed numerically by integrating these ODEs, there are closed-form solutions to these equations that are used for validation and verification purposes. The solutions to each of these differential equations are given, respectively, by

\[\kappa_i(t) = 1 + (\kappa_{0,i}-1)e^{-\omega t}, \qquad \kappa_i(t) = \kappa_{0,i}e^{-\omega t}\]

where \(\kappa_{0,i}\) corresponds to the initial conditions of the thrusterFactor variable for the i-th particular thruster.

Adding Thrusters to Auxiliary Bodies

This thruster effector does not have to only be attached to the primary spacecraft body \(B\). Rather, it is possible to attach this to a rigid body sub-component of the spacecraft where now the thruster location and orientations vary with time with respect to the \(B\) frame. However, note that currently attaching a thruster to a sub-component just determines where the thruster location and thrust direction are. The thrust does not impact the dynamics of a hinged panel, for example. Currently there is one-way coupling here where the sub-component states impact the location and orientation of the thruster, but firing the thruster does not impact the effector.

Let \(F\) be the body-fixed frame of the rigid body sub-component, such as Module: prescribedMotionStateEffector. With this effector case it is ok that the thruster does not impact the effector as the effector motion is prescribed. If the thruster is added to an auxiliary body \(F\) which is connected to the main spacecraft body \(B\), then this is accomplished using:

thrusterSet.addThruster(thruster1, bodyStatesMsg)

Here thruster1 is the thruster being added, and bodyStatesMsg is the state output message of the platform \(F\). In the Update() routine the position of the platform \(F\) relative to \(B\) is recomputed each time step.

The thruster state output message contains variables that end with _B. These vectors are always written with spacecraft body frame \(B\) vector components. However, the output message states thrusterDirection and thrusterLocation don’t contain the _B suffix because they are written in either \(B\) frame components if the thruster is attached to the body frame \(B\), and in the sub-component frame \(F\) if attached to an auxiliary spacecraft component.

Model Assumptions and Limitations

Assumptions

The model assumes that the behavior of a thruster is represented by a first-order filter. Therefore, due to the simplicity of the model, some real-world behaviors cannot be simulated, such as overshoot or damping.

The thruster module also assumes that the thruster always thrusts along its thrust directions axis. No dispersion is added to the thrust axis with respect to the nominal thruster axis.

Limitations

One of the limitations of this model relates to the dynamic nature of this thruster implementation. The thrust is simulated through the thrust factor, which is updated by integrating a differencial equation. This means that it is not possible to reproduce on-off behavior, where the thruster goes from not thrusting to being at maximum thrust or vice-versa. Using this dynamic model, we would have to use infinite derivatives to reproduce this behavior, which is not numerically feasible. To replicate this behavior, the user should use the older version of the thruster effector (Module: thrusterDynamicEffector) with both on or off-ramps disabled.

Another limitation is that the \(I_{sp}\) used is constant throughout the simulation. This means that the mass flow rate of the thruster is constant - the thruster will lose mass as soon as the valve is open, independent of how much thrust force is being produced. If the user needs to change the \(I_{sp}\) value of any of the thrusters, the simulation needs to be stop and restarted.

Note

The dynamic behaviour of this module is governed by the cutoffFrequency variable inside Module: THRSimConfig. Its default value is equal to 10 rad/s. All variables related to on and off-ramps have no impact on this module and are instead supposed to be used to determine the dynamic behaviour within Module: thrusterDynamicEffector.

User Guide

This section contains conceptual overviews of the code and clear examples for the prospective user.

Module Setup

To use the thruster state effector module, the user first needs to create the thruster and populate it with the necessary information, such as thruster magnitude, minimum on time, etc. This can be done with the help of the simIncludeThruster Basilisk Python library. The code to create a generic thruster is shown below:

thFactory = simIncludeThruster.thrusterFactory()
TH1 = thFactory.create('MOOG_Monarc_1',
                       [1, 0, 0],  # location in B-frame
                       [0, 1, 0]  # thruster force direction in B-frame
                      )

The code above creates the generic thruster Monarc 1. To create the thruster effector and connect the thruster to it, the code below is used:

thrustersStateEffector = thrusterStateEffector.ThrusterStateEffector()
thFactory.addToSpacecraft("Thrusters",
                          thrustersStateEffector,
                          scObject)

Assuming that the user has created a list of initial conditions called initialConditions, then setting the initial conditions for all thrusters is done with the code below:

thrustersStateEffector.kappaInit = messaging.DoubleVector(initialConditions)

class ThrusterStateEffector : public StateEffector, public SysModel
#include <thrusterStateEffector.h>

thruster dynamic effector class

Public Functions

ThrusterStateEffector()

The Constructor.

~ThrusterStateEffector()

The destructor.

void Reset(uint64_t CurrentSimNanos)

This method is used to reset the module.

Returns:

void

bool ReadInputs()

This method is used to read the incoming command message and set the associated command structure for operating the thrusters.

Returns:

void

void writeOutputStateMessages(uint64_t CurrentClock)

This method is here to write the output message structure into the specified message.

Parameters:

CurrentClock – The current time used for time-stamping the message

Returns:

void

void registerStates(DynParamManager &states)

&#8212; Method for the effector to register its states

This method allows the thruster state effector to register its state kappa with the dyn param manager

void linkInStates(DynParamManager &states)

&#8212; Method for the effector to get access of other states

This method is used to link the states to the thrusters

Parameters:

states – The states to link

Returns:

void

void computeDerivatives(double integTime, Eigen::Vector3d rDDot_BN_N, Eigen::Vector3d omegaDot_BN_B, Eigen::Vector3d sigma_BN)

&#8212; Method for each stateEffector to calculate derivatives

This method is used to find the derivatives for the thruster stateEffector

void calcForceTorqueOnBody(double integTime, Eigen::Vector3d omega_BN_B)
void updateContributions(double integTime, BackSubMatrices &backSubContr, Eigen::Vector3d sigma_BN, Eigen::Vector3d omega_BN_B, Eigen::Vector3d g_N)

Method to pass the forces and torques onto the hub.

void updateEffectorMassProps(double integTime)

This is the method for the thruster effector to add its contributions to the mass props and mass prop rates of the vehicle

void UpdateState(uint64_t CurrentSimNanos)

This method is the main cyclical call for the scheduled part of the thruster dynamics model. It reads the current commands array and sets the thruster configuration data based on that incoming command set. Note that the main dynamical method (ComputeDynamics()) is not called here and is intended to be called from the dynamics plant in the system

Parameters:

CurrentSimNanos – The current simulation time in nanoseconds

Returns:

void

void addThruster(THRSimConfig *newThruster)

&#8212; Add a new thruster to the thruster set

void addThruster(THRSimConfig *newThruster, Message<SCStatesMsgPayload> *bodyStateMsg)

&#8212; (overloaded) Add a new thruster to the thruster set connect to a body different than the hub

void ConfigureThrustRequests()

This method is used to read the new commands vector and set the thruster firings appropriately. It assumes that the ReadInputs method has already been run successfully. It honors all previous thruster firings if they are still active. Note that for unit testing purposes you can insert firings directly into NewThrustCmds.

Returns:

void

void UpdateThrusterProperties()

This method is used to update the location and orientation of the thrusters at every UpdateState call when the thrusters are attached to a body other than the hub.

Returns:

void

Public Members

ReadFunctor<THRArrayOnTimeCmdMsgPayload> cmdsInMsg

&#8212; input message with thruster commands

std::vector<Message<THROutputMsgPayload>*> thrusterOutMsgs

&#8212; output message vector for thruster data

std::vector<THRSimConfig> thrusterData

&#8212; Thruster information

std::vector<double> NewThrustCmds

&#8212; Incoming thrust commands

std::vector<double> kappaInit

[] Vector of initial thruster states

std::string nameOfKappaState

&#8212; Identifier for the kappa state data container

StateData *hubSigma

pointer to hub attitude states

StateData *hubOmega

pointer to hub angular velocity states

StateData *kappaState

&#8212; state manager of theta for hinged rigid body

Eigen::MatrixXd *inertialPositionProperty

[m] r_N inertial position relative to system spice zeroBase/refBase

BSKLogger bskLogger

&#8212; BSK Logging

double mDotTotal = 0.0

[kg/s] Current mass flow rate of thrusters

Private Members

std::vector<THROutputMsgPayload> thrusterOutBuffer

&#8212; Message buffer for thruster data

THRArrayOnTimeCmdMsgPayload incomingCmdBuffer

&#8212; One-time allocation for savings

std::vector<ReadFunctor<SCStatesMsgPayload>> attachedBodyInMsgs

vector of body states message where the thrusters attach to

SCStatesMsgPayload attachedBodyBuffer
std::vector<BodyToHubInfo> bodyToHubInfo
double prevCommandTime

[s] &#8212; Time for previous valid thruster firing

Private Static Attributes

static uint64_t effectorID = 1

[] ID number of this panel