Пример #1
0
        /// <summary>
        /// In Meters!
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="myMass"></param>
        /// <param name="parentMass"></param>
        /// <param name="sgp_m"></param>
        /// <param name="position_m"></param>
        /// <param name="velocity_m"></param>
        /// <param name="atDateTime"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static OrbitDB FromVector(Entity parent, double myMass, double parentMass, double sgp_m, Vector3 position_m, Vector3 velocity_m, DateTime atDateTime)
        {
            if (position_m.Length() > OrbitProcessor.GetSOI_AU(parent))
            {
                throw new Exception("Entity not in target SOI");
            }
            //var sgp  = GameConstants.Science.GravitationalConstant * (myMass + parentMass) / 3.347928976e33;
            var ke = OrbitMath.KeplerFromPositionAndVelocity(sgp_m, position_m, velocity_m, atDateTime);


            OrbitDB orbit = new OrbitDB(parent)
            {
                SemiMajorAxis            = ke.SemiMajorAxis,
                Eccentricity             = ke.Eccentricity,
                Inclination              = ke.Inclination,
                LongitudeOfAscendingNode = ke.LoAN,
                ArgumentOfPeriapsis      = ke.AoP,
                MeanAnomalyAtEpoch       = ke.MeanAnomalyAtEpoch,
                Epoch = atDateTime,

                _parentMass = parent.GetDataBlob <MassVolumeDB>().Mass,
                _myMass     = myMass
            };

            orbit.CalculateExtendedParameters();

            var pos = OrbitProcessor.GetAbsolutePosition_m(orbit, atDateTime);

            return(orbit);
        }
Пример #2
0
        /// <summary>
        /// Creates on Orbit at current location from a given velocity
        /// </summary>
        /// <returns>The Orbit Does not attach the OrbitDB to the entity!</returns>
        /// <param name="parent">Parent.</param>
        /// <param name="entity">Entity.</param>
        /// <param name="velocityAU">Velocity.</param>
        public static OrbitDB FromVector(Entity parent, Entity entity, Vector3 velocityAU, DateTime atDateTime)
        {
            var parentMass = parent.GetDataBlob <MassVolumeDB>().Mass;
            var myMass     = entity.GetDataBlob <MassVolumeDB>().Mass;

            var epoch1 = parent.Manager.ManagerSubpulses.StarSysDateTime;                                      //getting epoch from here is incorrect as the local datetime doesn't change till after the subpulse.

            var parentPos = OrbitProcessor.GetAbsolutePosition_AU(parent.GetDataBlob <OrbitDB>(), atDateTime); //need to use the parent position at the epoch
            var posdb     = entity.GetDataBlob <PositionDB>();

            posdb.SetParent(parent);
            var ralitivePos = posdb.RelativePosition_AU;//entity.GetDataBlob<PositionDB>().AbsolutePosition_AU - parentPos;

            if (ralitivePos.Length() > OrbitProcessor.GetSOI(parent))
            {
                throw new Exception("Entity not in target SOI");
            }

            var sgp = GameConstants.Science.GravitationalConstant * (myMass + parentMass) / 3.347928976e33;
            var ke  = OrbitMath.KeplerFromPositionAndVelocity(sgp, ralitivePos, velocityAU, atDateTime);

            var epoch = atDateTime;// - TimeSpan.FromSeconds(ke.Epoch); //ke.Epoch is seconds from periapsis.

            OrbitDB orbit = new OrbitDB(parent, parentMass, myMass,
                                        Math.Abs(ke.SemiMajorAxis),
                                        ke.Eccentricity,
                                        Angle.ToDegrees(ke.Inclination),
                                        Angle.ToDegrees(ke.LoAN),
                                        Angle.ToDegrees(ke.AoP),
                                        Angle.ToDegrees(ke.MeanAnomalyAtEpoch),
                                        epoch);

            var pos = OrbitProcessor.GetPosition_AU(orbit, atDateTime);
            var d   = Distance.AuToKm(pos - ralitivePos).Length();

            if (d > 1)
            {
                var e = new Event(atDateTime, "Positional difference of " + d + "Km when creating orbit from velocity");
                e.Entity     = entity;
                e.SystemGuid = entity.Manager.ManagerGuid;
                e.EventType  = EventType.Opps;
                //e.Faction =  entity.FactionOwner;
                StaticRefLib.EventLog.AddEvent(e);

                //other info:
                var keta  = Angle.ToDegrees(ke.TrueAnomalyAtEpoch);
                var obta  = Angle.ToDegrees(OrbitProcessor.GetTrueAnomaly(orbit, atDateTime));
                var tadif = Angle.ToDegrees(Angle.DifferenceBetweenRadians(keta, obta));
                var pos1  = OrbitProcessor.GetPosition_AU(orbit, atDateTime);
                var pos2  = OrbitProcessor.GetPosition_AU(orbit, ke.TrueAnomalyAtEpoch);
                var d2    = Distance.AuToKm(pos1 - pos2).Length();
            }
            return(orbit);
        }
Пример #3
0
        public KeplerElements GetElements()
        {
            // if there is not a change in Dv then the kepler elements wont have changed, it might be better to store them?
            double myMass   = OwningEntity.GetDataBlob <MassVolumeDB>().MassDry;
            var    sgp      = OrbitMath.CalculateStandardGravityParameterInM3S2(myMass, ParentMass);
            var    pos      = OwningEntity.GetDataBlob <PositionDB>().RelativePosition_m;
            var    dateTime = OwningEntity.StarSysDateTime;
            var    ke       = OrbitMath.KeplerFromPositionAndVelocity(sgp, pos, CurrentVector_ms, dateTime);

            return(ke);
        }
Пример #4
0
        public static OrbitDB FromVectorKM(Entity parent, double myMass, double parentMass, double sgp, Vector3 position, Vector3 velocity, DateTime atDateTime)
        {
            if (Distance.KmToAU(position.Length()) > OrbitProcessor.GetSOI(parent))
            {
                throw new Exception("Entity not in target SOI");
            }
            //var sgp  = GameConstants.Science.GravitationalConstant * (myMass + parentMass) / 3.347928976e33;
            var     ke    = OrbitMath.KeplerFromPositionAndVelocity(sgp, position, velocity, atDateTime);
            OrbitDB orbit = new OrbitDB(parent, parentMass, myMass,
                                        Distance.KmToAU(ke.SemiMajorAxis),
                                        ke.Eccentricity,
                                        Angle.ToDegrees(ke.Inclination),
                                        Angle.ToDegrees(ke.LoAN),
                                        Angle.ToDegrees(ke.AoP),
                                        Angle.ToDegrees(ke.MeanAnomalyAtEpoch),
                                        atDateTime);// - TimeSpan.FromSeconds(ke.Epoch));
            var pos = OrbitProcessor.GetAbsolutePosition_AU(orbit, atDateTime);

            return(orbit);
        }
Пример #5
0
        /// <summary>
        /// Creates on Orbit at current location from a given velocity
        /// </summary>
        /// <returns>The Orbit Does not attach the OrbitDB to the entity!</returns>
        /// <param name="parent">Parent. must have massdb</param>
        /// <param name="entity">Entity. must have massdb</param>
        /// <param name="velocity_m">Velocity in meters.</param>
        public static OrbitDB FromVelocity_m(Entity parent, Entity entity, Vector3 velocity_m, DateTime atDateTime)
        {
            var parentMass = parent.GetDataBlob <MassVolumeDB>().Mass;
            var myMass     = entity.GetDataBlob <MassVolumeDB>().Mass;

            //var epoch1 = parent.Manager.ManagerSubpulses.StarSysDateTime; //getting epoch from here is incorrect as the local datetime doesn't change till after the subpulse.

            //var parentPos = OrbitProcessor.GetAbsolutePosition_AU(parent.GetDataBlob<OrbitDB>(), atDateTime); //need to use the parent position at the epoch
            var posdb = entity.GetDataBlob <PositionDB>();

            posdb.SetParent(parent);
            var ralitivePos = posdb.RelativePosition_m;//entity.GetDataBlob<PositionDB>().AbsolutePosition_AU - parentPos;

            if (ralitivePos.Length() > OrbitProcessor.GetSOI_m(parent))
            {
                throw new Exception("Entity not in target SOI");
            }

            //var sgp = GameConstants.Science.GravitationalConstant * (myMass + parentMass) / 3.347928976e33;
            var sgp_m = GMath.StandardGravitationalParameter(myMass + parentMass);
            var ke_m  = OrbitMath.KeplerFromPositionAndVelocity(sgp_m, ralitivePos, velocity_m, atDateTime);


            OrbitDB orbit = new OrbitDB(parent)
            {
                SemiMajorAxis            = ke_m.SemiMajorAxis,
                Eccentricity             = ke_m.Eccentricity,
                Inclination              = ke_m.Inclination,
                LongitudeOfAscendingNode = ke_m.LoAN,
                ArgumentOfPeriapsis      = ke_m.AoP,
                MeanAnomalyAtEpoch       = ke_m.MeanAnomalyAtEpoch,
                Epoch = atDateTime,

                _parentMass = parentMass,
                _myMass     = myMass
            };

            orbit.CalculateExtendedParameters();

            var pos = OrbitProcessor.GetPosition_m(orbit, atDateTime);
            var d   = (pos - ralitivePos).Length();

            if (d > 1)
            {
                var e = new Event(atDateTime, "Positional difference of " + Stringify.Distance(d) + " when creating orbit from velocity");
                e.Entity     = entity;
                e.SystemGuid = entity.Manager.ManagerGuid;
                e.EventType  = EventType.Opps;
                //e.Faction =  entity.FactionOwner;
                StaticRefLib.EventLog.AddEvent(e);

                //other info:
                var keta  = Angle.ToDegrees(ke_m.TrueAnomalyAtEpoch);
                var obta  = Angle.ToDegrees(OrbitProcessor.GetTrueAnomaly(orbit, atDateTime));
                var tadif = Angle.ToDegrees(Angle.DifferenceBetweenRadians(keta, obta));
                var pos1  = OrbitProcessor.GetPosition_m(orbit, atDateTime);
                var pos2  = OrbitProcessor.GetPosition_m(orbit, ke_m.TrueAnomalyAtEpoch);
                var d2    = (pos1 - pos2).Length();
            }


            return(orbit);
        }
Пример #6
0
        /// <summary>
        /// This was designed so that fast moving objects will get interpolated a lot more than slow moving objects
        /// so fast moving objects shouldn't loose positional acuracy when close to a planet,
        /// and slow moving objects won't have processor time wasted on them by calulcating too often.
        /// However this seems to be unstable and looses energy, unsure why. currently set it to just itterate/interpolate every second.
        /// so currently will be using more time to get through this than neccisary.
        /// </summary>
        /// <param name="entity">Entity.</param>
        /// <param name="deltaSeconds">Delta seconds.</param>
        public static void NewtonMove(Entity entity, int deltaSeconds)
        {
            NewtonMoveDB          newtonMoveDB = entity.GetDataBlob <NewtonMoveDB>();
            NewtonThrustAbilityDB newtonThrust = entity.GetDataBlob <NewtonThrustAbilityDB>();
            PositionDB            positionDB   = entity.GetDataBlob <PositionDB>();
            double mass_Kg       = entity.GetDataBlob <MassVolumeDB>().Mass;
            double parentMass_kg = newtonMoveDB.ParentMass;

            var      manager        = entity.Manager;
            DateTime dateTimeFrom   = newtonMoveDB.LastProcessDateTime;
            DateTime dateTimeNow    = manager.ManagerSubpulses.StarSysDateTime;
            DateTime dateTimeFuture = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds);
            double   deltaT         = (dateTimeFuture - dateTimeFrom).TotalSeconds;

            double secondsToItterate = deltaT;

            while (secondsToItterate > 0)
            {
                //double timeStep = Math.Max(secondsToItterate / speed_kms, 1);
                //timeStep = Math.Min(timeStep, secondsToItterate);
                double timeStepInSeconds  = 1;//because the above seems unstable and looses energy.
                double distanceToParent_m = positionDB.GetDistanceTo_m(newtonMoveDB.SOIParent.GetDataBlob <PositionDB>());

                distanceToParent_m = Math.Max(distanceToParent_m, 0.1); //don't let the distance be 0 (once collision is in this will likely never happen anyway)

                double  gravForce       = GameConstants.Science.GravitationalConstant * (mass_Kg * parentMass_kg / Math.Pow(distanceToParent_m, 2));
                Vector3 gravForceVector = gravForce * -Vector3.Normalise(positionDB.RelativePosition_m);

                Vector3 totalDVFromGrav = (gravForceVector / mass_Kg) * timeStepInSeconds;

                double maxAccelFromThrust1 = newtonThrust.ExhaustVelocity * Math.Log(mass_Kg / (mass_Kg - newtonThrust.FuelBurnRate)); //per second
                double maxAccelFromThrust  = newtonThrust.ThrustInNewtons / mass_Kg;                                                   //per second


                Vector3 manuverDV = newtonMoveDB.DeltaVForManuver_m;                      //how much dv needed to complete the manuver.

                double dryMass = mass_Kg - newtonThrust.FuelBurnRate * timeStepInSeconds; //how much our ship weighs after a timestep of fuel is used.
                //how much dv can we get in this timestep.
                double deltaVThisStep = OrbitMath.TsiolkovskyRocketEquation(mass_Kg, dryMass, newtonThrust.ExhaustVelocity);
                deltaVThisStep = Math.Min(manuverDV.Length(), deltaVThisStep);  //don't use more Dv than what is called for.
                deltaVThisStep = Math.Min(newtonThrust.DeltaV, deltaVThisStep); //check we've got the deltaV to spend.

                Vector3 totalDVFromThrust = Vector3.Normalise(manuverDV) * deltaVThisStep;

                //remove the deltaV we're expending from the max (TODO: Remove fuel from cargo, change mass of ship)
                newtonThrust.DeltaV -= deltaVThisStep;
                //remove the vectorDV from the amount needed to fully complete the manuver.
                newtonMoveDB.DeltaVForManuver_m -= totalDVFromThrust;



                Vector3 totalDV     = totalDVFromGrav + totalDVFromThrust;
                Vector3 newVelocity = totalDV + newtonMoveDB.CurrentVector_ms;

                newtonMoveDB.CurrentVector_ms = newVelocity;
                Vector3 deltaPos = (newtonMoveDB.CurrentVector_ms + newVelocity) / 2 * timeStepInSeconds;

                positionDB.RelativePosition_m += deltaPos;

                double sOIRadius = OrbitProcessor.GetSOI_m(newtonMoveDB.SOIParent);



                if (positionDB.RelativePosition_m.Length() >= sOIRadius)
                {
                    Entity  newParent;
                    Vector3 parentRalitiveVector;
                    //if our parent is a regular kepler object (normaly this is the case)
                    if (newtonMoveDB.SOIParent.HasDataBlob <OrbitDB>())
                    {
                        var orbitDB = newtonMoveDB.SOIParent.GetDataBlob <OrbitDB>();
                        newParent = orbitDB.Parent;
                        var parentVelocity = OrbitProcessor.InstantaneousOrbitalVelocityVector_m(orbitDB, entity.StarSysDateTime);
                        parentRalitiveVector = newtonMoveDB.CurrentVector_ms + parentVelocity;
                    }
                    else //if (newtonMoveDB.SOIParent.HasDataBlob<NewtonMoveDB>())
                    {   //this will pretty much never happen.
                        newParent = newtonMoveDB.SOIParent.GetDataBlob <NewtonMoveDB>().SOIParent;
                        var parentVelocity = newtonMoveDB.SOIParent.GetDataBlob <NewtonMoveDB>().CurrentVector_ms;
                        parentRalitiveVector = newtonMoveDB.CurrentVector_ms + parentVelocity;
                    }
                    parentMass_kg = newParent.GetDataBlob <MassVolumeDB>().Mass;

                    Vector3 posRalitiveToNewParent = positionDB.AbsolutePosition_m - newParent.GetDataBlob <PositionDB>().AbsolutePosition_m;


                    var    dateTime = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds - secondsToItterate);
                    double sgp      = GMath.StandardGravitationalParameter(parentMass_kg + mass_Kg);
                    var    kE       = OrbitMath.KeplerFromPositionAndVelocity(sgp, posRalitiveToNewParent, parentRalitiveVector, dateTime);

                    positionDB.SetParent(newParent);
                    newtonMoveDB.ParentMass       = parentMass_kg;
                    newtonMoveDB.SOIParent        = newParent;
                    newtonMoveDB.CurrentVector_ms = parentRalitiveVector;
                }

                if (newtonMoveDB.DeltaVForManuver_m.Length() <= 0) //if we've completed the manuver.
                {
                    var    dateTime = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds - secondsToItterate);
                    double sgp      = GMath.StandardGravitationalParameter(parentMass_kg + mass_Kg);

                    KeplerElements kE = OrbitMath.KeplerFromPositionAndVelocity(sgp, positionDB.RelativePosition_m, newtonMoveDB.CurrentVector_ms, dateTime);

                    var parentEntity = Entity.GetSOIParentEntity(entity, positionDB);

                    if (kE.Eccentricity < 1) //if we're going to end up in a regular orbit around our new parent
                    {
                        var newOrbit = OrbitDB.FromKeplerElements(
                            parentEntity,
                            mass_Kg,
                            kE,
                            dateTime);
                        entity.RemoveDataBlob <NewtonMoveDB>();
                        entity.SetDataBlob(newOrbit);
                        positionDB.SetParent(parentEntity);
                        var newPos = OrbitProcessor.GetPosition_m(newOrbit, dateTime);
                        positionDB.RelativePosition_m = newPos;
                    }
                    break;
                }

                secondsToItterate -= timeStepInSeconds;
            }
            newtonMoveDB.LastProcessDateTime = dateTimeFuture;
        }
Пример #7
0
        /// <summary>
        /// This was designed so that fast moving objects will get interpolated a lot more than slow moving objects
        /// so fast moving objects shouldn't loose positional acuracy when close to a planet,
        /// and slow moving objects won't have processor time wasted on them by calulcating too often.
        /// However this seems to be unstable and looses energy, unsure why. currently set it to just itterate/interpolate every second.
        /// so currently will be using more time to get through this than neccisary.
        /// </summary>
        /// <param name="entity">Entity.</param>
        /// <param name="deltaSeconds">Delta seconds.</param>
        public static void NewtonMove(Entity entity, int deltaSeconds)
        {
            NewtonMoveDB newtonMoveDB  = entity.GetDataBlob <NewtonMoveDB>();
            PositionDB   positionDB    = entity.GetDataBlob <PositionDB>();
            double       Mass_Kg       = entity.GetDataBlob <MassVolumeDB>().Mass;
            double       ParentMass_kg = newtonMoveDB.ParentMass;

            var      manager        = entity.Manager;
            DateTime dateTimeFrom   = newtonMoveDB.LastProcessDateTime;
            DateTime dateTimeNow    = manager.ManagerSubpulses.StarSysDateTime;
            DateTime dateTimeFuture = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds);
            double   deltaT         = (dateTimeFuture - dateTimeFrom).TotalSeconds;

            double secondsToItterate = deltaT;

            while (secondsToItterate > 0)
            {
                double speed_kms = newtonMoveDB.CurrentVector_kms.Length();


                //double timeStep = Math.Max(secondsToItterate / speed_kms, 1);
                //timeStep = Math.Min(timeStep, secondsToItterate);
                double timeStep           = 1;//because the above seems unstable and looses energy.
                double distanceToParent_m = Distance.AuToMt(positionDB.GetDistanceTo(newtonMoveDB.SOIParent.GetDataBlob <PositionDB>()));

                distanceToParent_m = Math.Max(distanceToParent_m, 0.1); //don't let the distance be 0 (once collision is in this will likely never happen anyway)

                double  gravForce       = GameConstants.Science.GravitationalConstant * (Mass_Kg * ParentMass_kg / Math.Pow(distanceToParent_m, 2));
                Vector3 gravForceVector = gravForce * -Vector3.Normalise(positionDB.RelativePosition_AU);
                double  distance        = Distance.AuToKm(positionDB.RelativePosition_AU).Length();
                Vector3 totalForce      = gravForceVector + newtonMoveDB.ThrustVector;

                Vector3 acceleration_mps = totalForce / Mass_Kg;
                Vector3 newVelocity      = (acceleration_mps * timeStep * 0.001) + newtonMoveDB.CurrentVector_kms;

                newtonMoveDB.CurrentVector_kms = newVelocity;
                Vector3 deltaPos = (newtonMoveDB.CurrentVector_kms + newVelocity) / 2 * timeStep;
                //Vector4 deltaPos = newtonMoveDB.CurrentVector_kms * timeStep;

                positionDB.RelativePosition_AU += Distance.KmToAU(deltaPos);

                double sOIRadius_AU = OrbitProcessor.GetSOI(newtonMoveDB.SOIParent);

                if (positionDB.RelativePosition_AU.Length() >= sOIRadius_AU)
                {
                    Entity  newParent;
                    Vector3 parentRalitiveVector;
                    //if our parent is a regular kepler object (normaly this is the case)
                    if (newtonMoveDB.SOIParent.HasDataBlob <OrbitDB>())
                    {
                        var orbitDB = newtonMoveDB.SOIParent.GetDataBlob <OrbitDB>();
                        newParent = orbitDB.Parent;
                        var parentVelocity = OrbitProcessor.InstantaneousOrbitalVelocityVector(orbitDB, entity.Manager.ManagerSubpulses.StarSysDateTime);
                        parentRalitiveVector = Distance.KmToAU(newtonMoveDB.CurrentVector_kms) + parentVelocity;
                        var pvlen = Distance.AuToKm(parentVelocity.Length());
                        var vlen  = newtonMoveDB.CurrentVector_kms.Length();
                        var rvlen = Distance.AuToKm(parentRalitiveVector.Length());
                    }
                    else //if (newtonMoveDB.SOIParent.HasDataBlob<NewtonMoveDB>())
                    {   //this will pretty much never happen.
                        newParent = newtonMoveDB.SOIParent.GetDataBlob <NewtonMoveDB>().SOIParent;
                        var parentVelocity = newtonMoveDB.SOIParent.GetDataBlob <NewtonMoveDB>().CurrentVector_kms;
                        parentRalitiveVector = Distance.KmToAU(newtonMoveDB.CurrentVector_kms + parentVelocity);
                    }
                    double  newParentMass          = newParent.GetDataBlob <MassVolumeDB>().Mass;
                    double  sgp                    = GameConstants.Science.GravitationalConstant * (newParentMass + Mass_Kg) / 3.347928976e33;
                    Vector3 posRalitiveToNewParent = positionDB.AbsolutePosition_AU - newParent.GetDataBlob <PositionDB>().AbsolutePosition_AU;

                    var dateTime = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds - secondsToItterate);
                    var kE       = OrbitMath.KeplerFromPositionAndVelocity(sgp, posRalitiveToNewParent, parentRalitiveVector, dateTime);

                    if (kE.Eccentricity < 1) //if we're going to end up in a regular orbit around our new parent
                    {
                        /*
                         * var newOrbit = OrbitDB.FromKeplerElements(
                         *  newParent,
                         *  newParentMass,
                         *  Mass_Kg,
                         *  kE,
                         *  dateTime);
                         */
                        var newOrbit = OrbitDB.FromVector(newParent, entity, parentRalitiveVector, dateTime);
                        entity.RemoveDataBlob <NewtonMoveDB>();
                        entity.SetDataBlob(newOrbit);
                        positionDB.SetParent(newParent);
                        var currentPos = Distance.AuToKm(positionDB.RelativePosition_AU);
                        var newPos     = OrbitProcessor.GetPosition_AU(newOrbit, dateTime);
                        var newPosKM   = Distance.AuToKm(newPos);
                        positionDB.RelativePosition_AU = newPos;
                        break;
                    }
                    else //else we're in a hyperbolic trajectory around our new parent, so just coninue the newtonion move.
                    {
                        positionDB.SetParent(newParent);
                        newtonMoveDB.ParentMass = newParentMass;
                        newtonMoveDB.SOIParent  = newParent;
                    }
                }
                secondsToItterate -= timeStep;
            }
            newtonMoveDB.LastProcessDateTime = dateTimeFuture;
        }