C++ 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 C++ 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.

thrusterStateEffector module input and output messages

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 C++ 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 C++ 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 C++ 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 (C++ 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 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 C++ 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)

Initialization and Reset

kappaInit must contain exactly one finite thrust factor per thruster, with each value in the closed interval [0, 1]. addThruster() appends a zero initial value automatically. If replacing the vector, supply all entries, including zeros for initially inactive thrusters. State registration and Reset() validate the vector before accessing its entries; invalid dimensions or values raise BasiliskError.

A linked cmdsInMsg supports at most MAX_EFF_CNT thrusters. State registration, Reset(), and command reading enforce this limit, including an input connected after initialization. Larger sets remain supported with the input unlinked; input reading supplies zero commands without indexing the fixed-size payload. Direct calls to ConfigureThrustRequests() may supply partial NewThrustCmds vectors, but the vector cannot exceed the thruster count.

State registration sizes the command storage and initializes the integrated thrust factors from kappaInit. Reset() repeats validation, zeros command storage and the total mass-flow output, and leaves the integrated thrust-factor states unchanged. Add the effector to a task to process commands and publish thruster outputs.

Add all thrusters before InitializeSimulation() registers their states. After registration, addThruster() raises BasiliskError without adding a device. Changes to the length of the public thrusterData vector are also rejected before reset, command processing, output publication, or dynamics access, even when the effector is absent from the task. Reset() does not resize registered states; use a new effector and simulation when changing the number of thrusters. Calling Reset() before state registration does not freeze the count.


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.

Parameters:

CurrentSimNanos – [in] [ns] Current simulation time.

bool ReadInputs()

Read the incoming command message and populate the thruster command vector.

Returns:

Whether a new command is available, or zero commands were supplied for an unlinked input.

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

void registerStates(DynParamManager &states)

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

Parameters:

states – [inout] Dynamic parameter manager used to register states or properties.

void linkInStates(DynParamManager &states)

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

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

Method for each stateEffector to calculate derivatives.

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

Parameters:
  • integTime – [in] [s] Current integration time.

  • rDDot_BN_N – [in] [m/s^2] Hub translational acceleration expressed in inertial-frame components.

  • omegaDot_BN_B – [in] [rad/s^2] Hub angular acceleration expressed in body-frame components.

  • sigma_BN – [in] Hub attitude relative to the inertial frame.

void calcForceTorqueOnBody(double integTime, Eigen::Vector3d omega_BN_B)

Calculate the force and torque exerted on the attached body.

Parameters:
  • integTime – [in] [s] Current integration time.

  • omega_BN_B – [in] [rad/s] Hub angular velocity expressed in body-frame components.

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

Method to pass the forces and torques onto the hub.

Update the effector Backsubstitution contributions.

Parameters:
  • integTime – [in] [s] Current integration time.

  • backSubContr – [inout] Backsubstitution contributions.

  • sigma_BN – [in] Hub attitude relative to the inertial frame.

  • omega_BN_B – [in] [rad/s] Hub angular velocity expressed in body-frame components.

  • g_N – [in] [m/s^2] Gravitational acceleration expressed in inertial-frame components.

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

Parameters:

integTime – [in] [s] Current integration time.

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

void addThruster(std::shared_ptr<THRSimConfig> newThruster)

Add a new thruster to the thruster set.

Add a thruster.

Note

Thrusters can only be added before state registration.

Parameters:

newThruster – [in] Thruster configuration to add.

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

(overloaded) Add a new thruster to the thruster set connect to a body different than the hub

Add a thruster.

Note

Thrusters can only be added before state registration.

Parameters:
  • newThruster – [in] Thruster configuration to add.

  • bodyStateMsg – [in] State message for the body carrying the thruster.

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.

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.

Public Members

ReadFunctor<THRArrayOnTimeCmdMsgPayload> cmdsInMsg

input message with thruster commands

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

output message vector for thruster data

std::vector<std::shared_ptr<THRSimConfig>> thrusterData

Thruster information.

std::vector<double> NewThrustCmds

Incoming thrust commands.

std::vector<double> kappaInit

[] Vector of initial thruster states

std::string nameOfKappaState

Identifier for the kappa state data container.

StateData *hubSigma

pointer to hub attitude states

StateData *hubOmega

pointer to hub angular velocity states

StateData *kappaState

state manager of theta for hinged rigid body

Eigen::MatrixXd *inertialPositionProperty

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

Eigen::Vector3d r_PcP_P

[m] position vector of parent body CoM w.r.t. parent body frame origin (only used if thrusters attached to non-hub body)

BSKLogger bskLogger

BSK Logging.

double mDotTotal = 0.0

[kg/s] Current mass flow rate of thrusters

Private Functions

void validateConfiguration()

Validate dimensions before accessing thruster data or commands.

Validate configuration dimensions before initialization or command processing.

void validateRegisteredCount()

Reject changes to the number of registered thrust-factor states.

Reject device-count changes without relying on a live parent state pointer.

Private Members

std::optional<std::size_t> registeredThrusterCount

Thruster count after successful state registration.

std::vector<THROutputMsgPayload> thrusterOutBuffer

Message buffer for thruster data.

THRArrayOnTimeCmdMsgPayload incomingCmdBuffer

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] Time for previous valid thruster firing

Private Static Attributes

static uint64_t effectorID = 1

[] ID number of this panel