From aafe09c12a8e888179aeca2d3c1136705cbb2ef3 Mon Sep 17 00:00:00 2001
From: Michael Krisper <michael.krisper@tugraz.at>
Date: Tue, 23 Feb 2016 14:44:40 +0100
Subject: [PATCH] measured speed gear

---
 .../Simulation/Impl/PowertrainBuilder.cs      |   2 +-
 .../Impl/CombustionEngine.cs                  |   1 +
 .../SimulationComponent/Impl/CycleGearbox.cs  | 288 ++++++++++++++++++
 .../SimulationComponent/Impl/Gearbox.cs       | 267 ----------------
 .../Impl/PowertrainDrivingCycle.cs            | 227 +-------------
 VectoCore/VectoCore.csproj                    |   1 +
 .../Simulation/MeasuredSpeedModeTest.cs       |  21 +-
 .../MeasuredSpeed/MeasuredSpeedGear.vecto     |  10 +-
 VectoCoreTest/Utils/ResultFileHelper.cs       |  13 +-
 9 files changed, 314 insertions(+), 516 deletions(-)
 create mode 100644 VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs

diff --git a/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
index 9beee35306..d0609afbec 100644
--- a/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
+++ b/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
@@ -180,7 +180,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 			Debug.Assert(data.Cycle.CycleType == CycleType.MeasuredSpeedGear);
 
 			var container = new VehicleContainer(_modData, _sumWriter, ExecutionMode.Engineering) { RunData = data };
-			var cycle = new MeasuredSpeedGearDrivingCycle(container, data.Cycle);
+			var cycle = new MeasuredSpeedDrivingCycle(container, data.Cycle);
 			var vehicle = AddComponent(cycle, new Vehicle(container, data.VehicleData));
 			var wheels = AddComponent(vehicle,
 				new Wheels(container, data.VehicleData.DynamicTyreRadius, data.VehicleData.WheelsInertia));
diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
index 22f76e3e63..d512a473a3 100644
--- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
@@ -414,6 +414,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			//public Second AbsTime { get; set; }
 
+			// ReSharper disable once InconsistentNaming
 			public Second dt { get; set; }
 
 			public PerSecond EngineSpeed { get; set; }
diff --git a/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs b/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs
new file mode 100644
index 0000000000..23df337fa8
--- /dev/null
+++ b/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs
@@ -0,0 +1,288 @@
+using System.Diagnostics;
+using TUGraz.VectoCore.Configuration;
+using TUGraz.VectoCore.Exceptions;
+using TUGraz.VectoCore.Models.Connector.Ports;
+using TUGraz.VectoCore.Models.Connector.Ports.Impl;
+using TUGraz.VectoCore.Models.Simulation;
+using TUGraz.VectoCore.Models.Simulation.Data;
+using TUGraz.VectoCore.Models.Simulation.DataBus;
+using TUGraz.VectoCore.Models.Simulation.Impl;
+using TUGraz.VectoCore.Models.SimulationComponent.Data;
+using TUGraz.VectoCore.OutputData;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
+{
+	public class CycleGearbox : StatefulVectoSimulationComponent<Gearbox.GearboxState>, IGearbox, ITnOutPort, ITnInPort,
+		IClutchInfo
+	{
+		/// <summary>
+		/// The next port.
+		/// </summary>
+		protected ITnOutPort NextComponent;
+
+		/// <summary>
+		/// The data and settings for the gearbox.
+		/// </summary>
+		internal readonly GearboxData ModelData;
+
+		public bool ClutchClosed(Second absTime)
+		{
+			return DataBus.CycleData.LeftSample.Gear != 0;
+		}
+
+		public CycleGearbox(IVehicleContainer container, GearboxData gearboxModelData)
+			: base(container)
+		{
+			ModelData = gearboxModelData;
+		}
+
+		#region ITnInProvider
+
+		public ITnInPort InPort()
+		{
+			return this;
+		}
+
+		#endregion
+
+		#region ITnOutProvider
+
+		[DebuggerHidden]
+		public ITnOutPort OutPort()
+		{
+			return this;
+		}
+
+		#endregion
+
+		#region IGearboxCockpit
+
+		/// <summary>
+		/// The current gear.
+		/// </summary>
+		public uint Gear { get; private set; }
+
+		[DebuggerHidden]
+		public MeterPerSecond StartSpeed
+		{
+			get { return ModelData.StartSpeed; }
+		}
+
+		[DebuggerHidden]
+		public MeterPerSquareSecond StartAcceleration
+		{
+			get { return ModelData.StartAcceleration; }
+		}
+
+		public FullLoadCurve GearFullLoadCurve
+		{
+			get { return Gear == 0 ? null : ModelData.Gears[Gear].FullLoadCurve; }
+		}
+
+		#endregion
+
+		#region ITnInPort
+
+		void ITnInPort.Connect(ITnOutPort other)
+		{
+			NextComponent = other;
+		}
+
+		#endregion
+
+		#region ITnOutPort
+
+		public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity)
+		{
+			var dt = Constants.SimulationSettings.TargetTimeInterval;
+
+			Gear = DataBus.CycleData.LeftSample.Gear;
+
+			PerSecond inAngularVelocity;
+			NewtonMeter inTorque;
+
+			if (Gear != 0) {
+				inAngularVelocity = outAngularVelocity * ModelData.Gears[Gear].Ratio;
+				inTorque = ModelData.Gears[Gear].LossMap.GetInTorque(inAngularVelocity, outTorque);
+
+				var torqueLossInertia = outAngularVelocity.IsEqual(0)
+					? 0.SI<NewtonMeter>()
+					: Formulas.InertiaPower(inAngularVelocity, PreviousState.InAngularVelocity, ModelData.Inertia, dt) /
+					inAngularVelocity;
+
+				inTorque += torqueLossInertia;
+			} else {
+				inTorque = 0.SI<NewtonMeter>();
+				inAngularVelocity = 0.RPMtoRad();
+			}
+			PreviousState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity);
+			PreviousState.InertiaTorqueLossOut = 0.SI<NewtonMeter>();
+			PreviousState.Gear = Gear;
+
+			var response = NextComponent.Initialize(inTorque, inAngularVelocity);
+			response.GearboxPowerRequest = inTorque * inAngularVelocity;
+			return response;
+		}
+
+		internal ResponseDryRun Initialize(uint gear, NewtonMeter outTorque, PerSecond outAngularVelocity)
+		{
+			var inAngularVelocity = outAngularVelocity * ModelData.Gears[gear].Ratio;
+			var inTorque = ModelData.Gears[gear].LossMap.GetInTorque(inAngularVelocity, outTorque);
+
+			if (!inAngularVelocity.IsEqual(0)) {
+				var alpha = (ModelData.Inertia.IsEqual(0))
+					? 0.SI<PerSquareSecond>()
+					: outTorque / ModelData.Inertia;
+
+				var inertiaPowerLoss = Formulas.InertiaPower(inAngularVelocity, alpha, ModelData.Inertia,
+					Constants.SimulationSettings.TargetTimeInterval);
+				inTorque += inertiaPowerLoss / inAngularVelocity;
+			}
+
+			var response = NextComponent.Initialize(inTorque, inAngularVelocity);
+			response.Switch().
+				Case<ResponseSuccess>().
+				Case<ResponseOverload>().
+				Case<ResponseUnderload>().
+				Default(r => { throw new UnexpectedResponseException("Gearbox.Initialize", r); });
+
+			var fullLoadGearbox = ModelData.Gears[gear].FullLoadCurve.FullLoadStationaryTorque(inAngularVelocity) *
+								inAngularVelocity;
+			var fullLoadEngine = DataBus.EngineStationaryFullPower(inAngularVelocity);
+
+			var fullLoad = VectoMath.Min(fullLoadGearbox, fullLoadEngine);
+
+			return new ResponseDryRun {
+				Source = this,
+				EnginePowerRequest = response.EnginePowerRequest,
+				ClutchPowerRequest = response.ClutchPowerRequest,
+				GearboxPowerRequest = outTorque * outAngularVelocity,
+				DeltaFullLoad = response.EnginePowerRequest - fullLoad
+			};
+		}
+
+		/// <summary>
+		/// Requests the Gearbox to deliver torque and angularVelocity
+		/// </summary>
+		/// <returns>
+		/// <list type="bullet">
+		/// <item><description>ResponseDryRun</description></item>
+		/// <item><description>ResponseOverload</description></item>
+		/// <item><description>ResponseGearshift</description></item>
+		/// </list>
+		/// </returns>
+		public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun)
+		{
+			Log.Debug("Gearbox Power Request: torque: {0}, angularVelocity: {1}", outTorque, outAngularVelocity);
+			Gear = DataBus.CycleData.LeftSample.Gear;
+
+			var avgOutAngularVelocity = (PreviousState.OutAngularVelocity + outAngularVelocity) / 2.0;
+
+			if (Gear == 0) {
+				//disengaged
+				if (dryRun) {
+					// if gearbox is disengaged the 0-line is the limit for drag and full load
+					return new ResponseDryRun {
+						Source = this,
+						GearboxPowerRequest = outTorque * avgOutAngularVelocity,
+						DeltaDragLoad = outTorque * avgOutAngularVelocity,
+						DeltaFullLoad = outTorque * avgOutAngularVelocity,
+					};
+				}
+
+				if ((outTorque * avgOutAngularVelocity).IsGreater(0.SI<Watt>(),
+					Constants.SimulationSettings.EnginePowerSearchTolerance)) {
+					return new ResponseOverload {
+						Source = this,
+						Delta = outTorque * avgOutAngularVelocity,
+						GearboxPowerRequest = outTorque * avgOutAngularVelocity
+					};
+				}
+
+				if ((outTorque * avgOutAngularVelocity).IsSmaller(0.SI<Watt>(),
+					Constants.SimulationSettings.EnginePowerSearchTolerance)) {
+					return new ResponseUnderload {
+						Source = this,
+						Delta = outTorque * avgOutAngularVelocity,
+						GearboxPowerRequest = outTorque * avgOutAngularVelocity
+					};
+				}
+
+				CurrentState.SetState(0.SI<NewtonMeter>(), 0.RPMtoRad(), outTorque, outAngularVelocity);
+				CurrentState.Gear = Gear;
+
+				var disengagedResponse = NextComponent.Request(absTime, dt, 0.SI<NewtonMeter>(), null);
+				disengagedResponse.GearboxPowerRequest = outTorque * avgOutAngularVelocity;
+				return disengagedResponse;
+			} else {
+				//engaged
+				var inTorque = ModelData.Gears[Gear].LossMap.GetInTorque(avgOutAngularVelocity * ModelData.Gears[Gear].Ratio,
+					outTorque);
+				var inAngularVelocity = outAngularVelocity * ModelData.Gears[Gear].Ratio;
+
+				if (dryRun) {
+					var dryRunResponse = NextComponent.Request(absTime, dt, inTorque, inAngularVelocity, true);
+					dryRunResponse.GearboxPowerRequest = outTorque * avgOutAngularVelocity;
+					return dryRunResponse;
+				}
+
+				// this code has to be _after_ the check for a potential gear-shift!
+				// (the above block issues dry-run requests and thus may update the CurrentState!)
+				CurrentState.TransmissionTorqueLoss = inTorque - (outTorque / ModelData.Gears[Gear].Ratio);
+				if (!inAngularVelocity.IsEqual(0)) {
+					// MQ 19.2.2016: check! inertia is related to output side, torque loss accounts to input side
+					CurrentState.InertiaTorqueLossOut =
+						Formulas.InertiaPower(outAngularVelocity, PreviousState.OutAngularVelocity, ModelData.Inertia, dt) /
+						avgOutAngularVelocity;
+					inTorque += CurrentState.InertiaTorqueLossOut / ModelData.Gears[Gear].Ratio;
+				} else {
+					CurrentState.InertiaTorqueLossOut = 0.SI<NewtonMeter>();
+				}
+				CurrentState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity);
+				CurrentState.Gear = Gear;
+				// end critical section
+
+				var response = NextComponent.Request(absTime, dt, inTorque, inAngularVelocity);
+				response.GearboxPowerRequest = outTorque * avgOutAngularVelocity;
+				return response;
+			}
+		}
+
+		#endregion
+
+		#region VectoSimulationComponent
+
+		protected override void DoWriteModalResults(IModalDataContainer container)
+		{
+			container[ModalResultField.Gear] = Gear;
+
+			var avgInAngularSpeed = Gear != 0
+				? (PreviousState.OutAngularVelocity + CurrentState.OutAngularVelocity) / 2.0 * ModelData.Gears[Gear].Ratio
+				: 0.RPMtoRad();
+
+			container[ModalResultField.P_gbx_loss] = CurrentState.TransmissionTorqueLoss * avgInAngularSpeed;
+			container[ModalResultField.P_gbx_inertia] = CurrentState.InertiaTorqueLossOut * avgInAngularSpeed;
+			container[ModalResultField.P_gbx_in] = CurrentState.InTorque * avgInAngularSpeed;
+		}
+
+		protected override void DoCommitSimulationStep()
+		{
+			if (Gear != 0) {
+				if (ModelData.Gears[Gear].LossMap.Extrapolated) {
+					Log.Warn("Gear {0} LossMap data was extrapolated: range for loss map is not sufficient.", Gear);
+
+					if (DataBus.ExecutionMode == ExecutionMode.Declaration) {
+						// todo (MK, 2016-02-22): add operating point and loss values for easier debugging
+						throw new VectoException(
+							"Gear {0} LossMap data was extrapolated in Declaration Mode: range for loss map is not sufficient.", Gear);
+					}
+				}
+			}
+
+			AdvanceState();
+		}
+
+		#endregion
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
index 8a963ebc26..c9a2111e12 100644
--- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
@@ -421,271 +421,4 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public uint Gear;
 		}
 	}
-
-
-	public class CycleGearbox : StatefulVectoSimulationComponent<Gearbox.GearboxState>, IGearbox, ITnOutPort, ITnInPort,
-		IClutchInfo
-	{
-		/// <summary>
-		/// The next port.
-		/// </summary>
-		protected ITnOutPort NextComponent;
-
-		/// <summary>
-		/// The data and settings for the gearbox.
-		/// </summary>
-		internal readonly GearboxData ModelData;
-
-		public bool ClutchClosed(Second absTime)
-		{
-			return DataBus.CycleData.LeftSample.Gear != 0;
-		}
-
-		public CycleGearbox(IVehicleContainer container, GearboxData gearboxModelData)
-			: base(container)
-		{
-			ModelData = gearboxModelData;
-		}
-
-		#region ITnInProvider
-
-		public ITnInPort InPort()
-		{
-			return this;
-		}
-
-		#endregion
-
-		#region ITnOutProvider
-
-		[DebuggerHidden]
-		public ITnOutPort OutPort()
-		{
-			return this;
-		}
-
-		#endregion
-
-		#region IGearboxCockpit
-
-		/// <summary>
-		/// The current gear.
-		/// </summary>
-		public uint Gear { get; private set; }
-
-		[DebuggerHidden]
-		public MeterPerSecond StartSpeed
-		{
-			get { return ModelData.StartSpeed; }
-		}
-
-		[DebuggerHidden]
-		public MeterPerSquareSecond StartAcceleration
-		{
-			get { return ModelData.StartAcceleration; }
-		}
-
-		public FullLoadCurve GearFullLoadCurve
-		{
-			get { return Gear == 0 ? null : ModelData.Gears[Gear].FullLoadCurve; }
-		}
-
-		#endregion
-
-		#region ITnOutPort
-
-		public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity)
-		{
-			var dt = Constants.SimulationSettings.TargetTimeInterval;
-
-			Gear = DataBus.CycleData.LeftSample.Gear;
-
-			var inAngularVelocity = outAngularVelocity * ModelData.Gears[Gear].Ratio;
-			var inTorque = ModelData.Gears[Gear].LossMap.GetInTorque(inAngularVelocity, outTorque);
-
-			var torqueLossInertia = outAngularVelocity.IsEqual(0)
-				? 0.SI<NewtonMeter>()
-				: Formulas.InertiaPower(inAngularVelocity, PreviousState.InAngularVelocity, ModelData.Inertia, dt) /
-				inAngularVelocity;
-
-			inTorque += torqueLossInertia;
-
-			PreviousState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity);
-			PreviousState.InertiaTorqueLossOut = 0.SI<NewtonMeter>();
-			PreviousState.Gear = Gear;
-
-			var response = NextComponent.Initialize(inTorque, inAngularVelocity);
-			response.GearboxPowerRequest = inTorque * inAngularVelocity;
-			return response;
-		}
-
-		internal ResponseDryRun Initialize(uint gear, NewtonMeter outTorque, PerSecond outAngularVelocity)
-		{
-			var inAngularVelocity = outAngularVelocity * ModelData.Gears[gear].Ratio;
-			var inTorque = ModelData.Gears[gear].LossMap.GetInTorque(inAngularVelocity, outTorque);
-
-			if (!inAngularVelocity.IsEqual(0)) {
-				var alpha = (ModelData.Inertia.IsEqual(0))
-					? 0.SI<PerSquareSecond>()
-					: outTorque / ModelData.Inertia;
-
-				var inertiaPowerLoss = Formulas.InertiaPower(inAngularVelocity, alpha, ModelData.Inertia,
-					Constants.SimulationSettings.TargetTimeInterval);
-				inTorque += inertiaPowerLoss / inAngularVelocity;
-			}
-
-			var response = NextComponent.Initialize(inTorque, inAngularVelocity);
-			response.Switch().
-				Case<ResponseSuccess>().
-				Case<ResponseOverload>().
-				Case<ResponseUnderload>().
-				Default(r => { throw new UnexpectedResponseException("Gearbox.Initialize", r); });
-
-			var fullLoadGearbox = ModelData.Gears[gear].FullLoadCurve.FullLoadStationaryTorque(inAngularVelocity) *
-								inAngularVelocity;
-			var fullLoadEngine = DataBus.EngineStationaryFullPower(inAngularVelocity);
-
-			var fullLoad = VectoMath.Min(fullLoadGearbox, fullLoadEngine);
-
-			return new ResponseDryRun {
-				Source = this,
-				EnginePowerRequest = response.EnginePowerRequest,
-				ClutchPowerRequest = response.ClutchPowerRequest,
-				GearboxPowerRequest = outTorque * outAngularVelocity,
-				DeltaFullLoad = response.EnginePowerRequest - fullLoad
-			};
-		}
-
-		/// <summary>
-		/// Requests the Gearbox to deliver torque and angularVelocity
-		/// </summary>
-		/// <returns>
-		/// <list type="bullet">
-		/// <item><description>ResponseDryRun</description></item>
-		/// <item><description>ResponseOverload</description></item>
-		/// <item><description>ResponseGearshift</description></item>
-		/// </list>
-		/// </returns>
-		public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun)
-		{
-			Log.Debug("Gearbox Power Request: torque: {0}, angularVelocity: {1}", outTorque, outAngularVelocity);
-			Gear = DataBus.CycleData.LeftSample.Gear;
-
-			var avgOutAngularVelocity = (PreviousState.OutAngularVelocity + outAngularVelocity) / 2.0;
-
-			if (Gear == 0) {
-				//disengaged
-				if (dryRun) {
-					// if gearbox is disengaged the 0-line is the limit for drag and full load
-					return new ResponseDryRun {
-						Source = this,
-						GearboxPowerRequest = outTorque * avgOutAngularVelocity,
-						DeltaDragLoad = outTorque * avgOutAngularVelocity,
-						DeltaFullLoad = outTorque * avgOutAngularVelocity,
-					};
-				}
-
-				if ((outTorque * avgOutAngularVelocity).IsGreater(0.SI<Watt>(),
-					Constants.SimulationSettings.EnginePowerSearchTolerance)) {
-					return new ResponseOverload {
-						Source = this,
-						Delta = outTorque * avgOutAngularVelocity,
-						GearboxPowerRequest = outTorque * avgOutAngularVelocity
-					};
-				}
-
-				if ((outTorque * avgOutAngularVelocity).IsSmaller(0.SI<Watt>(),
-					Constants.SimulationSettings.EnginePowerSearchTolerance)) {
-					return new ResponseUnderload {
-						Source = this,
-						Delta = outTorque * avgOutAngularVelocity,
-						GearboxPowerRequest = outTorque * avgOutAngularVelocity
-					};
-				}
-
-				CurrentState.SetState(0.SI<NewtonMeter>(), outAngularVelocity * ModelData.Gears[PreviousState.Gear].Ratio, outTorque,
-					outAngularVelocity);
-				CurrentState.Gear = Gear;
-
-				var disengagedResponse = NextComponent.Request(absTime, dt, 0.SI<NewtonMeter>(), null);
-				disengagedResponse.GearboxPowerRequest = outTorque * avgOutAngularVelocity;
-				return disengagedResponse;
-			} else {
-				//engaged
-				var inTorque = ModelData.Gears[Gear].LossMap.GetInTorque(avgOutAngularVelocity * ModelData.Gears[Gear].Ratio,
-					outTorque);
-				var inAngularVelocity = outAngularVelocity * ModelData.Gears[Gear].Ratio;
-
-				if (dryRun) {
-					var dryRunResponse = NextComponent.Request(absTime, dt, inTorque, inAngularVelocity, true);
-					dryRunResponse.GearboxPowerRequest = outTorque * (PreviousState.OutAngularVelocity + outAngularVelocity) / 2.0;
-					return dryRunResponse;
-				}
-
-				// this code has to be _after_ the check for a potential gear-shift!
-				// (the above block issues dry-run requests and thus may update the CurrentState!)
-				CurrentState.TransmissionTorqueLoss = inTorque - (outTorque / ModelData.Gears[Gear].Ratio);
-				if (!inAngularVelocity.IsEqual(0)) {
-					// MQ 19.2.2016: check! inertia is related to output side, torque loss accounts to input side
-					CurrentState.InertiaTorqueLossOut =
-						Formulas.InertiaPower(outAngularVelocity, PreviousState.OutAngularVelocity, ModelData.Inertia, dt) /
-						avgOutAngularVelocity;
-					inTorque += CurrentState.InertiaTorqueLossOut / ModelData.Gears[Gear].Ratio;
-				} else {
-					CurrentState.InertiaTorqueLossOut = 0.SI<NewtonMeter>();
-				}
-				CurrentState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity);
-				CurrentState.Gear = Gear;
-				// end critical section
-
-				var response = NextComponent.Request(absTime, dt, inTorque, inAngularVelocity);
-				response.GearboxPowerRequest = outTorque * (PreviousState.OutAngularVelocity + CurrentState.OutAngularVelocity) /
-												2.0;
-				return response;
-			}
-		}
-
-		#endregion
-
-		#region ITnInPort
-
-		void ITnInPort.Connect(ITnOutPort other)
-		{
-			NextComponent = other;
-		}
-
-		#endregion
-
-		#region VectoSimulationComponent
-
-		protected override void DoWriteModalResults(IModalDataContainer container)
-		{
-			var avgInAngularSpeed = (PreviousState.OutAngularVelocity + CurrentState.OutAngularVelocity) / 2.0 *
-									ModelData.Gears[Gear].Ratio;
-
-			container[ModalResultField.Gear] = Gear;
-			container[ModalResultField.P_gbx_loss] = CurrentState.TransmissionTorqueLoss * avgInAngularSpeed;
-			container[ModalResultField.P_gbx_inertia] = CurrentState.InertiaTorqueLossOut * avgInAngularSpeed;
-			container[ModalResultField.P_gbx_in] = CurrentState.InTorque * avgInAngularSpeed;
-		}
-
-		protected override void DoCommitSimulationStep()
-		{
-			if (Gear != 0) {
-				if (ModelData.Gears[Gear].LossMap.Extrapolated) {
-					Log.Warn("Gear {0} LossMap data was extrapolated: range for loss map is not sufficient.", Gear);
-
-					if (DataBus.ExecutionMode == ExecutionMode.Declaration) {
-						// todo (MK, 2016-02-22): add operating point and loss values for easier debugging
-						throw new VectoException(
-							"Gear {0} LossMap data was extrapolated in Declaration Mode: range for loss map is not sufficient.", Gear);
-					}
-				}
-			}
-
-			AdvanceState();
-		}
-
-		#endregion
-	}
 }
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs
index c89317fc39..b86c492511 100644
--- a/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs
@@ -16,11 +16,8 @@
 * limitations under the Licence.
 */
 
-using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.Linq;
-using System.Runtime.CompilerServices;
 using TUGraz.VectoCore.Configuration;
 using TUGraz.VectoCore.Exceptions;
 using TUGraz.VectoCore.Models.Connector.Ports;
@@ -250,204 +247,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		}
 	}
 
-
-	/// <summary>
-	/// Driving Cycle for the Measured Speed Gear driving cycle.
-	/// </summary>
-	public class MeasuredSpeedGearDrivingCycle : VectoSimulationComponent, IDriverInfo, IDrivingCycleInfo,
-		IDriverDemandInProvider,
-		IDriverDemandInPort, ISimulationOutProvider, ISimulationOutPort, IClutchInfo
-	{
-		protected DrivingCycleData Data;
-		protected IDriverDemandOutPort NextComponent;
-		protected IEnumerator<DrivingCycleData.DrivingCycleEntry> RightSample { get; set; }
-		protected IEnumerator<DrivingCycleData.DrivingCycleEntry> LeftSample { get; set; }
-		private bool initialize;
-
-		protected Second AbsTime { get; set; }
-
-		/// <summary>
-		/// Initializes a new instance of the <see cref="PowertrainDrivingCycle"/> class.
-		/// </summary>
-		/// <param name="container">The container.</param>
-		/// <param name="cycle">The cycle.</param>
-		public MeasuredSpeedGearDrivingCycle(IVehicleContainer container, DrivingCycleData cycle)
-			: base(container)
-		{
-			Data = cycle;
-			LeftSample = Data.Entries.GetEnumerator();
-			LeftSample.MoveNext();
-
-			RightSample = Data.Entries.GetEnumerator();
-			RightSample.MoveNext();
-			RightSample.MoveNext();
-		}
-
-		#region IDriverDemandInProvider
-
-		public IDriverDemandInPort InPort()
-		{
-			return this;
-		}
-
-		#endregion
-
-		#region ISimulationOutProvider
-
-		public ISimulationOutPort OutPort()
-		{
-			return this;
-		}
-
-		#endregion
-
-		#region ISimulationOutPort
-
-		public IResponse Request(Second absTime, Meter ds)
-		{
-			throw new VectoSimulationException("MeasuredSpeed Cycle can not handle distance request.");
-		}
-
-		public virtual IResponse Request(Second absTime, Second dt)
-		{
-			// cycle finished (no more entries in cycle)
-			if (RightSample.Current == null || LeftSample.Current == null) {
-				return new ResponseCycleFinished { AbsTime = absTime, Source = this };
-			}
-
-			// interval exceeded
-			if (RightSample.Current != null && (absTime + dt).IsGreater(RightSample.Current.Time)) {
-				return new ResponseFailTimeInterval {
-					AbsTime = absTime,
-					Source = this,
-					DeltaT = RightSample.Current.Time - absTime
-				};
-			}
-
-			var delta_v = RightSample.Current.VehicleTargetSpeed - DataBus.VehicleSpeed;
-			var delta_t = RightSample.Current.Time - LeftSample.Current.Time;
-			var acceleration = delta_v / delta_t;
-			var gradient = LeftSample.Current.RoadGradient;
-
-			var response = NextComponent.Request(absTime, dt, acceleration, gradient);
-			var firstResponse = response;
-
-			response.Switch()
-				.Case<ResponseUnderload>(r => {
-					DataBus.BrakePower = SearchAlgorithm.Search(DataBus.BrakePower, -r.Delta, -r.Delta,
-						getYValue: result => ((ResponseDryRun)result).DeltaDragLoad,
-						evaluateFunction: x => {
-							DataBus.BrakePower = x;
-							return NextComponent.Request(absTime, dt, acceleration, gradient, true);
-						},
-						criterion: y => ((ResponseDryRun)y).DeltaDragLoad.Abs() < Constants.SimulationSettings.EnginePowerSearchTolerance);
-					response = NextComponent.Request(absTime, dt, acceleration, gradient);
-				})
-				.Case<ResponseOverload>(r => {
-					acceleration = SearchAlgorithm.Search(acceleration, r.Delta, -0.5.SI<MeterPerSquareSecond>(),
-						getYValue: result => ((ResponseDryRun)result).DeltaFullLoad,
-						evaluateFunction: x => NextComponent.Request(absTime, dt, x, gradient, true),
-						criterion: y => ((ResponseDryRun)y).DeltaFullLoad.Abs() < Constants.SimulationSettings.EnginePowerSearchTolerance);
-					response = NextComponent.Request(absTime, dt, acceleration, gradient);
-				})
-				.Case<ResponseSuccess>(() => { })
-				.Default(
-					r => { throw new UnexpectedResponseException("PowertrainDrivingCycle received an unexpected response.", r); });
-
-			if (!(response is ResponseSuccess)) {
-				throw new UnexpectedResponseException("PowertrainDrivingCycle received an unexpected response.", response);
-			}
-
-			AbsTime = absTime + dt;
-			return response;
-		}
-
-		public IResponse Initialize()
-		{
-			var first = Data.Entries.First();
-
-			AbsTime = first.Time;
-
-			initialize = true;
-
-			if (first.VehicleTargetSpeed.IsEqual(0)) {
-				var retVal = NextComponent.Initialize(DataBus.StartSpeed, first.RoadGradient, DataBus.StartAcceleration);
-				if (!(retVal is ResponseSuccess)) {
-					throw new UnexpectedResponseException("Couldn't find start gear.", retVal);
-				}
-			}
-
-			var response = NextComponent.Initialize(first.VehicleTargetSpeed, first.RoadGradient);
-			response.AbsTime = AbsTime;
-
-			initialize = false;
-			return response;
-		}
-
-		public string CycleName
-		{
-			get { return Data.Name; }
-		}
-
-		public double Progress
-		{
-			get { return AbsTime.Value() / Data.Entries.Last().Time.Value(); }
-		}
-
-		#endregion
-
-		#region IDriverDemandInPort
-
-		void IDriverDemandInPort.Connect(IDriverDemandOutPort other)
-		{
-			NextComponent = other;
-		}
-
-		#endregion
-
-		#region VectoSimulationComponent
-
-		protected override void DoCommitSimulationStep()
-		{
-			if ((RightSample.Current == null) || AbsTime.IsGreaterOrEqual(RightSample.Current.Time)) {
-				RightSample.MoveNext();
-				LeftSample.MoveNext();
-			}
-		}
-
-		#endregion
-
-		public CycleData CycleData
-		{
-			get
-			{
-				return new CycleData {
-					AbsTime = LeftSample.Current.Time,
-					AbsDistance = null,
-					LeftSample = LeftSample.Current,
-					RightSample = RightSample.Current,
-				};
-			}
-		}
-
-		protected override void DoWriteModalResults(IModalDataContainer container) {}
-
-		public bool VehicleStopped
-		{
-			get { return !initialize && LeftSample.Current.VehicleTargetSpeed.IsEqual(0); }
-		}
-
-		public DrivingBehavior DrivingBehavior
-		{
-			get { return DrivingBehavior.Driving; }
-		}
-
-		public virtual bool ClutchClosed(Second absTime)
-		{
-			return (RightSample.Current != null ? RightSample.Current.Gear : LeftSample.Current.Gear) != 0;
-		}
-	}
-
 	/// <summary>
 	/// Driving Cycle for the Measured Speed Gear driving cycle.
 	/// </summary>
@@ -456,7 +255,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 	{
 		protected DrivingCycleData Data;
 		protected IDriverDemandOutPort NextComponent;
-		private bool isInitializing = false;
+		private bool _isInitializing;
 		protected IEnumerator<DrivingCycleData.DrivingCycleEntry> RightSample { get; set; }
 		protected IEnumerator<DrivingCycleData.DrivingCycleEntry> LeftSample { get; set; }
 
@@ -522,9 +321,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 
 			// calc acceleration from speed diff vehicle to cycle
-			var delta_v = RightSample.Current.VehicleTargetSpeed - DataBus.VehicleSpeed;
-			var delta_t = RightSample.Current.Time - LeftSample.Current.Time;
-			var acceleration = delta_v / delta_t;
+			var deltaV = RightSample.Current.VehicleTargetSpeed - DataBus.VehicleSpeed;
+			var deltaT = RightSample.Current.Time - LeftSample.Current.Time;
+			var acceleration = deltaV / deltaT;
 			var gradient = LeftSample.Current.RoadGradient;
 
 			var response = NextComponent.Request(absTime, dt, acceleration, gradient);
@@ -532,13 +331,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				response = NextComponent.Request(absTime, dt, acceleration, gradient);
 			}
 
-
-			// todo mk-2016-02-19: remove after finished working on measured speed cycle
-			var debugFirstResponse = response;
-
-
-			//var delta = DataBus.ClutchClosed(absTime) ? response.DeltaDragLoad : response.GearboxPowerRequest
-
 			response.Switch()
 				.Case<ResponseUnderload>(r => {
 					DataBus.BrakePower = SearchAlgorithm.Search(DataBus.BrakePower, r.Delta, -r.Delta,
@@ -547,9 +339,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 							DataBus.BrakePower = x;
 							return NextComponent.Request(absTime, dt, acceleration, gradient, true);
 						},
-						criterion:
-							y =>
-								((ResponseDryRun)y).DeltaDragLoad.IsEqual(0.SI<Watt>(), Constants.SimulationSettings.EnginePowerSearchTolerance));
+						criterion: y =>
+							((ResponseDryRun)y).DeltaDragLoad.IsEqual(0.SI<Watt>(), Constants.SimulationSettings.EnginePowerSearchTolerance));
 					response = NextComponent.Request(absTime, dt, acceleration, gradient);
 				})
 				.Case<ResponseOverload>(r => {
@@ -578,7 +369,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			AbsTime = first.Time;
 
-			isInitializing = true;
+			_isInitializing = true;
 
 			IResponse response;
 			response = NextComponent.Initialize(first.VehicleTargetSpeed, first.RoadGradient);
@@ -586,7 +377,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				throw new UnexpectedResponseException("Couldn't find start gear.", response);
 			}
 
-			isInitializing = false;
+			_isInitializing = false;
 
 			response.AbsTime = AbsTime;
 			return response;
@@ -642,7 +433,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		public bool VehicleStopped
 		{
-			get { return !isInitializing && LeftSample.Current.VehicleTargetSpeed.IsEqual(0); }
+			get { return !_isInitializing && LeftSample.Current.VehicleTargetSpeed.IsEqual(0); }
 		}
 
 		public DrivingBehavior DrivingBehavior
diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj
index 0dbe72cdea..1439699f1a 100644
--- a/VectoCore/VectoCore.csproj
+++ b/VectoCore/VectoCore.csproj
@@ -170,6 +170,7 @@
     <Compile Include="Models\SimulationComponent\IDrivingCycleInfo.cs" />
     <Compile Include="Models\SimulationComponent\IEngineAuxPort.cs" />
     <Compile Include="Models\SimulationComponent\Impl\Brakes.cs" />
+    <Compile Include="Models\SimulationComponent\Impl\CycleGearbox.cs" />
     <Compile Include="Models\SimulationComponent\Impl\DefaultDriverStrategy.cs" />
     <Compile Include="Models\SimulationComponent\Impl\DummyRetarder.cs" />
     <Compile Include="Models\SimulationComponent\Impl\EngineAuxiliary.cs" />
diff --git a/VectoCoreTest/Models/Simulation/MeasuredSpeedModeTest.cs b/VectoCoreTest/Models/Simulation/MeasuredSpeedModeTest.cs
index 3ababa20cb..51b7035944 100644
--- a/VectoCoreTest/Models/Simulation/MeasuredSpeedModeTest.cs
+++ b/VectoCoreTest/Models/Simulation/MeasuredSpeedModeTest.cs
@@ -155,19 +155,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
 			var drivingCycle = DrivingCycleDataReader.ReadFromStream(inputData.GetStream(), cycleType);
 			Assert.AreEqual(cycleType, drivingCycle.CycleType);
 
-			if (cycleType == CycleType.MeasuredSpeed) {
-				var cycle = new MeasuredSpeedDrivingCycle(container, drivingCycle);
-			} else {
-				var gearbox = new CycleGearbox(container,
-					new GearboxData {
-						Gears = new Dictionary<uint, GearData> {
-							{ 1, new GearData { Ratio = 6.696 } },
-							{ 2, new GearData { Ratio = 3.806 } },
-							{ 3, new GearData { Ratio = 2.289 } }
-						}
-					});
-				var cycle = new MeasuredSpeedGearDrivingCycle(container, drivingCycle);
-			}
+			var cycle = new MeasuredSpeedDrivingCycle(container, drivingCycle);
 		}
 
 
@@ -327,10 +315,9 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
 
 			Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat(jobContainer.Runs.Select(r => r.ExecException)));
 
-			Assert.IsTrue(File.Exists(@"TestData\Jobs\MeasuredSpeed_Gear.vsum"));
-			Assert.IsTrue(File.Exists(@"TestData\Jobs\Measuredspeed_Gear.vmod"));
-
-			Assert.Fail("Implement this test!");
+			Assert.IsTrue(File.Exists(@"TestData\MeasuredSpeed\MeasuredSpeedGear.vsum"), "SUM file missing.");
+			Assert.IsTrue(File.Exists(@"TestData\MeasuredSpeed\MeasuredSpeedGear_MeasuredSpeed_Gear_Rural.vmod"),
+				"MOD File missing.");
 		}
 	}
 }
\ No newline at end of file
diff --git a/VectoCoreTest/TestData/MeasuredSpeed/MeasuredSpeedGear.vecto b/VectoCoreTest/TestData/MeasuredSpeed/MeasuredSpeedGear.vecto
index eb5f261d46..a5fe755fb7 100644
--- a/VectoCoreTest/TestData/MeasuredSpeed/MeasuredSpeedGear.vecto
+++ b/VectoCoreTest/TestData/MeasuredSpeed/MeasuredSpeedGear.vecto
@@ -12,15 +12,7 @@
     "EngineFile": "Engine.veng",
     "GearboxFile": "Gearbox.vgbx",
     "Cycles": [
-      "MeasuredSpeed_Gear_Motorway.vdri"
-    ],
-    "Aux": [
-      {
-        "ID": "Alt",
-        "Type": "Alternator",
-        "Path": "Alternator.vaux",
-        "Technology": ""
-      }
+      "MeasuredSpeed_Gear_Rural.vdri"
     ],
     "VACC": "Driver.vacc",
     "StartStop": {
diff --git a/VectoCoreTest/Utils/ResultFileHelper.cs b/VectoCoreTest/Utils/ResultFileHelper.cs
index 1371c1a59f..936a77dc44 100644
--- a/VectoCoreTest/Utils/ResultFileHelper.cs
+++ b/VectoCoreTest/Utils/ResultFileHelper.cs
@@ -66,8 +66,10 @@ namespace TUGraz.VectoCore.Tests.Utils
 				}
 
 				Assert.IsTrue(expectedCols.SequenceEqual(actualCols),
-					string.Format("Moddata: Columns differ:\nExpected: {0}\nActual: {1}", ", ".Join(expectedCols),
-						", ".Join(actualCols)));
+					string.Format("Moddata {3}: Columns differ:\nExpected: {0}\nMissing:{1},\nToo Much:{2}",
+						", ".Join(expectedCols),
+						", ".Join(expectedCols.Except(actualCols)),
+						", ".Join(actualCols.Except(expectedCols)), result.actualFile));
 
 				for (var i = 0; testRowcount && i < expected.Rows.Count; i++) {
 					var expectedRow = expected.Rows[i];
@@ -96,8 +98,11 @@ namespace TUGraz.VectoCore.Tests.Utils
 			var expectedCols = expected.Columns.Cast<DataColumn>().Select(x => x.ColumnName).OrderBy(x => x).ToList();
 
 			Assert.IsTrue(expectedCols.SequenceEqual(actualCols),
-				string.Format("SUM FILE: Columns differ:\nExpected: {0}\nActual: {1}", ", ".Join(expectedCols),
-					", ".Join(actualCols)));
+				string.Format("SUM FILE {3}: Columns differ:\nExpected: {0}\nMissing:{1},\nToo Much:{2}",
+					", ".Join(expectedCols),
+					", ".Join(expectedCols.Except(actualCols)),
+					", ".Join(actualCols.Except(expectedCols)),
+					actualFile));
 
 			for (var i = 0; i < expected.Rows.Count; i++) {
 				var expectedRow = expected.Rows[i];
-- 
GitLab