Ejemplo n.º 1
0
		internal void KeyDown(VirtualKeys key) {
			switch (key) {
				case VirtualKeys.S:
					if (vState.Vehicle.Speed.KilometersPerHour == 0 && 
					    doorCls && 
					   	vState.Handles.PowerNotch == 0 && 
					   	vState.Handles.BrakeNotch == vSpec.BrakeNotches)
					{
						ATOCurrentState = ATOStates.START;
						ATOStartLocation = vState.Vehicle.Location;
						ATOStarted = true;
					}
					break;
				case VirtualKeys.L:
					ATOFail = true;
					break;
			}
		}
Ejemplo n.º 2
0
		internal void Elapse(ATP2.ATPElapseData data)
		{
			vState = data.ElapseData;
			
			Handles atpHandlesResult = data.ElapseData.Handles;
			
			// UNDONE:
			if (vState.TotalTime.Milliseconds >= lastTimeRefreshATOAccelerationRate.Milliseconds + 100) {
				ATO_AccelerationRate = (vState.Vehicle.Speed.KilometersPerHour - lastTimeRefreshATOAccelerationRate_SpeedKMHS) / (vState.TotalTime.Milliseconds - lastTimeRefreshATOAccelerationRate.Milliseconds) * 1000;
				
				lastTimeRefreshATOAccelerationRate_SpeedKMHS = vState.Vehicle.Speed.KilometersPerHour;
				lastTimeRefreshATOAccelerationRate = vState.TotalTime;
			}
//			vState.DebugMessage = "Accel:" + ATO_AccelerationRate + "km/h/s; " + vState.DebugMessage;
			
			// fail the ATO if handles fail whilst ATO running
			if (ATOStarted && 
			   	vState.Handles.PowerNotch != 0 && 
			   	vState.Handles.BrakeNotch != vSpec.BrakeNotches)
			{
				ATOFail = true;
			}
			
			// reset fail only if (1) ATO is not start and (2) train is steady and (3) handles are OK and (4) ATO is on fail state
			if (ATOFail && !ATOStarted && 
			    vState.Vehicle.Speed.KilometersPerHour == 0 && 
			   	vState.Handles.PowerNotch == 0 && 
			   	vState.Handles.BrakeNotch == vSpec.BrakeNotches)
			{
				ATOFail = false;
			}
			
			// what will happen if ATO fails?
			if (ATOFail) {
				vState.DebugMessage = "!ATO FAIL!";
				if (vState.Vehicle.Speed.KilometersPerHour == 0) {
					ATOFail = false;
					ATOStarted = false;
				} else {
					// emg beep beep beep
					ATOPower = 0;
					ATOBrake = vSpec.BrakeNotches + 1;
				}
			}
			// how is ATO working?
			else if (ATOStarted) {
				// jump to stop working if not powering and stopped
				// OK: ATOStates.START + ATOStates.POWER
				if (vState.Vehicle.Speed.KilometersPerHour == 0.0 && ATOCurrentState > ATOStates.POWER) {
					ATOStarted = false;
				}
				
				#region Analysis and Switch States
				// brake due to next speed flag
				if (data.CurrentTargetSpeed < prevTargetSpeed) {
					ATOCurrentState = ATOStates.BRAKE_SPEED;
				}
				// accelerate
				else if (data.CurrentPermittedSpeed > prevPermittedSpeed) {
					ATOCurrentState = ATOStates.POWER;
				}
				// brake due to arriving at next stop
				// if next stop is available
				else if (lastCompletedDockingIndex + 1 < Stations.Count) {
					// if next stop should stop
					if (Stations[lastCompletedDockingIndex + 1].DoorOpen > -2) {
						// arriving at platform
						// UNDONE: 
						double BrakingDistanceByPermittedSpeed = AccelerationPhysics.GetDisplacement(data.CurrentPermittedSpeed, 0, BrakeRate[ATP2.DefaultNormalBrakeNotch]);
						if (Stations[lastCompletedDockingIndex + 1].StopPosition - GeneralSettings.BrakeCurveHigh_ReservingDistance - vState.Vehicle.Location <= BrakingDistanceByPermittedSpeed) {
							if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 2) {
//								vState.DebugMessage += "S1:" + ATOStartLocation + " >= " + (Stations[lastCompletedDockingIndex + 1].StopPosition - BrakingDistanceByPermittedSpeed) + ", ";
								if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 5 && ATOStartLocation >= Stations[lastCompletedDockingIndex + 1].StopPosition - BrakingDistanceByPermittedSpeed) {
									vState.DebugMessage += "SPower, ";
									ATOCurrentState = ATOStates.POWER;
								} else {
									ATOCurrentState = ATOStates.COASTING;
								}
							} else {
								ATOCurrentState = ATOStates.BRAKE_STOP;
							}
						}
					}
				}
				
				// remember things for analysis on next frame
				if (data.CurrentTargetSpeed != prevTargetSpeed)
					prevTargetSpeed = data.CurrentTargetSpeed;
				
				if (data.CurrentPermittedSpeed != prevPermittedSpeed)
					prevPermittedSpeed = data.CurrentPermittedSpeed;
				
				if (data.CurrentEmergencyBrakeSpeed != prevEmergencyBrakeSpeed)
					prevEmergencyBrakeSpeed = data.CurrentEmergencyBrakeSpeed;
				#endregion
				
				#region Behaviour
				if (data.ATPFail) {
					ATOFail = true;
				} else if (!data.ATPBrakeApplying) {
					data.ElapseData.DebugMessage += ATOCurrentState.ToString() + ", ";
					switch (ATOCurrentState) {
						case ATOStates.START:
							if (vState.Vehicle.Speed.KilometersPerHour >= 1) {
								ATOCurrentState = ATOStates.POWER;
								goto case ATOStates.POWER;
							}
							ATOPower = vSpec.PowerNotches;
							ATOBrake = 0;
							break;
						case ATOStates.POWER:
							if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + atoProfiles[profileID].StopAcceleratingSpeed) {
								ATOCurrentState = ATOStates.COASTING;
								goto case ATOStates.COASTING;
							}
							
							ATOPower = vSpec.PowerNotches;
							ATOBrake = 0;
							break;
						case ATOStates.COASTING:
							if (atoProfiles[profileID].HoldSpeedNotCoasting) {
								goto case ATOStates.KEEPSPEED;
							}
							#region brake to hold speed?
							// if new to coasting state, reset brake notch
							if(lastFrame_ATOState != ATOCurrentState)
								ATOBrake = BrakeToHoldSpeedNotch = 0;
							
							// if notches are interrupted, then recount the timer
							if (lastFrame_ATOState != ATOCurrentState || 
								last1s_PowerNotch != lastFrame_PowerNotch || last1s_BrakeNotch != lastFrame_BrakeNotch) {
//								System.Windows.Forms.MessageBox.Show(lastCheckSpeedCoasting + "");
								lastCheckSpeedCoasting = vState.TotalTime;
								last1s_Speed = vState.Vehicle.Speed.KilometersPerHour;
								last1s_PowerNotch = lastFrame_BrakeNotch;
								last1s_BrakeNotch = lastFrame_BrakeNotch;
							}
							
							if (vState.TotalTime.Milliseconds >= lastCheckSpeedCoasting.Milliseconds + 1000) {
								if (vState.Vehicle.Speed.KilometersPerHour - last1s_Speed > 0) { // accelerating
									for (int i = BrakeRate.Length - 1; i >= 0; i--) {
										if (vState.Vehicle.Speed.KilometersPerHour - last1s_Speed >= BrakeRate[i] * -1) {
											ATOPower = 0;
											ATOBrake = BrakeToHoldSpeedNotch = i;
											break;
										}
									}
								} else {
									ATOBrake = BrakeToHoldSpeedNotch = 0;
								}
								lastCheckSpeedCoasting = vState.TotalTime;
								last1s_Speed = vState.Vehicle.Speed.KilometersPerHour;
								last1s_PowerNotch = ATOPower;
								last1s_BrakeNotch = ATOBrake;
							}
							#endregion
							#region slight slope that above command cannot detect
							else if (vState.Vehicle.Speed.KilometersPerHour <= data.CurrentPermittedSpeed && slightSlopeBrakeEnabled) {
								slightSlopeBrakeEnabled = false;
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch = 0;
							}
							else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 4) {
								vState.DebugMessage += "(S)";
								slightSlopeBrakeEnabled = true;
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch = 3;
							}
							else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 3) {
								vState.DebugMessage += "(S)";
								slightSlopeBrakeEnabled = true;
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch = 2;
							}
							else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 2) {
								vState.DebugMessage += "(S)";
								slightSlopeBrakeEnabled = true;
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch = 1;
							}
							#endregion
							
							if (BrakeToHoldSpeedNotch > 0)
								vState.DebugMessage += "(" + (vState.Vehicle.Speed.KilometersPerHour - last1s_Speed) + ")BrakeToHoldSpeed(" + BrakeToHoldSpeedNotch + "),";
							if (slightSlopeBrakeEnabled)
								vState.DebugMessage += "slightSlopeBrakeEnabled,";
							
							// TODO: power if too low speed?
							else if (vState.Vehicle.Speed.KilometersPerHour <= data.CurrentPermittedSpeed + atoProfiles[profileID].CoastingTooSlowForcePowerSpeed) {
								ATOCurrentState = ATOStates.POWER;
								goto case ATOStates.POWER;
							}
							else {
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch;
							}
							break;
						case ATOStates.KEEPSPEED:
							throw new NotImplementedException();
							if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + atoProfiles[profileID].StopAcceleratingSpeed) {
								PowerToHoldSpeedNotch = 0;
							}
							#region slight slope that above command cannot detect
							else if (vState.Vehicle.Speed.KilometersPerHour <= data.CurrentPermittedSpeed && slightSlopeBrakeEnabled) {
								slightSlopeBrakeEnabled = false;
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch = 0;
							}
							else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 4) {
								vState.DebugMessage += "(S)";
								slightSlopeBrakeEnabled = true;
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch = 3;
							}
							else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 3) {
								vState.DebugMessage += "(S)";
								slightSlopeBrakeEnabled = true;
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch = 2;
							}
							else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 2) {
								vState.DebugMessage += "(S)";
								slightSlopeBrakeEnabled = true;
								ATOPower = 0;
								ATOBrake = BrakeToHoldSpeedNotch = 1;
							}
							#endregion
							#region power to keep speed
							else if (true) {
								#region deceleration caused by gradient
								// Rate = 1000 * Y / X
								double pitchInPerMill_KEEPSPEED = gPtMem[gPtMem.CurrentIndex(vState.Vehicle.Location)].Pitch;
								// Acceleration due to gravity is 9.79 ms^-2
								double accelerationCausedByGradient_KEEPSPEED = 9.79 / (1 / (-1 * pitchInPerMill_KEEPSPEED / 1000));
								vState.DebugMessage += "pitch: " + pitchInPerMill_KEEPSPEED + "; DCBG: " + accelerationCausedByGradient_KEEPSPEED + ", ";
								#endregion
								
								#region calculation
								#endregion
							}
							#endregion
							
							// debug
							if (BrakeToHoldSpeedNotch > 0)
								vState.DebugMessage += "(" + (vState.Vehicle.Speed.KilometersPerHour - last1s_Speed) + ")BrakeToHoldSpeed(" + BrakeToHoldSpeedNotch + "),";
							if (slightSlopeBrakeEnabled)
								vState.DebugMessage += "slightSlopeBrakeEnabled,";
							
							ATOPower = PowerToHoldSpeedNotch;
							ATOBrake = 0;
							break;
						case ATOStates.BRAKE_SPEED:
							if (vState.Vehicle.Speed.KilometersPerHour <= data.CurrentTargetSpeed + atoProfiles[profileID].StopBrakingSpeed)
							{
								ATOCurrentState = ATOStates.COASTING;
								goto case ATOStates.COASTING;
							}
							
							ATOPower = 0;
							
							// TODO: deceleration baused by gradient
							//
							
							for (int i = 0; i < BrakeRate.Length; i++) {
								// brake rates are negative numbers
								if (Math.Abs(BrakeRate[i]) >= Math.Abs(AccelerationPhysics.GetAccelerationRate(data.CurrentTargetSpeed,
								                                           	vState.Vehicle.Speed.KilometersPerHour, 
								                                           	data.NextSpeedFlag.StartingLocation - vState.Vehicle.Location)))
								{
									ATOBrake = i;
									break;
								}
							}
							
							if (vState.Vehicle.Speed.KilometersPerHour > data.CurrentTargetSpeed + 4) {
								ATOBrake = vSpec.BrakeNotches;
							}
							
							break;
						case ATOStates.BRAKE_STOP:
							ATOPower = 0;
							
							// TODO: more accurate calculation for gradient
							#region deceleration caused by gradient
							// Rate = 1000 * Y / X
							double pitchInPerMill_BRAKE_STOP = gPtMem[gPtMem.CurrentIndex(vState.Vehicle.Location)].Pitch;
							// Acceleration due to gravity is 9.79 ms^-2
							double accelerationCausedByGradient_BRAKE_STOP = 9.79 / (1 / (-1 * pitchInPerMill_BRAKE_STOP / 1000));
							vState.DebugMessage += "pitch: " + pitchInPerMill_BRAKE_STOP + "; DCBG: " + accelerationCausedByGradient_BRAKE_STOP + ", ";
							#endregion
							
							#region calculation
							for (int i = 0; i < BrakeRate.Length; i++) {
								if (Stations[lastCompletedDockingIndex + 1].StopPosition - vState.Vehicle.Location <= GeneralSettings.BrakeCurveHigh_ChangeToLowDistance) {
									// brake rates are negative numbers
									if (Math.Abs(BrakeRate[i]) - accelerationCausedByGradient_BRAKE_STOP >= Math.Abs(AccelerationPhysics.GetAccelerationRate(0,
									                                            vState.Vehicle.Speed.KilometersPerHour, 
									                                            Stations[lastCompletedDockingIndex + 1].StopPosition - vState.Vehicle.Location)))
									{
										ATOBrake = i;
										break;
									}
								} else {
									// brake rates are negative numbers
									if (Math.Abs(BrakeRate[i]) - accelerationCausedByGradient_BRAKE_STOP >= Math.Abs(AccelerationPhysics.GetAccelerationRate(0,
									                                            vState.Vehicle.Speed.KilometersPerHour, 
									                                            Stations[lastCompletedDockingIndex + 1].StopPosition - vState.Vehicle.Location - GeneralSettings.BrakeCurveHigh_ReservingDistance)))
									{
										ATOBrake = i;
										break;
									}
								}
							}
							#endregion
							
							#region don't decelerate if speed is too low
							if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentTargetSpeed - 5) {
								resistBrakingNotch = vSpec.BrakeNotches;
							} else if (resistBrakingNotch == 2) {
								if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed - 3
								    && vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 1) {
									resistBrakingNotch = 1;
								} else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed - 1) {
									resistBrakingNotch = 0;
								}
							} else if (resistBrakingNotch == 1) {
								if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 4) {
									resistBrakingNotch = 2;
								} else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed - 1) {
									resistBrakingNotch = 0;
								}
							} else if (resistBrakingNotch == 0) {
								if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 4) {
									resistBrakingNotch = 2;
								} else if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 2) {
									resistBrakingNotch = 1;
								}
							}
							
							ATOBrake -= (ATOBrake - resistBrakingNotch < 0 ? 0 : resistBrakingNotch);
							
							// debug
							if (resistBrakingNotch > 0)
								vState.DebugMessage += "ForceB-" + resistBrakingNotch + ", ";
							#endregion
							
							break;
					}
				}
				#endregion
			} else {
				ATOPower = 0;
			   	ATOBrake = vSpec.BrakeNotches;
			}
			
			vState.Handles.PowerNotch = ATOPower;
			vState.Handles.BrakeNotch = ATOBrake; 
			
			lastFrame_ATOState = ATOCurrentState;
			lastFrame_Speed = vState.Vehicle.Speed.KilometersPerHour;
			lastFrame_PowerNotch = ATOPower;
			lastFrame_BrakeNotch = ATOBrake;
		}