상속: SpaceSim.Physics.GravitationalBodyBase, IAerodynamicBody, ISpaceCraft
예제 #1
0
 public override void Initialize(SpaceCraftBase spaceCraft)
 {
     foreach (IEngine engine in spaceCraft.Engines)
     {
         _currentOrientation = engine.Cant;
     }
 }
예제 #2
0
        public override void Update(double elapsedTime, SpaceCraftBase spaceCraft)
        {
            // Only run the landing algorithm while the spacecraft hasn't touched down
            if (!_landed)
            {
                double speed = spaceCraft.GetRelativeVelocity().Length();

                if (spaceCraft.OnGround || speed < 2 || spaceCraft.PropellantMass <= 0)
                {
                    _landed = true;

                    foreach (IEngine engine in spaceCraft.Engines)
                    {
                        engine.Shutdown();
                    }
                }

                double t = elapsedTime - _lastUpdate;

                double altitude = spaceCraft.GetRelativeAltitude();

                double updateRate = Math.Max(10 - altitude / 300, 1);

                // Update required this iteration
                if (t > 1.0 / updateRate)
                {
                    PredictTargetThrottle(spaceCraft);

                    _lastUpdate = elapsedTime;
                }
            }
        }
예제 #3
0
 public override void Finalize(SpaceCraftBase spaceCraft)
 {
     foreach (IEngine engine in spaceCraft.Engines)
     {
         engine.AdjustCant(_targetOrientation);
     }
 }
예제 #4
0
 // Interpolate between current and target orientation over the duration
 public override void Update(double elapsedTime, SpaceCraftBase spaceCraft)
 {
     double ratio = (elapsedTime - StartTime) / Duration;
     foreach (IEngine engine in spaceCraft.Engines)
     {
         engine.AdjustCant(_currentOrientation * (1 - ratio) + _targetOrientation * ratio);
     }
 }
예제 #5
0
        public CommandController(List<CommandBase> commands, SpaceCraftBase spaceCraft, EventManager eventManager)
            : base(spaceCraft)
        {
            _queuedCommands = new List<CommandBase>();
            _activeCommands = new List<CommandBase>();

            foreach (CommandBase command in commands)
            {
                _queuedCommands.Add(command);

                command.LoadEventManager(eventManager);
            }
        }
예제 #6
0
        public override void Initialize(SpaceCraftBase spaceCraft)
        {
            if (_engineIds == null)
            {
                EventManager.AddMessage("Shutting down all engines", spaceCraft);
            }
            else
            {
                EventManager.AddMessage(string.Format("Shutting down {0} engines", _engineIds.Length), spaceCraft);
            }

            _currentThrottle = spaceCraft.Throttle;
        }
예제 #7
0
        public SpaceCraftProxy(DVector2 position, DVector2 velocity, SpaceCraftBase spaceCraft)
            : base(position, velocity, spaceCraft.Pitch)
        {
            PropellantMass = spaceCraft.PropellantMass;

            Engines = new IEngine[spaceCraft.Engines.Length];

            for (int i = 0; i < spaceCraft.Engines.Length; i++)
            {
                Engines[i] = spaceCraft.Engines[i].Clone();
            }

            _proxy = spaceCraft;
        }
예제 #8
0
        public override void Initialize(SpaceCraftBase spaceCraft)
        {
            EventManager.AddMessage("Auto-Landing Engaged", spaceCraft);

            if (_engineIds != null)
            {
                // Startup the required landing engines
                foreach (int id in _engineIds)
                {
                    IEngine engine = spaceCraft.Engines[id];

                    engine.Startup();
                }
            }
        }
예제 #9
0
        public override void Initialize(SpaceCraftBase spaceCraft)
        {
            // If no engines are requested start them all
            if (_engineIds == null)
            {
                _engineIds = new int[spaceCraft.Engines.Length];

                for (int i = 0; i < _engineIds.Length; i++)
                {
                    _engineIds[i] = i;
                }
            }

            if (_engineIds.Length > 0 && spaceCraft.Engines.Length > 0)
            {
                IEngine engine = spaceCraft.Engines[_engineIds[0]];

                if (_engineIds.Length == 1)
                {
                    if (spaceCraft.Engines.Length > 1)
                    {
                        EventManager.AddMessage(string.Format("Igniting {0} {1}", _engineIds.Length, engine), spaceCraft);
                    }
                    else
                    {
                        EventManager.AddMessage(string.Format("Igniting {0}", engine), spaceCraft);
                    }
                }
                else
                {
                    EventManager.AddMessage(string.Format("Igniting {0} {1}s", _engineIds.Length, engine), spaceCraft);
                }
            }

            foreach (int engineId in _engineIds)
            {
                if (engineId >= spaceCraft.Engines.Length)
                {
                    throw new Exception("The spacecraft does not contain engine id " + engineId + "!");
                }

                IEngine engine = spaceCraft.Engines[engineId];

                engine.Startup();
            }
        }
예제 #10
0
        public override void Initialize(SpaceCraftBase spaceCraft)
        {
            EventManager.AddMessage(string.Format("Deploying " + _part), spaceCraft);

            switch (_part)
            {
                case "Fairing":
                    spaceCraft.DeployFairing();
                    break;
                case "Grid Fins":
                    spaceCraft.DeployGridFins();
                    break;
                case "Landing Legs":
                    spaceCraft.DeployLandingLegs();
                    break;
                default:
                    throw new Exception(string.Format("{0} is not a known deployable!", _part));
            }
        }
예제 #11
0
 public override void Finalize(SpaceCraftBase spaceCraft)
 {
     // Shutdown all engines
     if (_engineIds == null)
     {
         foreach (IEngine engine in spaceCraft.Engines)
         {
             engine.Shutdown();
         }
     }
     else
     {
         // Shut down specific engines
         foreach (int engineId in _engineIds)
         {
             spaceCraft.Engines[engineId].Shutdown();
         }
     }
 }
예제 #12
0
        // Interpolate between current and target orientation over the duration
        public override void Update(double elapsedTime, SpaceCraftBase spaceCraft)
        {
            DVector2 prograde = spaceCraft.GetRelativeVelocity();
            prograde.Normalize();

            double retrogradeAngle = prograde.Angle();

            double adjustRatio = (elapsedTime - StartTime) / _adjustmentTime;

            if (adjustRatio > 1)
            {
                spaceCraft.SetPitch(retrogradeAngle);
            }
            else
            {
                double interpolatedAdjust = _curentOrientation * (1 - adjustRatio) + retrogradeAngle * adjustRatio;

                spaceCraft.SetPitch(interpolatedAdjust);
            }
        }
예제 #13
0
 // Nothing to finalize
 public override void Finalize(SpaceCraftBase spaceCraft)
 {
 }
예제 #14
0
 public override void Initialize(SpaceCraftBase spaceCraft)
 {
     _currentOrientation = spaceCraft.Roll;
 }
예제 #15
0
        // Interpolate between current and target orientation over the duration
        public override void Update(double elapsedTime, SpaceCraftBase spaceCraft)
        {
            double ratio = (elapsedTime - StartTime) / Duration;

            spaceCraft.SetRoll(_currentOrientation * (1 - ratio) + _targetOrientation * ratio);
        }
예제 #16
0
 public abstract void Update(double elapsedTime, SpaceCraftBase spaceCraft);
예제 #17
0
 public override void Finalize(SpaceCraftBase spaceCraft)
 {
     spaceCraft.SetRoll(_targetOrientation);
 }
예제 #18
0
 public override void Update(double elapsedTime, SpaceCraftBase spaceCraft)
 {
 }
예제 #19
0
 public abstract void Initialize(SpaceCraftBase spaceCraft);
예제 #20
0
        /// <summary>
        /// Traces a space craft orbit by re-centering the world around the parent.
        /// </summary>
        public static OrbitTrace TraceSpaceCraft(SpaceCraftBase satellite)
        {
            IMassiveBody parent = satellite.GravitationalParent;

            DVector2 initialPosition = satellite.Position - parent.Position;

            var shipOffset = new DVector2(Math.Cos(satellite.Rotation) * (satellite.TotalWidth - satellite.Width),
                                          Math.Sin(satellite.Rotation) * (satellite.TotalHeight - satellite.Height)) * 0.5;

            initialPosition -= shipOffset;

            var proxyParent = new MassiveBodyProxy(DVector2.Zero, DVector2.Zero, parent);
            var proxySatellite = new SpaceCraftProxy(initialPosition, satellite.Velocity - parent.Velocity, satellite);

            int stepCount;

            double targetDt;
            double proximityDt;
            double orbitalDt = 0;

            bool isOrbiting;
            double orbitalTerminationRadius = 0;

            double altitude = proxyParent.GetRelativeHeight(proxySatellite.Position);
            double proximityAltitude = proxyParent.SurfaceRadius * 0.15;

            if (altitude < proximityAltitude)
            {
                stepCount = 1000;

                isOrbiting = false;

                proximityDt = GetProximityDt(altitude, proximityAltitude);

                targetDt = proximityDt;
            }
            else
            {
                stepCount = 300;

                isOrbiting = true;

                orbitalDt = GetOrbitalDt(initialPosition, proxySatellite.Velocity, out orbitalTerminationRadius);

                targetDt = orbitalDt;
            }

            var trace = new OrbitTrace(satellite.Position - shipOffset, altitude);

            // Simulate 300 orbital steps, more for proximity
            for (int step = 0; step < stepCount; step++)
            {
                proxySatellite.ResetAccelerations();

                proxySatellite.ResolveGravitation(proxyParent);
                proxySatellite.ResolveAtmopsherics(proxyParent);

                proxySatellite.Update(targetDt);

                altitude = proxyParent.GetRelativeHeight(proxySatellite.Position);

                // Check if reference frame shifting needs to occur in atmosphere
                if (altitude < proxyParent.AtmosphereHeight)
                {
                    double offsetFactor = 1.0 - (altitude / proxyParent.AtmosphereHeight);

                    DVector2 difference = proxyParent.Position - proxySatellite.Position;
                    difference.Normalize();

                    var surfaceNormal = new DVector2(-difference.Y, difference.X);

                    double altitudeFromCenter = altitude + proxyParent.SurfaceRadius;

                    // Distance of circumference at this altitude ( c= 2r * pi )
                    double pathCirumference = 2 * Math.PI * altitudeFromCenter;

                    double rotationalSpeed = pathCirumference / parent.RotationPeriod;

                    DVector2 atmopshereVelocity = surfaceNormal * rotationalSpeed;

                    proxySatellite.ApplyFrameOffset(atmopshereVelocity * offsetFactor * targetDt);

                    // Return early if the trace goes into a planet
                    if (altitude <= 0)
                    {
                        trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
                        break;
                    }
                }

                // Determine the correct change overs from orbital to surface proximity
                if (isOrbiting)
                {
                    if (altitude < proximityAltitude)
                    {
                        proximityDt = GetProximityDt(altitude, proximityAltitude);

                        targetDt = MathHelper.Lerp(targetDt, proximityDt, 0.75);

                        isOrbiting = false;

                        stepCount = 1000;
                    }
                    else
                    {
                        targetDt = MathHelper.Lerp(targetDt, orbitalDt, 0.1);
                    }
                }
                else
                {
                    if (altitude > proximityAltitude)
                    {
                        orbitalDt = GetOrbitalDt(proxySatellite.Position, proxySatellite.Velocity, out orbitalTerminationRadius);

                        targetDt = MathHelper.Lerp(targetDt, orbitalDt, 0.1);

                        isOrbiting = true;

                        stepCount = 300;
                    }
                    else
                    {
                        proximityDt = GetProximityDt(altitude, proximityAltitude);

                        targetDt = MathHelper.Lerp(targetDt, proximityDt, 0.75);
                    }
                }

                // Check expensive termination conditions after half of the iterations
                if (isOrbiting && step > 100)
                {
                    DVector2 offsetVector = proxySatellite.Position - initialPosition;

                    double distanceFromStart = offsetVector.Length();

                    // Terminate and add the end point
                    if (distanceFromStart < orbitalTerminationRadius)
                    {
                        trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
                        break;
                    }
                }

                trace.AddPoint(proxySatellite.Position + parent.Position, altitude);
            }

            return trace;
        }
예제 #21
0
 public override void Initialize(SpaceCraftBase spaceCraft)
 {
     _currentRelativePitch = spaceCraft.GetRelativePitch();
 }
예제 #22
0
        // Interpolate between current and target orientation over the duration
        public override void Update(double elapsedTime, SpaceCraftBase spaceCraft)
        {
            double ratio = (elapsedTime - StartTime) / Duration;

            spaceCraft.SetRelativePitch(_currentRelativePitch * (1 - ratio) + _targetRelativePitch * ratio);
        }
예제 #23
0
        public override void Update(double elapsedTime, SpaceCraftBase spaceCraft)
        {
            double timeRatio = (elapsedTime - StartTime) / Duration;

            spaceCraft.SetThrottle(_throttle * timeRatio);
        }
예제 #24
0
 public override void Finalize(SpaceCraftBase spaceCraft)
 {
     spaceCraft.SetThrottle(_throttle);
 }
예제 #25
0
        public SimpleFlightController(SpaceCraftBase spaceCraft)
        {
            ElapsedTime -= MainWindow.ClockDelayInSeconds;

            SpaceCraft = spaceCraft;
        }
예제 #26
0
        public override void Initialize(SpaceCraftBase spaceCraft)
        {
            EventManager.AddMessage(string.Format("Throttling to {0}%", _targetThrottle.ToString("0.0")), spaceCraft);

            _currentThrottle = spaceCraft.Throttle;
        }
예제 #27
0
        public override void Initialize(SpaceCraftBase spaceCraft)
        {
            EventManager.AddMessage("Maneuvering to prograde", spaceCraft);

            _curentOrientation = spaceCraft.Pitch;
        }
예제 #28
0
 public abstract void Finalize(SpaceCraftBase spaceCraft);
예제 #29
0
        // Interpolate between current and target throttle over the duration
        public override void Update(double elapsedTime, SpaceCraftBase spaceCraft)
        {
            double ratio = (elapsedTime - StartTime) / Duration;

            spaceCraft.SetThrottle(_currentThrottle * (1 - ratio) + _targetThrottle * ratio);
        }
예제 #30
0
        public override void Initialize(SpaceCraftBase spaceCraft)
        {
            spaceCraft.Stage();

            EventManager.AddMessage("Staging", spaceCraft);
        }