001    /*
002     * This file is part of McIDAS-V
003     *
004     * Copyright 2007-2013
005     * Space Science and Engineering Center (SSEC)
006     * University of Wisconsin - Madison
007     * 1225 W. Dayton Street, Madison, WI 53706, USA
008     * https://www.ssec.wisc.edu/mcidas
009     * 
010     * All Rights Reserved
011     * 
012     * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013     * some McIDAS-V source code is based on IDV and VisAD source code.  
014     * 
015     * McIDAS-V is free software; you can redistribute it and/or modify
016     * it under the terms of the GNU Lesser Public License as published by
017     * the Free Software Foundation; either version 3 of the License, or
018     * (at your option) any later version.
019     * 
020     * McIDAS-V is distributed in the hope that it will be useful,
021     * but WITHOUT ANY WARRANTY; without even the implied warranty of
022     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023     * GNU Lesser Public License for more details.
024     * 
025     * You should have received a copy of the GNU Lesser Public License
026     * along with this program.  If not, see http://www.gnu.org/licenses.
027     */
028    // Shawn E. Gano
029    // Kepler routines
030    /**
031     * =====================================================================
032     * Copyright (C) 2009 Shawn E. Gano
033     * 
034     * This file is part of JSatTrak.
035     * 
036     * JSatTrak is free software: you can redistribute it and/or modify
037     * it under the terms of the GNU Lesser General Public License as published by
038     * the Free Software Foundation, either version 3 of the License, or
039     * (at your option) any later version.
040     * 
041     * JSatTrak is distributed in the hope that it will be useful,
042     * but WITHOUT ANY WARRANTY; without even the implied warranty of
043     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
044     * GNU Lesser General Public License for more details.
045     * 
046     * You should have received a copy of the GNU Lesser General Public License
047     * along with JSatTrak.  If not, see <http://www.gnu.org/licenses/>.
048     * =====================================================================
049     */
050    package edu.wisc.ssec.mcidasv.data.adde.sgp4;
051    
052    //import jsattrak.utilities.StateVector;
053    
054    public class Kepler
055    {
056            
057        /**
058         *  Overload for state
059         * @param GM Gravitational coefficient (gravitational constant * mass of central body)
060         * @param kepElements Keplarian elements (see other state function)
061         * @param dt Time since epoch (seconds?)
062         * @return State vector (x,y,z,vx,vy,vz)
063         */
064    /*
065        public static double[] state(double GM, double[] kepElements, double dt)
066        {
067            return state(GM, kepElements[0], kepElements[1],kepElements[2], kepElements[3], kepElements[4], kepElements[5], dt);
068        }
069    */    
070        /**
071         * Computes the satellite state vector from osculating Keplerian elements for elliptic orbits
072         * <p>Notes:
073         * <br> The semimajor axis a=Kep(0), dt and GM must be given in consistent units,
074         *      e.g. [m], [s] and [m^3/s^2]. The resulting units of length and velocity
075         *      are implied by the units of GM, e.g. [m] and [m/s].
076         *
077         * @param GM Gravitational coefficient (gravitational constant * mass of central body)
078         * @param a Semimajor axis
079         * @param e Eccentricity
080         * @param i Inclination [rad]
081         * @param Omega Longitude of the ascending node [rad] or is this RAAN? (I think it is RAAN)
082         * @param omega Argument of pericenter [rad]
083         * @param M0 Mean anomaly at epoch [rad]
084         * @param dt Time since epoch (seconds?)
085         * @return State vector (x,y,z,vx,vy,vz)
086         */
087    /*
088            public static double[] state(double GM, double a, double e, double i, double Omega, double omega, double M0, double dt)
089            {
090                    double M; // mean anomaly
091                    double n;
092                    double E, cosE, sinE; // eccentric anomaly
093                    double fac, R, V;
094    
095                    // vectors for position (r) and velocity (v)
096                    double[] r = new double[3];
097                    double[] v = new double[3];
098                    double[] state = new double[6]; // full state
099    
100                    // transformation matrices
101                    double[][] Rx = new double[3][3];
102                    // double[][] Ry = new double[3][3];
103                    double[][] Rz = new double[3][3];
104    
105                    // rotation matrix
106                    double[][] PQW = new double[3][3];
107    
108                    // Mean anomaly
109                    if (dt == 0.0)
110                    {
111                            M = M0;
112                    } else
113                    {
114                            n = Math.sqrt(GM / (a * a * a));
115                            M = M0 + n * dt;
116                    }
117    
118                    // Eccentric anomaly
119                    E = EccAnom(M, e);
120                    cosE = Math.cos(E);
121                    sinE = Math.sin(E);
122    
123                    // Perifocal coordinates
124                    fac = Math.sqrt((1.0 - e) * (1.0 + e));
125    
126                    R = a * (1.0 - e * cosE); // Distance
127                    V = Math.sqrt(GM * a) / R; // Velocity
128    
129                    // r
130                    r[0] = a * (cosE - e);
131                    r[1] = a * fac * sinE;
132                    r[2] = 0.0;
133    
134                    // v
135                    v[0] = -V * sinE;
136                    v[1] = +V * fac * cosE;
137                    v[2] = 0.0;
138    
139                    // Transformation to reference system (Gaussian vectors)
140                    Rx = MathUtils.R_x(-i);
141                    Rz = MathUtils.R_z(-Omega);
142    
143                    // PQW = R_z(-Omega) * R_x(-i) * R_z(-omega);
144                    PQW = MathUtils.mult(Rz, Rx);
145                    Rz = MathUtils.R_z(-omega);
146                    PQW = MathUtils.mult(PQW, Rz);
147    
148                    r = MathUtils.mult(PQW, r);
149                    v = MathUtils.mult(PQW, v);
150    
151                    // State vector
152                    state[0] = r[0];
153                    state[1] = r[1];
154                    state[2] = r[2];
155                    state[3] = v[0];
156                    state[4] = v[1];
157                    state[5] = v[2];
158    
159                    // return Stack(r,v);
160                    return state;
161    
162            } // state
163    */
164    
165        /**
166         * Computes the eccentric anomaly for elliptic orbits
167         *
168         * @param M Mean anomaly in [rad]
169         * @param e Eccentricity of the orbit [0,1]
170         * @return Eccentric anomaly in [rad]
171         */
172    /*
173            public static double EccAnom(double M, double e)
174            {
175    
176                    // Constants
177                    final int maxit = 15;
178                    final double eps = 100.0 * 2.22E-16; // JAVA FIND MACHINE PRECISION // 100.0*eps_mach
179    
180                    // Variables
181    
182                    int i = 0;
183                    double E, f;
184    
185                    // Starting value
186                    M = MathUtils.Modulo(M, 2.0 * Math.PI);
187                    if (e < 0.8)
188                            E = M;
189                    else
190                            E = Math.PI;
191    
192                    // Iteration
193                    do
194                    {
195                            f = E - e * Math.sin(E) - M;
196                            E = E - f / (1.0 - e * Math.cos(E));
197                            ++i;
198                            if (i == maxit)
199                            {
200                                    System.out.println(" convergence problems in EccAnom\n");
201                                    break;
202                            }
203                    } while (Math.abs(f) > eps);
204    
205                    return E;
206    
207            } // EccAnom
208    */
209            
210            /**
211             * Computes the osculating Keplerian elements from the satellite state vector for elliptic orbits for Earth
212             * @param StateVector j2K cartesian state vector object (t,x,y,z,dx,dy,dz)
213             * @return Keplerian elements (a,e,i,Omega,omega,M) see state function for element definitions
214             */
215    /*
216            public static double[] SingularOsculatingElementsEarth( StateVector state )
217            { 
218                double[] r = new double[] {state.state[1],state.state[2],state.state[3]};
219                double[] v = new double[] {state.state[4],state.state[5],state.state[6]};
220                
221                return SingularOsculatingElements( AstroConst.GM_Earth, r, v );
222            }
223    */       
224            /**
225             * Computes the osculating Keplerian elements from the satellite state vector for elliptic orbits
226             * @param GM Gravitational coefficient (gravitational constant * mass of central body)
227             * @param state j2K cartesian state vector (x,y,z,dx,dy,dz)
228             * @return Keplerian elements (a,e,i,Omega,omega,M) see state function for element definitions
229             */
230    /*
231            public static double[] SingularOsculatingElements( double GM, double[] state )
232            { 
233                double[] r = new double[] {state[0],state[1],state[2]};
234                double[] v = new double[] {state[3],state[4],state[5]};
235                
236                return SingularOsculatingElements( GM, r, v );
237            }
238    */        
239        /**
240         * Computes the osculating Keplerian elements from the satellite state vector for elliptic orbits
241         *
242         * @param GM Gravitational coefficient (gravitational constant * mass of central body)
243         * @param r State vector (x,y,z)
244         * @param v State vector (vx,vy,vz)
245         * @return Keplerian elements (a,e,i,Omega,omega,M) see state function for element definitions
246         */
247    /*
248            public static double[] SingularOsculatingElements( double GM, double[] r, double[] v )
249            { 
250                // Variables
251                
252                double[] h = new double[3];
253                double  H, u, R;
254                double  eCosE, eSinE, e2, E, nu;
255                double  a,e,i,Omega,omega,M;
256                            
257                h = MathUtils.cross(r,v);                         // Areal velocity
258                H = MathUtils.norm(h);
259                
260                Omega = Math.atan2( h[0], -h[1] );                     // Long. ascend. node
261                Omega = Omega % (Math.PI*2.0);
262                i     = Math.atan2( Math.sqrt(h[0]*h[0]+h[1]*h[1]), h[2] ); // Inclination
263                u     = Math.atan2( r[2]*H, -r[0]*h[1]+r[1]*h[0] );    // Arg. of latitude
264                
265                R  = MathUtils.norm(r);                                      // Distance
266                
267                //System.out.println("R="+R);
268                //System.out.println("v dot v="+(MathUtils.dot(v,v)));
269                //System.out.println("GM="+GM);
270                
271                a = 1.0 / (2.0/R-MathUtils.dot(v,v)/GM);                     // Semi-major axis
272                
273                eCosE = 1.0-R/a;                                   // e*cos(E)
274                eSinE = MathUtils.dot(r,v)/Math.sqrt(GM*a);                       // e*sin(E)
275                
276                e2 = eCosE*eCosE +eSinE*eSinE;
277                e  = Math.sqrt(e2);                                     // Eccentricity
278                E  = Math.atan2(eSinE,eCosE);                           // Eccentric anomaly
279                
280                M  = (E-eSinE)%(2.0*Math.PI);                          // Mean anomaly
281                
282                nu = Math.atan2(Math.sqrt(1.0-e2)*eSinE, eCosE-e2);          // True anomaly
283                
284                omega = (u-nu)%(2.0*Math.PI);                          // Arg. of perihelion
285                
286                // Keplerian elements vector
287                
288                //System.out.println("Real a = " + a);
289                
290                return (new double[] {a,e,i,Omega,omega,M});
291            } // SingularElements
292    */
293            
294        /**
295         * calculate oculating orbital period of a eliptical orbit from position and velocity
296         *
297         * @param GM Gravitational coefficient (gravitational constant * mass of central body)
298         * @param r State vector (x,y,z)
299         * @param v State vector (vx,vy,vz)
300         * @return oculating orbital period
301         */
302            public static double CalculatePeriod( double GM, double[] r, double[] v )
303            { 
304                double R  = MathUtils.norm(r); // current radius 
305                
306                double a = 1.0 / (2.0/R-MathUtils.dot(v,v)/GM);                     // Semi-major axis
307                
308                return ( 2.0*Math.PI*Math.sqrt(a*a*a/GM) );
309            } // CalculatePeriod
310    
311    } // Kepler