/// <summary> /// This is an aproximation of the mean velocity of an orbit. /// </summary> /// <returns>The orbital velocity in au.</returns> /// <param name="orbit">Orbit.</param> public static double MeanOrbitalVelocityInAU(OrbitDB orbit) { double a = orbit.SemiMajorAxis_AU; double b = EllipseMath.SemiMinorAxis(a, orbit.Eccentricity); double orbitalPerodSeconds = orbit.OrbitalPeriod.TotalSeconds; double peremeter = Math.PI * (3 * (a + b) - Math.Sqrt((3 * a + b) * (a + 3 * b))); return(peremeter / orbitalPerodSeconds); }
private const double Epsilon = 1.0e-15; //TODO: test how low we can go /// <summary> /// Kepler elements from velocity and position. /// Note, to get correct results ensure all Sgp, position, and velocity values are all in the same type (ie meters, km, or AU) /// </summary> /// <returns>a struct of Kepler elements.</returns> /// <param name="standardGravParam">Standard grav parameter.</param> /// <param name="position">Position ralitive to parent</param> /// <param name="velocity">Velocity ralitive to parent</param> public static KeplerElements KeplerFromPositionAndVelocity(double standardGravParam, Vector3 position, Vector3 velocity, DateTime epoch) { KeplerElements ke = new KeplerElements(); Vector3 angularVelocity = Vector3.Cross(position, velocity); Vector3 nodeVector = Vector3.Cross(new Vector3(0, 0, 1), angularVelocity); Vector3 eccentVector = EccentricityVector(standardGravParam, position, velocity); double eccentricity = eccentVector.Length(); double specificOrbitalEnergy = Math.Pow(velocity.Length(), 2) * 0.5 - standardGravParam / position.Length(); double semiMajorAxis; double p; //p is where the ellipse or hypobola crosses a line from the focal point 90 degrees from the sma if (Math.Abs(eccentricity) > 1) //hypobola { semiMajorAxis = -(-standardGravParam / (2 * specificOrbitalEnergy)); //in this case the sma is negitive p = semiMajorAxis * (1 - eccentricity * eccentricity); } else if (Math.Abs(eccentricity) < 1) //ellipse { semiMajorAxis = -standardGravParam / (2 * specificOrbitalEnergy); p = semiMajorAxis * (1 - eccentricity * eccentricity); } else //parabola { p = angularVelocity.Length() * angularVelocity.Length() / standardGravParam; semiMajorAxis = double.MaxValue; } double semiMinorAxis = EllipseMath.SemiMinorAxis(semiMajorAxis, eccentricity); double linierEccentricity = eccentricity * semiMajorAxis; double inclination = Math.Acos(angularVelocity.Z / angularVelocity.Length()); //should be 0 in 2d. or pi if counter clockwise orbit. if (double.IsNaN(inclination)) { inclination = 0; } double longdOfAN = CalculateLongitudeOfAscendingNode(nodeVector); double trueAnomaly = TrueAnomaly(eccentVector, position, velocity); double argOfPeriaps = GetArgumentOfPeriapsis2(position, inclination, longdOfAN, trueAnomaly); var meanMotion = Math.Sqrt(standardGravParam / Math.Pow(semiMajorAxis, 3)); double eccentricAnomoly = GetEccentricAnomalyFromTrueAnomaly(trueAnomaly, eccentricity); var meanAnomaly = GetMeanAnomaly(eccentricity, eccentricAnomoly); ke.SemiMajorAxis = semiMajorAxis; ke.SemiMinorAxis = semiMinorAxis; ke.Eccentricity = eccentricity; ke.Apoapsis = EllipseMath.Apoapsis(eccentricity, semiMajorAxis); ke.Periapsis = EllipseMath.Periapsis(eccentricity, semiMajorAxis); ke.LinierEccentricity = EllipseMath.LinierEccentricity(ke.Apoapsis, semiMajorAxis); ke.LoAN = longdOfAN; ke.AoP = argOfPeriaps; ke.Inclination = inclination; ke.MeanMotion = meanMotion; ke.MeanAnomalyAtEpoch = meanAnomaly; ke.TrueAnomalyAtEpoch = trueAnomaly; ke.Epoch = epoch; //TimeFromPeriapsis(semiMajorAxis, standardGravParam, meanAnomaly); //Epoch(semiMajorAxis, semiMinorAxis, eccentricAnomoly, OrbitalPeriod(standardGravParam, semiMajorAxis)); return(ke); }