Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS will be completely phased out by mid-2025. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit e146986f authored by Markus Quaritsch's avatar Markus Quaritsch
Browse files

fix testcases with hybrid powertrain after e-motor refactoring

parent a8757756
No related branches found
No related tags found
No related merge requests found
Showing
with 122 additions and 39 deletions
......@@ -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; }
......
......@@ -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
......@@ -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; }
......
......@@ -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>().
......
......@@ -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;
......
......@@ -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; }
......
......@@ -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)
{
......
......@@ -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;
......
......@@ -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 &&
......
......@@ -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,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment