private bool IsTrainApproaching(TrackBlock curr, TrackBlock dest)
            {
                if (dest == null)
                {
                    throw new ArgumentNullException();
                }

                List <TrackBlock> blocks = new List <TrackBlock>(m_trackBlocks.Values);

                while (blocks.Count > 0)
                {
                    TrackBlock b = blocks.ElementAt <TrackBlock>(0);
                    blocks.Remove(b);
                    if (b == curr)
                    {
                        continue;
                    }
                    if (b.Status.TrainPresent)
                    {
                        for (TrackBlock t = b.GetNextBlock(b.Status.TrainDirection);
                             t != null && blocks.Contains <TrackBlock>(t) &&
                             t.Status.IsOpen && !t.Status.TrainPresent;
                             t = (t.NextBlock == t) ? t.PreviousBlock : t.NextBlock)
                        {
                            if (t == dest)
                            {
                                return(true);
                            }
                            blocks.Remove(t);
                        }
                    }
                }
                return(false);
            }
Exemple #2
0
        public void GetNextBlockTest()
        {
            TrackBlock target    = new TrackBlock(); // TODO: Initialize to an appropriate value
            TrackBlock NextBlock = new TrackBlock();

            target.NextBlock = NextBlock;
            Direction  direction = Direction.East; // TODO: Initialize to an appropriate value
            TrackBlock expected  = null;           // TODO: Initialize to an appropriate value
            TrackBlock actual;

            actual = target.GetNextBlock(direction);
            Assert.AreEqual(expected, actual);
        }
Exemple #3
0
        // METHOD: DetermineSetPoint
        //--------------------------------------------------------------------------------------
        /// <summary>
        /// Determine the set point
        /// </summary>
        //--------------------------------------------------------------------------------------
        private void DetermineSetPoint()
        {
            // If a manual speed command has been given and does not exceed the speed limit, make the manual speed the setpoint
            // Else, the setpoint should be set to the speed limit
            if (ManualMode && ManualSpeed >= 0)
            {
                if (ManualSpeed < m_currentBlock.Authority.SpeedLimitKPH)
                {
                    m_setPoint = ManualSpeed / 3.6;
                }
                else
                {
                    m_setPoint = m_currentBlock.Authority.SpeedLimitKPH / 3.6;
                }
            }
            else
            {
                m_setPoint = m_currentBlock.Authority.SpeedLimitKPH / 3.6;
            }

            // The setpoint should never be negative
            if (m_setPoint < 0)
            {
                m_setPoint = 0;
            }

            // If the authority is negative, the train has exceeded its authority and must apply the emergency brake
            // If the authority is zero, the train cannot pass into the next block
            // So, when the train reaches its stopping distance, the setPoint must be set to zero to engage the brake.
            // If the authority is zero and the train is stopped, the train should stay stopped, so the setpoint should be zero
            // If the next block has a lower speed limit, the setpoint must be reduced
            if (m_currentBlock.Authority.Authority < 0)
            {
                EmergencyBrake = true;
            }
            else if (m_currentBlock.Authority.Authority == 0 && (CalculateStoppingDistance(0) >= m_currentBlock.LengthMeters - m_currentState.BlockProgress || (!m_atStation && m_currentState.Speed <= 2)))
            {
                m_setPoint = 0;
            }
            else if (m_currentBlock.GetNextBlock(m_currentState.Direction) == null)
            {
                m_setPoint = 0;
            }
            else if (m_currentBlock.GetNextBlock(m_currentState.Direction).Authority.SpeedLimitKPH < m_currentBlock.Authority.SpeedLimitKPH && CalculateStoppingDistance(m_currentBlock.GetNextBlock(m_currentState.Direction).Authority.SpeedLimitKPH / 3.6) >= m_currentBlock.LengthMeters - m_currentState.BlockProgress)
            {
                m_setPoint = m_currentBlock.GetNextBlock(m_currentState.Direction).Authority.SpeedLimitKPH / 3.6;
            }

            // If the train is approaching a station and is reaches the safe stopping distance, the setpoint should be zet to zero
            if (m_approachingStation)
            {
                if (m_currentBlock.HasTransponder && m_currentBlock.Transponder.DistanceToStation == 1 && CalculateStoppingDistance(0) >= m_currentBlock.LengthMeters + m_currentBlock.GetNextBlock(m_currentState.Direction).LengthMeters * 0.5 - m_currentState.BlockProgress)
                {
                    m_setPoint = 0;
                }
                else if (m_currentBlock.HasTransponder && m_currentBlock.Transponder.DistanceToStation == 0 && CalculateStoppingDistance(0) >= m_currentBlock.LengthMeters * 0.5 - m_currentState.BlockProgress)
                {
                    m_setPoint = 0;
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Updates the position of the Train.
        /// </summary>
        /// <param name="deltaTime">The number of seconds elapsed since last update.</param>
        private void UpdatePosition(double deltaTime)
        {
            double     timestep = deltaTime;
            double     distance = timestep * state.Speed;
            TrackBlock block    = state.CurrentBlock;
            int        startX   = block.StartPoint.X;
            int        startY   = block.StartPoint.Y;
            int        endX     = block.EndPoint.X;
            int        endY     = block.EndPoint.Y;
            double     length   = block.LengthMeters;

            switch (state.Direction)
            {
            case Direction.East:
                state.X            += distance;
                state.BlockProgress = (state.X - startX);
                break;

            case Direction.North:
                state.Y            -= distance;
                state.BlockProgress = (state.Y - startY);
                break;

            case Direction.Northeast:
                distance           /= Math.Sqrt(2);
                state.X            += distance;
                state.Y            -= distance;
                state.BlockProgress = Math.Sqrt(Math.Pow(state.Y - startY, 2) + Math.Pow(state.X - startX, 2));
                break;

            case Direction.Northwest:
                distance           /= Math.Sqrt(2);
                state.X            -= distance;
                state.Y            -= distance;
                state.BlockProgress = Math.Sqrt(Math.Pow(state.Y - endY, 2) + Math.Pow(state.X - endX, 2));
                break;

            case Direction.South:
                state.Y            += distance;
                state.BlockProgress = (state.Y - endY);
                break;

            case Direction.Southeast:
                distance           /= Math.Sqrt(2);
                state.X            += distance;
                state.Y            += distance;
                state.BlockProgress = Math.Sqrt(Math.Pow(state.Y - startY, 2) + Math.Pow(state.X - startX, 2));
                break;

            case Direction.Southwest:
                distance           /= Math.Sqrt(2);
                state.X            -= distance;
                state.Y            += distance;
                state.BlockProgress = Math.Sqrt(Math.Pow(state.Y - endY, 2) + Math.Pow(state.X - endX, 2));
                break;

            case Direction.West:
                state.X            -= distance;
                state.BlockProgress = (state.X - endX);
                break;

            default:
                break;                         // Unreachable
            }
            state.BlockProgress = Math.Abs(state.BlockProgress);

            // Move to next block
            if (state.BlockProgress > length)
            {
                // Subtract length of previous block from progress
                state.BlockProgress -= length;

                // Fire an event to alert the block
                if (TrainEnteredNewBlock != null)
                {
                    TrainEnteredNewBlock(state.CurrentBlock, state.CurrentBlock.GetNextBlock(state.Direction));
                }
                // Move train's presence to next block
                state.CurrentBlock.Status.TrainPresent = false;
                state.CurrentBlock = block.GetNextBlock(state.Direction);
                state.CurrentBlock.Status.TrainPresent = true;

                // Set the train's direction according to new block
                switch (state.CurrentBlock.Orientation)
                {
                case TrackOrientation.EastWest:
                    if (state.Direction == Direction.East || state.Direction == Direction.Northeast || state.Direction == Direction.Southeast)
                    {
                        state.Direction = Direction.East;
                    }
                    else if (state.Direction == Direction.West || state.Direction == Direction.Northwest || state.Direction == Direction.Southwest)
                    {
                        state.Direction = Direction.West;
                    }
                    else
                    {
                        Debug.Fail("Invalid transition to EastWest block!");
                    }
                    break;

                case TrackOrientation.NorthSouth:
                    if (state.Direction == Direction.North || state.Direction == Direction.Northeast || state.Direction == Direction.Northwest)
                    {
                        state.Direction = Direction.North;
                    }
                    else if (state.Direction == Direction.South || state.Direction == Direction.Southeast || state.Direction == Direction.Southwest)
                    {
                        state.Direction = Direction.South;
                    }
                    else
                    {
                        Debug.Fail("Invalid transition to NorthSouth block!");
                    }
                    break;

                case TrackOrientation.NorthWestSouthEast:
                    if (state.Direction == Direction.North || state.Direction == Direction.West || state.Direction == Direction.Northwest)
                    {
                        state.Direction = Direction.Northwest;
                    }
                    else if (state.Direction == Direction.South || state.Direction == Direction.East || state.Direction == Direction.Southeast)
                    {
                        state.Direction = Direction.Southeast;
                    }
                    else
                    {
                        Debug.Fail("Invalid transition to NorthwestSoutheast block!");
                    }
                    break;

                case TrackOrientation.SouthWestNorthEast:
                    if (state.Direction == Direction.South || state.Direction == Direction.West || state.Direction == Direction.Southwest)
                    {
                        state.Direction = Direction.Southwest;
                    }
                    else if (state.Direction == Direction.North || state.Direction == Direction.East || state.Direction == Direction.Northeast)
                    {
                        state.Direction = Direction.Northeast;
                    }
                    else
                    {
                        Debug.Fail("Invalid transition to NorthSouth block!");
                    }
                    break;

                default:
                    break;                             // Unreachable
                }
                // Set the train's direction in the TrainBlock
                state.CurrentBlock.Status.TrainDirection = state.Direction;
                // Update the slope according to the new block
                slope = Math.Atan(block.Grade / 100.0);
            }
        }