| Earth Observation Mission CFI Software Usage Guide for Object Oriented Software |

# COORDINATE TRANSFORMATIONS

The Earth Observation CFI software provides the following classes in [LIB_SUM]for handling coordinate systems and object state vectors:

- Topocentric:It contais a set of topocentric coordinates in term of azimuth, elevation, range and its derivatives.
- Geodetic: It contains a set of geodetic coordinates (longitude, latitude, altitude and its derivatives).
  This class provides a method to compute the distance between two geodetic points.
- Kepler: It contains the keplerian elements (mean or osculating) for the satellite vector
- Coord: It contains a set of cartesian coordinates for a position, velocity and acceleration vectors in a given CS. This class allows the following operations:
  - Transform between cartesian and geodetic coordinates.
  - Transform between cartesian and keplerian elements.
  - Get spherical coordianates (RA and decliantion)
  - Transform between cartesian and topocentric coordinates

- StateVector: It contatins a set of coordinates (as a Coord object) assciated to a time (as a Time object). This class allows the following operations:

  - Transform between different coordinate systems.
  - Get Sun, Moon or a Planet coordinates for a given time.
  - Get the true latitude for the satellite position.

- StarData: It contains the position and velocity of an star in term of RA, Declination, parallax and proper motion. It allows:
  - transformation to cartesian coordinates as a Coord object.
  - to get the position of the star at a given time
  - to get the star coordinates in a new star catalogue.

Together with these classes, the change method for the Attitude class (in Pointing Library) allows to transform between two reference frames, including satellite or instrument attitude CS. This CS change can include the translation between the frames or only the rotation. For more info about how to set the Attitude go to Attitude computation.

## Example

    // ------------------------------------------------------------------------
    //
    //                           JAVA Example Program.
    //                           COORDINATES
    //
    // ------------------------------------------------------------------------

    import EECFI.*;

    import java.util.Vector;
    import java.lang.String;
    import java.lang.Long;

    // Main program
    public class Example
    {
      public static void main(String[] args)
      {
        //-------------------------------------------------
        //-------------------------------------------------

        try
        {
          ModelId modelId;

          // ------------------------------------------------------------------------
          // Time references initialization
          // ------------------------------------------------------------------------

          double[] initTime = new double[4];

          initTime[0] = -245.1000000000000000;   // TAI time [days]
          initTime[1] = -245.0995949074074074;   // UTC time [days] (= TAI - 35.0 s)
          initTime[2] = -245.0995879629629630;   // UT1 time [days] (= TAI - 35.6 s)
          initTime[3] = -245.0997800925925926;   // GPS time [days] (= TAI - 19.0 s)

          // Construct the TimeCorrelation object
          TimeCorrelation timeCorr = new TimeCorrelation(initTime);

          // ------------------------------------------------------------------------
          //  Transform cartesian coordinates.
          // ------------------------------------------------------------------------

          System.out.println( "\n\nState vector: Change of reference frame" );

          Time t = new Time(timeCorr, -2456.0, XLCFI_TIME_TAI);

          double[] efPos = new double[]{4859964.138, -5265612.059, 0.002};
          double[] efVel = new double[]{-1203.303801, -1098.845511, 7377.224410};
          double[] efAcc = new double[]{0.0, 0.0, 0.0};

          Coord efCoord = new Coord(XLCFI_CS_EF, XLCFI_DER_2ND, efPos, efVel, efAcc);

          StateVector efVector = new StateVector(t, efCoord);

          // Change From GM2000 to MOD
          StateVector todVector = efVector.change(modelId, XLCFI_DER_2ND, XLCFI_CS_TOD);

          System.out.println( "Input state vector:" );
          System.out.println( "   Time = " + efVector.time.time + " ref= " + efVector.time.ref );
          System.out.println( "   Position (EF)    : " + efVector.coord.pos[0] + efVector.coord.pos[1] + efVector.coord.pos[2] );
          System.out.println( "   Velocity (EF)    : " + efVector.coord.vel[0] + efVector.coord.vel[1] + efVector.coord.vel[2] );
          System.out.println( "   Acceleration (EF): " + efVector.coord.acc[0] + efVector.coord.acc[1] + efVector.coord.acc[2] );

          System.out.println( "Output state vector:" );
          System.out.println( "   Time = " + todVector.time.time + " ref= " + todVector.time.ref );
          System.out.println( "   Position (EF)    : " + todVector.coord.pos[0] + todVector.coord.pos[1] + todVector.coord.pos[2] );
          System.out.println( "   Velocity (EF)    : " + todVector.coord.vel[0] + todVector.coord.vel[1] + todVector.coord.vel[2] );
          System.out.println( "   Acceleration (EF): " + todVector.coord.acc[0] + todVector.coord.acc[1] + todVector.coord.acc[2] );

          // ------------------------------------------------------------------------
          // Transform  cartesian to and from geodetic coordinates
          // ------------------------------------------------------------------------

          System.out.println( "\n\nGeodetic: Transform  cartesian to geodetic coordinates" );

          //using efCoord from previous example
          Geodetic geo = efCoord.getGeodetic(modelId, XLCFI_DER_1ST);

          System.out.println( "Input state vector:" );
          System.out.println( "   Position (EF)    : " + efCoord.pos[0] + efCoord.pos[1] + efCoord.pos[2] );
          System.out.println( "   Velocity (EF)    : " + efCoord.vel[0] + efCoord.vel[1] + efCoord.vel[2] );
          System.out.println( "   Acceleration (EF): " + efCoord.acc[0] + efCoord.acc[1] + efCoord.acc[2] );

          System.out.println( "Output geodetic coordinates:" );
          System.out.println( "   Longitude = " + geo.lon );
          System.out.println( "   Latitude  = " + geo.lat );
          System.out.println( "   Altitude  = " + geo.alt );
          System.out.println( "   Long. Der = " + geo.lonDer );
          System.out.println( "   Lat Der   = " + geo.latDer );
          System.out.println( "   Alt Der   = " + geo.altDer );

          System.out.println( "\n\nGeodetic: Transform geodetic to cartesian coordinates" );

          efCoord.setGeodetic(modelId, XLCFI_DER_1ST, geo);

          System.out.println( "Output state vector:" );

          System.out.println( "   Position (EF)    : " + efCoord.pos[0] + efCoord.pos[1] + efCoord.pos[2] );
          System.out.println( "   Velocity (EF)    : " + efCoord.vel[0] + efCoord.vel[1] + efCoord.vel[2] );
          System.out.println( "   Acceleration (EF): " + efCoord.acc[0] + efCoord.acc[1] + efCoord.acc[2] );

          // ------------------------------------------------------------------------
          // Transform from cartesian state vector to keplerian elements
          // ------------------------------------------------------------------------

          System.out.println( "\nCoord: Transform from cartesian state vector to keplerian elements" );

          double[] pos = new double[]{4859964.138, -5265612.059, 0.002};
          double[] vel = new double[]{-1203.303801, -1098.845511, 7377.224410};
          double[] acc = new double[]{0., 0., 0.};

          Coord coord2 = new Coord(XLCFI_CS_TOD, XLCFI_DER_1ST, pos, vel, acc);

          Kepler kep = coord2.getKepler(modelId, XLCFI_KEPLER_OSC);
          System.out.println( "- Elements type  : "
          + (kep.mode == XLCFI_KEPLER_OSC? "OSCULATING": "MEAN") );
          System.out.println( "- Reference frame  : " + kep.cs );
          System.out.println( "- Semi-major axis  : " + kep.a  );
          System.out.println( "- Eccenticity      : " + kep.e  );
          System.out.println( "- Inclination      : " + kep.i  );
          System.out.println( "- RAAN             : " + kep.ra );
          System.out.println( "- Arg. of Perigee  : " + kep.w  );
          System.out.println( "- Mean Anomaly     : " + kep.m  );

          // ------------------------------------------------------------------------
          // Transform from keplerian elements to cartesian state vector
          // ------------------------------------------------------------------------
          System.out.println( "\nCoord: Transform from keplerian elements to cartesian state vector" );

          Kepler kep2 = new Kepler();

          kep2.mode = XLCFI_KEPLER_OSC;
          kep2.cs   = XLCFI_CS_TOD;
          kep2.a    = 7000.0;       // Semi-major axis          [m]
          kep2.e    =    0.001;     // Eccenticity
          kep2.i    =   92.0;       // Inclination            [deg]
          kep2.ra   =  128.0;       // R.A. of Ascending Node [deg]
          kep2.w    =  110.0;       // Arg. of Perigee        [deg]
          kep2.m    =   73.1;       // Mean Anomaly           [deg]

          Coord coord3 = coord3.setKepler(modelId, kep2);

          System.out.println( "Output state vector:" );
          System.out.println( "   Position (EF)    : " + coord3.pos[0] + coord3.pos[1] + coord3.pos[2] );
          System.out.println( "   Velocity (EF)    : " + coord3.vel[0] + coord3.vel[1] + coord3.vel[2] );

          // ------------------------------------------------------------------------
          // Calculate the geodesic (minimum) distance between two points that lay
          // at a given altitude on the same ellipsoid
          // ------------------------------------------------------------------------
          System.out.println( "\nGeodetic: Distance between two points on an ellipsoid" );

          Geodetic geo2 = new Geodetic(4.17,  // longitude
                                       10.0,  // latitude
                                       0.0);  // altitude

          double distance, az1, az2, auxD;
          double lon, lat;

          // get geodesic distance to the following point
          lon = 90.0;
          lat = 0.0;

          distance = geo2.geoDistance(modelId, lon, lat, az1, az2);

          System.out.println( "Geodesic distance = " + distance/1000. + " Km" );
          System.out.println( "Geodesic azimuth of initial point = " + az1 + " deg" );
          System.out.println( "Geodesic azimuth of final point = "   + az2 + " deg" );

          // ------------------------------------------------------------------------
          // Calculate Sun, Moon and Planets position and velocity in the Earth Fixed CS
          // ------------------------------------------------------------------------
          System.out.println( "\nStateVector: get Sun, Moon and Planets state vector" );

          Time ut1Time = new Time(timeCorr, 0.0, XLCFI_TIME_UT1);

          StateVector sunVec = new StateVector();
          StateVector moonVec = new StateVector();
          StateVector planetVec = new StateVector();

          sunVec.setSun(modelId, ut1Time);
          moonVec.setMoon(modelId, ut1Time);
          planetVec.setPlanet(modelId, ut1Time, XLCFI_VENUS);

          System.out.println( "Output Sun state vector:" );

          System.out.println( "   Time = " + sunVec.time.time + " ref= " + sunVec.time.ref );
          System.out.println( "   CS = "   + sunVec.coord.cs + "deriv = " + sunVec.coord.deriv );
          System.out.println( "   Position (EF)    : " + sunVec.coord.pos[0] + sunVec.coord.pos[1] + sunVec.coord.pos[2] );
          System.out.println( "   Velocity (EF)    : " + sunVec.coord.vel[0] + sunVec.coord.vel[1] + sunVec.coord.vel[2] );
          System.out.println( "   Acceleration (EF): " + sunVec.coord.acc[0] + sunVec.coord.acc[1] + sunVec.coord.acc[2] );

          System.out.println( "Output Moon state vector:" );

          System.out.println( "   Time = " + moonVec.time.time + " ref= " + moonVec.time.ref );
          System.out.println( "   CS = "   + moonVec.coord.cs + "deriv = " + moonVec.coord.deriv );
          System.out.println( "   Position (EF)    : " + moonVec.coord.pos[0] + moonVec.coord.pos[1] + moonVec.coord.pos[2] );

          // [...]

          // ------------------------------------------------------------------------
          // Calculating star coordinates in the Mean of Date coordinate system
          // ------------------------------------------------------------------------
          System.out.println( "\nStar: get star RA and Decl." );

          ut1Time.time = -200.0; // using the same object as before

          double ra, dec;

          double ra0     =   0.35399670615; // Star right ascension in the Barycentric Mean of 2000.0 coordinate at J2000.0 [rad]
          double dec0    =   4.8672587;     // Star declination in the Barycentric Mean of 2000.0 coordinate at J2000.0 [rad]
          double muRa    =   0.001;         // Star proper motion in the right ascension [rad/century]
          double muDec   =  -0.001;         // Star proper motion in the declination [rad/century]
          double radVel  =   0.01;            // Star radial velocity [au/century]
          double par     =   0.0001;        // Star parallax [rad]

          StarData star = new StarData(ra0,     dec0,
            muRa,    muDec,
            radVel,  radVel,
            XLCFI_CS_BM2000);

          StarRaDec radec = star.getStar(modelId, ut1Time);

          System.out.println( "Output Star:" );
          System.out.println( "   RA  = " + radec.ra  );
          System.out.println( "   Dec = " + radec.dec );

          // ------------------------------------------------------------------------
          // Calculation of the satellite orbital position (True Latitude)
          // ------------------------------------------------------------------------
          System.out.println( "\nStateVector: getPositionOnOrbit" );

          long angleType, deriv;
          double angle, angleRate, angleRateRate;

          pos[0] =          0.138;
          pos[1] =   -2365612.059;
          pos[2] =    6763859.946;

          vel[0] =       132.303801;
          vel[1] =     -1203.845511;
          vel[2] =     -1203.845511;

          acc[0] =         0.0634168;
          acc[1] =        -0.0249763;
          acc[2] =        -0.3018956;

          Time t1 = new Time(timeCorr, 0.0, XLCFI_TIME_UT1);

          Coord coord4 = new Coord(XLCFI_CS_EF, XLCFI_DER_2ND, pos, vel, acc);

          StateVector sv = new StateVector(t1, coord4);

          angleType = XLCFI_ANGLE_TYPE_TRUE_LAT_TOD;
          deriv = XLCFI_DER_2ND;

          OrbitPos orbpos = sv.getPositionOnOrbit(modelId, angleType, deriv);

          System.out.println( "Output Position On Orbit = "
          + orbpos.angle + "deg; "
          + orbpos.angleRate + "deg/s; "
          + orbpos.angleRateRate + "deg/s2 " ) );

          // ------------------------------------------------------------------------
          // Conversion between cartesian coordinates and RA and declination
          // ------------------------------------------------------------------------
          System.out.println( "\nCoord: getRaDec & Star:getCart" );

          double pc        = 3.08568025E16;

          pos[0] = -8.82*pc;
          pos[1] = -5.93*pc;
          pos[2] = 3.7*pc;

          vel[0] = -57.7E3;
          vel[1] = 31.5E3;
          vel[2] = -102.3E3;

          Coord coord5 = new Coord(XLCFI_CS_BM1950, XLCFI_DER_1ST, pos, vel, acc);

          // Get spherical coords.
          StarData radec = coord5.getRaDec(modelId, XLCFI_DER_1ST);

          System.out.println( "Input cartesian coordinates" );
          System.out.println( "   CS = " + coord5.cs );
          System.out.println( "   Position = " + coord5.pos[0] + ", " + coord5.pos[1] + ", " + coord5.pos[2] );
          System.out.println( "   Velocity = " + coord5.vel[0] + ", " + coord5.vel[1] + ", " + coord5.vel[2] );

          System.out.println( "Output Star coordinates from input cartesian coordinates" );
          System.out.println( "   Right Ascension      = " + radec.ra       );
          System.out.println( "   Declination          = " + radec.dec      );
          System.out.println( "   Proper motion in RA  = " + radec.muRa     );
          System.out.println( "   Proper motion in Dec = " + radec.muDec    );
          System.out.println( "   Radial Velocity      = " + radec.radVel   );
          System.out.println( "   Parallax             = " + radec.parallax ) );

          // Get cartesian coords.
          Coord coordFromStar = radec.getCart(modelId, XLCFI_DER_1ST);

          System.out.println( "Output Cartesian Star coordinates from previous spherical coordinates" );
          System.out.println( "   CS = " + coordFromStar.cs );
          System.out.println( "   Position = " + coordFromStar.pos[0] + ", " + coordFromStar.pos[1] + ", " + coordFromStar.pos[2] );
          System.out.println( "   Velocity = " + coordFromStar.vel[0] + ", " + coordFromStar.vel[1] + ", " + coordFromStar.vel[2] );

          // ------------------------------------------------------------------------
          // Star coordinates conversion from Fk4 to FK5
          // ------------------------------------------------------------------------
          System.out.println( "\nStar: changeCatalog" );

          StarData star1 = new StarData(6.27906181420277,     // RA
            -1.34986658532673,    // Dec
            -0.0001394081738438,  // mu_ra
            -0.0000857635400903,  // mu_dec
            0.,                   // radial vel.
            0.,                   // parallax
            XLCFI_CS_BM1950);        // reference frame (XLCFI_FK4)

            Time starTime = new Time(timeCorr, 1646.0, XLCFI_TIME_UTC);

            long newCatalog = XLCFI_FK5;

            StarData star2 = star1.changeCatalog(modelId, starTime, newCatalog);

            System.out.println( "   INPUTS." );
            System.out.println( "       UTC time = " + starTime.time );
            System.out.println( "       RA = " + star1.ra + " \tDec = " + star1.dec );
            System.out.println( "       mu_ra = " + star1.muRa + " \tmu_dec = " + star1.muDec );
            System.out.println( "       rad_vel = "  + star1.radVel + ", \tparallax = " + star1.parallax );

            System.out.println( "   OUTPUTS." );
            System.out.println( "       RA = " + star2.ra + " \tDec = " + star2.dec ) );

            // ------------------------------------------------------------------------
            // Conversion between EF and Topocentric coordinates
            // ------------------------------------------------------------------------
            System.out.println( "\nCoord: topocentricToEf & efToTopocentric" );

            Topocentric topo = new Topocentric{20, 30, 10000, 0, 0, 0};
            Topocentric topo2 = new Topocentric();

            pos[0] = 3460675.389;
            pos[1] = 2903851.443;
            pos[2] = 4487348.409;

            vel[0] = 0.;
            vel[1] = 0.;
            vel[2] = 0.;

            Coord topOrigin = new Coord(XLCFI_CS_EF, XLCFI_DER_1ST, pos, vel, acc);

            Coord coordFromTop = new Coord();

            // topocentric to EF CS
            coordFromTop.topocentricToEf(modelId, XLCFI_MODE_FLAG_LOCATION, XLCFI_DER_1ST,
              topOrigin, topo);

            System.out.println( "Inputs." );
            System.out.println( "   Mode = LOCATION" );
            System.out.println( "   Deriv = 1st. Derivative" );
            System.out.println( "   Center of the Topocentric CS   = " + pos[0] +",  " + pos[1] + ", " + pos[2] );
            System.out.println( "   Velocity of the Topocentric CS = " + vel[0] +",  " + vel[1] + ", " + vel[2] );
            System.out.println( "   Azimuth, Elevation, Altitude = "
            + topo.azim + ",  " + topo.elev + ", " + topo.range );
            System.out.println( "   Rates for Azimuth, Elevation, Altitude = "
            + topo.azimDer  + ", " + topo.elevDer + ", " + topo.rangeDer );

            System.out.println( "Output Cartesian coordinates" );
            System.out.println( "   CS = " + coordFromStar.cs );
            System.out.println( "   Position = " + coordFromTop.pos[0] + ", " + coordFromTop.pos[1] + ", " + coordFromTop.pos[2] );
            System.out.println( "   Velocity = " + coordFromTop.vel[0] + ", " + coordFromTop.vel[1] + ", " + coordFromTop.vel[2] );

            // EF to topocentric
            coordFromTop.efToTopocentric(modelId, XLCFI_MODE_FLAG_LOCATION, XLCFI_DER_1ST,
              topOrigin, topo2);

            System.out.println( "Output topocentric parameters from previous cartesian coordinates" );
            System.out.println( "Topocentric Azimuth = "   + topo2.azim  );
            System.out.println( "Topocentric Elevation = " + topo2.elev  );
            System.out.println( "Topocentric Range = "     + topo2.range );

            System.out.println( "Topocentric Azimuth rate = "   + topo2.azimDer  );
            System.out.println( "Topocentric Elevation rate = " + topo2.elevDer  );
            System.out.println( "Topocentric Range rate = "     + topo2.rangeDer );

        }//end try

        catch (CfiError cfiError)
        {
          //If an exception is thrown, there have been errors during execution
          Vector<String> errorMessages = new Vector<String>();

          // Get error messages
          errorMessages = cfiError.getMsg(errorMessages);

          // Pring Error messages
          for (int i = 0; i < errorMessages.size(); i++)
          {
            System.out.println( errorMessages.elementAt(i) );
          }
        }

      }

    }