//! 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;

}
Exemplo n.º 2
0
//! 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;
}