From e146986f5e58e66b260d82c2706649a90d7f698c Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Fri, 27 Nov 2020 15:37:44 +0100
Subject: [PATCH] fix testcases with hybrid powertrain after e-motor
 refactoring

---
 .../Models/HybridStrategyResponse.cs          |  6 +-
 .../Simulation/DataBus/IElectricMotorInfo.cs  |  1 +
 .../DataBus/IHybridControllerInfo.cs          |  3 +
 .../Models/SimulationComponent/Impl/Driver.cs | 19 ++++
 .../SimulationComponent/Impl/ElectricMotor.cs | 94 +++++++++++++------
 .../Impl/HybridController.cs                  |  8 ++
 .../Impl/SimpleHybridController.cs            |  1 +
 .../VelocitySpeedGearshiftPreprocessor.cs     |  4 +-
 .../Strategies/HybridStrategy.cs              | 23 ++++-
 .../Class2_RigidTruck_ParHyb_ENG.vecto        |  2 +-
 10 files changed, 122 insertions(+), 39 deletions(-)

diff --git a/VectoCommon/VectoCommon/Models/HybridStrategyResponse.cs b/VectoCommon/VectoCommon/Models/HybridStrategyResponse.cs
index 31645d5c81..c886e3319d 100644
--- a/VectoCommon/VectoCommon/Models/HybridStrategyResponse.cs
+++ b/VectoCommon/VectoCommon/Models/HybridStrategyResponse.cs
@@ -18,7 +18,9 @@ namespace TUGraz.VectoCommon.Models {
 	public class HybridStrategyResponse : AbstractComponentResponse, IHybridStrategyResponse
 	{
 		public Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>> MechanicalAssistPower;
-		public bool ShiftRequired { get; set; }
+
+        public Second SimulationInterval;
+        public bool ShiftRequired { get; set; }
 		public uint NextGear { get; set; }
 		public bool GearboxInNeutral { get; set; }
 		public bool CombustionEngineOn { get; set; }
@@ -30,6 +32,8 @@ namespace TUGraz.VectoCommon.Models {
 	[DebuggerDisplay("{U}: {Score} - G{Gear}")]
 	public class HybridResultEntry
 	{
+		public Second SimulationInterval
+			;
 		public double U { get; set; }
 
 		public HybridStrategyResponse Setting { get; set; }
diff --git a/VectoCore/VectoCore/Models/Simulation/DataBus/IElectricMotorInfo.cs b/VectoCore/VectoCore/Models/Simulation/DataBus/IElectricMotorInfo.cs
index 0415b9820d..1980ad7b06 100644
--- a/VectoCore/VectoCore/Models/Simulation/DataBus/IElectricMotorInfo.cs
+++ b/VectoCore/VectoCore/Models/Simulation/DataBus/IElectricMotorInfo.cs
@@ -12,5 +12,6 @@ namespace TUGraz.VectoCore.Models.Simulation.DataBus
 		PerSecond MaxSpeed { get; }
 		Watt DragPower(PerSecond electricMotorSpeed);
 		Watt MaxPowerDrive(PerSecond inAngularVelocity);
+		NewtonMeter GetTorqueForElectricPower(Watt electricPower, PerSecond avgEmSpeed, Second dt);
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/Simulation/DataBus/IHybridControllerInfo.cs b/VectoCore/VectoCore/Models/Simulation/DataBus/IHybridControllerInfo.cs
index e9f029be4a..bfc5f43bb9 100644
--- a/VectoCore/VectoCore/Models/Simulation/DataBus/IHybridControllerInfo.cs
+++ b/VectoCore/VectoCore/Models/Simulation/DataBus/IHybridControllerInfo.cs
@@ -10,6 +10,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent
 		PerSecond ICESpeed { get; }
 		bool GearboxEngaged { get; }
 
+
+		Second SimulationInterval { get; }
+
 		PerSecond ElectricMotorSpeed(PowertrainPosition pos);
 
 		//IList<PowertrainPosition> ElectricMotors { get; }
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs
index ab22a687b2..6ff1f6bc79 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs
@@ -769,6 +769,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				Log.Debug("Gear changed after a valid operating point was found - braking is no longer applicable due to overload"); 
 				return null;
 			}
+
+			if (DataBus.HybridControllerCtl != null && response is ResponseEngineSpeedTooHigh &&
+				!(retVal is ResponseSuccess)) {
+				// search brakingpower found a solution but request resulted in non-success - try again
+				DataBus.Brakes.BrakePower = 0.SI<Watt>();
+				try {
+					operatingPoint = SearchBrakingPower(
+						absTime, operatingPoint.SimulationDistance, gradient,
+						operatingPoint.Acceleration, response);
+				} catch (VectoSearchAbortedException vsa) {
+					Log.Warn("Search braking power aborted {0}", vsa);
+					if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission()) {
+						operatingPoint = SetTCOperatingPointATGbxBraking(absTime, gradient, operatingPoint, response);
+					}
+				}
+				retVal = NextComponent.Request(absTime, operatingPoint.SimulationInterval, operatingPoint.Acceleration,
+					gradient, false);
+			}
+
 			retVal.Switch().
 				Case<ResponseSuccess>().
 				Case<ResponseGearShift>().
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
index 67d0073fc5..d84db22b5d 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
@@ -69,6 +69,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			return ModelData.FullLoadCurve.FullLoadDriveTorque(electricMotorSpeed) * electricMotorSpeed;
 		}
 
+		public NewtonMeter GetTorqueForElectricPower(Watt electricPower, PerSecond avgEmSpeed, Second dt)
+		{
+			var maxTorque = electricPower > 0
+				? GetMaxRecuperationTorque(dt, avgEmSpeed)
+				: GetMaxDriveTorque(dt, avgEmSpeed);
+			var tqEmMap = ModelData.EfficiencyMap.LookupTorque(electricPower, avgEmSpeed, maxTorque);
+			if (tqEmMap == null) {
+				return null;
+			}
+
+			var emSpeed = avgEmSpeed * 2 - PreviousState.EMSpeed;
+
+			var tqInertia = Formulas.InertiaPower(emSpeed, PreviousState.EMSpeed, ModelData.Inertia, dt) / avgEmSpeed;
+			var tqEm = tqEmMap + tqInertia;
+			var tqDt = ConvertEmTorqueToDrivetrain(tqEm);
+			return tqDt;
+
+		}
+
 		public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity)
 		{
 			var emOutAngularVelocity = outAngularVelocity * ModelData.Ratio;
@@ -117,8 +136,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				? 0.SI<NewtonMeter>()
 				: Formulas.InertiaPower(avgEmSpeed, PreviousState.EMSpeed, ModelData.Inertia, dt) / avgEmSpeed;
 
-			var maxDriveTorqueEmMap = GetMaxDriveTorque(absTime, dt, avgEmSpeed);
-			var maxRecuperationTorqueEmMap = GetMaxRecuperationTorque(absTime, dt, avgEmSpeed);
+			var maxDriveTorqueEmMap = GetMaxDriveTorque(dt, avgEmSpeed);
+			var maxRecuperationTorqueEmMap = GetMaxRecuperationTorque(dt, avgEmSpeed);
 
 			// inertia has to be added here. drive torque is negative, when accelerating inertia is positive and thus 'reduces' drive torque, i.e 'less negative'
 			var maxDriveTorqueEm = maxDriveTorqueEmMap == null ? null : maxDriveTorqueEmMap + inertiaTorqueEm;
@@ -132,10 +151,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var emTorqueDt = Control.MechanicalAssistPower(absTime, dt, outTorque,
 				PreviousState.DrivetrainSpeed, outAngularVelocity, maxDriveTorqueDt, maxRecuperationTorqueDt, Position, dryRun);
 
-			if (!dryRun && emTorqueDt != null && (emTorqueDt.IsSmaller(maxDriveTorqueDt ?? 0.SI<NewtonMeter>(), 1e-3) ||
-									emTorqueDt.IsGreater(maxRecuperationTorqueDt ?? 0.SI<NewtonMeter>(), 1e-3))) {
+			var emTorque = emTorqueDt == null ? null : ConvertDrivetrainTorqueToEm(emTorqueDt);
+			var emOff = emTorqueDt == null;
+
+			if (!dryRun && emTorqueDt != null && ((emTorque).IsSmaller(maxDriveTorqueEm ?? 0.SI<NewtonMeter>(), 1e-3) ||
+									(emTorque).IsGreater(maxRecuperationTorqueEm ?? 0.SI<NewtonMeter>(), 1e-3))) {
 				// check if provided EM torque (drivetrain) is valid)
-				if (DataBus.HybridControllerInfo != null && !avgDtSpeed.IsEqual(DataBus.HybridControllerInfo.ElectricMotorSpeed(Position))) {
+				if (DataBus.HybridControllerInfo != null && (!avgDtSpeed.IsEqual(DataBus.HybridControllerInfo.ElectricMotorSpeed(Position)) ||
+															!dt.IsEqual(DataBus.HybridControllerInfo.SimulationInterval))) {
 					return new ResponseInvalidOperatingPoint(this);
 				}
 				throw new VectoException(
@@ -144,18 +167,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 
 
-			var emTorque = emTorqueDt == null ? null : ConvertDrivetrainTorqueToEm(emTorqueDt);
-			var emOff = false;
-
-			if (ElectricPower == null || emTorqueDt == null) {
-				// no electric system or EM shall be off - apply drag only
-				// if EM is off, calculate EM drag torque 'forward' to be applied on drivetrain
-				// add inertia, drag is positive
-				emTorque =  ModelData.DragCurve.Lookup(avgEmSpeed) + inertiaTorqueEm;
-				emTorqueDt = ConvertEmTorqueToDrivetrain(emTorque);
-				emOff = true;
-			}
-
+			
 			if (Position == PowertrainPosition.HybridP2 && !DataBus.GearboxInfo.GearEngaged(absTime)) {
 				// electric motor is between gearbox and clutch, but no gear is engaged...
 				if (emTorque != null) {
@@ -175,6 +187,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 							"electric motor cannot provide torque when gearbox and clutch are disengaged");
 					}
 				}
+				// gearbox is disengaged - ignore em inertia and drag...
+				emTorqueDt = 0.SI<NewtonMeter>();
+				emTorque = 0.SI<NewtonMeter>();
+			}
+
+			if (ElectricPower == null || emTorqueDt == null) {
+				// no electric system or EM shall be off - apply drag only
+				// if EM is off, calculate EM drag torque 'forward' to be applied on drivetrain
+				// add inertia, drag is positive
+				emTorque =  ModelData.DragCurve.Lookup(avgEmSpeed) + inertiaTorqueEm;
+				emTorqueDt = ConvertEmTorqueToDrivetrain(emTorque);
+				emOff = true;
 			}
 
 			// inertia torque 'brakes' - electric motor has to provide this torque in addition (T_inertia > 0 when angular speed increases)
@@ -186,7 +210,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				emTorqueMap = null;
 			}
 
-			var electricPower = emOff // TODO: still needed? || ModelData.DragCurve.Lookup(avgEmSpeed).IsEqual(emTorque)
+			var electricPower = emOff || (ModelData.DragCurve.Lookup(avgEmSpeed) + inertiaTorqueEm).IsEqual(emTorque)
 				? 0.SI<Watt>()
 				: ModelData.EfficiencyMap
 					.LookupElectricPower(avgEmSpeed, emTorqueMap, DataBus.ExecutionMode != ExecutionMode.Declaration)
@@ -195,7 +219,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var electricSupplyResponse =
 				ElectricPower.Request(absTime, dt, electricPower, dryRun);
 			if (!dryRun && !(electricSupplyResponse is ElectricSystemResponseSuccess)) {
-				if (DataBus.HybridControllerInfo != null && !avgEmSpeed.IsEqual(DataBus.HybridControllerInfo.ElectricMotorSpeed(Position))) {
+				if (!emOff && DataBus.HybridControllerInfo != null && !avgEmSpeed.IsEqual(DataBus.HybridControllerInfo.ElectricMotorSpeed(Position))) {
 					return new ResponseInvalidOperatingPoint(this);
 				}
 				throw new VectoException(
@@ -283,32 +307,42 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			return retVal;
 		}
 
-		private NewtonMeter GetMaxRecuperationTorque(Second absTime, Second dt, PerSecond avgSpeed)
+		private NewtonMeter GetMaxRecuperationTorque(Second dt, PerSecond avgSpeed)
 		{
 			var tqContinuousPwr = DeRatingActive ? ContinuousTorque : null;
 			if (!avgSpeed.IsEqual(0)) {
 				tqContinuousPwr = DeRatingActive ? ModelData.ContinuousPower / avgSpeed : null;
 			}
 			var maxEmTorque = VectoMath.Min(tqContinuousPwr, ModelData.FullLoadCurve.FullGenerationTorque(avgSpeed));
-			var electricSystemResponse = ElectricPower.Request(absTime, dt, 0.SI<Watt>(), true);
+			var electricSystemResponse = ElectricPower.Request(0.SI<Second>(), dt, 0.SI<Watt>(), true);
 			var maxBatPower = electricSystemResponse.MaxPowerDrag;
 
-			var maxBatRecuperationTorque = maxBatPower.IsEqual(0) ? ModelData.DragCurve.Lookup(avgSpeed) : ModelData.EfficiencyMap.LookupTorque(maxBatPower, avgSpeed, maxEmTorque);
+			if (maxBatPower.IsSmaller(0, 1e-3)) {
+				// has to be positive for recuperation - battery is full
+				return null;
+			}
+
+			var maxBatRecuperationTorque = maxBatPower.IsEqual(0, 1e-3) ? ModelData.DragCurve.Lookup(avgSpeed) : ModelData.EfficiencyMap.LookupTorque(maxBatPower, avgSpeed, maxEmTorque);
 			var maxTorqueRecuperate = VectoMath.Min(maxEmTorque, maxBatRecuperationTorque);
 			return maxTorqueRecuperate < 0 ? null : maxTorqueRecuperate;
 		}
 
-		private NewtonMeter GetMaxDriveTorque(Second absTime, Second dt, PerSecond avgSpeed)
+		private NewtonMeter GetMaxDriveTorque(Second dt, PerSecond avgSpeed)
 		{
 			var tqContinuousPwr = DeRatingActive ? -ContinuousTorque : null;
 			if (!avgSpeed.IsEqual(0)) {
 				tqContinuousPwr = DeRatingActive ? -ModelData.ContinuousPower / avgSpeed : null;
 			}
 			var maxEmTorque = VectoMath.Max(tqContinuousPwr ,ModelData.FullLoadCurve.FullLoadDriveTorque(avgSpeed));
-			var electricSystemResponse = ElectricPower.Request(absTime, dt, 0.SI<Watt>(), true);
+			var electricSystemResponse = ElectricPower.Request(0.SI<Second>(), dt, 0.SI<Watt>(), true);
 			var maxBatPower = electricSystemResponse.MaxPowerDrive;
 
-			var maxBatDriveTorque = maxBatPower.IsEqual(0) ? ModelData.DragCurve.Lookup(avgSpeed) : ModelData.EfficiencyMap.LookupTorque(maxBatPower, avgSpeed, maxEmTorque);
+			if (maxBatPower.IsGreater(0, 1e-3)) {
+				// has to be negative for propelling - so battery is below min SoC
+				return null;
+			}
+
+			var maxBatDriveTorque = maxBatPower.IsEqual(0, 1e-3) ? ModelData.DragCurve.Lookup(avgSpeed) : ModelData.EfficiencyMap.LookupTorque(maxBatPower, avgSpeed, maxEmTorque);
 			//if (maxBatDriveTorque == null) {
 			//	return ModelData.DragCurve.Lookup(avgSpeed);
 			//}
@@ -413,13 +447,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 	public class ElectricMotorState // : SimpleComponentState
 	{
-		
-		public PerSecond DrivetrainSpeed;
-		public NewtonMeter DrivetrainInTorque;
-		public NewtonMeter DrivetrainOutTorque;
+
+		public PerSecond DrivetrainSpeed = 0.RPMtoRad();
+		public NewtonMeter DrivetrainInTorque = 0.SI<NewtonMeter>();
+		public NewtonMeter DrivetrainOutTorque = 0.SI<NewtonMeter>();
 		public NewtonMeter TransmissionTorqueLoss;
 
-		public PerSecond EMSpeed;
+		public PerSecond EMSpeed = 0.RPMtoRad();
 		public NewtonMeter EMTorque;
 		public NewtonMeter EmTorqueMap;
 
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs
index 004f7b072e..3f407110f8 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs
@@ -105,6 +105,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			return CurrentStrategySettings.MechanicalAssistPower[pos].Item1;
 		}
 
+		public Second SimulationInterval
+		{
+			get
+			{
+				return CurrentStrategySettings.SimulationInterval;
+			}
+		}
+
 		public PerSecond ICESpeed
 		{
 			get { return CurrentStrategySettings.EvaluatedSolution.Response?.Engine.EngineSpeed; }
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimpleHybridController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimpleHybridController.cs
index 52b20ef324..838cf675c3 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimpleHybridController.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimpleHybridController.cs
@@ -182,6 +182,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl {
 		public GearInfo SelectedGear { get; }
 		public PerSecond ICESpeed { get; }
 		public bool GearboxEngaged { get; }
+		public Second SimulationInterval { get; }
 
 		public PerSecond ElectricMotorSpeed(PowertrainPosition pos)
 		{
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VelocitySpeedGearshiftPreprocessor.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VelocitySpeedGearshiftPreprocessor.cs
index 45b4997ec4..efdc23d265 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/VelocitySpeedGearshiftPreprocessor.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/VelocitySpeedGearshiftPreprocessor.cs
@@ -155,7 +155,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					acceleration, delta, Constants.SimulationSettings.OperatingPointInitialSearchIntervalAccelerating,
 					getYValue: response => {
 						var r = (ResponseDryRun)response;
-						return r.Gearbox.PowerRequest;
+						return r.Clutch.PowerRequest;
 					},
 					evaluateFunction: acc => {
 						var response = vehicle.Request(time, simulationInterval, acc, gradient, true);
@@ -164,7 +164,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					},
 					criterion: response => {
 						var r = (ResponseDryRun)response;
-						return r.Gearbox.PowerRequest.Value() * 100;
+						return r.Clutch.PowerRequest.Value() * 100;
 					},
 					abortCriterion: (response, cnt) => {
 						var r = (ResponseDryRun)response;
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs
index 32b11ca845..a496aa7f04 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs
@@ -183,7 +183,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 			}
 
 			if (DryRunSolution != null && DryRunSolution.DrivingAction == DataBus.DriverInfo.DrivingAction) {
-				return CreateResponse(DryRunSolution.Solution, currentGear);
+				var tmp = CreateResponse(DryRunSolution.Solution, currentGear);
+				return tmp;
 			}
 
 
@@ -220,7 +221,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 			//	Log.Debug("best: {0}, origBest: {1}", best.ToString(), origBest.ToString());
 			//}
 
+			//best.SimulationInterval = dt;
 			var retVal = CreateResponse(best, currentGear);
+			
 			retVal.GearboxEngaged = DataBus.GearboxInfo.GearEngaged(absTime);
 			if (!DataBus.EngineInfo.EngineOn && !best.ICEOff && retVal.ShiftRequired) {
 				CurrentState.ICEStartTStmp = absTime + dt;
@@ -623,6 +626,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 			var best = DoSelectBestOption(eval, absTime, dt, outTorque, outAngularVelocity, dryRun, currentGear);
 			if (best == null || !best.IgnoreReason.InvalidEngineSpeed() || best.ICEOff ||
 				eval.Select(x => x.Gear).Distinct().Count() <= 1) {
+				best.SimulationInterval = dt;
 				return best;
 			}
 
@@ -647,6 +651,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 					best = DoSelectBestOption(newEval, absTime, dt, outTorque, outAngularVelocity, dryRun, currentGear);
 				}
 			}
+
+			best.SimulationInterval = dt;
 			return best;
 		}
 
@@ -847,7 +853,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 				ShiftRequired = best.Gear != 0 && best.Gear != currentGear, //  gs?.Item1 ?? false,
 				NextGear = best.Gear, // gs?.Item2 ?? 0,
 				EvaluatedSolution = best,
-			};
+                SimulationInterval = best.SimulationInterval
+            };
+			//var pos = retVal.MechanicalAssistPower.Keys.First();
+			//if (retVal.MechanicalAssistPower[pos].Item1 == null) {
+			//	retVal.MechanicalAssistPower[pos] = Tuple.Create(best.Response.ElectricMotor.AngularVelocity, retVal.MechanicalAssistPower[pos].Item2);
+			//}
 			if (best.IgnoreReason.EngineSpeedTooHigh() && !DataBus.EngineInfo.EngineOn) {
 				// ICE is off, selected solution has a too low or too high engine speed - keep ICE off
 				retVal.CombustionEngineOn = false;
@@ -1056,10 +1067,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 				// if battery is getting empty try to set EM-torque to discharge battery to lower SoC boundary
 				
 				if (maxEmTorque.IsSmaller(0) && (-emDrivePower).IsGreaterOrEqual(maxEmTorque * firstResponse.ElectricMotor.AngularVelocity)) {
-					// maxEmTorque < 0  ==> EM can still propell
+					// maxEmTorque < 0  ==> EM can still propel
 					// (-emDrivePower).IsGreaterOrEqual(maxEmTorque * firstResponse.ElectricMotor.AngularVelocity) ==> power available from battery for driving does not exceed max EM power (otherwise torque lookup may fail) 
-					var emDriveTorque = ModelData.ElectricMachinesData.Where(x => x.Item1 == emPos).First().Item2.EfficiencyMap
-												.LookupTorque(emDrivePower, firstResponse.ElectricMotor.AngularVelocity, maxEmTorque);
+					//var emDriveTorque = ModelData.ElectricMachinesData.Where(x => x.Item1 == emPos).First().Item2.EfficiencyMap
+					//							.LookupTorque(emDrivePower, firstResponse.ElectricMotor.AngularVelocity, maxEmTorque);
+
+					var emDriveTorque = DataBus.ElectricMotorInfo(emPos).GetTorqueForElectricPower(emDrivePower, firstResponse.ElectricMotor.AngularVelocity, dt);
 					var emDragTorque = ModelData.ElectricMachinesData.Where(x => x.Item1 == emPos).First().Item2
 												.DragCurve.Lookup(firstResponse.ElectricMotor.AngularVelocity);
 					if (emDriveTorque != null &&
diff --git a/VectoCore/VectoCoreTest/TestData/Hybrids/GenericVehicle_Group2_P2/Class2_RigidTruck_ParHyb_ENG.vecto b/VectoCore/VectoCoreTest/TestData/Hybrids/GenericVehicle_Group2_P2/Class2_RigidTruck_ParHyb_ENG.vecto
index 44cacce02b..968cdd3046 100644
--- a/VectoCore/VectoCoreTest/TestData/Hybrids/GenericVehicle_Group2_P2/Class2_RigidTruck_ParHyb_ENG.vecto
+++ b/VectoCore/VectoCoreTest/TestData/Hybrids/GenericVehicle_Group2_P2/Class2_RigidTruck_ParHyb_ENG.vecto
@@ -19,7 +19,7 @@
     "AdvancedAuxiliaryFilePath": "",
     "Aux": [],
     "Padd": 3540.0,
-    "Padd_electric": 3540.0,
+    "Padd_electric": 0.0,
     "VACC": "Truck.vacc",
     "EngineStopStartAtVehicleStopThreshold": 2.0,
     "EngineStopStartMaxOffTimespan": 120.0,
-- 
GitLab