예제 #1
0
        static void Main0(string[] args)
        {
            // Ground station

            const double lon_Sta = 11.0 * OrbitConsts.RadPerDeg;          // [rad]
            const double lat_Sta = 48.0 * OrbitConsts.RadPerDeg;          // [rad]
            const double alt_h   = 0.0e3;                                 // [m]

            GeoCoord StaGeoCoord = new GeoCoord(lon_Sta, lat_Sta, alt_h); // Geodetic coordinates


            // Spacecraft orbit

            double Mjd_Epoch = DateUtil.DateToMjd(1997, 01, 01, 0, 0, 0);             // Epoch

            const double a     = 960.0e3 + OrbitConsts.RadiusOfEarth;                 // Semimajor axis [m]
            const double e     = 0.0;                                                 // Eccentricity
            const double i     = 97.0 * OrbitConsts.RadPerDeg;                        // Inclination [rad]
            const double Omega = 130.7 * OrbitConsts.RadPerDeg;                       // RA ascend. node [rad]
            const double omega = 0.0 * OrbitConsts.RadPerDeg;                         // Argument of latitude [rad]
            const double M0    = 0.0 * OrbitConsts.RadPerDeg;                         // Mean anomaly at epoch [rad]

            Vector kepElements = new Geo.Algorithm.Vector(a, e, i, Omega, omega, M0); // Keplerian elements

            // Variables
            double Mjd_UTC, dt;

            // Station
            var    R_Sta = StaGeoCoord.ToXyzVector(OrbitConsts.RadiusOfEarth, OrbitConsts.FlatteningOfEarth); // Geocentric position vector
            Matrix E     = StaGeoCoord.ToLocalNez_Matrix();                                                   // Transformation to
            // local tangent coordinates
            // Header

            var info = "Exercise 2-4: Topocentric satellite motion" + "\r\n"
                       + "   Date         UTC           Az         El      Dist" + "\r\n"
                       + "yyyy/mm/dd  hh:mm:ss.sss     [deg]     [deg]     [km]";

            Console.WriteLine(info);

            // Orbit
            for (int Minute = 6; Minute <= 24; Minute++)
            {
                Mjd_UTC = Mjd_Epoch + Minute / 1440.0;                                                    // Time
                dt      = (Mjd_UTC - Mjd_Epoch) * 86400.0;                                                // Time since epoch [s]
                Geo.Algorithm.Vector r = Kepler.State(OrbitConsts.GM_Earth, kepElements, dt).Slice(0, 2); // Inertial position vector
                Matrix U = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC));                                    // Earth rotation
                var    enz = E * (U * r - R_Sta);                                                         // Topocentric position vector
                double Azim = 0, Elev = 0, Dist;
                GeoCoord.LocalEnzToPolar(enz, out Azim, out Elev, out Dist);                              // Azimuth, Elevation

                info = DateUtil.MjdToDateTimeString(Mjd_UTC) + "  " + String.Format("{0, 9:F3}", (Azim * OrbitConsts.DegPerRad)) + "  " + String.Format("{0, 9:F3}", (Elev * OrbitConsts.DegPerRad))
                       + "  " + String.Format("{0, 9:F3}", (Dist / 1000.0));
                Console.WriteLine(info);
            }
            ;

            Console.ReadKey();
        }
        static void Main0(string[] args)
        {
            // Constants
            const double GM    = 1.0;                                                          // Gravitational coefficient
            const double e     = 0.1;                                                          // Eccentricity
            const double t_end = 20.0;                                                         // End time

            Geo.Algorithm.Vector Kep   = new Geo.Algorithm.Vector(1.0, e, 0.0, 0.0, 0.0, 0.0); // (a,e,i,Omega,omega,M)
            Geo.Algorithm.Vector y_ref = Kepler.State(GM, Kep, t_end);                         // Reference solution

            int[] Steps = { 50, 100, 250, 500, 750, 1000, 1500, 2000 };

            // Variables

            // Function call count
            int    iCase;
            double t, h;                                                                                     // Time and step aboutSize

            Geo.Algorithm.Vector y = new Geo.Algorithm.Vector(6);                                            // State vector

            RungeKutta4StepIntegrator Orbit = new RungeKutta4StepIntegrator(f_Kep6D, 6, (Action)nCallsPlus); // Object for integrating the
            // differential equation
            // defined by f_Kep6D using the
            // 4th-order Runge-Kutta method
            // Header

            var info = "Exercise 4-1: Runge-Kutta 4th-order integration" + "\r\n" + "\r\n"
                       + "  Problem D1 (e=0.1)" + "\r\n" + "\r\n"
                       + "  N_fnc   Accuracy   Digits " + "\r\n";

            Console.WriteLine(info);

            // Loop over test cases
            for (iCase = 0; iCase < 8; iCase++)
            {
                // Step aboutSize
                h = t_end / Steps[iCase];

                // Initial values
                t      = 0.0;
                y      = new Geo.Algorithm.Vector(1.0 - e, 0.0, 0.0, 0.0, Math.Sqrt((1 + e) / (1 - e)), 0.0);
                nCalls = 0;

                // Integration from t=t to t=t_end
                for (int i = 1; i <= Steps[iCase]; i++)
                {
                    Orbit.Step(ref t, ref y, h);
                }

                // Output
                info = String.Format("{0, 6:D}{1, 14:E4}{2, 9:F}", nCalls, (y - y_ref).Norm(), -Math.Log10((y - y_ref).Norm()));
                Console.WriteLine(info);
            }
            ;

            Console.ReadKey();
        }
예제 #3
0
        static void Main0(string[] args)
        {
            // Constants

            const double GM    = 1.0;                                                          // Gravitational coefficient
            const double e     = 0.1;                                                          // Eccentricity
            const double t_end = 20.0;                                                         // End time

            Geo.Algorithm.Vector Kep   = new Geo.Algorithm.Vector(1.0, e, 0.0, 0.0, 0.0, 0.0); // (a,e,i,Omega,omega,M)
            Geo.Algorithm.Vector y_ref = Kepler.State(GM, Kep, t_end);                         // Reference solution

            int[] Steps = { 100, 300, 600, 1000, 1500, 2000, 3000, 4000 };

            // Variables
            // Function call count
            int    iCase;
            double t, h;                                                                                 // Time and step aboutSize

            GaussJackson4OrderPredictor Orbit = new GaussJackson4OrderPredictor(f_Kep3D, 3, nCallsPlus); // Object for integrating the
            // 2nd order diff. equation
            // defined by f_Kep3D using the 4th-order GJ predictor

            // Header

            var info = "Exercise 4-2: Gauss-Jackson 4th-order predictor" + "\r\n";

            info += "  Problem D1 (e=0.1)" + "\r\n";
            info += "  N_fnc   Accuracy   Digits " + "\r\n";
            Console.WriteLine(info);
            // Loop over test cases

            for (iCase = 0; iCase < 8; iCase++)
            {
                // Step aboutSize
                var step = Steps[iCase];
                h = t_end / step;
                // Initial values
                nCalls = 0;
                t      = 0.0;
                var y = Orbit.GetState(e, t, h, step);

                info = String.Format("{0, 6:D}{1, 14:E4}{2, 9:F}", nCalls, (y - y_ref).Norm(), -Math.Log10((y - y_ref).Norm()));
                Console.WriteLine(info);
            }
            Console.ReadKey();
        }
예제 #4
0
        static void Main0(string[] args)
        {
            // Constants

            const double GM    = 1.0;                                                          // Gravitational coefficient
            const double e     = 0.9;                                                          // Eccentricity
            const double t_end = 20.0;                                                         // End time

            Geo.Algorithm.Vector Kep   = new Geo.Algorithm.Vector(1.0, e, 0.0, 0.0, 0.0, 0.0); // (a,e,i,Omega,omega,M)
            Geo.Algorithm.Vector y_ref = Kepler.State(GM, Kep, t_end);                         // Reference solution

            // Variables

            double t;                                                        // Time
            double relerr, abserr;                                           // Accuracy requirements

            Geo.Algorithm.Vector y     = new Geo.Algorithm.Vector(6);        // State vector
            AuxDataRecord        Aux   = new AuxDataRecord();                // Auxiliary satData
            DeIntegrator         Orbit = new DeIntegrator(f_Kep6D_, 6, Aux); // Object for integrating the
            // differential equation
            // defined by f_Kep6D_
            // Header

            var info = "Exercise 4-3: Step size control of DE multistep method" + "\r\n";

            info += "  Step       t           h          r " + "\r\n";
            Console.WriteLine(info);
            // Initial values
            t = 0.0;
            y = new Geo.Algorithm.Vector(1.0 - e, 0.0, 0.0, 0.0, Math.Sqrt((1 + e) / (1 - e)), 0.0);

            Aux.n_step = 0;
            Aux.t      = 0;

            relerr = 0.0;
            abserr = 1.0e-8;

            // Integration from t=t to t=t_end
            Orbit.Init(t, relerr, abserr);
            Orbit.Integ(t_end, y);

            Console.ReadKey();
        }
예제 #5
0
        static void Main0(string[] args)
        {
            // Ground station

            const double lon_Sta = 11.0 * OrbitConsts.RadPerDeg;  // [rad]
            const double lat_Sta = 48.0 * OrbitConsts.RadPerDeg;  // [rad]
            const double alt_h   = 0.0e3;                         // [m]

            GeoCoord Sta = new GeoCoord(lon_Sta, lat_Sta, alt_h); // Geodetic coordinates


            // Fixed media satData at ground site

            const double T0 = 273.2;                  // Temperature at 0 deg C [K]
            const double pa = 1024.0;                 // Partial pressure of dry air [mb]
            const double fh = 0.7;                    // Relative humidity

            // Spacecraft orbit

            double Mjd_Epoch = DateUtil.DateToMjd(1997, 01, 01); // Epoch

            const double a     = 42164.0e3;                      // Semimajor axis [m]
            const double e     = 0.000296;                       // Eccentricity
            const double i     = 0.05 * OrbitConsts.RadPerDeg;   // Inclination [rad]
            const double Omega = 150.7 * OrbitConsts.RadPerDeg;  // RA ascend. node [rad]
            const double omega = 0.0 * OrbitConsts.RadPerDeg;    // Argument of latitude [rad]
            const double M0    = 0.0 * OrbitConsts.RadPerDeg;    // Mean anomaly at epoch [rad]

            Vector Kep = new Vector(a, e, i, Omega, omega, M0);  // Keplerian elements


            // Variables

            int    Hour;
            double Mjd_UTC, dt;
            double Azim = 0, Elev = 0, Elev0 = 0, Dist;
            double Ns, eh, T, TC;
            Vector dElev = new Vector(2);
            Vector R_Sta = new Vector(3);
            Vector r = new Vector(3), s = new Vector(3);
            Matrix U = new Matrix(3, 3), E = new Matrix(3, 3);

            double[] Tv = { 303.0, 283.0 };          // Temperature [K]

            // Station

            R_Sta = Sta.ToXyzVector(OrbitConsts.RadiusOfEarth, OrbitConsts.FlatteningOfEarth); // Geocentric position vector
            E     = Sta.ToLocalNez_Matrix();                                                   // Transformation to
            // local tangent coordinates


            // Header
            var endl = "\r\n";
            var info = "Exercise 6-4: Tropospheric Refraction" + endl + endl;

            Console.Write(info);

            // Orbit

            for (Hour = 0; Hour <= 8; Hour++)
            {
                Mjd_UTC = Mjd_Epoch + 3.0 * Hour / 24.0;                     // Modified Julian Date [UTC]

                dt = (Mjd_UTC - Mjd_Epoch) * 86400.0;                        // Time since epoch [s]

                r = Kepler.State(OrbitConsts.GM_Earth, Kep, dt).Slice(0, 2); // Inertial position vector

                U = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC));              // Earth rotation
                s = E * (U * r - R_Sta);                                     // Topocentric position vector

                GeoCoord.LocalEnzToPolar(s, out Azim, out Elev, out Dist);   // Azimuth, Elevation

                if (Hour == 0)
                {
                    Elev0 = Elev;                              // Store initial elevation
                    info  = "E0 [deg] " + String.Format("{0, 10:F3}", Elev0 * OrbitConsts.DegPerRad) + endl + endl;
                    Console.Write(info);
                    info = "   Date         UTC          E-E0      dE_t1     dE_t2 " + endl
                           + "yyyy/mm/dd  hh:mm:ss.sss     [deg]     [deg]     [deg]" + endl;
                    Console.Write(info);
                }
                ;

                for (int Ti = 0; Ti <= 1; Ti++)
                {                                                                // Evaluate at 2 temperatures
                    T         = Tv[Ti];                                          // Map to scalar
                    TC        = T - T0;                                          // Temperature [C]
                    eh        = 6.10 * fh * Math.Exp(17.15 * TC / (234.7 + TC)); // Partial water pressure
                    Ns        = 77.64 * pa / T + 3.734e5 * eh / (T * T);         // Refractivity
                    dElev[Ti] = Ns * 1.0e-6 / Math.Tan(Elev);                    // Tropospheric refraction
                }
                ;


                info = DateUtil.MjdToDateTimeString(Mjd_UTC)
                       + String.Format("{0, 10:F3}", (Elev - Elev0) * OrbitConsts.DegPerRad)
                       + String.Format("{0, 10:F3}", dElev[0] * OrbitConsts.DegPerRad) + String.Format("{0, 10:F3}", dElev[1] * OrbitConsts.DegPerRad) + endl;
                Console.Write(info);
            }
            ;
            Console.ReadKey();
        }
        static void Main0(string[] args)
        {
            // Ground station

            const double lon_Sta = 11.0 * OrbitConsts.RadPerDeg;  // [rad]
            const double lat_Sta = 48.0 * OrbitConsts.RadPerDeg;  // [rad]
            const double alt_h   = 0.0e3;                         // [m]

            GeoCoord Sta = new GeoCoord(lon_Sta, lat_Sta, alt_h); // Geodetic coordinates


            // Spacecraft orbit

            double Mjd_Epoch = DateUtil.DateToMjd(1997, 01, 01);      // Epoch

            const double a     = 960.0e3 + OrbitConsts.RadiusOfEarth; // Semimajor axis [m]
            const double e     = 0.0;                                 // Eccentricity
            const double i     = 97.0 * OrbitConsts.RadPerDeg;        // Inclination [rad]
            const double Omega = 130.7 * OrbitConsts.RadPerDeg;       // RA ascend. node [rad]
            const double omega = 0.0 * OrbitConsts.RadPerDeg;         // Argument of latitude [rad]
            const double M0    = 0.0 * OrbitConsts.RadPerDeg;         // Mean anomaly at epoch [rad]

            Vector Kep = new Vector(a, e, i, Omega, omega, M0);       // Keplerian elements

            // Light time iteration
            const int I_max = 2;                      // Maxim. number of iterations

            // Variables
            int    Iteration, Step;                                                  // Loop counters
            double Mjd_UTC, t;                                                       // Time
            double rho, range;                                                       // Range 1-way/2-way
            double tau_up, tau_down;                                                 // Upleg/downleg light time
            Vector R_Sta = new Vector(3);                                            // Earth-fixed station position
            Vector r_Sta = new Vector(3);                                            // Inertial station position
            Vector r = new Vector(3);                                                // Inertial satellite position
            Vector rho_up = new Vector(I_max + 1), rho_down = new Vector(I_max + 1); // Upleg/downleg range
            Matrix U = new Matrix(3, 3);                                             // Earth rotation matrix

            // Station
            R_Sta = Sta.ToXyzVector(OrbitConsts.RadiusOfEarth, OrbitConsts.FlatteningOfEarth);         // Geocentric position vector


            // Header
            var endl = "\r\n";
            var info = "Exercise 6-1: Light time iteration" + endl + endl
                       + "   Date         UTC        Distance   " +
                       "Down It 1   It 2   Up It 1    Range" + endl
                       + "yyyy/mm/dd  hh:mm:ss.sss      [m]     " +
                       "    [m]     [mm]      [m]      [m] " + endl;

            Console.WriteLine(info);

            // Orbit

            for (Step = 0; Step <= 6; Step++)
            {
                // Ground-received time

                t = 360.0 + 180.0 * Step;                       // Time since epoch [s]

                Mjd_UTC = Mjd_Epoch + t / 86400.0;              // Modified Julian Date [UTC]

                U = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC)); // Earth rotation matrix

                r_Sta = U.Transpose() * R_Sta;                  // Inertial station position

                // Light time iteration for downleg satellite -> station

                tau_down = 0.0;
                for (Iteration = 0; Iteration <= I_max; Iteration++)
                {
                    r                   = Kepler.State(OrbitConsts.GM_Earth, Kep, t - tau_down).Slice(0, 2); // Spacecraft position
                    rho                 = (r - r_Sta).Norm();                                                // Downleg range
                    tau_down            = rho / OrbitConsts.SpeedOfLight;                                    // Downleg light time
                    rho_down[Iteration] = rho;
                }
                ;

                // Light time iteration for upleg station -> satellite

                tau_up = 0.0;
                for (Iteration = 0; Iteration <= I_max; Iteration++)
                {
                    U                 = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC - (tau_down + tau_up) / 86400.0));
                    r_Sta             = U.Transpose() * R_Sta;           // Inertial station pos.
                    rho               = (r - r_Sta).Norm();              // at ground transmit time
                    tau_up            = rho / OrbitConsts.SpeedOfLight;  // Upleg light time
                    rho_up[Iteration] = rho;
                }
                ;

                // Two-way range

                range = 0.5 * (rho_down[I_max] + rho_up[I_max]);

                info = DateUtil.MjdToDateTimeString(Mjd_UTC)
                       + String.Format("{0,15:F3}{1,9:F3}{2,9:F3}{3,8:F3}{4,12:F3}", rho_down[0], rho_down[1] - rho_down[0], (rho_down[2] - rho_down[1]) * 1000.0, rho_up[1] - rho_up[0], range);
                Console.WriteLine(info);
            }


            Console.ReadKey();
        }
        static void Main(string[] args)
        {
            // Constants

            const double relerr = 1.0e-13;                                                                // Relative and absolute
            const double abserr = 1.0e-6;                                                                 // accuracy requirement

            const double a   = OrbitConsts.RadiusOfEarth + 650.0e3;                                       // Semi-major axis [m]
            const double e   = 0.001;                                                                     // Eccentricity
            const double inc = OrbitConsts.RadPerDeg * 51.0;                                              // Inclination [rad]

            double n = Math.Sqrt(OrbitConsts.GM_Earth / (a * a * a));                                     // Mean motion

            Matrix Scale = Matrix.CreateDiagonal(new Geo.Algorithm.Vector(1, 1, 1, 1 / n, 1 / n, 1 / n)); // Velocity
            Matrix scale = Matrix.CreateDiagonal(new Geo.Algorithm.Vector(1, 1, 1, n, n, n));             // normalization

            const double t_end = 86400.0;
            const double step  = 300.0;

            // Variables

            int       i, j;                                           // Loop counters
            double    Mjd0;                                           // Epoch (Modified Julian Date)
            double    t;                                              // Integration time [s]
            double    max, max_Kep;                                   // Matrix error norm
            AuxParam7 Aux1 = new AuxParam7(), Aux2 = new AuxParam7(); // Auxiliary parameter records

            // Model parameters for reference solution (full 10x10 gravity model) and
            // simplified variational equations

            // Epoch state and transition matrix

            Mjd0 = OrbitConsts.MJD_J2000;

            Aux1.Mjd_0 = Mjd0; // Reference epoch
            Aux1.n_a   = 10;   // Degree of gravity field for trajectory computation
            Aux1.m_a   = 10;   // Order of gravity field for trajectory computation
            Aux1.n_G   = 10;   // Degree of gravity field for variational equations
            Aux1.m_G   = 10;   // Order of gravity field for variational equations

            Aux2.Mjd_0 = Mjd0; // Reference epoch
            Aux2.n_a   = 2;    // Degree of gravity field for trajectory computation
            Aux2.m_a   = 0;    // Order of gravity field for trajectory computation
            Aux2.n_G   = 2;    // Degree of gravity field for variational equations
            Aux2.m_G   = 0;    // Order of gravity field for variational equations



            DeIntegrator Int1 = new DeIntegrator(VarEqn, 42, Aux1);                                          // Object for integrating the variat. eqns.
            DeIntegrator Int2 = new DeIntegrator(VarEqn, 42, Aux2);                                          //

            Geo.Algorithm.Vector y0 = new Geo.Algorithm.Vector(6), y = new Geo.Algorithm.Vector(6);          // State vector
            Geo.Algorithm.Vector yPhi1 = new Geo.Algorithm.Vector(42), yPhi2 = new Geo.Algorithm.Vector(42); // State and transition matrix vector
            Matrix Phi1 = new Matrix(6, 6), Phi2 = new Matrix(6, 6);                                         // State transition matrix
            Matrix Phi_Kep = new Matrix(6, 6);                                                               // State transition matrix (Keplerian)


            y0 = Kepler.State(OrbitConsts.GM_Earth, new Geo.Algorithm.Vector(a, e, inc, 0.0, 0.0, 0.0));

            for (i = 0; i <= 5; i++)
            {
                yPhi1[i] = y0[i];
                for (j = 0; j <= 5; j++)
                {
                    yPhi1[6 * (j + 1) + i] = (i == j ? 1 : 0);
                }
            }

            yPhi2 = new Geo.Algorithm.Vector(yPhi1);



            // Initialization

            t = 0.0;
            Int1.Init(t, relerr, abserr);
            Int2.Init(t, relerr, abserr);

            // Header
            var endl = "\r\n";
            var info = "Exercise 7-1: State transition matrix" + endl
                       + endl
                       + "  Time [s]  Error (J2)  Error(Kep)" + endl;

            // Steps

            while (t < t_end)
            {
                // New output time

                t += step;

                // Integration

                Int1.Integ(t, ref yPhi1); // Reference
                Int2.Integ(t, ref yPhi2); // Simplified

                //info= setprecision(5) + setw(12)+yPhi1 + endl;
                //info= setprecision(5) + setw(12) + yPhi2 + endl;


                // Extract and normalize state transition matrices

                for (j = 0; j <= 5; j++)
                {
                    Phi1.SetCol(j, yPhi1.Slice(6 * (j + 1), 6 * (j + 1) + 5));
                }
                for (j = 0; j <= 5; j++)
                {
                    Phi2.SetCol(j, yPhi2.Slice(6 * (j + 1), 6 * (j + 1) + 5));
                }

                Phi1 = Scale * Phi1 * scale;
                Phi2 = Scale * Phi2 * scale;

                // Keplerian state transition matrix (normalized)

                Kepler.TwoBody(OrbitConsts.GM_Earth, y0, t, ref y, ref Phi_Kep);
                Phi_Kep = Scale * Phi_Kep * scale;

                // Matrix error norms

                max     = Max(Matrix.CreateIdentity(6) - Phi1 * InvSymp(Phi2));
                max_Kep = Max(Matrix.CreateIdentity(6) - Phi1 * InvSymp(Phi_Kep));

                // Output
                //   info = String.Format( "{0, 10:F }{1, 10:F }{2, 10:F } ",  t,  max , max_Kep );
                info = String.Format("{0, 10:F2}{1, 10:F2}{2, 12:F2}", t, max, max_Kep);
                Console.WriteLine(info);
            }
            ;

            // Output

            info = endl
                   + "Time since epoch [s]" + endl
                   + endl
                   + String.Format("{0, 10:F}", t) + endl
                   + endl;
            Console.Write(info);
            info = "State transition matrix (reference)" + endl
                   + endl
                   + Phi1 + endl;
            Console.Write(info);
            info = "J2 State transition matrix" + endl
                   + endl
                   + Phi2 + endl;
            Console.Write(info);
            info = "Keplerian State transition matrix" + endl
                   + endl
                   + Phi_Kep + endl;
            Console.Write(info);

            Console.ReadKey();
        }
        static void Main0(string[] args)
        {
            // Ground station

            const double lon_Sta = 11.0 * OrbitConsts.RadPerDeg;  // [rad]
            const double lat_Sta = 48.0 * OrbitConsts.RadPerDeg;  // [rad]
            const double alt_h   = 0.0e3;                         // [m]

            GeoCoord Sta = new GeoCoord(lon_Sta, lat_Sta, alt_h); // Geodetic coordinates

            // Earth rotation

            Vector omega_vec = new Vector(0.0, 0.0, OrbitConsts.RotationSpeedOfEarth_Rad); // Earth rotation vector

            // Spacecraft orbit

            double Mjd_Epoch = DateUtil.DateToMjd(1997, 01, 01);      // Epoch

            const double a     = 960.0e3 + OrbitConsts.RadiusOfEarth; // Semimajor axis [m]
            const double e     = 0.0;                                 // Eccentricity
            const double i     = 97.0 * OrbitConsts.RadPerDeg;        // Inclination [rad]
            const double Omega = 130.7 * OrbitConsts.RadPerDeg;       // RA ascend. node [rad]
            const double omega = 0.0 * OrbitConsts.RadPerDeg;         // Argument of latitude [rad]
            const double M0    = 0.0 * OrbitConsts.RadPerDeg;         // Mean anomaly at epoch [rad]

            Vector Kep = new Vector(a, e, i, Omega, omega, M0);       // Keplerian elements


            // Radar Modelling

            const int    I_max = 3;                   // Maximum light time iterations
            const double Count = 1.0;                 // Doppler count time [s]


            // Variables

            int    Iteration, Step;                      // Loop counters
            double Mjd_UTC, t;                           // Time
            double rho;                                  // Range 1-way
            double range1, range0;                       // Range 2-way at end, begin of count
            double range_rate;                           // Range rate
            double Doppler;                              // Instantaneous Doppler
            double tau_up, tau_down;                     // Upleg/downleg light time
            double rho_up = 0, rho_down = 0;             // Upleg/downleg range
            Vector R_Sta = new Vector(3);                // Earth-fixed station position
            Vector r_Sta = new Vector(3);                // Inertial station position
            Vector r = new Vector(3);                    // Inertial satellite position
            Vector x = new Vector(3), v = new Vector(3); // Earth-fixed satellite position, velocity
            Vector u = new Vector(3);                    // Unit vector satellite station
            Matrix U = new Matrix(3, 3);                 // Earth rotation matrix


            // Station

            R_Sta = Sta.ToXyzVector(OrbitConsts.RadiusOfEarth, OrbitConsts.FlatteningOfEarth);         // Geocentric position vector


            // Header
            var endl = "\r\n";
            var info = "Exercise 6-2: Range Rate Modelling" + endl + endl
                       + "   Date         UTC       Range Rate     Doppler  Difference" + endl
                       + "yyyy/mm/dd  hh:mm:ss.sss      [m/s]       [m/s]       [m/s] " + endl;

            Console.WriteLine(info);
            // Orbit

            for (Step = 0; Step <= 6; Step++)
            {
                // Ground-received time

                t = 360.0 + 180.0 * Step;                       // Time since epoch [s]

                Mjd_UTC = Mjd_Epoch + t / 86400.0;              // Modified Julian Date [UTC]

                U = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC)); // Earth rotation matrix

                r_Sta = U.Transpose() * R_Sta;                  // Inertial station position

                // Light time iteration at count interval end for downleg satellite -> station

                tau_down = 0.0;
                for (Iteration = 0; Iteration <= I_max; Iteration++)
                {
                    r        = Kepler.State(OrbitConsts.GM_Earth, Kep, t - tau_down).Slice(0, 2); // Spacecraft position
                    rho      = (r - r_Sta).Norm();                                                // Downleg range
                    tau_down = rho / OrbitConsts.SpeedOfLight;                                    // Downleg light time
                    rho_down = rho;
                }
                ;

                // Light time iteration at count interval end for upleg station -> satellite

                tau_up = 0.0;
                for (Iteration = 0; Iteration <= I_max; Iteration++)
                {
                    U      = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC - (tau_down + tau_up) / 86400.0));
                    r_Sta  = U.Transpose() * R_Sta;                      // Inertial station pos.
                    rho    = (r - r_Sta).Norm();                         // at ground transmit time
                    tau_up = rho / OrbitConsts.SpeedOfLight;             // Upleg light time
                    rho_up = rho;
                }
                ;

                // Two-way range at end of count interval

                range1 = 0.5 * (rho_down + rho_up);

                // Station position at begin of count interval

                U = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC - Count / 86400.0)); // Earth rotation matrix

                r_Sta = U.Transpose() * R_Sta;                                    // Inertial station position

                // Light time iteration at count interval begin for downleg satellite -> station

                tau_down = 0.0;
                for (Iteration = 0; Iteration <= I_max; Iteration++)
                {
                    r        = Kepler.State(OrbitConsts.GM_Earth, Kep, t - tau_down - Count).Slice(0, 2); // Spacecraft position
                    rho      = (r - r_Sta).Norm();                                                        // Downleg range
                    tau_down = rho / OrbitConsts.SpeedOfLight;                                            // Downleg light time
                    rho_down = rho;
                }
                ;

                // Light time iteration at count interval begin for upleg station -> satellite

                tau_up = 0.0;
                for (Iteration = 0; Iteration <= I_max; Iteration++)
                {
                    U      = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC - (tau_down + tau_up + Count) / 86400.0));
                    r_Sta  = U.Transpose() * R_Sta;                      // Inertial station pos.
                    rho    = (r - r_Sta).Norm();                         // at ground transmit time
                    tau_up = rho / OrbitConsts.SpeedOfLight;             // Upleg light time
                    rho_up = rho;
                }
                ;

                // Two-way range at begin of count interval

                range0 = 0.5 * (rho_down + rho_up);

                // Two-way average range rate

                range_rate = (range1 - range0) / Count;


                // Instantaneous Doppler modelling at mid of count interval

                U = Matrix.RotateZ3D(IERS.GetGmstRad(Mjd_UTC - (Count / 2.0) / 86400));         // Earth rotation matrix
                x = U * Kepler.State(OrbitConsts.GM_Earth, Kep, t - (Count / 2.0)).Slice(0, 2); // Spacecraft position
                v = U * Kepler.State(OrbitConsts.GM_Earth, Kep, t - (Count / 2.0)).Slice(3, 5)  // Spacecraft velocity
                    - omega_vec.Cross3D(x);
                u = (x - R_Sta) / (x - R_Sta).Norm();                                           // Unit vector s/c-station

                Doppler = v.Dot(u);                                                             // Instantaneous Doppler


                // Output

                info = DateUtil.MjdToDateTimeString(Mjd_UTC) + String.Format("{0, 12:F3}{1, 12:F3}{2, 12:F3}", range_rate, Doppler, range_rate - Doppler);

                Console.WriteLine(info);
            }
            Console.ReadKey();
        }
        static void Main0(string[] args)
        {
            // Constants
            const int N_Step = 720;   // Maximum number of steps

            // Variables
            int    i;
            int    N_Step1;
            int    N_Step2;
            double Step;
            double Mjd0_UTC;

            Geo.Algorithm.Vector Y0 = new Geo.Algorithm.Vector(6);
            Geo.Algorithm.Vector Kep = new Geo.Algorithm.Vector(6);
            ForceModelOption     Aux_ref = new ForceModelOption(), Aux = new ForceModelOption();          // Auxiliary parameters
            double Max_J20, Max_J22, Max_J44, Max_J1010;
            double Max_Sun, Max_Moon, Max_SRad, Max_Drag;

            Geo.Algorithm.Vector[] Eph_Ref   = new Geo.Algorithm.Vector[N_Step + 1];
            Geo.Algorithm.Vector[] Eph_J20   = new Geo.Algorithm.Vector[N_Step + 1];
            Geo.Algorithm.Vector[] Eph_J22   = new Geo.Algorithm.Vector[N_Step + 1];
            Geo.Algorithm.Vector[] Eph_J44   = new Geo.Algorithm.Vector[N_Step + 1];
            Geo.Algorithm.Vector[] Eph_J1010 = new Geo.Algorithm.Vector[N_Step + 1];
            Geo.Algorithm.Vector[] Eph_Sun   = new Geo.Algorithm.Vector[N_Step + 1];
            Geo.Algorithm.Vector[] Eph_Moon  = new Geo.Algorithm.Vector[N_Step + 1];
            Geo.Algorithm.Vector[] Eph_SRad  = new Geo.Algorithm.Vector[N_Step + 1];
            Geo.Algorithm.Vector[] Eph_Drag  = new Geo.Algorithm.Vector[N_Step + 1];

            // Initialize UT1-UTC and UTC-TAI time difference
            IERS = new IERS(-0.05, -30.00, 0.0, 0.0);

            // Epoch state (remote sensing satellite)
            Mjd0_UTC = DateUtil.DateToMjd(1999, 03, 01, 00, 00, 0.0);
            Kep      = new Vector(7178.0e3, 0.0010, 98.57 * OrbitConsts.RadPerDeg, 0.0, 0.0, 0.0);
            Y0       = Kepler.State(OrbitConsts.GM_Earth, Kep, 0.0);

            // Model parameters
            Aux_ref.Mjd0_TT              = Mjd0_UTC - IERS.GetTT_UTC(Mjd0_UTC) / 86400.0;
            Aux_ref.Area                 = 5.0;    // [m^2]  Remote sensing satellite
            Aux_ref.Mass                 = 1000.0; // [kg]
            Aux_ref.CoefOfRadiation      = 1.3;
            Aux_ref.CoefOfDrag           = 2.3;
            Aux_ref.MaxDegree            = 20;
            Aux_ref.MaxOrder             = 20;
            Aux_ref.EnableSun            = true;
            Aux_ref.EnableMoon           = true;
            Aux_ref.EnableSolarRadiation = true;
            Aux_ref.EnableDrag           = true;

            // Reference orbit

            Step    = 120.0; // [s]
            N_Step1 = 50;    // 100 mins
            N_Step2 = 720;   // 1 day

            Aux = Aux_ref;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_Ref);

            // J2,0 perturbations
            Aux.MaxDegree = 2; Aux.MaxOrder = 0;

            Ephemeris(Y0, N_Step2, Step, Aux, Eph_J20);

            // J2,2 perturbations
            Aux.MaxDegree = 2; Aux.MaxOrder = 2;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_J22);

            // J4,4 perturbations
            Aux.MaxDegree = 4; Aux.MaxOrder = 4;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_J44);

            // J10,10 perturbations
            Aux.MaxDegree = 10; Aux.MaxOrder = 10;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_J1010);
            Aux.MaxDegree = 20; Aux.MaxOrder = 20;

            // Solar perturbations
            Aux.EnableSun = false;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_Sun);
            Aux.EnableSun = true;

            // Lunar perturbations
            Aux.EnableMoon = false;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_Moon);
            Aux.EnableMoon = true;

            // Solar radiation pressure perturbations
            Aux.EnableSolarRadiation = false;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_SRad);
            Aux.EnableSolarRadiation = true;

            // Drag perturbations
            Aux.EnableDrag = false;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_Drag);
            Aux.EnableDrag = true;

            // Find maximum over N_Step1 steps
            Max_J20 = Max_J22 = Max_J44 = Max_J1010 = Max_Sun = Max_Moon = Max_SRad = Max_Drag = 0.0;
            for (i = 0; i <= N_Step1; i++)
            {
                var refEph = Eph_Ref[i].Slice(0, 2);
                Max_J20   = max(Norm(Eph_J20[i].Slice(0, 2) - refEph), Max_J20);
                Max_J22   = max(Norm(Eph_J22[i].Slice(0, 2) - refEph), Max_J22);
                Max_J44   = max(Norm(Eph_J44[i].Slice(0, 2) - refEph), Max_J44);
                Max_J1010 = max(Norm(Eph_J1010[i].Slice(0, 2) - refEph), Max_J1010);
                Max_Sun   = max(Norm(Eph_Sun[i].Slice(0, 2) - refEph), Max_Sun);
                Max_Moon  = max(Norm(Eph_Moon[i].Slice(0, 2) - refEph), Max_Moon);
                Max_SRad  = max(Norm(Eph_SRad[i].Slice(0, 2) - refEph), Max_SRad);
                Max_Drag  = max(Norm(Eph_Drag[i].Slice(0, 2) - refEph), Max_Drag);
            }
            ;

            // Output
            var info = "Exercise 3-4: Orbit Perturbations " + "\r\n" + "\r\n";

            info += "Remote sensing satellite: " + "\r\n" + "\r\n";
            info += "  Maximum position errors within ";
            Console.Write(info);
            info  = String.Format("{0, 8:F}", N_Step1 * Step / 60.0);
            info += " min propagation interval " + "\r\n";
            info += "    J2,0    J2,2    J4,4  J10,10" + "     Sun    Moon  SolRad    Drag" + "\r\n";
            info += "     [m]     [m]     [m]     [m]" + "     [m]     [m]     [m]     [m]";
            Console.WriteLine(info);
            info = String.Format("{0, 8:F}{1, 8:F}{2, 8:F}{3, 8:F}{4, 8:F}{5, 8:F}{6, 8:F}{7, 8:F}", Max_J20, Max_J22, Max_J44, Max_J1010, Max_Sun, Max_Moon, Max_SRad, Max_Drag);
            Console.WriteLine(info);
            Console.WriteLine();

            // Find maximum over N_Step2 steps
            for (i = N_Step1 + 1; i <= N_Step2; i++)
            {
                var refEph = Eph_Ref[i].Slice(0, 2);
                Max_J20   = max(Norm(Eph_J20[i].Slice(0, 2) - refEph), Max_J20);
                Max_J22   = max(Norm(Eph_J22[i].Slice(0, 2) - refEph), Max_J22);
                Max_J44   = max(Norm(Eph_J44[i].Slice(0, 2) - refEph), Max_J44);
                Max_J1010 = max(Norm(Eph_J1010[i].Slice(0, 2) - refEph), Max_J1010);
                Max_Sun   = max(Norm(Eph_Sun[i].Slice(0, 2) - refEph), Max_Sun);
                Max_Moon  = max(Norm(Eph_Moon[i].Slice(0, 2) - refEph), Max_Moon);
                Max_SRad  = max(Norm(Eph_SRad[i].Slice(0, 2) - refEph), Max_SRad);
                Max_Drag  = max(Norm(Eph_Drag[i].Slice(0, 2) - refEph), Max_Drag);
            }
            ;

            // Output
            info = "  Maximum position errors within ";
            Console.Write(info);
            info  = String.Format("{0, 8:F}", N_Step2 * Step / 60.0);
            info += " min propagation interval " + "\r\n";
            info += "    J2,0    J2,2    J4,4  J10,10" + "     Sun    Moon  SolRad    Drag" + "\r\n";
            info += "     [m]     [m]     [m]     [m]" + "     [m]     [m]     [m]     [m]";
            Console.WriteLine(info);
            info = String.Format("{0, 8:F}{1, 8:F}{2, 8:F}{3, 8:F}{4, 8:F}{5, 8:F}{6, 8:F}{7, 8:F}", Max_J20, Max_J22, Max_J44, Max_J1010, Max_Sun, Max_Moon, Max_SRad, Max_Drag);
            Console.WriteLine(info);
            Console.WriteLine();

            // Epoch state (geostationary satellite)
            Kep = new Vector(42166.0e3, 0.0004, 0.02 * OrbitConsts.RadPerDeg, 0.0, 0.0, 0.0);
            Y0  = Kepler.State(OrbitConsts.GM_Earth, Kep, 0.0);

            // Model parameters
            Aux_ref.Area = 10.0;    // [m^2]  Geostationary satellite

            // Reference orbit
            Step    = 1200.0; // [s]
            N_Step1 = 72;     // 1 day
            N_Step2 = 144;    // 2 days

            Aux = Aux_ref;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_Ref);

            // J2,0 perturbations
            Aux.MaxDegree = 2; Aux.MaxOrder = 0;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_J20);

            // J2,2 perturbations
            Aux.MaxDegree = 2; Aux.MaxOrder = 2;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_J22);

            // J4,4 perturbations
            Aux.MaxDegree = 4; Aux.MaxOrder = 4;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_J44);

            // J10,10 perturbations
            Aux.MaxDegree = 10; Aux.MaxOrder = 10;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_J1010);
            Aux.MaxDegree = 20; Aux.MaxOrder = 20;

            // Solar perturbations
            Aux.EnableSun = false;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_Sun);
            Aux.EnableSun = true;

            // Lunar perturbations
            Aux.EnableMoon = false;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_Moon);
            Aux.EnableMoon = true;

            // Solar radiation pressure perturbations
            Aux.EnableSolarRadiation = false;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_SRad);
            Aux.EnableSolarRadiation = true;

            // Drag perturbations
            Aux.EnableDrag = false;
            Ephemeris(Y0, N_Step2, Step, Aux, Eph_Drag);
            Aux.EnableDrag = true;

            // Find maximum over N_Step1 steps

            Max_J20 = Max_J22 = Max_J44 = Max_J1010 = Max_Sun = Max_Moon = Max_SRad = Max_Drag = 0.0;
            for (i = 0; i <= N_Step1; i++)
            {
                var refEph = Eph_Ref[i].Slice(0, 2);
                Max_J20   = max(Norm(Eph_J20[i].Slice(0, 2) - refEph), Max_J20);
                Max_J22   = max(Norm(Eph_J22[i].Slice(0, 2) - refEph), Max_J22);
                Max_J44   = max(Norm(Eph_J44[i].Slice(0, 2) - refEph), Max_J44);
                Max_J1010 = max(Norm(Eph_J1010[i].Slice(0, 2) - refEph), Max_J1010);
                Max_Sun   = max(Norm(Eph_Sun[i].Slice(0, 2) - refEph), Max_Sun);
                Max_Moon  = max(Norm(Eph_Moon[i].Slice(0, 2) - refEph), Max_Moon);
                Max_SRad  = max(Norm(Eph_SRad[i].Slice(0, 2) - refEph), Max_SRad);
                Max_Drag  = max(Norm(Eph_Drag[i].Slice(0, 2) - refEph), Max_Drag);
            }
            ;

            // Output
            // Output
            info  = "Geostationary satellite: " + "\r\n";
            info += "  Maximum position errors within ";
            Console.Write(info);
            info  = String.Format("{0, 8:F}", N_Step1 * Step / 60.0);
            info += " min propagation interval " + "\r\n";
            info += "    J2,0    J2,2    J4,4  J10,10" + "     Sun    Moon  SolRad    Drag" + "\r\n";
            info += "     [m]     [m]     [m]     [m]" + "     [m]     [m]     [m]     [m]";
            Console.WriteLine(info);
            info = String.Format("{0, 8:F}{1, 8:F}{2, 8:F}{3, 8:F}{4, 8:F}{5, 8:F}{6, 8:F}{7, 8:F}", Max_J20, Max_J22, Max_J44, Max_J1010, Max_Sun, Max_Moon, Max_SRad, Max_Drag);
            Console.WriteLine(info);
            Console.WriteLine();

            // Find maximum over N_Step2 steps

            for (i = N_Step1 + 1; i <= N_Step2; i++)
            {
                var refEph = Eph_Ref[i].Slice(0, 2);
                Max_J20   = max(Norm(Eph_J20[i].Slice(0, 2) - refEph), Max_J20);
                Max_J22   = max(Norm(Eph_J22[i].Slice(0, 2) - refEph), Max_J22);
                Max_J44   = max(Norm(Eph_J44[i].Slice(0, 2) - refEph), Max_J44);
                Max_J1010 = max(Norm(Eph_J1010[i].Slice(0, 2) - refEph), Max_J1010);
                Max_Sun   = max(Norm(Eph_Sun[i].Slice(0, 2) - refEph), Max_Sun);
                Max_Moon  = max(Norm(Eph_Moon[i].Slice(0, 2) - refEph), Max_Moon);
                Max_SRad  = max(Norm(Eph_SRad[i].Slice(0, 2) - refEph), Max_SRad);
                Max_Drag  = max(Norm(Eph_Drag[i].Slice(0, 2) - refEph), Max_Drag);
            }
            ;

            // Output
            info = "  Maximum position errors within ";
            Console.Write(info);
            info  = String.Format("{0, 8:F}", N_Step2 * Step / 60.0);
            info += " min propagation interval " + "\r\n";
            info += "    J2,0    J2,2    J4,4  J10,10" + "     Sun    Moon  SolRad    Drag" + "\r\n";
            info += "     [m]     [m]     [m]     [m]" + "     [m]     [m]     [m]     [m]";
            Console.WriteLine(info);
            info = String.Format("{0, 8:F}{1, 8:F}{2, 8:F}{3, 8:F}{4, 8:F}{5, 8:F}{6, 8:F}{7, 8:F}", Max_J20, Max_J22, Max_J44, Max_J1010, Max_Sun, Max_Moon, Max_SRad, Max_Drag);
            Console.WriteLine(info);
            Console.WriteLine();


            Console.ReadKey();
        }