C++ Module: dragDynamicEffector

Executive Summary

Drag dynamics class used to compute drag effects on spacecraft bodies. This class is used to implement drag dynamic effects on spacecraft using a variety of simple or complex models, which will include cannonball (attitude-independent) drag, single flat-plate drag, faceted drag models, and an interface to full-CAD GPU-accelerated drag models.

Density Correction State

The module supports an optional density correction state that scales the incoming atmospheric density. If densityCorrectionStateName is set, the drag model uses

\[\rho = \max\!\left(0,\; \rho_{\text{in}} \left(1 + \delta_\rho\right)\right)\]

where \(\rho_{\text{in}}\) is read from atmoDensInMsg and \(\delta_\rho\) is the scalar state referenced by densityCorrectionStateName. The \(\max(0,\cdot)\) guards against a non-positive correction: a stochastic correction state (e.g. an C++ Module: igbmNoiseStateEffector factor) can, under an explicit integrator, occasionally make \(1+\delta_\rho\) negative, and a negative density is unphysical.

If densityCorrectionStateName is left empty (default), no correction is applied and atmoDensInMsg.neutralDensity is used directly.

Example setup:

# Drag model
drag = dragDynamicEffector.DragDynamicEffector()
drag.coreParams.dragCoeff = 2.2
drag.coreParams.projectedArea = 10.0
drag.atmoDensInMsg.subscribeTo(atmo.envOutMsgs[0])

# Optional: apply multiplicative density correction from a scalar state
stochasticAtmo = meanRevertingNoiseStateEffector.MeanRevertingNoiseStateEffector()
# ... Configure stochasticAtmo here
scObject.addStateEffector(stochasticAtmo)
drag.densityCorrectionStateName = stochasticAtmo.getStateName()

scObject.addDynamicEffector(drag)
scSim.AddModelToTask(simTaskName, drag)

Wind Velocity Input

When windVelInMsg is linked to a C++ Module: windBase-derived module (e.g. C++ Module: zeroWindModel), the drag model subtracts the air velocity v_air_N from the spacecraft inertial velocity before computing drag, yielding the atmosphere-relative velocity:

\[\mathbf{v}_{rel} = \mathbf{v}_{sc} - \mathbf{v}_{air}\]

If windVelInMsg is not linked, the inertial spacecraft velocity is used directly.

Example setup:

drag = dragDynamicEffector.DragDynamicEffector()
drag.coreParams.dragCoeff = 2.2
drag.coreParams.projectedArea = 10.0
drag.atmoDensInMsg.subscribeTo(atmo.envOutMsgs[0])

# Optional: link a wind model for atmosphere-relative velocity
drag.windVelInMsg.subscribeTo(windModel.envOutMsgs[0])

scObject.addDynamicEffector(drag)
scSim.AddModelToTask(simTaskName, drag)

Input Message Timing

Both atmoDensInMsg and windVelInMsg are refreshed only during UpdateState(). Because Spacecraft::computeForceTorque() calls dynamic effectors before the atmosphere and wind models receive their next UpdateState(), the drag computation always uses the values from the previous time step (zero-initialized on the first step). Both inputs are therefore treated as piecewise-constant over each integration step.

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.

dragDynamicEffector module input and output messages

Module I/O Messages

Msg Variable Name

Msg Type

Description

atmoDensInMsg

AtmoPropsMsgPayload

atmospheric density input message.

windVelInMsg

WindMsgPayload

(optional) wind velocity input message; when linked, v_air_N is subtracted from the spacecraft inertial velocity to obtain the atmosphere-relative velocity.

Initialization and Reset

When the spacecraft links this effector to the hub states, initialization verifies that atmoDensInMsg is connected. This validation occurs even if only the spacecraft is added to a task.

Attachment-time validation does not replace task scheduling for this effector. Add it to a task so that UpdateState() refreshes the cached atmospheric density and optional wind data used during force evaluation.

When the effector is scheduled, its Reset() repeats the required-message check. Reset() does not clear the cached density, wind, force, or torque data.


struct DragBaseData
#include <dragDynamicEffector.h>

Container for basic drag parameters - the spacecraft’s atmosphere-relative velocity, its projected area, and its drag coefficient.

Public Members

double projectedArea

m^2 Area of spacecraft projected in velocity direction

double dragCoeff

Nondimensional drag coefficient.

Eigen::Vector3d comOffset

m distance from center of mass to center of projected area

class DragDynamicEffector : public SysModel, public DynamicEffector
#include <dragDynamicEffector.h>

drag dynamic effector

Public Functions

DragDynamicEffector()
~DragDynamicEffector()

The destructor.

void linkInStates(DynParamManager &states)

class method

This method is used to link the dragEffector to the hub attitude and velocity, which are required for calculating drag forces and torques.

Parameters:

states – simulation states

void computeForceTorque(double integTime, double timeStep)

This method computes the body forces and torques for the dragEffector in a simulation loop, selecting the model type based on the settable attribute “modelType.”

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

  • timeStep – [in] [s] Integration time step.

void Reset(uint64_t CurrentSimNanos)

Validate the module configuration when the scheduler resets the model.

Parameters:

CurrentSimNanos – [ns] Time at which the reset occurs

void UpdateState(uint64_t CurrentSimNanos)

This method is called to update the local atmospheric conditions at each timestep. Naturally, this means that conditions are held piecewise-constant over an integration step.

Parameters:

CurrentSimNanos – The current simulation time in nanoseconds

void WriteOutputMessages(uint64_t CurrentClock)

The DragEffector does not write output messages to the rest of the sim.

Parameters:

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

bool ReadInputs()

This method is used to read the incoming density message and wind velocity message (if linked) and update the internal density/atmospheric data.

void cannonballDrag()

This method implements a simple “cannonball” (attitude-independent) drag model.

void updateDragDir()

This method updates the internal drag direction based on the spacecraft velocity vector. It accounts for wind velocity if the wind message is linked.

double getDensity()

This method obtains the density from the input data and applies a correction based on the density correction state (if it was configured)

Public Members

DragBaseData coreParams

Struct used to hold drag parameters.

ReadFunctor<AtmoPropsMsgPayload> atmoDensInMsg

message used to read density inputs

ReadFunctor<WindMsgPayload> windVelInMsg

message used to read wind velocity inputs

std::string modelType

String used to set the type of model used to compute drag.

StateData *hubSigma

Hub/Inertial attitude represented by MRP.

StateData *hubVelocity

m/s Hub inertial velocity vector

std::string densityCorrectionStateName = ""

If not ‘’, finds a state with this name to get densityCorrection.

StateData *densityCorrection

Used density is (1 + densityCorrection) * atmoInData.neutralDensity.

Eigen::Vector3d v_B

m/s spacecraft velocity expressed in body frame B (relative to air if windVelInMsg is linked, else relative to inertial frame N)

Eigen::Vector3d v_hat_B

Drag force direction in the body frame.

BSKLogger bskLogger

BSK Logging.

Private Functions

void validateConfiguration()

Validate required input-message connections.

Validate that the required atmospheric density input is connected.

Private Members

AtmoPropsMsgPayload atmoInData
WindMsgPayload windInData