Exemplo n.º 1
0
        /// <summary>
        /// 构造函数(注意单位的一致性)
        /// </summary>
        /// <param name="t0">初始时刻(s),没有多大意义</param>
        /// <param name="elements">初始轨道根数</param>
        /// <param name="j2UnnormalizedValue">J2项系数</param>
        /// <param name="referenceDistance">参考椭球体半长轴</param>
        public J2NumericalPropagator(double t0, KeplerianElements elements, double j2UnnormalizedValue, double referenceDistance)
            : this(elements.GravitationalParameter, j2UnnormalizedValue, referenceDistance)
        {
            this.T0 = t0;

            //  初始位置、速度
            InitialCondition = elements.ToCartesian();
        }
Exemplo n.º 2
0
        /// <summary>
        /// Propagate a Platform using a NumericalPropagator configured with the entered KeplerianElements,
        /// ForceModels, NumericalIntegrator, and start and stop dates.
        /// </summary>
        private void PropagateSatellite()
        {
            KeplerianElements orbitalElements = m_keplerianOrbitalElementsEntry.KeplerianElementValues;

            if (orbitalElements == null)
            {
                return;
            }

            Motion <Cartesian>        initialMotion = orbitalElements.ToCartesian();
            PropagationNewtonianPoint point         = new PropagationNewtonianPoint(m_elementID, m_forceModelSettings.CurrentCentralBody.InertialFrame, initialMotion.Value, initialMotion.FirstDerivative);

            point.Mass = new ScalarFixed(double.Parse(m_mass.Text));
            m_forceModelSettings.SetForceModelsOnPoint(point, new ScalarFixed(double.Parse(m_area.Text)));
            CentralBody primaryCentralBody = m_forceModelSettings.CurrentCentralBody;

            NumericalPropagatorDefinition state = new NumericalPropagatorDefinition();

            state.IntegrationElements.Add(point);
            state.Integrator = m_integratorSettings.GetIntegrator();

            JulianDate start = new JulianDate(GregorianDate.ParseExact(m_start.Text, DateFormat, null));
            JulianDate end   = new JulianDate(GregorianDate.ParseExact(m_end.Text, DateFormat, null));

            state.Epoch = start;
            NumericalPropagator propagator = state.CreatePropagator();

            propagator.StepTaken += (sender, args) =>
            {
                // Telling the propagator to stop if we get too close to the central body
                Cartesian position = propagator.Converter.ConvertState <Cartesian>(m_elementID, args.CurrentState).Value;
                if (position.Magnitude <= primaryCentralBody.Shape.SemimajorAxisLength + 10000)
                {
                    args.Indication = PropagationEventIndication.StopPropagationAfterStep;
                }
            };

            DateMotionCollection <Cartesian> answer = null;

            var backgroundCalculation = new BackgroundCalculation();

            backgroundCalculation.DoWork += (sender, e) =>
            {
                // actually propagate
                var result = propagator.Propagate(end.Subtract(start), 1, backgroundCalculation);
                answer = result.GetDateMotionCollection <Cartesian>(m_elementID);
            };
            backgroundCalculation.ProgressChanged    += (sender, e) => m_propagationProgress.Value = e.ProgressPercentage;
            backgroundCalculation.RunWorkerCompleted += (sender, e) =>
            {
                // when finished, draw the satellite
                DrawSatellite(answer, primaryCentralBody.InertialFrame);
                m_propagate.Enabled = true;
            };

            m_propagate.Enabled = false;
            backgroundCalculation.RunWorkerAsync();
        }
Exemplo n.º 3
0
        /// <summary>
        /// 计算两轨道面夹角、北半球交线的纬度幅角
        /// </summary>
        /// <param name="element1"></param>
        /// <param name="element2"></param>
        /// <param name="u1"></param>
        /// <param name="u2"></param>
        /// <param name="theta"></param>
        public static void TwoOrbitPlaneIntersection(KeplerianElements element1, KeplerianElements element2, out double u1, out double u2, out double theta)
        {
            double inc1  = element1.Inclination;
            double inc2  = element2.Inclination;
            double raan1 = element1.RightAscensionOfAscendingNode;
            double raan2 = element2.RightAscensionOfAscendingNode;

            TwoOrbitPlaneIntersection(inc1, inc2, raan1, raan2, out u1, out u2, out theta);
        }
Exemplo n.º 4
0
        /// <summary>
        /// kepler根数TA对应的r,V,theta的转换(注意参数单位统一)
        /// </summary>
        /// <param name="elements">kepler根数</param>
        /// <param name="r">地心距</param>
        /// <param name="V">速度</param>
        /// <param name="theta">水平飞行路径角(rad)</param>
        public static void KeplerElements2rvtheta(KeplerianElements elements, out double r, out double v, out double theta)
        {
            double a  = elements.SemimajorAxis;
            double e  = elements.Eccentricity;
            double f  = elements.TrueAnomaly;
            double Gm = elements.GravitationalParameter;

            r     = a * (1 - e * e) / (1 + e * Math.Cos(f));
            v     = Math.Sqrt(Gm * (1 + 2 * e * Math.Cos(f) + e * e) / a / (1 - e * e));
            theta = Math.Asin(e * Math.Sin(f) / Math.Sqrt(1 + 2 * e * Math.Cos(f) + e * e));
        }
Exemplo n.º 5
0
        /// <summary>
        /// 计算真近点角从f1飞行到f2的时间(f1,f2的区间在[0,2*pi]),f1沿逆时针飞行到f2
        /// </summary>
        /// <param name="f1">初始真近点角(rad)</param>
        /// <param name="f2">终点真近点角(rad)</param>
        /// <param name="sma">半长轴</param>
        /// <param name="ecc">偏心率</param>
        /// <param name="mu">引力常数</param>
        /// <returns></returns>
        public static double ComputeTimeOfFlight(double f1, double f2, double sma, double ecc, double mu)
        {
            double dt = KeplerianElements.ComputeTimeOfFlight(Round0_2Pi(f1), Round0_2Pi(f2), sma, ecc, mu);

            if (dt < 0)
            {
                dt = KeplerianElements.SemimajorAxisToPeriod(sma, mu) + dt;
            }

            return(dt);
        }
        /// <summary>
        /// 计算Dt时间后的平均根数(RAAN,omg,M考虑一阶长期项,RAAN考虑二阶长期项)
        /// </summary>
        /// <param name="dt">一段时间(s)</param>
        /// <returns></returns>
        public KeplerianElements ComputeMeanElementAfterDt(double dt)
        {
            //  无量纲时间
            dt = dt / unitT;

            double RAANt = Round2Pi(RAAN + (RAANdot + RAANdot2) * dt);
            double omgt = Round2Pi(omg + omgdot * dt);
            double mat = Round2Pi(ma + (n + madot) * dt);
            double tat = KeplerianElements.MeanAnomalyToTrueAnomaly(mat, ecc);

            //  返回dt时间后的平均根数
            return new KeplerianElements(sma * Re, ecc, inc, omgt, RAANt, tat, Mu);
        }
Exemplo n.º 7
0
 public static OrbitModKep ToModKep(KeplerianElements elements, double mu)
 {
     return OrbitModKep.OrbitMK(
         elements.p,
         elements.ecc,
         elements.inc / 180.0 * OrbMath.PI,
         elements.argPe / 180.0 * OrbMath.PI,
         elements.raan / 180.0 * OrbMath.PI,
         elements.ta0 / 180.0 * OrbMath.PI,
         elements.t0,
         mu
     );
 }
Exemplo n.º 8
0
        public static void testTimeOfFlight()
        {
            double mu  = 3.986004418e5;
            double sma = 7078.14;
            double ecc = 0.1;
            double f1  = 0.0;
            double f2  = Math.PI * 2.0;

            double t0  = ComputeTimeOfFlight(f1, f2, sma, ecc, mu);
            double t1  = ComputeTimeOfFlight(0, 2.0, sma, ecc, mu);
            double t2  = ComputeTimeOfFlight(-2.0, 0, sma, ecc, mu);
            double t2p = KeplerianElements.ComputeTimeOfFlight(-2.0, 0, sma, ecc, mu);
            double T   = KeplerianElements.SemimajorAxisToPeriod(sma, mu);
        }
Exemplo n.º 9
0
        /// <summary>
        /// 求解Dt时间后的轨道根数
        /// </summary>
        /// <param name="elem0">初始轨道根数</param>
        /// <param name="dt">时间</param>
        /// <returns></returns>
        public static KeplerianElements KeplerElementsAfterDt(KeplerianElements elem0, double dt)
        {
            //double M0 = elem0.ComputeMeanMotion();
            //double Mt = M0 + elem0.ComputeMeanMotion() * dt;
            double t0 = KeplerianElements.ComputeTimePastPeriapsis(elem0.TrueAnomaly, elem0.SemimajorAxis, elem0.Eccentricity, elem0.GravitationalParameter);
            double ta = KeplerianElements.TimePastPeriapsisToTrueAnomaly(t0 + dt, elem0.SemimajorAxis, elem0.Eccentricity, elem0.GravitationalParameter);

            return(new KeplerianElements(elem0.SemimajorAxis,
                                         elem0.Eccentricity,
                                         elem0.Inclination,
                                         elem0.ArgumentOfPeriapsis,
                                         elem0.RightAscensionOfAscendingNode,
                                         ta,
                                         elem0.GravitationalParameter));
        }
Exemplo n.º 10
0
        //#########################################################################################
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="elements">初始轨道根数(平瞬根数由inputIsMean决定)</param>
        /// <param name="inputIsMean">true:平均根数;false:瞬时根数</param>
        /// <param name="j2UnnormalizedValue">未归一化的J2项系数</param>
        /// <param name="referenceDistance">参考半径(与elements单位一致)</param>
        public J2MeanElements(KeplerianElements elements, bool inputIsMean, double j2UnnormalizedValue, double referenceDistance)
        {
            Name = "DefaultName";

            Mu = elements.GravitationalParameter;
            J2 = j2UnnormalizedValue;
            Re = referenceDistance;
            unitT = Math.Sqrt(Re * Re * Re / Mu);

            //  保留初始输入的根数
            InitialElement = elements;

            //  利用kozai方法计算平均根数
            KozaiIzsakMeanElements kozaiElement = new KozaiIzsakMeanElements(elements, inputIsMean, j2UnnormalizedValue, referenceDistance);

            //  初始平均根数(Kozai)
            KozaiMeanElement = kozaiElement.ToMeanKeplerianElements();

            this.sma = KozaiMeanElement.SemimajorAxis / Re;
            this.ecc = KozaiMeanElement.Eccentricity;
            this.inc = KozaiMeanElement.Inclination;
            this.RAAN = KozaiMeanElement.RightAscensionOfAscendingNode;
            this.omg = KozaiMeanElement.ArgumentOfPeriapsis;
            this.ma = KozaiMeanElement.ComputeMeanAnomaly();

            //  计算长期项
            //  以下公式皆为无量纲
            double A2 = 1.5 * J2;
            double sini2 = Math.Sin(inc) * Math.Sin(inc);
            double sq1e2 = Math.Sqrt(1.0 - ecc * ecc);
            double p2 = sma * sma * (1.0 - ecc * ecc) * (1.0 - ecc * ecc);

            n = Math.Sqrt(1.0 / sma / sma / sma);

            //  平近点角的一阶长期项
            madot = A2 / p2 * n * (1 - 1.5 * sini2) * sq1e2;
            //  RAAN和Argument Of Periapse的一阶长期项
            RAANdot = -A2 / p2 * n * Math.Cos(inc);
            omgdot = A2 / p2 * n * (2 - 2.5 * sini2);
            //  RAAN的二阶长期项
            RAANdot2 = -A2 * A2 / p2 / p2 * n * Math.Cos(inc) * ((1.5 + ecc * ecc / 6.0 + sq1e2) - (5.0 / 3.0 - 5.0 * ecc * ecc / 24.0 + 1.5 * sq1e2) * sini2);
        }
Exemplo n.º 11
0
        public static void TestLamber1()
        {
            double Gm  = 3.986e14;
            double sma = 7000000;
            double ecc = 0.09956;
            double f1  = 0.0;
            double f2  = Math.PI;
            //double f2 = 1.0;
            //double f2 = 5.0;
            KeplerianElements k1 = new KeplerianElements(sma, ecc, 0.2, 0.4, 1.0, f1, Gm);
            KeplerianElements k2 = new KeplerianElements(sma, ecc, 0.2, 0.4, 1.0, f2, Gm);

            double tof = KeplerianElements.ComputeTimeOfFlight(f1, f2, sma, ecc, Gm);

            Motion <Cartesian> rv1 = k1.ToCartesian();
            Motion <Cartesian> rv2 = k2.ToCartesian();

            Cartesian v1p, v2p;

            Lambert_RhGooding(Gm, rv1.Value, rv1.FirstDerivative, rv2.Value, rv2.FirstDerivative, tof, out v1p, out v2p);

            Cartesian dv1 = v1p - rv1.FirstDerivative;
            Cartesian dv2 = v2p - rv2.FirstDerivative;
        }
Exemplo n.º 12
0
 /// <summary>
 /// 构造函数
 /// </summary>
 /// <param name="elements">初始轨道根数(平瞬根数由inputIsMean决定)</param>
 /// <param name="inputIsMean">true:平均根数;false:瞬时根数</param>
 /// <param name="j2UnnormalizedValue">未归一化的J2项系数</param>
 /// <param name="referenceDistance">参考半径(与elements单位一致)</param>
 /// <param name="name">名称</param>
 public J2MeanElements(KeplerianElements elements, bool inputIsMean, double j2UnnormalizedValue, double referenceDistance, string name)
     : this(elements, inputIsMean, j2UnnormalizedValue, referenceDistance)
 {
     Name = name;
 }
Exemplo n.º 13
0
        private static KeplerianElements stateVectorToKeplerian(Vector3d position, Vector3d velocity, double mu)
        {
            // Work in units of km and seconds
            var r = position * UiTools.KilometersPerAu;
            var v = velocity / 86400.0 * UiTools.KilometersPerAu;

            var rmag = r.Length();
            var vmag = v.Length();

            var sma = 1.0 / (2.0 / rmag - vmag * vmag / mu);

            // h is the orbital angular momentum vector
            var h = Vector3d.Cross(r, v);

            // ecc is the eccentricity vector, which points from the
            // planet at periapsis to the center point.
            var ecc = Vector3d.Cross(v, h) / mu - r / rmag;
            var e = ecc.Length();

            h.Normalize();
            ecc.Normalize();

            // h, s, and ecc are orthogonal vectors that define a coordinate
            // system. h is normal to the orbital plane.
            var s = Vector3d.Cross(h, ecc);

            // Calculate the sine and cosine of the true anomaly
            r.Normalize();
            var cosNu = Vector3d.Dot(ecc, r);
            var sinNu = Vector3d.Dot(s, r);

            // Compute the eccentric anomaly
            var E = Math.Atan2(Math.Sqrt(1 - e * e) * sinNu, e + cosNu);

            // Mean anomaly not required
            // double M = E - e * Math.Sin(E);

            var elements = new KeplerianElements();

            // Create a rotation matrix given the three orthogonal vectors:
            //   ecc - eccentricity vector
            //   s   - in the orbital plane, perpendicular to ecc
            //   h   - angular momentum vector, normal to orbital plane
            elements.orientation = new Matrix3d(ecc.X, ecc.Y, ecc.Z, 0.0,
                                                s.X, s.Y, s.Z, 0.0,
                                                h.X, h.Y, h.Z, 0.0,
                                                0.0, 0.0, 0.0, 1.0);
            elements.a = sma;
            elements.e = e;
            elements.E = E;

            return elements;
        }
Exemplo n.º 14
0
        private static void DrawSingleOrbit(RenderContext11 renderContext, int eclipticColor, int id, Vector3d centerPoint, double xstartAngle, Vector3d planetNow, KeplerianElements el)
        {
            double scaleFactor;
            switch (id)
            {
                case (int)SolarSystemObjects.Moon:
                    if (Settings.Active.SolarSystemScale > 1)
                        scaleFactor = Settings.Active.SolarSystemScale / 2;
                    else
                        scaleFactor = 1.0;
                    break;

                case (int)SolarSystemObjects.Io:
                case (int)SolarSystemObjects.Europa:
                case (int)SolarSystemObjects.Ganymede:
                case (int)SolarSystemObjects.Callisto:
                    scaleFactor = Settings.Active.SolarSystemScale;
                    break;

                default:
                    scaleFactor = 1.0;
                    break;
            }

            var translation = -centerPoint;
            if (id == (int)SolarSystemObjects.Moon)
            {
                translation += planet3dLocations[(int)SolarSystemObjects.Earth];
            }
            else if (id == (int)SolarSystemObjects.Io || id == (int)SolarSystemObjects.Europa || id == (int)SolarSystemObjects.Ganymede || id == (int)SolarSystemObjects.Callisto)
            {
                translation += planet3dLocations[(int)SolarSystemObjects.Jupiter];
            }

            var currentPosition = planetNow - centerPoint;
            if (orbitTraces[id] != null)
            {
                var worldMatrix = Matrix3d.Translation(translation) * renderContext.World;
                orbitTraces[id].render(renderContext, Color.FromArgb(eclipticColor), worldMatrix, jNow, currentPosition, 0.0);
            }
            else
            {
                var worldMatrix = el.orientation * Matrix3d.Translation(translation) * renderContext.World;
                EllipseRenderer.DrawEllipse(renderContext, el.a / UiTools.KilometersPerAu * scaleFactor, el.e, el.E, Color.FromArgb(eclipticColor), worldMatrix, currentPosition);
            }
        }