//! Function to create a gravity field model. boost::shared_ptr< gravitation::GravityFieldModel > createGravityFieldModel( const boost::shared_ptr< GravityFieldSettings > gravityFieldSettings, const std::string& body, const NamedBodyMap& bodyMap, const std::vector< boost::shared_ptr< GravityFieldVariationSettings > >& gravityFieldVariationSettings ) { using namespace tudat::gravitation; // Declare return object. boost::shared_ptr< GravityFieldModel > gravityFieldModel; // Check which type of gravity field model is to be created. switch( gravityFieldSettings->getGravityFieldType( ) ) { case central: { // Check whether settings for point mass gravity field model are consistent with its type. boost::shared_ptr< CentralGravityFieldSettings > centralFieldSettings = boost::dynamic_pointer_cast< CentralGravityFieldSettings >( gravityFieldSettings ); if( centralFieldSettings == NULL ) { throw std::runtime_error( "Error, expected central field settings when making gravity field model for body " + body); } else if( gravityFieldVariationSettings.size( ) != 0 ) { std::cerr<<"Error, requested central gravity field, but field variations settings are not empty."<<std::endl; } else { // Create and initialize point mass gravity field model. gravityFieldModel = boost::make_shared< GravityFieldModel >( centralFieldSettings->getGravitationalParameter( ) ); } break; } #if USE_CSPICE case central_spice: { if( gravityFieldVariationSettings.size( ) != 0 ) { std::cerr<<"Error, requested central gravity field, but field variations settings are not empty."<<std::endl; } else { // Create and initialize point mass gravity field model from Spice. gravityFieldModel = boost::make_shared< GravityFieldModel >( spice_interface::getBodyGravitationalParameter( body ) ); } break; } #endif case spherical_harmonic: { // Check whether settings for spherical harmonic gravity field model are consistent with // its type. boost::shared_ptr< SphericalHarmonicsGravityFieldSettings > sphericalHarmonicFieldSettings = boost::dynamic_pointer_cast< SphericalHarmonicsGravityFieldSettings >( gravityFieldSettings ); if( sphericalHarmonicFieldSettings == NULL ) { throw std::runtime_error( "Error, expected spherical harmonic field settings when making gravity field model of " + body ); } else { // Check consistency of cosine and sine coefficients. if( ( sphericalHarmonicFieldSettings->getCosineCoefficients( ).rows( ) != sphericalHarmonicFieldSettings->getSineCoefficients( ).rows( ) ) || ( sphericalHarmonicFieldSettings->getCosineCoefficients( ).cols( ) != sphericalHarmonicFieldSettings->getSineCoefficients( ).cols( ) ) ) { throw std::runtime_error( std::string( "Error when making spherical harmonic field, sine and " ) + std::string( "cosine matrix sizes are not equal for body " ) + body ); } else { if( gravityFieldVariationSettings.size( ) == 0 && sphericalHarmonicFieldSettings->getCreateTimeDependentField( ) == 0 ) { // Create and initialize spherical harmonic gravity field model. gravityFieldModel = boost::make_shared< SphericalHarmonicsGravityField >( sphericalHarmonicFieldSettings->getGravitationalParameter( ), sphericalHarmonicFieldSettings->getReferenceRadius( ), sphericalHarmonicFieldSettings->getCosineCoefficients( ), sphericalHarmonicFieldSettings->getSineCoefficients( ), sphericalHarmonicFieldSettings->getAssociatedReferenceFrame( ) ); } else { if( bodyMap.at( body )->getGravityFieldModel( ) != NULL ) { std::cerr<<"Warning when making time-dependent gravity field model for body "<<body<<" existing gravity field " <<" is not empty but overwritten in Body! "<<std::endl; } // Create preliminary TimeDependentSphericalHarmonicsGravityField, without actual variation settings. gravityFieldModel = boost::make_shared< TimeDependentSphericalHarmonicsGravityField >( sphericalHarmonicFieldSettings->getGravitationalParameter( ), sphericalHarmonicFieldSettings->getReferenceRadius( ), sphericalHarmonicFieldSettings->getCosineCoefficients( ), sphericalHarmonicFieldSettings->getSineCoefficients( ), sphericalHarmonicFieldSettings->getAssociatedReferenceFrame( ) ); } } } break; } default: throw std::runtime_error( "Error, did not recognize gravity field model settings type " + boost::lexical_cast< std::string >( gravityFieldSettings->getGravityFieldType( ) ) ); } return gravityFieldModel; }
Eigen::Matrix< StateScalarType, 6, 1 > propagateForwardBackwards( const int integratorCase ) { //Load spice kernels. spice_interface::loadStandardSpiceKernels( ); // Define bodies in simulation. std::vector< std::string > bodyNames; bodyNames.push_back( "Earth" ); bodyNames.push_back( "Moon" ); bodyNames.push_back( "Sun" ); bodyNames.push_back( "Mars" ); bodyNames.push_back( "Venus" ); // Specify initial time double initialEphemerisTime = 1.0E7; double finalEphemerisTime = initialEphemerisTime + 86400.0; double buffer = 3600.0; // Create bodies needed in simulation std::map< std::string, boost::shared_ptr< BodySettings > > bodySettings = getDefaultBodySettings( bodyNames, initialEphemerisTime - 2.0 * buffer, finalEphemerisTime + 2.0 * buffer ); boost::dynamic_pointer_cast< InterpolatedSpiceEphemerisSettings >( bodySettings[ "Moon" ]->ephemerisSettings )-> resetFrameOrigin( "Earth" ); NamedBodyMap bodyMap = createBodies( bodySettings ); setGlobalFrameBodyEphemerides( bodyMap, "Earth", "ECLIPJ2000" ); // Set accelerations between bodies that are to be taken into account. SelectedAccelerationMap accelerationMap; std::map< std::string, std::vector< boost::shared_ptr< AccelerationSettings > > > accelerationsOfMoon; accelerationsOfMoon[ "Earth" ].push_back( boost::make_shared< AccelerationSettings >( central_gravity ) ); accelerationsOfMoon[ "Sun" ].push_back( boost::make_shared< AccelerationSettings >( central_gravity ) ); accelerationMap[ "Moon" ] = accelerationsOfMoon; // Propagate the moon only std::vector< std::string > bodiesToIntegrate; bodiesToIntegrate.push_back( "Moon" ); std::vector< std::string > centralBodies; centralBodies.push_back( "Earth" ); // Define settings for numerical integrator. boost::shared_ptr< IntegratorSettings< TimeType > > integratorSettings = getIntegrationSettings< TimeType >( integratorCase, initialEphemerisTime, true ); // Propagate forwards { // Create acceleration models and propagation settings. Eigen::Matrix< StateScalarType, 6, 1 > systemInitialState = spice_interface::getBodyCartesianStateAtEpoch( bodiesToIntegrate[ 0 ], centralBodies[ 0 ], "ECLIPJ2000", "NONE", initialEphemerisTime ). template cast< StateScalarType >( ); AccelerationMap accelerationModelMap = createAccelerationModelsMap( bodyMap, accelerationMap, bodiesToIntegrate, centralBodies ); boost::shared_ptr< TranslationalStatePropagatorSettings< StateScalarType > > propagatorSettings = boost::make_shared< TranslationalStatePropagatorSettings< StateScalarType > > ( centralBodies, accelerationModelMap, bodiesToIntegrate, systemInitialState, finalEphemerisTime + buffer ); // Create dynamics simulation object. SingleArcDynamicsSimulator< StateScalarType, TimeType > dynamicsSimulator( bodyMap, integratorSettings, propagatorSettings, true, true, true ); } double testTime = initialEphemerisTime + ( finalEphemerisTime - initialEphemerisTime ) / 2.0; Eigen::Vector6d forwardState = bodyMap.at( "Moon" )->getEphemeris( )->getCartesianState( testTime ); // Re-define settings for numerical integrator. integratorSettings = getIntegrationSettings< TimeType >( integratorCase, finalEphemerisTime, false ); // Propagate backwards { // Create acceleration models and propagation settings. Eigen::Matrix< StateScalarType, 6, 1 > systemInitialState = spice_interface::getBodyCartesianStateAtEpoch( bodiesToIntegrate[ 0 ], centralBodies[ 0 ], "ECLIPJ2000", "NONE", finalEphemerisTime ). template cast< StateScalarType >( ); AccelerationMap accelerationModelMap = createAccelerationModelsMap( bodyMap, accelerationMap, bodiesToIntegrate, centralBodies ); boost::shared_ptr< TranslationalStatePropagatorSettings< StateScalarType > > propagatorSettings = boost::make_shared< TranslationalStatePropagatorSettings< StateScalarType > > ( centralBodies, accelerationModelMap, bodiesToIntegrate, systemInitialState, initialEphemerisTime - buffer ); // Create dynamics simulation object. SingleArcDynamicsSimulator< StateScalarType, TimeType > dynamicsSimulator( bodyMap, integratorSettings, propagatorSettings, true, true, true ); } Eigen::Vector6d backwardState = bodyMap.at( "Moon" )->getEphemeris( )->getCartesianState( testTime ); return forwardState - backwardState; }