Skip to content
This repository was archived by the owner on Feb 14, 2025. It is now read-only.

Spherical coordinate conversions #47

Merged
merged 10 commits into from
Jun 27, 2016
2 changes: 1 addition & 1 deletion Tudat/Astrodynamics/Aerodynamics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ setup_tudat_library_target(tudat_aerodynamics "${SRCROOT}{AERODYNAMICSDIR}")
# Add unit tests.
add_executable(test_AerodynamicMomentAndAerodynamicForce "${SRCROOT}${AERODYNAMICSDIR}/UnitTests/unitTestAerodynamicMomentAndAerodynamicForce.cpp")
setup_custom_test_program(test_AerodynamicMomentAndAerodynamicForce "${SRCROOT}${AERODYNAMICSDIR}")
target_link_libraries(test_AerodynamicMomentAndAerodynamicForce tudat_simulation_setup tudat_aerodynamics tudat_reference_frames tudat_ephemerides tudat_basic_mathematics ${Boost_LIBRARIES})
target_link_libraries(test_AerodynamicMomentAndAerodynamicForce tudat_simulation_setup tudat_aerodynamics tudat_reference_frames tudat_ephemerides tudat_basic_astrodynamics tudat_basic_mathematics ${Boost_LIBRARIES})

add_executable(test_AerodynamicsNamespace "${SRCROOT}${AERODYNAMICSDIR}/UnitTests/unitTestAerodynamicsNamespace.cpp")
setup_custom_test_program(test_AerodynamicsNamespace "${SRCROOT}${AERODYNAMICSDIR}")
Expand Down
6 changes: 6 additions & 0 deletions Tudat/Astrodynamics/BasicAstrodynamics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ set(BASICASTRODYNAMICS_SOURCES
"${SRCROOT}${BASICASTRODYNAMICSDIR}/astrodynamicsFunctions.cpp"
"${SRCROOT}${BASICASTRODYNAMICSDIR}/physicalConstants.cpp"
"${SRCROOT}${BASICASTRODYNAMICSDIR}/bodyShapeModel.cpp"
"${SRCROOT}${BASICASTRODYNAMICSDIR}/sphericalStateConversions.cpp"
"${SRCROOT}${BASICASTRODYNAMICSDIR}/unifiedStateModelElementConversions.cpp"
)

Expand All @@ -76,6 +77,7 @@ set(BASICASTRODYNAMICS_HEADERS
"${SRCROOT}${BASICASTRODYNAMICSDIR}/bodyShapeModel.h"
"${SRCROOT}${BASICASTRODYNAMICSDIR}/oblateSpheroidBodyShapeModel.h"
"${SRCROOT}${BASICASTRODYNAMICSDIR}/sphericalBodyShapeModel.h"
"${SRCROOT}${BASICASTRODYNAMICSDIR}/sphericalStateConversions.h"
"${SRCROOT}${BASICASTRODYNAMICSDIR}/unifiedStateModelElementConversions.h"
)

Expand Down Expand Up @@ -149,6 +151,10 @@ add_executable(test_GeodeticCoordinateConversions "${SRCROOT}${BASICASTRODYNAMIC
setup_custom_test_program(test_GeodeticCoordinateConversions "${SRCROOT}${BASICASTRODYNAMICSDIR}")
target_link_libraries(test_GeodeticCoordinateConversions tudat_basic_astrodynamics tudat_basic_mathematics ${Boost_LIBRARIES})

add_executable(test_SphericalOrbitalStateConversions "${SRCROOT}${BASICASTRODYNAMICSDIR}/UnitTests/unitTestSphericalOrbitStateConversions.cpp")
setup_custom_test_program(test_SphericalOrbitalStateConversions "${SRCROOT}${BASICASTRODYNAMICSDIR}")
target_link_libraries(test_SphericalOrbitalStateConversions tudat_basic_astrodynamics tudat_reference_frames tudat_basic_mathematics ${Boost_LIBRARIES})

add_executable(test_BodyShapeModels "${SRCROOT}${BASICASTRODYNAMICSDIR}/UnitTests/unitTestBodyShapeModels.cpp")
setup_custom_test_program(test_BodyShapeModels "${SRCROOT}${BASICASTRODYNAMICSDIR}")
target_link_libraries(test_BodyShapeModels tudat_basic_astrodynamics tudat_basic_mathematics ${Boost_LIBRARIES})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
/* Copyright (c) 2010-2016, Delft University of Technology
* All rigths reserved
*
* This file is part of the Tudat. Redistribution and use in source and
* binary forms, with or without modification, are permitted exclusively
* under the terms of the Modified BSD license. You should have received
* a copy of the license with this file. If not, please or visit:
* http://tudat.tudelft.nl/LICENSE.
*/

#define BOOST_TEST_MAIN

#include <iostream>

#include <boost/test/unit_test.hpp>

#include <Eigen/Core>

#include "Tudat/Basics/testMacros.h"
#include "Tudat/Astrodynamics/BasicAstrodynamics/unitConversions.h"
#include "Tudat/Astrodynamics/BasicAstrodynamics/sphericalStateConversions.h"
#include "Tudat/Astrodynamics/ReferenceFrames/referenceFrameTransformations.h"

namespace tudat
{
namespace unit_tests
{

using namespace orbital_element_conversions;
using namespace unit_conversions;
using namespace reference_frames;

BOOST_AUTO_TEST_SUITE( test_spherical_state_conversions )

//! Test Cartesian to spherical orbital state transformations, using Matlab script of Erwin Mooij to generate reference data.
//! See test_aerodynamic_angle_calculator unit test
BOOST_AUTO_TEST_CASE( testSphericalStateConversions )
{
// Test case 1: arbitrary rotation
{
// Define Cartesian state
basic_mathematics::Vector6d cartesianState;
cartesianState<<-1656517.23153109, -5790058.28764025, -2440584.88186829,
6526.30784888051, -2661.34558272018, 2377.09572383163;

// Define associated spherical orbital state
double testHeadingAngle = 1.229357188236127;
double testFlightPathAngle = -0.024894033070522;
double testLatitude = -0.385027359562548;
double testLongitude = -1.849449608688977;
double radius = cartesianState.segment( 0, 3 ).norm( );
double speed = cartesianState.segment( 3, 3 ).norm( );

// Convert pack and forth
basic_mathematics::Vector6d sphericalOrbitState = convertCartesianToSphericalOrbitalState(
cartesianState );
basic_mathematics::Vector6d reconvertedCartesianState = convertSphericalOrbitalToCartesianState(
sphericalOrbitState );

// Check computed spherical orbital state against reference data
BOOST_CHECK_SMALL(
std::fabs( radius - sphericalOrbitState( radiusIndex ) ),
radius * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testLatitude - sphericalOrbitState( latitudeIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testLongitude - sphericalOrbitState( longitudeIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( speed - sphericalOrbitState( speedIndex ) ),
speed * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testFlightPathAngle - sphericalOrbitState( flightPathIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testHeadingAngle - sphericalOrbitState( headingAngleIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );

// Check consistency of back-and-forth conversion
for( unsigned int i = 0; i < 3; i++ )
{
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i ) - cartesianState( i ) ),
radius * 2.0 * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i + 3 ) - cartesianState( i + 3 ) ),
speed * 2.0 * std::numeric_limits< double >::epsilon( ) );
}
}

// Test case 2: rotation with zero (heading, flight path, latitude) and half pi (longitude) angles.
{
// Define Cartesian state
basic_mathematics::Vector6d cartesianState;
cartesianState<<0.0, 6498098.09700000, 0.0, 0.0, 0.0, 7.438147520000000e+03;

// Define associated spherical orbital state
double testHeadingAngle = 0.0;
double testFlightPathAngle = 0.0;
double testLatitude = 0.0;
double testLongitude = mathematical_constants::PI / 2.0;
double radius = cartesianState.segment( 0, 3 ).norm( );
double speed = cartesianState.segment( 3, 3 ).norm( );

// Convert pack and forth
basic_mathematics::Vector6d sphericalOrbitState = convertCartesianToSphericalOrbitalState(
cartesianState );
basic_mathematics::Vector6d reconvertedCartesianState = convertSphericalOrbitalToCartesianState(
sphericalOrbitState );

// Check computed spherical orbital state against reference data
BOOST_CHECK_SMALL(
std::fabs( radius - sphericalOrbitState( radiusIndex ) ),
radius * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testLatitude - sphericalOrbitState( latitudeIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testLongitude - sphericalOrbitState( longitudeIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( speed - sphericalOrbitState( speedIndex ) ),
speed * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testFlightPathAngle - sphericalOrbitState( flightPathIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testHeadingAngle - sphericalOrbitState( headingAngleIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );

// Check consistency of back-and-forth conversion
for( unsigned int i = 0; i < 3; i++ )
{
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i ) - cartesianState( i ) ),
radius * 2.0 * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i + 3 ) - cartesianState( i + 3 ) ),
speed * 2.0 * std::numeric_limits< double >::epsilon( ) );
}
}

// Test case 3: rotation with zero (heading, flight path, longitude) and half pi (latitude) angles.
{
// Define Cartesian state
basic_mathematics::Vector6d cartesianState;
cartesianState<<0.0, 0.0, 6.498098097000000e3, -7.438147520000000e3, 0.0, 0.0;

// Define associated spherical orbital state
double testHeadingAngle = 0.0;
double testFlightPathAngle = 0.0;
double testLatitude = mathematical_constants::PI / 2.0;
double testLongitude = 0.0;
double radius = cartesianState.segment( 0, 3 ).norm( );
double speed = cartesianState.segment( 3, 3 ).norm( );

// Convert pack and forth
basic_mathematics::Vector6d sphericalOrbitState = convertCartesianToSphericalOrbitalState(
cartesianState );
basic_mathematics::Vector6d reconvertedCartesianState = convertSphericalOrbitalToCartesianState(
sphericalOrbitState );

// Check computed spherical orbital state against reference data
BOOST_CHECK_SMALL(
std::fabs( radius - sphericalOrbitState( radiusIndex ) ),
radius * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testLatitude - sphericalOrbitState( latitudeIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testLongitude - sphericalOrbitState( longitudeIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( speed - sphericalOrbitState( speedIndex ) ),
speed * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testFlightPathAngle - sphericalOrbitState( flightPathIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testHeadingAngle - sphericalOrbitState( headingAngleIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );

// Check consistency of back-and-forth conversion
for( unsigned int i = 0; i < 3; i++ )
{
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i ) - cartesianState( i ) ),
radius * 2.0 * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i + 3 ) - cartesianState( i + 3 ) ),
speed * 2.0 * std::numeric_limits< double >::epsilon( ) );
}
}

// Test case 4: rotation with zero (heading, longitude) and half pi (latitude, flight path) angles.
{
basic_mathematics::Vector6d cartesianState;
cartesianState<<0.0, 0.0, 6.498098097000000e3, 0.0, 0.0, -7.438147520000000e3;

// Define associated spherical orbital state
double testFlightPathAngle = -mathematical_constants::PI / 2.0;
double testLatitude = mathematical_constants::PI / 2.0;
double testLongitude = 0.0;
double radius = cartesianState.segment( 0, 3 ).norm( );
double speed = cartesianState.segment( 3, 3 ).norm( );

// Convert pack and forth
basic_mathematics::Vector6d sphericalOrbitState = convertCartesianToSphericalOrbitalState(
cartesianState );
basic_mathematics::Vector6d reconvertedCartesianState = convertSphericalOrbitalToCartesianState(
sphericalOrbitState );

// Check computed spherical orbital state against reference data (heading angle not tested, because close to
// undefined; value is numerically irrelevant for physical state).
BOOST_CHECK_SMALL(
std::fabs( radius - sphericalOrbitState( radiusIndex ) ),
radius * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testLatitude - sphericalOrbitState( latitudeIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testLongitude - sphericalOrbitState( longitudeIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( speed - sphericalOrbitState( speedIndex ) ),
speed * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( testFlightPathAngle - sphericalOrbitState( flightPathIndex ) ),
2.0 * mathematical_constants::PI * std::numeric_limits< double >::epsilon( ) );


// Check consistency of back-and-forth conversion
for( unsigned int i = 0; i < 3; i++ )
{
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i ) - cartesianState( i ) ),
radius * 2.0 * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i + 3 ) - cartesianState( i + 3 ) ),
speed * 2.0 * std::numeric_limits< double >::epsilon( ) );
}
}

// Test case 5: rotation with undefined heading angle.
{
basic_mathematics::Vector6d cartesianState;
cartesianState<<0.0, 0.0, 6.498098097000000e3, 0.0, 0.0, -7.438147520000000e3;

// Define associated spherical orbital state
basic_mathematics::Vector6d sphericalOrbitalState;
sphericalOrbitalState( headingAngleIndex ) = TUDAT_NAN;
sphericalOrbitalState( flightPathIndex ) = -mathematical_constants::PI / 2.0;
sphericalOrbitalState( latitudeIndex ) = mathematical_constants::PI / 2.0;
sphericalOrbitalState( longitudeIndex ) = 0.0;
sphericalOrbitalState( radiusIndex ) = cartesianState.segment( 0, 3 ).norm( );
sphericalOrbitalState( speedIndex ) = cartesianState.segment( 3, 3 ).norm( );

basic_mathematics::Vector6d reconvertedCartesianState = convertSphericalOrbitalToCartesianState(
sphericalOrbitalState );

// Check consistency of back-and-forth conversion
for( unsigned int i = 0; i < 3; i++ )
{
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i ) - cartesianState( i ) ),
sphericalOrbitalState( radiusIndex ) * 2.0 * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i + 3 ) - cartesianState( i + 3 ) ),
sphericalOrbitalState( speedIndex ) * 2.0 * std::numeric_limits< double >::epsilon( ) );
}
}

// Test case 5: rotation with undefined flight path angle.
{
basic_mathematics::Vector6d cartesianState;
cartesianState<<0.0, 0.0, 6.498098097000000e3, 0.0, 0.0, 0.0;

// Define associated spherical orbital state
basic_mathematics::Vector6d sphericalOrbitalState;
sphericalOrbitalState( headingAngleIndex ) = TUDAT_NAN;
sphericalOrbitalState( flightPathIndex ) = TUDAT_NAN;
sphericalOrbitalState( latitudeIndex ) = mathematical_constants::PI / 2.0;
sphericalOrbitalState( longitudeIndex ) = 0.0;
sphericalOrbitalState( radiusIndex ) = cartesianState.segment( 0, 3 ).norm( );
sphericalOrbitalState( speedIndex ) = cartesianState.segment( 3, 3 ).norm( );

basic_mathematics::Vector6d reconvertedCartesianState = convertSphericalOrbitalToCartesianState(
sphericalOrbitalState );

// Check consistency of back-and-forth conversion
for( unsigned int i = 0; i < 3; i++ )
{
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i ) - cartesianState( i ) ),
sphericalOrbitalState( radiusIndex ) * 2.0 * std::numeric_limits< double >::epsilon( ) );
BOOST_CHECK_SMALL(
std::fabs( reconvertedCartesianState( i + 3 ) - cartesianState( i + 3 ) ),
2.0 * std::numeric_limits< double >::epsilon( ) );
}
}

}

BOOST_AUTO_TEST_SUITE_END( )

} // namespace unit_tests
} // namespace tudat


Loading