示例#1
0
            private void GetNewState(double Time, out double NewMileage, out double NewPosition, out TravelDirection NewDirection, out bool OpenLeftDoors, out bool OpenRightDoors)
            {
                double DeltaT;
                double DeltaPosition;

                OpenLeftDoors  = false;
                OpenRightDoors = false;

                {
                    // The first point must be TravelStopData.
                    TravelStopData FirstData = (TravelStopData)Data[0];

                    NewMileage   = FirstData.Mileage;
                    NewPosition  = FirstData.Position;
                    NewDirection = FirstData.Direction;

                    if (Time <= FirstData.ArrivalTime)
                    {
                        return;
                    }

                    if (Time <= FirstData.ClosingDoorsStartTime)
                    {
                        OpenLeftDoors  = FirstData.OpenLeftDoors;
                        OpenRightDoors = FirstData.OpenRightDoors;
                        return;
                    }

                    if (Time <= FirstData.DepartureTime)
                    {
                        return;
                    }

                    // The start point does not slow down. Acceleration only.
                    if (Time <= FirstData.AccelerationEndTime)
                    {
                        DeltaT        = Time - FirstData.DepartureTime;
                        DeltaPosition = 0.5 * FirstData.Accelerate * Math.Pow(DeltaT, 2.0);
                        NewMileage   += DeltaPosition;
                        NewPosition  += (int)NewDirection * DeltaPosition;
                        return;
                    }

                    NewMileage += Math.Abs(FirstData.AccelerationEndPosition - NewPosition);
                    NewPosition = FirstData.AccelerationEndPosition;
                }

                for (int i = 1; i < Data.Length; i++)
                {
                    if (Time <= Data[i].DecelerationStartTime)
                    {
                        DeltaT        = Time - Data[i - 1].AccelerationEndTime;
                        DeltaPosition = Data[i - 1].TargetSpeed * DeltaT;
                        NewMileage   += DeltaPosition;
                        NewPosition  += (int)NewDirection * DeltaPosition;
                        return;
                    }

                    NewMileage += Math.Abs(Data[i].DecelerationStartPosition - NewPosition);
                    NewPosition = Data[i].DecelerationStartPosition;

                    if (Time <= Data[i].ArrivalTime)
                    {
                        DeltaT        = Time - Data[i].DecelerationStartTime;
                        DeltaPosition = Data[i - 1].TargetSpeed * DeltaT + 0.5 * Data[i].Decelerate * Math.Pow(DeltaT, 2.0);
                        NewMileage   += DeltaPosition;
                        NewPosition  += (int)NewDirection * DeltaPosition;
                        return;
                    }

                    TravelStopData StopData = Data[i] as TravelStopData;

                    NewMileage   = Data[i].Mileage;
                    NewPosition  = Data[i].Position;
                    NewDirection = StopData?.Direction ?? NewDirection;

                    if (Time <= StopData?.ClosingDoorsStartTime)
                    {
                        OpenLeftDoors  = StopData.OpenLeftDoors;
                        OpenRightDoors = StopData.OpenRightDoors;
                        return;
                    }

                    // The end point does not accelerate.
                    if (Time <= Data[i].DepartureTime || i == Data.Length - 1)
                    {
                        return;
                    }

                    if (Time <= Data[i].AccelerationEndTime)
                    {
                        DeltaT        = Time - Data[i].DepartureTime;
                        DeltaPosition = Data[i].PassingSpeed * DeltaT + 0.5 * Data[i].Accelerate * Math.Pow(DeltaT, 2.0);
                        NewMileage   += DeltaPosition;
                        NewPosition  += (int)NewDirection * DeltaPosition;
                        return;
                    }

                    NewMileage += Math.Abs(Data[i].AccelerationEndPosition - NewPosition);
                    NewPosition = Data[i].AccelerationEndPosition;
                }
            }
        /// <summary>
        /// Function to parse the contents of TravelStopData class
        /// </summary>
        /// <param name="FileName">The filename of the containing XML file</param>
        /// <param name="SectionElement">The XElement to parse</param>
        /// <returns>An instance of the new TravelStopData class with the parse result applied</returns>
        private static TravelStopData ParseTravelStopNode(string FileName, XElement SectionElement)
        {
            string Section = SectionElement.Name.LocalName;

            TravelStopData Data = new TravelStopData();

            ParseTravelDataNode(FileName, SectionElement, Data);

            foreach (XElement KeyNode in SectionElement.Elements())
            {
                string Key        = KeyNode.Name.LocalName;
                string Value      = KeyNode.Value;
                int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                switch (Key.ToLowerInvariant())
                {
                case "stoptime":
                    if (Value.Any() && !Interface.TryParseTime(Value, out Data.StopTime))
                    {
                        Interface.AddMessage(MessageType.Error, false, $"Value is invalid in {Key} in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                    }
                    break;

                case "doors":
                {
                    int  Door     = 0;
                    bool DoorBoth = false;

                    switch (Value.ToLowerInvariant())
                    {
                    case "l":
                    case "left":
                        Door = -1;
                        break;

                    case "r":
                    case "right":
                        Door = 1;
                        break;

                    case "n":
                    case "none":
                    case "neither":
                        Door = 0;
                        break;

                    case "b":
                    case "both":
                        DoorBoth = true;
                        break;

                    default:
                        if (Value.Any() && !NumberFormats.TryParseIntVb6(Value, out Door))
                        {
                            Interface.AddMessage(MessageType.Error, false, $"Value is invalid in {Key} in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                        }
                        break;
                    }

                    Data.OpenLeftDoors  = Door < 0.0 | DoorBoth;
                    Data.OpenRightDoors = Door > 0.0 | DoorBoth;
                }
                break;

                case "direction":
                {
                    int d = 0;
                    switch (Value.ToLowerInvariant())
                    {
                    case "f":
                        d = 1;
                        break;

                    case "r":
                        d = -1;
                        break;

                    default:
                        if (Value.Any() && (!NumberFormats.TryParseIntVb6(Value, out d) || !Enum.IsDefined(typeof(TravelDirection), d)))
                        {
                            Interface.AddMessage(MessageType.Error, false, $"Value is invalid in {Key} in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                            d = 1;
                        }
                        break;
                    }

                    Data.Direction = (TravelDirection)d;
                }
                break;

                case "decelerate":
                case "position":
                case "stopposition":
                case "accelerate":
                case "targetspeed":
                case "rail":
                    // Already parsed
                    break;

                default:
                    Interface.AddMessage(MessageType.Warning, false, $"Unsupported key {Key} encountered in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                    break;
                }
            }

            return(Data);
        }
示例#3
0
            /// <summary>Create a train operation plan.</summary>
            internal void SetupTravelData(double InitializeTime)
            {
                // The first point must be TravelStopData.
                TravelStopData FirstData = (TravelStopData)Data[0];

                // Calculate the end point of acceleration and the start point of deceleration.
                {
                    TravelDirection LastDirection;
                    double          DeltaPosition;

                    // The start point does not slow down. Acceleration only.
                    {
                        FirstData.Mileage = 0.0;
                        LastDirection     = FirstData.Direction;
                        DeltaPosition     = 0.0;
                        if (FirstData.Accelerate != 0.0)
                        {
                            DeltaPosition = Math.Pow(FirstData.TargetSpeed, 2.0) / (2.0 * FirstData.Accelerate);
                        }
                        FirstData.AccelerationEndPosition = FirstData.Position + (int)LastDirection * DeltaPosition;
                    }

                    for (int i = 1; i < Data.Length; i++)
                    {
                        DeltaPosition = 0.0;
                        if (Data[i].Decelerate != 0.0)
                        {
                            DeltaPosition = (Math.Pow(Data[i].PassingSpeed, 2.0) - Math.Pow(Data[i - 1].TargetSpeed, 2.0)) / (2.0 * Data[i].Decelerate);
                        }
                        Data[i].DecelerationStartPosition = Data[i].Position - (int)LastDirection * DeltaPosition;

                        Data[i].Mileage = Data[i - 1].Mileage + Math.Abs(Data[i].Position - Data[i - 1].Position);
                        LastDirection   = (Data[i] as TravelStopData)?.Direction ?? LastDirection;
                        DeltaPosition   = 0.0;
                        if (Data[i].Accelerate != 0.0)
                        {
                            DeltaPosition = (Math.Pow(Data[i].TargetSpeed, 2.0) - Math.Pow(Data[i].PassingSpeed, 2.0)) / (2.0 * Data[i].Accelerate);
                        }
                        Data[i].AccelerationEndPosition = Data[i].Position + (int)LastDirection * DeltaPosition;
                    }
                }

                // Time to operate the door
                double OpeningDoorsTime = 0.0;
                double ClosingDoorsTime = 0.0;

                if (Train.Cars[0].Specs.DoorOpenFrequency != 0.0)
                {
                    OpeningDoorsTime = 1.0 / Train.Cars[0].Specs.DoorOpenFrequency;
                }
                if (Train.Cars[0].Specs.DoorCloseFrequency != 0.0)
                {
                    ClosingDoorsTime = 1.0 / Train.Cars[0].Specs.DoorCloseFrequency;
                }

                // Reflect the delay until the TFO becomes effective at the first point.
                {
                    FirstData.ArrivalTime = InitializeTime;
                    AppearanceTime        = InitializeTime;
                    LeaveTime             = Train.LeaveTime + InitializeTime;

                    FirstData.OpeningDoorsEndTime = FirstData.ArrivalTime;
                    if (FirstData.OpenLeftDoors || FirstData.OpenRightDoors)
                    {
                        FirstData.OpeningDoorsEndTime += OpeningDoorsTime;
                    }
                    FirstData.ClosingDoorsStartTime = FirstData.OpeningDoorsEndTime + FirstData.StopTime;
                    FirstData.DepartureTime         = FirstData.ClosingDoorsStartTime;
                    if (FirstData.OpenLeftDoors || FirstData.OpenRightDoors)
                    {
                        FirstData.DepartureTime += ClosingDoorsTime;
                    }
                }

                // Calculate the time of each point.
                {
                    double DeltaT;

                    // The start point does not slow down. Acceleration only.
                    {
                        DeltaT = 0.0;
                        if (FirstData.Accelerate != 0.0)
                        {
                            DeltaT = FirstData.TargetSpeed / FirstData.Accelerate;
                        }
                        FirstData.AccelerationEndTime = FirstData.DepartureTime + DeltaT;
                    }

                    for (int i = 1; i < Data.Length; i++)
                    {
                        DeltaT = 0.0;
                        if (Data[i - 1].TargetSpeed != 0.0)
                        {
                            DeltaT = Math.Abs(Data[i].DecelerationStartPosition - Data[i - 1].AccelerationEndPosition) / Data[i - 1].TargetSpeed;
                        }
                        Data[i].DecelerationStartTime = Data[i - 1].AccelerationEndTime + DeltaT;

                        DeltaT = 0.0;
                        if (Data[i].Decelerate != 0.0)
                        {
                            DeltaT = (Data[i].PassingSpeed - Data[i - 1].TargetSpeed) / Data[i].Decelerate;
                        }
                        Data[i].ArrivalTime = Data[i].DecelerationStartTime + DeltaT;

                        TravelStopData StopData = Data[i] as TravelStopData;

                        if (StopData != null)
                        {
                            StopData.OpeningDoorsEndTime = StopData.ArrivalTime;
                            if (StopData.OpenLeftDoors || StopData.OpenRightDoors)
                            {
                                StopData.OpeningDoorsEndTime += OpeningDoorsTime;
                            }
                            StopData.ClosingDoorsStartTime = StopData.OpeningDoorsEndTime + StopData.StopTime;
                            StopData.DepartureTime         = StopData.ClosingDoorsStartTime;
                            if (StopData.OpenLeftDoors || StopData.OpenRightDoors)
                            {
                                StopData.DepartureTime += ClosingDoorsTime;
                            }
                        }

                        DeltaT = 0.0;
                        if (Data[i].Accelerate != 0.0)
                        {
                            DeltaT = (Data[i].TargetSpeed - Data[i].PassingSpeed) / Data[i].Accelerate;
                        }
                        Data[i].AccelerationEndTime = Data[i].DepartureTime + DeltaT;
                    }
                }
            }