//! Function to convert a Cartesian to a spherical orbital state. basic_mathematics::Vector6d convertCartesianToSphericalOrbitalState( const basic_mathematics::Vector6d& bodyFixedCartesianState ) { basic_mathematics::Vector6d sphericalOrbitalState; // Compute and set spherical position Eigen::Vector3d sphericalPosition = coordinate_conversions::convertCartesianToSpherical( bodyFixedCartesianState.segment( 0, 3 ) ); sphericalOrbitalState( radiusIndex ) = sphericalPosition( 0 ); sphericalOrbitalState( latitudeIndex ) = mathematical_constants::PI / 2.0 - sphericalPosition( 1 ); sphericalOrbitalState( longitudeIndex ) = sphericalPosition( 2 ); // Convert velocity to vertical frame. Eigen::Vector3d verticalFrameVelocity = reference_frames::getRotatingPlanetocentricToLocalVerticalFrameTransformationQuaternion( sphericalOrbitalState( longitudeIndex ), sphericalOrbitalState( latitudeIndex ) ) * bodyFixedCartesianState.segment( 3, 3 ); // Set velocity in spherical orbital state. sphericalOrbitalState( speedIndex ) = verticalFrameVelocity.norm( ); sphericalOrbitalState( flightPathIndex ) = calculateFlightPathAngle( verticalFrameVelocity ); sphericalOrbitalState( headingAngleIndex ) = calculateHeadingAngle( verticalFrameVelocity ); return sphericalOrbitalState; }
//! Transform a state (Cartesian position and velocity) from one frame to another. basic_mathematics::Vector6d transformStateToFrame( const basic_mathematics::Vector6d& stateInBaseFrame, const Eigen::Quaterniond& rotationToFrame, const Eigen::Matrix3d& rotationMatrixToFrameDerivative ) { basic_mathematics::Vector6d stateInTargetFrame; stateInTargetFrame.segment( 0, 3 ) = rotationToFrame * stateInBaseFrame.segment( 0, 3 ); stateInTargetFrame.segment( 3, 3 ) = rotationMatrixToFrameDerivative * stateInBaseFrame.segment( 0, 3 ) + rotationToFrame * stateInBaseFrame.segment( 3, 3 ); return stateInTargetFrame; }
//! Function to convert a spherical orbital to a Cartesian state. basic_mathematics::Vector6d convertSphericalOrbitalToCartesianState( const basic_mathematics::Vector6d& sphericalOrbitalState ) { basic_mathematics::Vector6d cartesianState; // Compute Cartesian position Eigen::Vector3d sphericalPosition = sphericalOrbitalState.segment( 0, 3 ); sphericalPosition( 1 ) = mathematical_constants::PI / 2.0 - sphericalOrbitalState( 1 ); cartesianState.segment( 0, 3 ) = coordinate_conversions::convertSphericalToCartesian( sphericalPosition ); // Check whether flight path angle and heading angle are valid (corresponding velocity components are zero otherwise) bool isFlightPathAngleValid = ( sphericalOrbitalState( flightPathIndex ) == sphericalOrbitalState( flightPathIndex ) ); bool isHeadingAngleValid = ( sphericalOrbitalState( headingAngleIndex ) == sphericalOrbitalState( headingAngleIndex ) ); // Compute velocity in vertical frame. Eigen::Vector3d velocityInVerticalFrame = Eigen::Vector3d::Zero( ); if( isFlightPathAngleValid && isHeadingAngleValid ) { velocityInVerticalFrame( 0 ) = sphericalOrbitalState( speedIndex ) * std::cos( sphericalOrbitalState( flightPathIndex ) ) * std::cos( sphericalOrbitalState( headingAngleIndex ) ); velocityInVerticalFrame( 1 ) = sphericalOrbitalState( speedIndex ) * std::cos( sphericalOrbitalState( flightPathIndex ) ) * std::sin( sphericalOrbitalState( headingAngleIndex ) ); } if( isFlightPathAngleValid ) { velocityInVerticalFrame( 2 ) = -sphericalOrbitalState( speedIndex ) * std::sin( sphericalOrbitalState( flightPathIndex ) ); } // Set velocity in body-fixed frame. cartesianState.segment( 3, 3 ) = reference_frames::getLocalVerticalToRotatingPlanetocentricFrameTransformationQuaternion( sphericalOrbitalState( longitudeIndex ), sphericalOrbitalState( latitudeIndex ) ) * velocityInVerticalFrame; return cartesianState; }
int main( ) { // Set directory where output files will be stored. By default, this is your project // root-directory. const std::string outputDirectory = basic_input_output::getApplicationRootPath( ) + "/"; // Set bounds for the departure dates from Earth to the target planet, its step-size and number // of steps. Notice how an integer is cast into a double. const double lowerBoundDepartureDate = 8400.0; const double upperBoundDepartureDate = 9860.0; const unsigned int numberOfStepsDepartureDate = 1461; const double stepSizeDepartureDate = ( upperBoundDepartureDate - lowerBoundDepartureDate ) / static_cast< double >( numberOfStepsDepartureDate - 1 ); // Set bounds for the transfer time from Earth to the target planet, its step-size and number // of steps. const double lowerBoundTransferTime = 100.0; const double upperBoundTransferTime = 400.0; const unsigned int numberOfStepsTransferTime = 301; const double stepSizeTransferTime = ( upperBoundTransferTime - lowerBoundTransferTime ) / static_cast< double >( numberOfStepsTransferTime - 1 ); // Fill the departure dates vector and the transfer times vector. // Note that you can use the variable "counter" in both for-loops, since it is in local scope. Eigen::VectorXd departureDates( numberOfStepsDepartureDate ), transferTimes( numberOfStepsTransferTime ); for ( unsigned int counter = 0; counter < numberOfStepsDepartureDate; counter++ ) { departureDates( counter ) = lowerBoundDepartureDate + counter * stepSizeDepartureDate; } for ( unsigned int counter = 0; counter < numberOfStepsTransferTime; counter++ ) { transferTimes( counter ) = lowerBoundTransferTime + counter * stepSizeTransferTime; } // Initialize a matrix that will keep track of the deltaVs. Eigen::MatrixXd deltaVs( numberOfStepsTransferTime, numberOfStepsDepartureDate ); // Start the grid search. // Loop through all the transfer times. // Note in this case that because there are nested loops, the counter variables must be named // differently! for ( unsigned int counter1 = 0; counter1 < numberOfStepsTransferTime; counter1++ ) { // Set the transfer time. const double transferTimeInDays = transferTimes( counter1 ); // Loop through all the departure dates. for( unsigned int counter2 = 0; counter2 < numberOfStepsDepartureDate; counter2++ ) { // Set the departure date. const double departureDateInMJD2000 = departureDates( counter2 ); // Calculate the arrival date. const double arrivalDateInMJD2000 = departureDateInMJD2000 + transferTimeInDays; // Obtain Keplerian elements of the planets. const basic_mathematics::Vector6d earthKeplerianElements = ephemeris::getKeplerianElementsOfPlanet( mission_definitions::ephemerisEarth, departureDateInMJD2000 ); const basic_mathematics::Vector6d targetKeplerianElements = ephemeris::getKeplerianElementsOfPlanet( mission_definitions::ephemerisTarget, arrivalDateInMJD2000 ); // Convert Keplerian elements into Cartesian position and velocity of the planets. const basic_mathematics::Vector6d earthCartesianElements = orbital_element_conversions::convertKeplerianToCartesianElements( earthKeplerianElements, mission_definitions::gravitationalParameterSun ); const basic_mathematics::Vector6d targetCartesianElements = orbital_element_conversions::convertKeplerianToCartesianElements( targetKeplerianElements, mission_definitions::gravitationalParameterSun ); // Split the cartesian elements into position and velocity. const Eigen::Vector3d earthPosition = earthCartesianElements.segment( 0, 3 ); const Eigen::Vector3d earthVelocity = earthCartesianElements.segment( 3, 3 ); const Eigen::Vector3d targetPosition = targetCartesianElements.segment( 0, 3 ); const Eigen::Vector3d targetVelocity = targetCartesianElements.segment( 3, 3 ); // Convert transfer time to seconds. const double transferTime = tudat:: unit_conversions::convertJulianDaysToSeconds( transferTimeInDays ); // Initialize the vectors that will contain the spacecraft velocities. Eigen::Vector3d velocityAtEarth, velocityAtTarget; // Compute these velocities using the Lambert targeter. mission_segments::solveLambertProblemIzzo( earthPosition, targetPosition, transferTime, mission_definitions::gravitationalParameterSun, velocityAtEarth, velocityAtTarget ); // Compute the velocity increments at Earth and the target. const Eigen::Vector3d velocityIncrementAtEarth = velocityAtEarth - earthVelocity; const Eigen::Vector3d velocityIncrementAtTarget = velocityAtTarget - targetVelocity; // Compute the excess velocities at Earth and the target. const double excessVelocityAtEarth = velocityIncrementAtEarth.norm( ); const double excessVelocityAtTarget = velocityIncrementAtTarget.norm( ); // Compute the deltaV for the escape and capture maneuvers. const double deltaVatEarth = mission_segments::computeEscapeOrCaptureDeltaV( mission_definitions::gravitationalParameterEarth, mission_definitions::parkingOrbitSemiMajorAxis, mission_definitions::parkingOrbitEccentricity, excessVelocityAtEarth ); const double deltaVAtTarget = mission_segments::computeEscapeOrCaptureDeltaV( mission_definitions::gravitationalParameterTarget, mission_definitions::captureOrbitSemiMajorAxis, mission_definitions::captureOrbitEccentricity, excessVelocityAtTarget ); // Compute the total deltaV and store it in the matrix. deltaVs( counter1, counter2 ) = deltaVatEarth + deltaVAtTarget; } } // Write the results to comma separated files. These are ready to be read in by MATLAB using // the csvread() function and the matrix can be plotted directly as a mesh. // Set output format for matrix output. Eigen::IOFormat csvFormat( 15, 0, ", ", "\n" ); // Set absolute path to file containing deltaVs. const std::string deltaVOutputFileAbsolutePath = outputDirectory + "DeltaVsPartD.csv"; // Export the deltaV matrix. std::ofstream exportFile1( deltaVOutputFileAbsolutePath.c_str( ) ); exportFile1 << deltaVs.format( csvFormat ); exportFile1.close( ); // Set absolute path to file containing departure dates. const std::string departureDateOutputFileAbsolutePath = outputDirectory + "DepartureDatesPartD.csv"; // Export the departure dates vector. std::ofstream exportFile2( departureDateOutputFileAbsolutePath.c_str( ) ); exportFile2.precision( 15 ); exportFile2 << departureDates; exportFile2.close( ); // Set absolute path to file containing transfer times. const std::string transferTimesOutputFileAbsolutePath = outputDirectory + "TransferTimesPartD.csv"; // Export the transfer times vector. std::ofstream exportFile3( transferTimesOutputFileAbsolutePath.c_str( ) ); exportFile3.precision( 15 ); exportFile3 << transferTimes; exportFile3.close( ); return 0; }