Пример #1
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);
        }
Пример #2
0
        public static double CalcDVDifference_m(Entity entity1, Entity entity2)
        {
            double dvDif = 0;

            Entity parent;
            double parentMass;
            double sgp;
            double r1;
            double r2;

            Entity soi1 = Entity.GetSOIParentEntity(entity1);
            Entity soi2 = Entity.GetSOIParentEntity(entity2);


            if (soi1 == soi2)
            {
                parent     = soi1;
                parentMass = parent.GetDataBlob <MassVolumeDB>().MassDry;
                sgp        = OrbitMath.CalculateStandardGravityParameterInM3S2(0, parentMass);


                var state1 = Entity.GetRalitiveState(entity1);
                var state2 = Entity.GetRalitiveState(entity2);
                r1 = state1.pos.Length();
                r2 = state2.pos.Length();
            }
            else
            {
                StaticRefLib.EventLog.AddEvent(new Event("Cargo calc failed, entities must have same soi parent"));
                return(double.PositiveInfinity);
            }

            var hohmann = InterceptCalcs.Hohmann(sgp, r1, r2);

            return(dvDif = hohmann[0].deltaV.Length() + hohmann[1].deltaV.Length());
        }
Пример #3
0
        /// <summary>
        /// creates an asteroid that will collide with the given entity on the given date.
        /// </summary>
        /// <param name="starSys"></param>
        /// <param name="target"></param>
        /// <param name="collisionDate"></param>
        /// <returns></returns>
        public static Entity CreateAsteroid(StarSystem starSys, Entity target, DateTime collisionDate, double asteroidMass = -1.0)
        {
            //todo rand these a bit.
            double radius = Distance.KmToAU(0.5);

            double mass;

            if (asteroidMass < 0)
            {
                mass = 1.5e+12; //about 1.5 billion tonne
            }
            else
            {
                mass = asteroidMass;
            }

            var     speed    = 40000;
            Vector3 velocity = new Vector3(speed, 0, 0);


            var massVolume  = MassVolumeDB.NewFromMassAndRadius_AU(mass, radius);
            var planetInfo  = new SystemBodyInfoDB();
            var name        = new NameDB("Ellie");
            var AsteroidDmg = new AsteroidDamageDB();

            AsteroidDmg.FractureChance = new PercentValue(0.75f);
            var dmgPfl     = EntityDamageProfileDB.AsteroidDamageProfile(massVolume.Volume_km3, massVolume.Density, massVolume.RadiusInM, 50);
            var sensorPfil = new SensorProfileDB();

            planetInfo.SupportsPopulations = false;
            planetInfo.BodyType            = BodyType.Asteroid;

            Vector3  targetPos       = OrbitProcessor.GetAbsolutePosition_m(target.GetDataBlob <OrbitDB>(), collisionDate);
            TimeSpan timeToCollision = collisionDate - StaticRefLib.CurrentDateTime;


            var parent     = target.GetDataBlob <OrbitDB>().Parent;
            var parentMass = parent.GetDataBlob <MassVolumeDB>().Mass;
            var myMass     = massVolume.Mass;

            double  sgp   = OrbitMath.CalculateStandardGravityParameterInM3S2(myMass, parentMass);
            OrbitDB orbit = OrbitDB.FromVector(parent, myMass, parentMass, sgp, targetPos, velocity, collisionDate);

            var currentpos = OrbitProcessor.GetAbsolutePosition_AU(orbit, StaticRefLib.CurrentDateTime);
            var posDB      = new PositionDB(currentpos.X, currentpos.Y, currentpos.Z, parent.Manager.ManagerGuid, parent);


            var planetDBs = new List <BaseDataBlob>
            {
                posDB,
                massVolume,
                planetInfo,
                name,
                orbit,
                AsteroidDmg,
                dmgPfl,
                sensorPfil
            };

            Entity newELE = new Entity(starSys, planetDBs);

            return(newELE);
        }
Пример #4
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>().MassDry;
            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 sgp = OrbitMath.CalculateStandardGravityParameterInM3S2(mass_Kg, parentMass_kg);


            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_FoRO_m; //how much dv needed to complete the manuver.
                Vector3 totalDVFromThrust = new Vector3(0, 0, 0);



                if (manuverDV.Length() > 0)
                {
                    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.

                    totalDVFromThrust = Vector3.Normalise(manuverDV) * deltaVThisStep;

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

                //convert prograde to global frame of reference for thrust direction
                Vector3 globalCoordDVFromThrust = OrbitMath.ProgradeToParentVector(sgp, totalDVFromThrust,
                                                                                   positionDB.RelativePosition_m,
                                                                                   newtonMoveDB.CurrentVector_ms);



                Vector3 totalDV     = totalDVFromGrav + globalCoordDVFromThrust;
                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>().MassDry;

                    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_FoRO_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
                    {
                        if (entity.HasDataBlob <ProjectileInfoDB>()) //this feels a bit hacky.
                        {
                            var newOrbit  = OrbitDB.FromKeplerElements(parentEntity, mass_Kg, kE, dateTime);
                            var fastOrbit = new OrbitUpdateOftenDB(newOrbit);
                            entity.RemoveDataBlob <NewtonMoveDB>();
                            entity.SetDataBlob(fastOrbit);
                            positionDB.SetParent(parentEntity);
                            var newPos = OrbitProcessor.GetPosition_m(fastOrbit, dateTime);
                            positionDB.RelativePosition_m = newPos;
                        }
                        else
                        {
                            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;
        }