//! Function to get the unit vector colinear with position segment of a translational state. Eigen::Vector3d getForceDirectionColinearWithPosition( const boost::function< void( Eigen::Vector6d& ) > currentStateFunction, const double currentTime, const bool putForceInOppositeDirection ) { static Eigen::Vector6d currentState; currentStateFunction( currentState ); return ( ( putForceInOppositeDirection == 1 ) ? -1.0 : 1.0 ) * ( currentState.segment( 0, 3 ) ).normalized( ); }
//! Function determine the numerical partial derivative of the true anomaly wrt the elements of the Cartesian state Eigen::Matrix< double, 1, 6 > calculateNumericalPartialOfTrueAnomalyWrtState( const Eigen::Vector6d& cartesianElements, const double gravitationalParameter, const Eigen::Vector6d& cartesianStateElementPerturbations ) { using namespace tudat::orbital_element_conversions; // Initialize partial to zero Eigen::Matrix< double, 1, 6 > partial = Eigen::Matrix< double, 1, 6 >::Zero( ); // Iterate over all six elements and calculate partials. Eigen::Vector6d perturbedCartesianElements; double upPerturbedTrueAnomaly, downPerturbedTrueAnomaly; for( int i = 0; i < 6; i++ ) { // Calculate true anomaly at up-perturbed cartesian element i perturbedCartesianElements = cartesianElements; perturbedCartesianElements( i ) += cartesianStateElementPerturbations( i ); upPerturbedTrueAnomaly = convertCartesianToKeplerianElements( perturbedCartesianElements, gravitationalParameter )( trueAnomalyIndex ); // Check validity of result if( upPerturbedTrueAnomaly != upPerturbedTrueAnomaly ) { std::cout << "Error 1 in partial of true anomaly wrt cartesian state, element" << i << ", keplerian state: " << std::endl << convertCartesianToKeplerianElements( perturbedCartesianElements, gravitationalParameter ).transpose( ) << std::endl << perturbedCartesianElements.transpose( ) << std::endl; } // Calculate true anomaly at down-perturbed cartesian element i perturbedCartesianElements = cartesianElements; perturbedCartesianElements( i ) -= cartesianStateElementPerturbations( i ); downPerturbedTrueAnomaly = convertCartesianToKeplerianElements( perturbedCartesianElements, gravitationalParameter )( trueAnomalyIndex ); // Check validity of result if( downPerturbedTrueAnomaly != downPerturbedTrueAnomaly ) { std::cout << "Error 2 in partial of true anomaly wrt cartesian state, element" << i << ", keplerian state: " << std::endl << convertCartesianToKeplerianElements( perturbedCartesianElements, gravitationalParameter ).transpose( ) << std::endl << perturbedCartesianElements.transpose( ) << std::endl; } // Calculate central difference of term i partial( 0, i ) = ( upPerturbedTrueAnomaly - downPerturbedTrueAnomaly ) / ( 2.0 * cartesianStateElementPerturbations( i ) ); // Check validity of result if( partial( 0, i ) != partial( 0, i ) ) { std::cout << "Error 2 in partial of true anomaly wrt cartesian state, element" << i << std::endl; } } return partial; }
double BodyNode::VelocityObjFunc::eval(Eigen::Map<const Eigen::VectorXd>& _x) { assert(mBodyNode->getParentJoint()->getNumGenCoords() == _x.size()); // Update forward kinematics information with _x // We are just insterested in spacial velocity of mBodyNode mBodyNode->getParentJoint()->setGenVels(_x, true, false); // Compute and return the geometric distance between body node transformation // and target transformation Eigen::Vector6d diff = mBodyNode->getWorldVelocity() - mVelocity; return diff.dot(diff); }
double BodyNode::TransformObjFunc::eval(Eigen::Map<const Eigen::VectorXd>& _x) { assert(mBodyNode->getParentJoint()->getNumGenCoords() == _x.size()); // Update forward kinematics information with _x // We are just insterested in transformation of mBodyNode mBodyNode->getParentJoint()->setConfigs(_x, true, false, false); // Compute and return the geometric distance between body node transformation // and target transformation Eigen::Isometry3d bodyT = mBodyNode->getWorldTransform(); Eigen::Vector6d dist = math::logMap(bodyT.inverse() * mT); return dist.dot(dist); }
//! Function to compute proper-time rate w.r.t. coordinate time, minus 1.0, from a speed and scalar potential double calculateFirstCentralBodyProperTimeRateDifference( const Eigen::Vector6d relativeStateVector, const double centralBodyGravitationalParameter, const double equivalencePrincipleLpiViolationParameter ) { return calculateFirstCentralBodyProperTimeRateDifference( relativeStateVector.segment( 3, 3 ).norm( ), centralBodyGravitationalParameter / relativeStateVector.segment( 0, 3 ).norm( ), equivalencePrincipleLpiViolationParameter ); }
void check_values(const std::vector<SimpleFrame*>& targets, const std::vector<SimpleFrame*>& followers, const Frame* relativeTo, const Frame* inCoordinatesOf, double tolerance) { for(std::size_t i=0; i<targets.size(); ++i) { Frame* T = targets[i]; Frame* F = followers[i]; const Eigen::Isometry3d& tf_error = T->getTransform(relativeTo)*F->getTransform(relativeTo).inverse(); Eigen::Vector6d error; Eigen::AngleAxisd rot_error(tf_error.rotation()); error.block<3,1>(0,0) = rot_error.angle()*rot_error.axis(); error.block<3,1>(3,0) = tf_error.translation(); EXPECT_TRUE( error.norm() < tolerance ); EXPECT_TRUE( equals(T->getSpatialVelocity(relativeTo, inCoordinatesOf), F->getSpatialVelocity(relativeTo, inCoordinatesOf), tolerance) ); EXPECT_TRUE( equals(T->getLinearVelocity(relativeTo, inCoordinatesOf), F->getLinearVelocity(relativeTo, inCoordinatesOf), tolerance) ); EXPECT_TRUE( equals(T->getAngularVelocity(relativeTo, inCoordinatesOf), F->getAngularVelocity(relativeTo, inCoordinatesOf), tolerance) ); EXPECT_TRUE( equals(T->getSpatialAcceleration(relativeTo, inCoordinatesOf), F->getSpatialAcceleration(relativeTo, inCoordinatesOf), tolerance) ); EXPECT_TRUE( equals(T->getLinearAcceleration(relativeTo, inCoordinatesOf), F->getLinearAcceleration(relativeTo, inCoordinatesOf), tolerance) ); EXPECT_TRUE( equals(T->getAngularAcceleration(relativeTo, inCoordinatesOf), F->getAngularAcceleration(relativeTo, inCoordinatesOf), tolerance) ); } }
bool InverseKinematics::inverseKinematics(const MultiBody& mb, MultiBodyConfig& mbc, const sva::PTransformd& ef_target) { int iter = 0; bool converged = false; int dof = 0; rbd::forwardKinematics(mb, mbc); Eigen::MatrixXd jacMat; Eigen::Vector6d v = Eigen::Vector6d::Ones(); Eigen::Vector3d rotErr; Eigen::VectorXd res = Eigen::VectorXd::Zero(3); while( ! converged && iter < max_iterations_) { jacMat = jac_.jacobian(mb, mbc); //non-strict zeros in jacobian can be a problem... jacMat = jacMat.unaryExpr(CwiseRoundOp(-almost_zero_, almost_zero_)); svd_.compute(jacMat, Eigen::ComputeThinU | Eigen::ComputeThinV); rotErr = sva::rotationError(mbc.bodyPosW[ef_index_].rotation(), ef_target.rotation()); v << rotErr, ef_target.translation() - mbc.bodyPosW[ef_index_].translation(); converged = v.norm() < threshold_; res = svd_.solve(v); dof = 0; for(auto index : jac_.jointsPath()) { std::vector<double>& qi = mbc.q[index]; for(auto &qv : qi) { qv += lambda_*res[dof]; ++dof; } } rbd::forwardKinematics(mb, mbc); rbd::forwardVelocity(mb, mbc); iter++; } return converged; }
//! Convert dimensionless Cartesian state to dimensional units. Eigen::VectorXd convertDimensionlessCartesianStateToDimensionalUnits( const Eigen::Vector6d &dimensionlessCartesianState, const double gravitationalParameterOfPrimaryBody, const double gravitationalParameterOfSecondaryBody, const double distanceBetweenPrimaries ) { // Declare dimensional Cartesian state. Eigen::Vector6d dimensionalCartesianState; // Convert position to dimensional units. dimensionalCartesianState.segment( 0, 3 ) = dimensionlessCartesianState.segment( 0, 3 ) * distanceBetweenPrimaries; // Convert velocity to dimensional units. dimensionalCartesianState.segment( 3, 3 ) = dimensionlessCartesianState.segment( 3, 3 ) * std::sqrt( ( gravitationalParameterOfPrimaryBody + gravitationalParameterOfSecondaryBody ) / distanceBetweenPrimaries ); // Return state in dimensional units. return dimensionalCartesianState; }
//! Compute state derivative. Eigen::Vector6d StateDerivativeCircularRestrictedThreeBodyProblem::computeStateDerivative( const double time, const Eigen::Vector6d& cartesianState ) { using namespace orbital_element_conversions; TUDAT_UNUSED_PARAMETER( time ); // Compute distance to primary body. const double xCoordinateToPrimaryBodySquared = ( cartesianState( xCartesianPositionIndex ) + massParameter ) * ( cartesianState( xCartesianPositionIndex ) + massParameter ); const double yCoordinateSquared = cartesianState( yCartesianPositionIndex ) * cartesianState( yCartesianPositionIndex ); const double zCoordinateSquared = cartesianState( zCartesianPositionIndex ) * cartesianState( zCartesianPositionIndex ); const double normDistanceToPrimaryBodyCubed = pow( xCoordinateToPrimaryBodySquared + yCoordinateSquared + zCoordinateSquared, 1.5 ); // Compute distance to secondary body. const double xCoordinateSecondaryBodySquared = ( cartesianState( xCartesianPositionIndex ) - ( 1.0 - massParameter ) ) * ( cartesianState( xCartesianPositionIndex ) - ( 1.0 - massParameter ) ); double normDistanceToSecondaryBodyCubed = pow( xCoordinateSecondaryBodySquared + yCoordinateSquared + zCoordinateSquared, 1.5 ); // Compute derivative of state. Eigen::VectorXd stateDerivative( 6 ); stateDerivative.segment( xCartesianPositionIndex, 3 ) = cartesianState.segment( xCartesianVelocityIndex, 3 ); stateDerivative( 3 ) = cartesianState( xCartesianPositionIndex ) - ( ( 1.0 - massParameter ) / normDistanceToPrimaryBodyCubed ) * ( cartesianState( xCartesianPositionIndex ) + massParameter ) - ( massParameter / normDistanceToSecondaryBodyCubed ) * ( cartesianState( xCartesianPositionIndex ) - ( 1.0 - massParameter ) ) + 2.0 * cartesianState( yCartesianVelocityIndex ); stateDerivative( 4 ) = cartesianState( yCartesianPositionIndex ) * ( 1.0 - ( ( 1.0 - massParameter ) / normDistanceToPrimaryBodyCubed ) - ( massParameter / normDistanceToSecondaryBodyCubed ) ) - 2.0 * cartesianState( xCartesianVelocityIndex ); stateDerivative( 5 ) = -cartesianState( zCartesianPositionIndex ) * ( ( ( 1.0 - massParameter ) / normDistanceToPrimaryBodyCubed ) + ( massParameter / normDistanceToSecondaryBodyCubed ) ); // Return computed state derivative. return stateDerivative; }
//============================================================================== void ZeroDofJoint::setPartialAccelerationTo( Eigen::Vector6d& _partialAcceleration, const Eigen::Vector6d& /*_childVelocity*/) { _partialAcceleration.setZero(); }
//============================================================================== std::string toString(const Eigen::Vector6d& _v) { return boost::lexical_cast<std::string>(_v.transpose()); }
//! Function for updating common blocks of partial to current state. void EmpiricalAccelerationPartial::update( const double currentTime ) { if( !( currentTime_ == currentTime ) ) { using namespace tudat::basic_mathematics; using namespace tudat::linear_algebra; // Get current state and associated data. Eigen::Vector6d currentState = empiricalAcceleration_->getCurrentState( ); Eigen::Vector3d angularMomentumVector = Eigen::Vector3d( currentState.segment( 0, 3 ) ).cross( Eigen::Vector3d( currentState.segment( 3, 3 ) ) ); Eigen::Vector3d crossVector = angularMomentumVector.cross( Eigen::Vector3d( currentState.segment( 0, 3 ) ) ); // Compute constituent geometric partials. Eigen::Matrix3d normPositionWrtPosition = calculatePartialOfNormalizedVector( Eigen::Matrix3d::Identity( ), currentState.segment( 0, 3 ) ); Eigen::Matrix3d angularMomentumWrtPosition = -getCrossProductMatrix( currentState.segment( 3, 3 ) ); Eigen::Matrix3d angularMomentumWrtVelocity = getCrossProductMatrix( currentState.segment( 0, 3 ) ); Eigen::Matrix3d normAngularMomentumWrtPosition = calculatePartialOfNormalizedVector( angularMomentumWrtPosition, angularMomentumVector ); Eigen::Matrix3d normAngularMomentumWrtVelocity = calculatePartialOfNormalizedVector( angularMomentumWrtVelocity, angularMomentumVector ); Eigen::Matrix3d crossVectorWrtPosition = getCrossProductMatrix( angularMomentumVector ) - angularMomentumWrtVelocity * angularMomentumWrtPosition; Eigen::Matrix3d crossVectorWrtVelocity = -getCrossProductMatrix( currentState.segment( 0, 3 ) ) * getCrossProductMatrix( currentState.segment( 0, 3 ) ); Eigen::Matrix3d normCrossVectorWrtPosition = calculatePartialOfNormalizedVector( crossVectorWrtPosition, crossVector ); Eigen::Matrix3d normCrossVectorWrtVelocity = calculatePartialOfNormalizedVector( crossVectorWrtVelocity, crossVector ); // Retrieve current empirical acceleration Eigen::Vector3d localAcceleration = empiricalAcceleration_->getCurrentLocalAcceleration( ); // Compute partial derivative contribution of derivative of rotation matrix from RSW to inertial frame currentPositionPartial_ = localAcceleration.x( ) * normPositionWrtPosition + localAcceleration.y( ) * normCrossVectorWrtPosition + localAcceleration.z( ) * normAngularMomentumWrtPosition; currentVelocityPartial_ = localAcceleration.y( ) * normCrossVectorWrtVelocity + localAcceleration.z( ) * normAngularMomentumWrtVelocity; // Compute partial derivative contribution of derivative of true anomaly Eigen::Matrix< double, 1, 6 > localTrueAnomalyPartial = calculateNumericalPartialOfTrueAnomalyWrtState( empiricalAcceleration_->getCurrentState( ), empiricalAcceleration_->getCurrentGravitationalParameter( ), cartesianStateElementPerturbations ); Eigen::Matrix< double, 1, 6 > trueAnomalyPartial = localTrueAnomalyPartial; currentPositionPartial_ += empiricalAcceleration_->getCurrentToInertialFrame( ) * ( empiricalAcceleration_->getCurrentAccelerationComponent( basic_astrodynamics::sine_empirical ) * std::cos( empiricalAcceleration_->getCurrentTrueAnomaly( ) ) - empiricalAcceleration_->getCurrentAccelerationComponent( basic_astrodynamics::cosine_empirical ) * std::sin( empiricalAcceleration_->getCurrentTrueAnomaly( ) ) ) * trueAnomalyPartial.block( 0, 0, 1, 3 ); currentVelocityPartial_ += ( empiricalAcceleration_->getCurrentToInertialFrame( ) * ( empiricalAcceleration_->getCurrentAccelerationComponent( basic_astrodynamics::sine_empirical ) * std::cos( empiricalAcceleration_->getCurrentTrueAnomaly( ) ) - empiricalAcceleration_->getCurrentAccelerationComponent( basic_astrodynamics::cosine_empirical ) * std::sin( empiricalAcceleration_->getCurrentTrueAnomaly( ) ) ) ) * trueAnomalyPartial.block( 0, 3, 1, 3 ); currentTime_ = currentTime; // Check output. if( currentPositionPartial_ != currentPositionPartial_ ) { throw std::runtime_error( "Error, empirical acceleration position partials are NaN" ); } if( currentVelocityPartial_ != currentVelocityPartial_ ) { throw std::runtime_error( "Error, empirical acceleration velocity partials are NaN" ); } } }
//! Execute propagation of orbit of TeslaRoadster around the Earth. int main( ) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////// USING STATEMENTS ////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// using namespace tudat; using namespace tudat::simulation_setup; using namespace tudat::propagators; using namespace tudat::numerical_integrators; using namespace tudat::orbital_element_conversions; using namespace tudat::basic_mathematics; using namespace tudat::gravitation; using namespace tudat::numerical_integrators; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////// CREATE ENVIRONMENT AND VEHICLE ////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Load Spice kernels. spice_interface::loadStandardSpiceKernels( { input_output::getSpiceKernelPath( ) + "de430.bsp" } ); // Set simulation time settings. const double simulationStartEpoch = ( 2458163.500000000 - basic_astrodynamics::JULIAN_DAY_ON_J2000 ) * 86400.0; const double simulationEndEpoch = 500.0 * physical_constants::JULIAN_YEAR; // Define body settings for simulation. std::vector< std::string > bodiesToCreate; bodiesToCreate.push_back( "Sun" ); bodiesToCreate.push_back( "Earth" ); bodiesToCreate.push_back( "Moon" ); bodiesToCreate.push_back( "Mars" ); bodiesToCreate.push_back( "Venus" ); bodiesToCreate.push_back( "Jupiter" ); bodiesToCreate.push_back( "Saturn" ); bodiesToCreate.push_back( "Mercury" ); // Create body objects. std::map< std::string, std::shared_ptr< BodySettings > > bodySettings = getDefaultBodySettings( bodiesToCreate ); // bodySettings[ "Sun" ]->ephemerisSettings->resetFrameOrientation( "J2000" ); // bodySettings[ "Moon" ]->ephemerisSettings->resetFrameOrientation( "J2000" ); // bodySettings[ "Earth" ]->ephemerisSettings->resetFrameOrientation( "J2000" ); // for( unsigned int i = 0; i < bodiesToCreate.size( ); i++ ) // { // bodySettings[ bodiesToCreate.at( i ) ]->rotationModelSettings->resetOriginalFrame( "J2000" ); // } bodySettings[ "Mars" ]->ephemerisSettings = std::make_shared< ApproximatePlanetPositionSettings >( ephemerides::ApproximatePlanetPositionsBase::mars, false ); bodySettings[ "Jupiter" ]->ephemerisSettings = std::make_shared< ApproximatePlanetPositionSettings >( ephemerides::ApproximatePlanetPositionsBase::mars, false ); bodySettings[ "Saturn" ]->ephemerisSettings = std::make_shared< ApproximatePlanetPositionSettings >( ephemerides::ApproximatePlanetPositionsBase::mars, false ); bodySettings[ "Venus" ]->ephemerisSettings = std::make_shared< ApproximatePlanetPositionSettings >( ephemerides::ApproximatePlanetPositionsBase::mars, false ); bodySettings[ "Mercury" ]->ephemerisSettings = std::make_shared< ApproximatePlanetPositionSettings >( ephemerides::ApproximatePlanetPositionsBase::mars, false ); NamedBodyMap bodyMap = createBodies( bodySettings ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////// CREATE VEHICLE ///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Create spacecraft object. bodyMap[ "TeslaRoadster" ] = std::make_shared< simulation_setup::Body >( ); bodyMap[ "TeslaRoadster" ]->setConstantBodyMass( 1500.0 ); // Create radiation pressure settings double referenceAreaRadiation = 8.0; double radiationPressureCoefficient = 1.2; std::vector< std::string > occultingBodies; std::shared_ptr< RadiationPressureInterfaceSettings > teslaRoadsterRadiationPressureSettings = std::make_shared< CannonBallRadiationPressureInterfaceSettings >( "Sun", referenceAreaRadiation, radiationPressureCoefficient, occultingBodies ); // Create and set radiation pressure settings bodyMap[ "TeslaRoadster" ]->setRadiationPressureInterface( "Sun", createRadiationPressureInterface( teslaRoadsterRadiationPressureSettings, "TeslaRoadster", bodyMap ) ); // Finalize body creation. setGlobalFrameBodyEphemerides( bodyMap, "SSB", "ECLIPJ2000" ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////// CREATE ACCELERATIONS ////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Define propagator settings variables. SelectedAccelerationMap accelerationMap; std::vector< std::string > bodiesToPropagate; std::vector< std::string > centralBodies; // Define propagation settings. std::map< std::string, std::vector< std::shared_ptr< AccelerationSettings > > > accelerationsOfAsterix; accelerationsOfAsterix[ "Earth" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::central_gravity ) ); accelerationsOfAsterix[ "Sun" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::central_gravity ) ); accelerationsOfAsterix[ "Moon" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::central_gravity ) ); accelerationsOfAsterix[ "Mars" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::central_gravity ) ); accelerationsOfAsterix[ "Venus" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::central_gravity ) ); accelerationsOfAsterix[ "Mercury" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::central_gravity ) ); accelerationsOfAsterix[ "Saturn" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::central_gravity ) ); accelerationsOfAsterix[ "Jupiter" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::central_gravity ) ); accelerationsOfAsterix[ "Sun" ].push_back( std::make_shared< AccelerationSettings >( basic_astrodynamics::cannon_ball_radiation_pressure ) ); accelerationMap[ "TeslaRoadster" ] = accelerationsOfAsterix; bodiesToPropagate.push_back( "TeslaRoadster" ); centralBodies.push_back( "Sun" ); basic_astrodynamics::AccelerationMap accelerationModelMap = createAccelerationModelsMap( bodyMap, accelerationMap, bodiesToPropagate, centralBodies ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////// CREATE PROPAGATION SETTINGS //////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Set Keplerian elements for TeslaRoadster. Eigen::Vector6d teslaRoadsterInitialStateJ2000; teslaRoadsterInitialStateJ2000 << -1.484544094935328E+06, -1.530028575781120E+06, -4.100899567817330E+05, -2.358201939417945E+00, -2.459124989364402E+00, -6.370785284397021E-01; teslaRoadsterInitialStateJ2000 *= 1000.0; teslaRoadsterInitialStateJ2000 += spice_interface::getBodyCartesianStateAtEpoch( "Earth", "SSB", "J2000", "None", simulationStartEpoch ); Eigen::Quaterniond toEclipJ2000 = spice_interface::computeRotationQuaternionBetweenFrames( "J2000", "ECLIPJ2000", 0.0 ); Eigen::Vector6d teslaRoadsterInitialState; teslaRoadsterInitialState.segment( 0, 3 ) = toEclipJ2000 * teslaRoadsterInitialStateJ2000.segment( 0, 3 ); teslaRoadsterInitialState.segment( 3, 3 ) = toEclipJ2000 * teslaRoadsterInitialStateJ2000.segment( 3, 3 ); \ // Define list of dependent variables to save. std::vector< std::shared_ptr< SingleDependentVariableSaveSettings > > dependentVariablesList; dependentVariablesList.push_back( std::make_shared< SingleDependentVariableSaveSettings >( relative_position_dependent_variable, "Earth", "Sun" ) ); dependentVariablesList.push_back( std::make_shared< SingleDependentVariableSaveSettings >( relative_position_dependent_variable, "Mars", "Sun" ) ); dependentVariablesList.push_back( std::make_shared< SingleDependentVariableSaveSettings >( relative_position_dependent_variable, "Venus", "Sun" ) ); dependentVariablesList.push_back( std::make_shared< SingleDependentVariableSaveSettings >( relative_distance_dependent_variable, "TeslaRoadster", "Earth" ) ); // Create object with list of dependent variables std::shared_ptr< DependentVariableSaveSettings > dependentVariablesToSave = std::make_shared< DependentVariableSaveSettings >( dependentVariablesList ); std::shared_ptr< TranslationalStatePropagatorSettings< double > > propagatorSettings = std::make_shared< TranslationalStatePropagatorSettings< double > > ( centralBodies, accelerationModelMap, bodiesToPropagate, teslaRoadsterInitialState, simulationEndEpoch, cowell, dependentVariablesToSave ); std::shared_ptr< IntegratorSettings< > > integratorSettings = std::make_shared< tudat::numerical_integrators::BulirschStoerIntegratorSettings< > >( simulationStartEpoch, 3600.0, numerical_integrators::bulirsch_stoer_sequence, 4, std::numeric_limits< double >::epsilon( ), std::numeric_limits< double >::infinity( ), 1.0E-15, 1.0E-12 ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////// PROPAGATE ORBIT //////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Create simulation object and propagate dynamics. SingleArcDynamicsSimulator< > dynamicsSimulator( bodyMap, integratorSettings, propagatorSettings, true, false, false ); std::map< double, Eigen::VectorXd > integrationResult = dynamicsSimulator.getEquationsOfMotionNumericalSolution( ); std::map< double, Eigen::VectorXd > dependentVariableResult = dynamicsSimulator.getDependentVariableHistory( ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////// PROVIDE OUTPUT TO CONSOLE AND FILES ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// std::string outputSubFolder = "SpacexTeslaExample/"; // Write perturbed satellite propagation history to file. input_output::writeDataMapToTextFile( integrationResult, "spacexTeslaPropagationHistory.dat", tudat_applications::getOutputPath( ) + outputSubFolder, "", std::numeric_limits< double >::digits10, std::numeric_limits< double >::digits10, "," ); input_output::writeDataMapToTextFile( dependentVariableResult, "spacexTeslaDependentVariableHistory.dat", tudat_applications::getOutputPath( ) + outputSubFolder, "", std::numeric_limits< double >::digits10, std::numeric_limits< double >::digits10, "," ); // Final statement. // The exit code EXIT_SUCCESS indicates that the program was successfully executed. return EXIT_SUCCESS; }