3. Un-guided Capsule Entry¶
The example described on this page is that of Apollo on a re-entry trajectory towards the surface of Earth. The code for this tutorial is given on Github, and is also located in your Tudat bundle at:
tudatBundle/tudatExampleApplications/satellitePropagatorExamples/SatellitePropagatorExamples/apolloCapsuleEntry.cpp
For this example, we have the following problem statement:
Given the position and velocity of the Apollo capsule at a certain point in time with respect to the Earth, what will its position and velocity be once it reaches an altitude of 25 km over the surface of Earth?
Warning
The example described in this page assumes that the user has read the Unperturbed Earth-orbiting Satellite. This page only describes the differences with respect to such example, so please go back before proceeding.
3.1. Create the Vehicle¶
First, the vehicle is created by placing an "Apollo"
entry vehicle in the bodyMap
, as shown below:
// Create vehicle objects.
bodyMap[ "Apollo" ] = std::make_shared< simulation_setup::Body >( );
Once that is done, an AerodynamicCoefficientInterface
is linked to the vehicle by means of the following command:
// Create vehicle aerodynamic coefficients
bodyMap[ "Apollo" ]->setAerodynamicCoefficientInterface(
unit_tests::getApolloCoefficientInterface( ) );
In this example a pre-made interface is used to define the aerodynamic coefficients. The getApolloCoefficientInterface( )
function returns a HypersonicLocalInclinationAnalysis
object, which is a derived-class from AerodynamicCoefficientInterface
. It computes the aerodynamic coefficients during propagation by means of a local-inclination method. Finally, the mass of the Apollo capsule is set and the body creation is finalized:
bodyMap[ "Apollo" ]->setConstantBodyMass( 5.0E3 );
// Finalize body creation.
setGlobalFrameBodyEphemerides( bodyMap, "SSB", "J2000" );
Tip
If you want to include a different vehicle, you will have to define a new AerodynamicCoefficientInterface
and implement your own custom aerodynamic database. Please go to Aerodynamic Guidance for further details.
3.2. Set Up the Acceleration Models¶
A major difference with respect to the Unperturbed Earth-orbiting Satellite is the use of a spherical-harmonic gravity model and the presence of an aerodynamic force on the vehicle. The spherical-harmonic gravity model is selected by the derived-class SphericalHarmonicAccelerationSettings
with degree and order as input parameters. Both acceleration models are added to the accelerationMap
as follows:
// Define acceleration model settings.
std::map< std::string, std::vector< std::shared_ptr< AccelerationSettings > > > accelerationsOfApollo;
accelerationsOfApollo[ "Earth" ].push_back( std::make_shared< SphericalHarmonicAccelerationSettings >( 4, 0 ) );
accelerationsOfApollo[ "Earth" ].push_back( std::make_shared< AccelerationSettings >( aerodynamic ) );
accelerationMap[ "Apollo" ] = accelerationsOfApollo;
A crucial step in re-entry modelling is the definition of an AerodynamicGuidance
model. Controlling the orientation of the vehicle during atmospheric flight plays an important role in the shape of the trajectory as well as on the magnitude of the aerodynamic and thermal loads. In this example, a simple fixed-angle aerodynamic guidance model is used. This is implemented using a lambda expression (explained in detail here). In short this function always outputs the value of constantAngleOfAttack
, which in turn sets the orientation angles of the "Apollo"
body:
// Define constant 30 degree angle of attack
double constantAngleOfAttack = unit_conversions::convertDegreesToRadians(30.0);
bodyMap.at( "Apollo" )->getFlightConditions( )->getAerodynamicAngleCalculator( )->setOrientationAngleFunctions(
[ = ]( ){ return constantAngleOfAttack; } );
Tip
To view the available options for aerodynamic guidance check out the Aerodynamic Guidance section.
3.3. Set Up the Propagation Settings¶
In most re-entry studies, it is convenient to define the entry conditions using a spherical state. The following entry state is used:
Altitude: 120 km
Latitude: 0 deg
Longitude: 68.75 deg
Inertial speed: 7.7 km/s
Flight-path angle: -0.9 deg
Heading angle: 34.37 deg
Such state must be defined and converted to Cartesian state variables as follows:
// Set spherical elements for Apollo.
Eigen::Vector6d apolloSphericalEntryState;
apolloSphericalEntryState( SphericalOrbitalStateElementIndices::radiusIndex ) =
spice_interface::getAverageRadius( "Earth" ) + 120.0E3;
apolloSphericalEntryState( SphericalOrbitalStateElementIndices::latitudeIndex ) =
unit_conversions::convertDegreesToRadians( 0.0 );
apolloSphericalEntryState( SphericalOrbitalStateElementIndices::longitudeIndex ) =
unit_conversions::convertDegreesToRadians( 68.75 );
apolloSphericalEntryState( SphericalOrbitalStateElementIndices::speedIndex ) = 7.7E3;
apolloSphericalEntryState( SphericalOrbitalStateElementIndices::flightPathIndex ) =
unit_conversions::convertDegreesToRadians( -0.9 );
apolloSphericalEntryState( SphericalOrbitalStateElementIndices::headingAngleIndex ) =
unit_conversions::convertDegreesToRadians( 34.37 );
// Convert apollo state from spherical elements to Cartesian elements.
Eigen::Vector6d systemInitialState = convertSphericalOrbitalToCartesianState(
apolloSphericalEntryState );
Finally, the state needs to be converted to inertial frame. As it is customary, in fact, the spherical state above (and thus also the converted Cartesian state), is defined in the rotating frame centered at the Earth center (ECEF). However, as mentioned in Unperturbed Earth-orbiting Satellite, in Tudat propagation can only occurr in inertial frames. Hence, the following lines are included:
// Convert the state to the global (inertial) frame.
std::shared_ptr< ephemerides::RotationalEphemeris > earthRotationalEphemeris =
bodyMap.at( "Earth" )->getRotationalEphemeris( );
systemInitialState = transformStateToGlobalFrame( systemInitialState, simulationStartEpoch, earthRotationalEphemeris );
Note
Note that the latitudeIndex
of apolloSphericalEntryState
makes reference to the geocentric latitude.
3.3.1. Create a List of Dependent Variables to Save¶
In this example, a number of dependent variables are saved to plot the trajectory of Apollo after re-entry. The following dependent variables are saved:
Mach number
Altitude
Aerodynamic acceleration norm
Aerodynamic force coefficients (\(C_D\), \(C_S\), \(C_L\))
First, a dependentVariablesList
needs to be created, which will list all the variables to save:
// Define list of dependent variables to save.
std::vector< std::shared_ptr< SingleDependentVariableSaveSettings > > dependentVariablesList;
Next, the list is populated with the desired dependent variables. Please go to Propagator Settings: Dependent Variables for further details on the various dependent variables that can be stored:
dependentVariablesList.push_back( std::make_shared< SingleDependentVariableSaveSettings >(
mach_number_dependent_variable, "Apollo" ) );
dependentVariablesList.push_back( std::make_shared< SingleDependentVariableSaveSettings >(
altitude_dependent_variable, "Apollo", "Earth" ) );
dependentVariablesList.push_back( std::make_shared< SingleAccelerationDependentVariableSaveSettings >(
aerodynamic, "Apollo", "Earth", 1 ) );
dependentVariablesList.push_back( std::make_shared< SingleDependentVariableSaveSettings >(
aerodynamic_force_coefficients_dependent_variable, "Apollo" ) );
// Create object with list of dependent variables
std::shared_ptr< DependentVariableSaveSettings > dependentVariablesToSave =
std::make_shared< DependentVariableSaveSettings >( dependentVariablesList );
Tip
If you do not want the console output generated by DependentVariableSaveSettings
to show, you can simply set the second input argument as false
.
3.3.2. Define the Termination Conditions¶
Finally, the termination conditions are established. The termination settings are stored in the PropagationTerminationSettings
object. In this example, the re-entry trajectory is propagated until Apollo’s altitude drops below 25 km. The boolean in the constructor of the derived-class PropagationDependentVariableTerminationSettings
indicates whether the simulation is terminated when terminationDependentVariable
goes below the supplied value (true
) or above (false
):
// Define termination conditions
std::shared_ptr< SingleDependentVariableSaveSettings > terminationDependentVariable =
std::make_shared< SingleDependentVariableSaveSettings >( altitude_dependent_variable, "Apollo", "Earth" );
std::shared_ptr< PropagationTerminationSettings > terminationSettings =
std::make_shared< PropagationDependentVariableTerminationSettings >( terminationDependentVariable, 25.0E3, true );
Tip
Please go to Propagator Settings: Termination Settings for a detailed description of the available termination conditions.
3.4. Results¶
Below the history of some of the saved parameters is shown. One can see the capsule skipping several times before its final descent into the atmosphere, where it reaches 25 km altitude. The dependent variable history can be obtained in Tudat from the getDependentVariableHistory
function of the DynamicsSimulator
class. The resulting std::map
can be saved as discussed in Input/Output.

Tip
Open the figure in a new tab for more detail.