diff --git a/VectoCore/FileIO/Reader/DataObjectAdaper/AbstractSimulationDataAdapter.cs b/VectoCore/FileIO/Reader/DataObjectAdaper/AbstractSimulationDataAdapter.cs index e698bfa75ad9a03c4dd2ed6aea86bd95a3995149..cbaf59f9a19df6ff1fe0c30e6bd90d97479a8ab6 100644 --- a/VectoCore/FileIO/Reader/DataObjectAdaper/AbstractSimulationDataAdapter.cs +++ b/VectoCore/FileIO/Reader/DataObjectAdaper/AbstractSimulationDataAdapter.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using TUGraz.VectoCore.FileIO.DeclarationFile; using TUGraz.VectoCore.Models.Declaration; @@ -9,76 +8,72 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.FileIO.Reader.DataObjectAdaper { - public abstract class AbstractSimulationDataAdapter - { - public abstract VehicleData CreateVehicleData(VectoVehicleFile vehicle, Mission mission, Kilogram loading); + public abstract class AbstractSimulationDataAdapter + { + public abstract VehicleData CreateVehicleData(VectoVehicleFile vehicle, Mission mission, Kilogram loading); + public abstract VehicleData CreateVehicleData(VectoVehicleFile vehicle); + public abstract CombustionEngineData CreateEngineData(VectoEngineFile engine); + public abstract GearboxData CreateGearboxData(VectoGearboxFile gearbox, CombustionEngineData engine); + // ========================= - public abstract VehicleData CreateVehicleData(VectoVehicleFile vehicle); + internal VehicleData SetCommonVehicleData(VehicleFileV7Declaration.DataBodyDecl data, string basePath) + { + var retVal = new VehicleData { + SavedInDeclarationMode = data.SavedInDeclarationMode, + VehicleCategory = data.VehicleCategory(), + AxleConfiguration = AxleConfigurationHelper.Parse(data.AxleConfig.TypeStr), + CurbWeight = data.CurbWeight.SI<Kilogram>(), + //CurbWeigthExtra = data.CurbWeightExtra.SI<Kilogram>(), + //Loading = data.Loading.SI<Kilogram>(), + GrossVehicleMassRating = data.GrossVehicleMassRating.SI<Ton>().Cast<Kilogram>(), + //DragCoefficient = data.DragCoefficient, + //CrossSectionArea = data.CrossSectionArea.SI<SquareMeter>(), + //DragCoefficientRigidTruck = data.DragCoefficientRigidTruck, + //CrossSectionAreaRigidTruck = data.CrossSectionAreaRigidTruck.SI<SquareMeter>(), + //TyreRadius = data.TyreRadius.SI().Milli.Meter.Cast<Meter>(), + Rim = data.RimStr + }; - public abstract CombustionEngineData CreateEngineData(VectoEngineFile engine); + var retarder = new RetarderData { + Type = + (RetarderData.RetarderType) + Enum.Parse(typeof(RetarderData.RetarderType), data.Retarder.TypeStr, true) + }; + if (retarder.Type == RetarderData.RetarderType.Primary || + retarder.Type == RetarderData.RetarderType.Secondary) { + retarder.LossMap = RetarderLossMap.ReadFromFile(Path.Combine(basePath, data.Retarder.File)); + retarder.Ratio = data.Retarder.Ratio; + } + retVal.Retarder = retarder; - public abstract GearboxData CreateGearboxData(VectoGearboxFile gearbox, CombustionEngineData engine); + return retVal; + } - // ========================= + internal CombustionEngineData SetCommonCombustionEngineData(EngineFileV3Declaration.DataBodyDecl data, + string basePath) + { + var retVal = new CombustionEngineData { + SavedInDeclarationMode = data.SavedInDeclarationMode, + ModelName = data.ModelName, + Displacement = data.Displacement.SI().Cubic.Centi.Meter.Cast<CubicMeter>(), // convert vom ccm to m^3 + IdleSpeed = data.IdleSpeed.RPMtoRad(), + ConsumptionMap = FuelConsumptionMap.ReadFromFile(Path.Combine(basePath, data.FuelMap)), + WHTCUrban = data.WHTCUrban.SI<KilogramPerWattSecond>(), + WHTCMotorway = data.WHTCMotorway.SI<KilogramPerWattSecond>(), + WHTCRural = data.WHTCRural.SI<KilogramPerWattSecond>() + }; + return retVal; + } - internal VehicleData SetCommonVehicleData(VehicleFileV7Declaration.DataBodyDecl data, string basePath) - { - var retVal = new VehicleData { - SavedInDeclarationMode = data.SavedInDeclarationMode, - VehicleCategory = data.VehicleCategory(), - AxleConfiguration = AxleConfigurationHelper.Parse(data.AxleConfig.TypeStr), - CurbWeight = data.CurbWeight.SI<Kilogram>(), - //CurbWeigthExtra = data.CurbWeightExtra.SI<Kilogram>(), - //Loading = data.Loading.SI<Kilogram>(), - GrossVehicleMassRating = data.GrossVehicleMassRating.SI<Ton>().Cast<Kilogram>(), - //DragCoefficient = data.DragCoefficient, - //CrossSectionArea = data.CrossSectionArea.SI<SquareMeter>(), - //DragCoefficientRigidTruck = data.DragCoefficientRigidTruck, - //CrossSectionAreaRigidTruck = data.CrossSectionAreaRigidTruck.SI<SquareMeter>(), - //TyreRadius = data.TyreRadius.SI().Milli.Meter.Cast<Meter>(), - Rim = data.RimStr, - }; + internal GearboxData SetCommonGearboxData(GearboxFileV5Declaration.DataBodyDecl data) + { + return new GearboxData { + SavedInDeclarationMode = data.SavedInDeclarationMode, + ModelName = data.ModelName, + Type = data.GearboxType.Parse<GearboxType>() + }; + } - var retarder = new RetarderData { - Type = - (RetarderData.RetarderType) - Enum.Parse(typeof(RetarderData.RetarderType), data.Retarder.TypeStr.ToString(), true), - }; - if (retarder.Type == RetarderData.RetarderType.Primary || - retarder.Type == RetarderData.RetarderType.Secondary) { - retarder.LossMap = RetarderLossMap.ReadFromFile(Path.Combine(basePath, data.Retarder.File)); - retarder.Ratio = data.Retarder.Ratio; - } - retVal.Retarder = retarder; - - return retVal; - } - - internal CombustionEngineData SetCommonCombustionEngineData(EngineFileV3Declaration.DataBodyDecl data, - string basePath) - { - var retVal = new CombustionEngineData { - SavedInDeclarationMode = data.SavedInDeclarationMode, - ModelName = data.ModelName, - Displacement = data.Displacement.SI().Cubic.Centi.Meter.Cast<CubicMeter>(), // convert vom ccm to m^3 - IdleSpeed = data.IdleSpeed.RPMtoRad(), - ConsumptionMap = FuelConsumptionMap.ReadFromFile(Path.Combine(basePath, data.FuelMap)), - WHTCUrban = data.WHTCUrban.SI<KilogramPerWattSecond>(), - WHTCMotorway = data.WHTCMotorway.SI<KilogramPerWattSecond>(), - WHTCRural = data.WHTCRural.SI<KilogramPerWattSecond>(), - }; - return retVal; - } - - internal GearboxData SetCommonGearboxData(GearboxFileV5Declaration.DataBodyDecl data) - { - return new GearboxData { - SavedInDeclarationMode = data.SavedInDeclarationMode, - ModelName = data.ModelName, - Type = data.GearboxType.Parse<GearboxType>() - }; - } - - public abstract DriverData CreateDriverData(VectoJobFile job); - } + public abstract DriverData CreateDriverData(VectoJobFile job); + } } \ No newline at end of file diff --git a/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs b/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs index a258d3720591d7dd4675e3563aa75d1463689b38..1b6690546a833ef57c4ce48fae0abfc70fc41f86 100644 --- a/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs +++ b/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs @@ -12,320 +12,316 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Utils; - namespace TUGraz.VectoCore.FileIO.Reader.DataObjectAdaper { - public class DeclarationDataAdapter : AbstractSimulationDataAdapter - { - public override VehicleData CreateVehicleData(VectoVehicleFile vehicle, Mission mission, Kilogram loading) - { - var fileV5Decl = vehicle as VehicleFileV7Declaration; - if (fileV5Decl != null) { - return CreateVehicleData(fileV5Decl, mission, loading); - } - throw new VectoException("Unsupported VehicleData File Instance"); - } - - public override VehicleData CreateVehicleData(VectoVehicleFile vehicle) - { - var fileV7Decl = vehicle as VehicleFileV7Declaration; - if (fileV7Decl != null) { - return SetCommonVehicleData(fileV7Decl.Body, fileV7Decl.BasePath); - } - throw new VectoException("Mission Data and loading required in DeclarationMode"); - } - - public override CombustionEngineData CreateEngineData(VectoEngineFile engine) - { - var fileV2Decl = engine as EngineFileV3Declaration; - if (fileV2Decl != null) { - return CreateEngineData(fileV2Decl); - } - throw new VectoException("Unsupported EngineData File Instance"); - } - - public override GearboxData CreateGearboxData(VectoGearboxFile gearbox, CombustionEngineData engine) - { - var fileV5Decl = gearbox as GearboxFileV5Declaration; - if (fileV5Decl != null) { - return CreateGearboxData(fileV5Decl, engine); - } - throw new VectoException("Unsupported GearboxData File Instance"); - } - - public override DriverData CreateDriverData(VectoJobFile job) - { - var fileV2Decl = job as VectoJobFileV2Declaration; - if (fileV2Decl != null) { - return CreateDriverData(fileV2Decl); - } - throw new VectoException("Unsupported Job File Instance"); - } - - //========================== - - - public DriverData CreateDriverData(VectoJobFileV2Declaration job) - { - var data = job.Body; - - var lookAheadData = new DriverData.LACData { - Enabled = DeclarationData.Driver.LookAhead.Enabled, - Deceleration = DeclarationData.Driver.LookAhead.Deceleration, - MinSpeed = DeclarationData.Driver.LookAhead.MinimumSpeed - }; - var overspeedData = new DriverData.OverSpeedEcoRollData { - Mode = DriverData.ParseDriverMode(data.OverSpeedEcoRoll.Mode), - MinSpeed = DeclarationData.Driver.OverSpeedEcoRoll.MinSpeed, - OverSpeed = DeclarationData.Driver.OverSpeedEcoRoll.OverSpeed, - UnderSpeed = DeclarationData.Driver.OverSpeedEcoRoll.UnderSpeed - }; - if (!DeclarationData.Driver.OverSpeedEcoRoll.AllowedModes.Contains(overspeedData.Mode)) { - throw new VectoSimulationException( - "Specified Overspeed/EcoRoll Mode not allowed in declaration mode! {0}", - overspeedData.Mode); - } - var startstopData = new VectoRunData.StartStopData { - Enabled = data.StartStop.Enabled, - Delay = DeclarationData.Driver.StartStop.Delay, - MinTime = DeclarationData.Driver.StartStop.MinTime, - MaxSpeed = DeclarationData.Driver.StartStop.MaxSpeed, - }; - var retVal = new DriverData { - LookAheadCoasting = lookAheadData, - OverSpeedEcoRoll = overspeedData, - StartStop = startstopData, - }; - return retVal; - } - - - internal VehicleData CreateVehicleData(VehicleFileV7Declaration vehicle, Mission mission, Kilogram loading) - { - var data = vehicle.Body; - var retVal = SetCommonVehicleData(data, vehicle.BasePath); - - retVal.BasePath = vehicle.BasePath; - - retVal.GrossVehicleMassRating = vehicle.Body.GrossVehicleMassRating.SI<Ton>().Cast<Kilogram>(); - - retVal.CurbWeigthExtra = mission.MassExtra; - retVal.Loading = loading; - retVal.DynamicTyreRadius = - DeclarationData.DynamicTyreRadius(data.AxleConfig.Axles[DeclarationData.PoweredAxle()].WheelsStr, - data.RimStr); - - retVal.AerodynamicDragAera = mission.UseCdA2 - ? data.DragCoefficientRigidTruck.SI<SquareMeter>() - : data.DragCoefficient.SI<SquareMeter>(); - - - retVal.CrossWindCorrectionCurve = GetDeclarationAirResistanceCurve(retVal.VehicleCategory, - retVal.AerodynamicDragAera); - - if (data.AxleConfig.Axles.Count < mission.AxleWeightDistribution.Length) { - throw new VectoException( - string.Format("Vehicle does not contain sufficient axles. {0} axles defined, {1} axles required", - data.AxleConfig.Axles.Count, mission.AxleWeightDistribution.Count())); - } - var axleData = new List<Axle>(); - for (var i = 0; i < mission.AxleWeightDistribution.Length; i++) { - var axleInput = data.AxleConfig.Axles[i]; - var axle = new Axle { - AxleWeightShare = mission.AxleWeightDistribution[i], - TwinTyres = axleInput.TwinTyres, - RollResistanceCoefficient = axleInput.RollResistanceCoefficient, - TyreTestLoad = axleInput.TyreTestLoad.SI<Newton>(), - Inertia = DeclarationData.Wheels.Lookup(axleInput.WheelsStr.Replace(" ", "")).Inertia, - }; - axleData.Add(axle); - } - - axleData.AddRange(mission.TrailerAxleWeightDistribution.Select(tmp => new Axle { - AxleWeightShare = tmp, - TwinTyres = DeclarationData.Trailer.TwinTyres, - RollResistanceCoefficient = DeclarationData.Trailer.RollResistanceCoefficient, - TyreTestLoad = DeclarationData.Trailer.TyreTestLoad.SI<Newton>(), - Inertia = DeclarationData.Wheels.Lookup(DeclarationData.Trailer.WheelsType).Inertia - })); - retVal.AxleData = axleData; - return retVal; - } - - - internal CombustionEngineData CreateEngineData(EngineFileV3Declaration engine) - { - var retVal = SetCommonCombustionEngineData(engine.Body, engine.BasePath); - retVal.Inertia = DeclarationData.Engine.EngineInertia(retVal.Displacement); - retVal.FullLoadCurve = - EngineFullLoadCurve.ReadFromFile(Path.Combine(engine.BasePath, engine.Body.FullLoadCurve), - true); - retVal.FullLoadCurve.EngineData = retVal; - return retVal; - } - - internal GearboxData CreateGearboxData(GearboxFileV5Declaration gearbox, CombustionEngineData engine) - { - var retVal = SetCommonGearboxData(gearbox.Body); - switch (retVal.Type) { - case GearboxType.AT: - throw new VectoSimulationException( - "Automatic Transmission currently not supported in DeclarationMode!"); - case GearboxType.Custom: - throw new VectoSimulationException("Custom Transmission not supported in DeclarationMode!"); - } - if (gearbox.Body.Gears.Count < 2) { - throw new VectoSimulationException( - "At least two Gear-Entries must be defined in Gearbox: 1 Axle-Gear and at least 1 Gearbox-Gear!"); - } - - retVal.Inertia = DeclarationData.Gearbox.Inertia.SI<KilogramSquareMeter>(); - retVal.TractionInterruption = retVal.Type.TractionInterruption(); - retVal.SkipGears = retVal.Type.SkipGears(); - retVal.EarlyShiftUp = retVal.Type.EarlyShiftGears(); - - retVal.TorqueReserve = DeclarationData.Gearbox.TorqueReserve; - retVal.StartTorqueReserve = DeclarationData.Gearbox.TorqueReserveStart; - retVal.ShiftTime = DeclarationData.Gearbox.MinTimeBetweenGearshifts.SI<Second>(); - retVal.StartSpeed = DeclarationData.Gearbox.StartSpeed.SI<MeterPerSecond>(); - retVal.StartAcceleration = DeclarationData.Gearbox.StartAcceleration.SI<MeterPerSquareSecond>(); - - retVal.HasTorqueConverter = false; - - var axleGear = gearbox.Body.Gears.First(); - var axleLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, axleGear.LossMap), - axleGear.Ratio, - "AxleGear"); - retVal.AxleGearData = new GearData { - LossMap = axleLossMap, - Ratio = axleGear.Ratio, - TorqueConverterActive = false - }; - - retVal.Gears = gearbox.Body.Gears.Skip(1).Select((gear, i) => { - var gearLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, gear.LossMap), - gear.Ratio, - string.Format("Gear {0}", i)); - var gearFullLoad = (string.IsNullOrWhiteSpace(gear.FullLoadCurve) || gear.FullLoadCurve == "<NOFILE>") - ? engine.FullLoadCurve - : FullLoadCurve.ReadFromFile(Path.Combine(gearbox.BasePath, gear.FullLoadCurve)); - - var fullLoadCurve = IntersectFullLoadCurves(engine.FullLoadCurve, gearFullLoad); - var shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(fullLoadCurve, engine.IdleSpeed); - return new KeyValuePair<uint, GearData>((uint)i + 1, - new GearData { - LossMap = gearLossMap, - ShiftPolygon = shiftPolygon, - FullLoadCurve = gearFullLoad ?? engine.FullLoadCurve, - Ratio = gear.Ratio, - TorqueConverterActive = false - }); - }).ToDictionary(kv => kv.Key, kv => kv.Value); - return retVal; - } - - /// <summary> - /// Intersects full load curves. - /// </summary> - /// <param name="engineCurve">engine's full-load curve</param> - /// <param name="gearCurve">gearbox' full-load curve for a certain gear</param> - /// <returns>A combined EngineFullLoadCurve with the minimum full load torque over all inputs curves.</returns> - private static EngineFullLoadCurve IntersectFullLoadCurves(EngineFullLoadCurve engineCurve, - FullLoadCurve gearCurve) - { - var entries = gearCurve.FullLoadEntries.Concat(engineCurve.FullLoadEntries) - .Select(entry => entry.EngineSpeed) - .OrderBy(engineSpeed => engineSpeed) - .Distinct() - .Select(engineSpeed => new FullLoadCurve.FullLoadCurveEntry { - EngineSpeed = engineSpeed, - TorqueFullLoad = - VectoMath.Min(engineCurve.FullLoadStationaryTorque(engineSpeed), - gearCurve.FullLoadStationaryTorque(engineSpeed)) - }); - - var flc = new EngineFullLoadCurve { - FullLoadEntries = entries.ToList(), - EngineData = engineCurve.EngineData, - PT1Data = engineCurve.PT1Data - }; - return flc; - } - - public IEnumerable<VectoRunData.AuxData> CreateAuxiliaryData(IEnumerable<VectoRunData.AuxData> auxList, - MissionType mission, VehicleClass hvdClass) - { - foreach (var auxData in auxList) { - var aux = new VectoRunData.AuxData { DemandType = AuxiliaryDemandType.Constant }; - - switch (auxData.Type) { - case AuxiliaryType.Fan: - aux.PowerDemand = DeclarationData.Fan.Lookup(mission, auxData.Technology); - aux.ID = Constants.Auxiliaries.IDs.Fan; - break; - case AuxiliaryType.SteeringPump: - aux.PowerDemand = DeclarationData.SteeringPump.Lookup(mission, hvdClass, auxData.Technology); - aux.ID = Constants.Auxiliaries.IDs.SteeringPump; - break; - case AuxiliaryType.HeatingVentilationAirCondition: - aux.PowerDemand = DeclarationData.HeatingVentilationAirConditioning.Lookup(mission, hvdClass); - aux.ID = Constants.Auxiliaries.IDs.HeatingVentilationAirCondition; - break; - case AuxiliaryType.PneumaticSystem: - aux.PowerDemand = DeclarationData.PneumaticSystem.Lookup(mission, hvdClass); - aux.ID = Constants.Auxiliaries.IDs.PneumaticSystem; - break; - case AuxiliaryType.ElectricSystem: - aux.PowerDemand = DeclarationData.ElectricSystem.Lookup(mission, auxData.TechList); - aux.ID = Constants.Auxiliaries.IDs.ElectricSystem; - break; - } - yield return aux; - } - } - - public static CrossWindCorrectionCurve GetDeclarationAirResistanceCurve(VehicleCategory vehicleCategory, - SquareMeter aerodynamicDragAera) - { - var values = DeclarationData.AirDrag.Lookup(vehicleCategory); - var points = new List<CrossWindCorrectionCurve.CrossWindCorrectionEntry> { - new CrossWindCorrectionCurve.CrossWindCorrectionEntry { - Velocity = 0.SI<MeterPerSecond>(), - EffectiveCrossSectionArea = 0.SI<SquareMeter>() - } - }; - - for (var speed = 60; speed <= 100; speed += 5) { - var vVeh = speed.KMPHtoMeterPerSecond(); - var cdASum = 0.0.SI<SquareMeter>(); - for (var alpha = 0; alpha <= 180; alpha += 10) { - var vWindX = Physics.BaseWindSpeed * Math.Cos(alpha.ToRadian()); - var vWindY = Physics.BaseWindSpeed * Math.Sin(alpha.ToRadian()); - var vAirX = vVeh + vWindX; - var vAirY = vWindY; + public class DeclarationDataAdapter : AbstractSimulationDataAdapter + { + public override VehicleData CreateVehicleData(VectoVehicleFile vehicle, Mission mission, Kilogram loading) + { + var fileV5Decl = vehicle as VehicleFileV7Declaration; + if (fileV5Decl != null) { + return CreateVehicleData(fileV5Decl, mission, loading); + } + throw new VectoException("Unsupported VehicleData File Instance"); + } + + public override VehicleData CreateVehicleData(VectoVehicleFile vehicle) + { + var fileV7Decl = vehicle as VehicleFileV7Declaration; + if (fileV7Decl != null) { + return SetCommonVehicleData(fileV7Decl.Body, fileV7Decl.BasePath); + } + throw new VectoException("Mission Data and loading required in DeclarationMode"); + } + + public override CombustionEngineData CreateEngineData(VectoEngineFile engine) + { + var fileV2Decl = engine as EngineFileV3Declaration; + if (fileV2Decl != null) { + return CreateEngineData(fileV2Decl); + } + throw new VectoException("Unsupported EngineData File Instance"); + } + + public override GearboxData CreateGearboxData(VectoGearboxFile gearbox, CombustionEngineData engine) + { + var fileV5Decl = gearbox as GearboxFileV5Declaration; + if (fileV5Decl != null) { + return CreateGearboxData(fileV5Decl, engine); + } + throw new VectoException("Unsupported GearboxData File Instance"); + } + + public override DriverData CreateDriverData(VectoJobFile job) + { + var fileV2Decl = job as VectoJobFileV2Declaration; + if (fileV2Decl != null) { + return CreateDriverData(fileV2Decl); + } + throw new VectoException("Unsupported Job File Instance"); + } + + //========================== + + + public DriverData CreateDriverData(VectoJobFileV2Declaration job) + { + var data = job.Body; + + var lookAheadData = new DriverData.LACData { + Enabled = DeclarationData.Driver.LookAhead.Enabled, + Deceleration = DeclarationData.Driver.LookAhead.Deceleration, + MinSpeed = DeclarationData.Driver.LookAhead.MinimumSpeed + }; + var overspeedData = new DriverData.OverSpeedEcoRollData { + Mode = DriverData.ParseDriverMode(data.OverSpeedEcoRoll.Mode), + MinSpeed = DeclarationData.Driver.OverSpeedEcoRoll.MinSpeed, + OverSpeed = DeclarationData.Driver.OverSpeedEcoRoll.OverSpeed, + UnderSpeed = DeclarationData.Driver.OverSpeedEcoRoll.UnderSpeed + }; + if (!DeclarationData.Driver.OverSpeedEcoRoll.AllowedModes.Contains(overspeedData.Mode)) { + throw new VectoSimulationException( + "Specified Overspeed/EcoRoll Mode not allowed in declaration mode! {0}", + overspeedData.Mode); + } + var startstopData = new VectoRunData.StartStopData { + Enabled = data.StartStop.Enabled, + Delay = DeclarationData.Driver.StartStop.Delay, + MinTime = DeclarationData.Driver.StartStop.MinTime, + MaxSpeed = DeclarationData.Driver.StartStop.MaxSpeed + }; + var retVal = new DriverData { + LookAheadCoasting = lookAheadData, + OverSpeedEcoRoll = overspeedData, + StartStop = startstopData + }; + return retVal; + } + + internal VehicleData CreateVehicleData(VehicleFileV7Declaration vehicle, Mission mission, Kilogram loading) + { + var data = vehicle.Body; + var retVal = SetCommonVehicleData(data, vehicle.BasePath); + + retVal.BasePath = vehicle.BasePath; + + retVal.GrossVehicleMassRating = vehicle.Body.GrossVehicleMassRating.SI<Ton>().Cast<Kilogram>(); + + retVal.CurbWeigthExtra = mission.MassExtra; + retVal.Loading = loading; + retVal.DynamicTyreRadius = + DeclarationData.DynamicTyreRadius(data.AxleConfig.Axles[DeclarationData.PoweredAxle()].WheelsStr, + data.RimStr); + + retVal.AerodynamicDragAera = mission.UseCdA2 + ? data.DragCoefficientRigidTruck.SI<SquareMeter>() + : data.DragCoefficient.SI<SquareMeter>(); + + + retVal.CrossWindCorrectionCurve = GetDeclarationAirResistanceCurve(retVal.VehicleCategory, + retVal.AerodynamicDragAera); + + if (data.AxleConfig.Axles.Count < mission.AxleWeightDistribution.Length) { + throw new VectoException("Vehicle does not contain sufficient axles. {0} axles defined, {1} axles required", + data.AxleConfig.Axles.Count, mission.AxleWeightDistribution.Count()); + } + var axleData = new List<Axle>(); + for (var i = 0; i < mission.AxleWeightDistribution.Length; i++) { + var axleInput = data.AxleConfig.Axles[i]; + var axle = new Axle { + AxleWeightShare = mission.AxleWeightDistribution[i], + TwinTyres = axleInput.TwinTyres, + RollResistanceCoefficient = axleInput.RollResistanceCoefficient, + TyreTestLoad = axleInput.TyreTestLoad.SI<Newton>(), + Inertia = DeclarationData.Wheels.Lookup(axleInput.WheelsStr.Replace(" ", "")).Inertia + }; + axleData.Add(axle); + } + + axleData.AddRange(mission.TrailerAxleWeightDistribution.Select(tmp => new Axle { + AxleWeightShare = tmp, + TwinTyres = DeclarationData.Trailer.TwinTyres, + RollResistanceCoefficient = DeclarationData.Trailer.RollResistanceCoefficient, + TyreTestLoad = DeclarationData.Trailer.TyreTestLoad.SI<Newton>(), + Inertia = DeclarationData.Wheels.Lookup(DeclarationData.Trailer.WheelsType).Inertia + })); + retVal.AxleData = axleData; + return retVal; + } + + internal CombustionEngineData CreateEngineData(EngineFileV3Declaration engine) + { + var retVal = SetCommonCombustionEngineData(engine.Body, engine.BasePath); + retVal.Inertia = DeclarationData.Engine.EngineInertia(retVal.Displacement); + retVal.FullLoadCurve = + EngineFullLoadCurve.ReadFromFile(Path.Combine(engine.BasePath, engine.Body.FullLoadCurve), + true); + retVal.FullLoadCurve.EngineData = retVal; + return retVal; + } + + internal GearboxData CreateGearboxData(GearboxFileV5Declaration gearbox, CombustionEngineData engine) + { + var retVal = SetCommonGearboxData(gearbox.Body); + switch (retVal.Type) { + case GearboxType.AT: + throw new VectoSimulationException( + "Automatic Transmission currently not supported in DeclarationMode!"); + case GearboxType.Custom: + throw new VectoSimulationException("Custom Transmission not supported in DeclarationMode!"); + } + if (gearbox.Body.Gears.Count < 2) { + throw new VectoSimulationException( + "At least two Gear-Entries must be defined in Gearbox: 1 Axle-Gear and at least 1 Gearbox-Gear!"); + } + + retVal.Inertia = DeclarationData.Gearbox.Inertia.SI<KilogramSquareMeter>(); + retVal.TractionInterruption = retVal.Type.TractionInterruption(); + retVal.SkipGears = retVal.Type.SkipGears(); + retVal.EarlyShiftUp = retVal.Type.EarlyShiftGears(); + + retVal.TorqueReserve = DeclarationData.Gearbox.TorqueReserve; + retVal.StartTorqueReserve = DeclarationData.Gearbox.TorqueReserveStart; + retVal.ShiftTime = DeclarationData.Gearbox.MinTimeBetweenGearshifts.SI<Second>(); + retVal.StartSpeed = DeclarationData.Gearbox.StartSpeed.SI<MeterPerSecond>(); + retVal.StartAcceleration = DeclarationData.Gearbox.StartAcceleration.SI<MeterPerSquareSecond>(); + + retVal.HasTorqueConverter = false; + + var axleGear = gearbox.Body.Gears.First(); + var axleLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, axleGear.LossMap), + axleGear.Ratio, + "AxleGear"); + retVal.AxleGearData = new GearData { + LossMap = axleLossMap, + Ratio = axleGear.Ratio, + TorqueConverterActive = false + }; + + retVal.Gears = gearbox.Body.Gears.Skip(1).Select((gear, i) => { + var gearLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, gear.LossMap), + gear.Ratio, + string.Format("Gear {0}", i)); + var gearFullLoad = (string.IsNullOrWhiteSpace(gear.FullLoadCurve) || gear.FullLoadCurve == "<NOFILE>") + ? engine.FullLoadCurve + : FullLoadCurve.ReadFromFile(Path.Combine(gearbox.BasePath, gear.FullLoadCurve)); + + var fullLoadCurve = IntersectFullLoadCurves(engine.FullLoadCurve, gearFullLoad); + var shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(fullLoadCurve, engine.IdleSpeed); + return new KeyValuePair<uint, GearData>((uint)i + 1, + new GearData { + LossMap = gearLossMap, + ShiftPolygon = shiftPolygon, + FullLoadCurve = gearFullLoad ?? engine.FullLoadCurve, + Ratio = gear.Ratio, + TorqueConverterActive = false + }); + }).ToDictionary(kv => kv.Key, kv => kv.Value); + return retVal; + } + + /// <summary> + /// Intersects full load curves. + /// </summary> + /// <param name="engineCurve">engine's full-load curve</param> + /// <param name="gearCurve">gearbox' full-load curve for a certain gear</param> + /// <returns>A combined EngineFullLoadCurve with the minimum full load torque over all inputs curves.</returns> + private static EngineFullLoadCurve IntersectFullLoadCurves(EngineFullLoadCurve engineCurve, + FullLoadCurve gearCurve) + { + var entries = gearCurve.FullLoadEntries.Concat(engineCurve.FullLoadEntries) + .Select(entry => entry.EngineSpeed) + .OrderBy(engineSpeed => engineSpeed) + .Distinct() + .Select(engineSpeed => new FullLoadCurve.FullLoadCurveEntry { + EngineSpeed = engineSpeed, + TorqueFullLoad = + VectoMath.Min(engineCurve.FullLoadStationaryTorque(engineSpeed), + gearCurve.FullLoadStationaryTorque(engineSpeed)) + }); + + var flc = new EngineFullLoadCurve { + FullLoadEntries = entries.ToList(), + EngineData = engineCurve.EngineData, + PT1Data = engineCurve.PT1Data + }; + return flc; + } + + public IEnumerable<VectoRunData.AuxData> CreateAuxiliaryData(IEnumerable<VectoRunData.AuxData> auxList, + MissionType mission, VehicleClass hvdClass) + { + foreach (var auxData in auxList) { + var aux = new VectoRunData.AuxData { DemandType = AuxiliaryDemandType.Constant }; + + switch (auxData.Type) { + case AuxiliaryType.Fan: + aux.PowerDemand = DeclarationData.Fan.Lookup(mission, auxData.Technology); + aux.ID = Constants.Auxiliaries.IDs.Fan; + break; + case AuxiliaryType.SteeringPump: + aux.PowerDemand = DeclarationData.SteeringPump.Lookup(mission, hvdClass, auxData.Technology); + aux.ID = Constants.Auxiliaries.IDs.SteeringPump; + break; + case AuxiliaryType.HeatingVentilationAirCondition: + aux.PowerDemand = DeclarationData.HeatingVentilationAirConditioning.Lookup(mission, hvdClass); + aux.ID = Constants.Auxiliaries.IDs.HeatingVentilationAirCondition; + break; + case AuxiliaryType.PneumaticSystem: + aux.PowerDemand = DeclarationData.PneumaticSystem.Lookup(mission, hvdClass); + aux.ID = Constants.Auxiliaries.IDs.PneumaticSystem; + break; + case AuxiliaryType.ElectricSystem: + aux.PowerDemand = DeclarationData.ElectricSystem.Lookup(mission, auxData.TechList); + aux.ID = Constants.Auxiliaries.IDs.ElectricSystem; + break; + } + yield return aux; + } + } + + public static CrossWindCorrectionCurve GetDeclarationAirResistanceCurve(VehicleCategory vehicleCategory, + SquareMeter aerodynamicDragAera) + { + var values = DeclarationData.AirDrag.Lookup(vehicleCategory); + var points = new List<CrossWindCorrectionCurve.CrossWindCorrectionEntry> { + new CrossWindCorrectionCurve.CrossWindCorrectionEntry { + Velocity = 0.SI<MeterPerSecond>(), + EffectiveCrossSectionArea = 0.SI<SquareMeter>() + } + }; + + for (var speed = 60; speed <= 100; speed += 5) { + var vVeh = speed.KMPHtoMeterPerSecond(); + var cdASum = 0.0.SI<SquareMeter>(); + for (var alpha = 0; alpha <= 180; alpha += 10) { + var vWindX = Physics.BaseWindSpeed * Math.Cos(alpha.ToRadian()); + var vWindY = Physics.BaseWindSpeed * Math.Sin(alpha.ToRadian()); + var vAirX = vVeh + vWindX; + var vAirY = vWindY; // var vAir = VectoMath.Sqrt<MeterPerSecond>(vAirX * vAirX + vAirY * vAirY); - var beta = Math.Atan((vAirY / vAirX).Value()).ToDegree(); - var deltaCdA = ComputeDeltaCd(beta, values); - var cdA = aerodynamicDragAera + deltaCdA; + var beta = Math.Atan((vAirY / vAirX).Value()).ToDegree(); + var deltaCdA = ComputeDeltaCd(beta, values); + var cdA = aerodynamicDragAera + deltaCdA; - var degreeShare = ((alpha != 0 && alpha != 180) ? 10.0 / 180.0 : 5.0 / 180.0); + var degreeShare = ((alpha != 0 && alpha != 180) ? 10.0 / 180.0 : 5.0 / 180.0); // cdASum += degreeShare * cdA * (vAir * vAir / (vVeh * vVeh)).Cast<Scalar>(); - cdASum += degreeShare * cdA * ((vAirX * vAirX + vAirY * vAirY) / (vVeh * vVeh)).Cast<Scalar>(); - } - points.Add(new CrossWindCorrectionCurve.CrossWindCorrectionEntry { - Velocity = vVeh, - EffectiveCrossSectionArea = cdASum - }); - } - - points[0].EffectiveCrossSectionArea = points[1].EffectiveCrossSectionArea; - return new CrossWindCorrectionCurve(points, CrossWindCorrectionMode.DeclarationModeCorrection); - } - - protected static SquareMeter ComputeDeltaCd(double beta, AirDrag.AirDragEntry values) - { - return (values.A1 * beta + values.A2 * beta * beta + values.A3 * beta * beta * beta).SI<SquareMeter>(); - } - } + cdASum += degreeShare * cdA * ((vAirX * vAirX + vAirY * vAirY) / (vVeh * vVeh)).Cast<Scalar>(); + } + points.Add(new CrossWindCorrectionCurve.CrossWindCorrectionEntry { + Velocity = vVeh, + EffectiveCrossSectionArea = cdASum + }); + } + + points[0].EffectiveCrossSectionArea = points[1].EffectiveCrossSectionArea; + return new CrossWindCorrectionCurve(points, CrossWindCorrectionMode.DeclarationModeCorrection); + } + + protected static SquareMeter ComputeDeltaCd(double beta, AirDrag.AirDragEntry values) + { + return (values.A1 * beta + values.A2 * beta * beta + values.A3 * beta * beta * beta).SI<SquareMeter>(); + } + } } \ No newline at end of file diff --git a/VectoCore/FileIO/Reader/DataObjectAdaper/EngineeringDataAdapter.cs b/VectoCore/FileIO/Reader/DataObjectAdaper/EngineeringDataAdapter.cs index 4f1249011f4fa31f6152c88f37fde7437e8a287c..1dec2481b497d3c3186f263049996f3d03a71907 100644 --- a/VectoCore/FileIO/Reader/DataObjectAdaper/EngineeringDataAdapter.cs +++ b/VectoCore/FileIO/Reader/DataObjectAdaper/EngineeringDataAdapter.cs @@ -119,6 +119,10 @@ namespace TUGraz.VectoCore.FileIO.Reader.DataObjectAdaper CrossWindCorrectionCurve.GetNoCorrectionCurve(retVal.AerodynamicDragAera); break; case CrossWindCorrectionMode.SpeedDependentCorrectionFactor: + retVal.CrossWindCorrectionCurve = + CrossWindCorrectionCurve.ReadSpeedDependentCorrectionFromFile( + Path.Combine(vehicle.BasePath, data.CrossWindCorrectionFile), + retVal.AerodynamicDragAera); break; case CrossWindCorrectionMode.VAirBetaLookupTable: throw new VectoException("CrosswindCorrection mode {0} not implemented", crosswindCorrectionMode); diff --git a/VectoCore/Models/Declaration/AirDrag.cs b/VectoCore/Models/Declaration/AirDrag.cs index 1b66bee4583411ae8306e248319088675ac08b47..1e1d886ba788f4485e8010f375b7baf9d9baff62 100644 --- a/VectoCore/Models/Declaration/AirDrag.cs +++ b/VectoCore/Models/Declaration/AirDrag.cs @@ -58,7 +58,7 @@ namespace TUGraz.VectoCore.Models.Declaration if (ReferenceEquals(this, obj)) { return true; } - if (obj.GetType() != this.GetType()) { + if (obj.GetType() != GetType()) { return false; } return Equals((AirDragEntry)obj); diff --git a/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurve.cs b/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurve.cs index 00c3391e7941caf41345331bab388d7fb10590c5..3a8d5a4ee9f4ab893b6f48e5a2465d9cce145e56 100644 --- a/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurve.cs +++ b/VectoCore/Models/SimulationComponent/Data/CrossWindCorrectionCurve.cs @@ -1,113 +1,125 @@ using System.Collections.Generic; using System.Data; +using System.IO; using System.Linq; -using iTextSharp.text; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data { - public class CrossWindCorrectionCurve : LoggingObject - { - public CrossWindCorrectionMode CorrectionMode { get; internal set; } - - protected List<CrossWindCorrectionEntry> Entries; - - public CrossWindCorrectionCurve(List<CrossWindCorrectionEntry> entries, CrossWindCorrectionMode correctionMode) - { - CorrectionMode = correctionMode; - Entries = entries; - } - - public static CrossWindCorrectionCurve ReadSpeedDependentCorrectionFromFile(string fileName, - SquareMeter aerodynamicDragArea) - { - var data = VectoCSVFile.Read(fileName); - if (data.Columns.Count != 2) { - throw new VectoException("Crosswind correction file must consist of 2 columns."); - } - if (data.Rows.Count < 2) { - throw new VectoException("Crosswind correction file must consist of at least two entries"); - } - - if (HeaderIsValid(data.Columns)) { - return new CrossWindCorrectionCurve(ReadFromColumnNames(data, aerodynamicDragArea), - CrossWindCorrectionMode.SpeedDependentCorrectionFactor); - } else { - Logger<CrossWindCorrectionCurve>() - .Warn( - "Crosswind correction file: Header line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.", - Fields.Velocity, Fields.Cd, - string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); - return new CrossWindCorrectionCurve(ReadFromColumnIndizes(data, aerodynamicDragArea), - CrossWindCorrectionMode.SpeedDependentCorrectionFactor); - } - } - - private static List<CrossWindCorrectionEntry> ReadFromColumnIndizes(DataTable data, - SquareMeter aerodynamicDragArea) - { - return (from DataRow row in data.Rows - select new CrossWindCorrectionEntry { - Velocity = row.ParseDouble(0).KMPHtoMeterPerSecond(), - EffectiveCrossSectionArea = row.ParseDouble(1) * aerodynamicDragArea - }).ToList(); - } - - private static List<CrossWindCorrectionEntry> ReadFromColumnNames(DataTable data, - SquareMeter aerodynamicDragArea) - { - return (from DataRow row in data.Rows - select new CrossWindCorrectionEntry { - Velocity = row.ParseDouble(Fields.Velocity).KMPHtoMeterPerSecond(), - EffectiveCrossSectionArea = row.ParseDouble(Fields.Cd) * aerodynamicDragArea - }).ToList(); - } - - private static bool HeaderIsValid(DataColumnCollection columns) - { - return columns.Contains(Fields.Velocity) && columns.Contains(Fields.Cd); - } - - public static CrossWindCorrectionCurve GetNoCorrectionCurve(SquareMeter aerodynamicDragArea) - { - return new CrossWindCorrectionCurve(new[] { - new CrossWindCorrectionEntry() { - Velocity = 0.KMPHtoMeterPerSecond(), - EffectiveCrossSectionArea = aerodynamicDragArea - }, - new CrossWindCorrectionEntry() { - Velocity = 100.KMPHtoMeterPerSecond(), - EffectiveCrossSectionArea = aerodynamicDragArea - } - }.ToList(), CrossWindCorrectionMode.NoCorrection); - } - - public SquareMeter EffectiveAirDragArea(MeterPerSecond x) - { - var p = Entries.GetSection(c => c.Velocity < x); - - if (x < p.Item1.Velocity || p.Item2.Velocity < x) { - //Log.Error(_data.CrossWindCorrectionMode == CrossWindCorrectionMode.VAirBetaLookupTable - // ? string.Format("CdExtrapol β = {0}", x) - // : string.Format("CdExtrapol v = {0}", x)); - Log.Error("CdExtrapol v = {0}", x); - } - - return VectoMath.Interpolate(p.Item1.Velocity, p.Item2.Velocity, - p.Item1.EffectiveCrossSectionArea, p.Item2.EffectiveCrossSectionArea, x); - } - - public class Fields - { - public static readonly string Velocity = "v"; - public static readonly string Cd = "Cd"; - } - - public class CrossWindCorrectionEntry - { - public MeterPerSecond Velocity; - public SquareMeter EffectiveCrossSectionArea; - } - } + public class CrossWindCorrectionCurve : LoggingObject + { + protected List<CrossWindCorrectionEntry> Entries; + + public CrossWindCorrectionCurve(List<CrossWindCorrectionEntry> entries, CrossWindCorrectionMode correctionMode) + { + CorrectionMode = correctionMode; + Entries = entries; + } + + public CrossWindCorrectionMode CorrectionMode { get; internal set; } + + public static CrossWindCorrectionCurve ReadSpeedDependentCorrectionCurveFromStream(Stream inputData, + SquareMeter aerodynamicDragArea) + { + var data = VectoCSVFile.ReadStream(inputData); + return Parse(data, aerodynamicDragArea); + } + + public static CrossWindCorrectionCurve ReadSpeedDependentCorrectionFromFile(string fileName, + SquareMeter aerodynamicDragArea) + { + var data = VectoCSVFile.Read(fileName); + return Parse(data, aerodynamicDragArea); + } + + private static CrossWindCorrectionCurve Parse(DataTable data, + SquareMeter aerodynamicDragArea) + { + if (data.Columns.Count != 2) { + throw new VectoException("Crosswind correction file must consist of 2 columns."); + } + if (data.Rows.Count < 2) { + throw new VectoException("Crosswind correction file must consist of at least two entries"); + } + + if (HeaderIsValid(data.Columns)) { + return new CrossWindCorrectionCurve(ReadFromColumnNames(data, aerodynamicDragArea), + CrossWindCorrectionMode.SpeedDependentCorrectionFactor); + } + Logger<CrossWindCorrectionCurve>() + .Warn( + "Crosswind correction file: Header line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.", + Fields.Velocity, Fields.Cd, + string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); + return new CrossWindCorrectionCurve(ReadFromColumnIndizes(data, aerodynamicDragArea), + CrossWindCorrectionMode.SpeedDependentCorrectionFactor); + } + + private static List<CrossWindCorrectionEntry> ReadFromColumnIndizes(DataTable data, + SquareMeter aerodynamicDragArea) + { + return (from DataRow row in data.Rows + select new CrossWindCorrectionEntry { + Velocity = row.ParseDouble(0).KMPHtoMeterPerSecond(), + EffectiveCrossSectionArea = row.ParseDouble(1) * aerodynamicDragArea + }).ToList(); + } + + private static List<CrossWindCorrectionEntry> ReadFromColumnNames(DataTable data, + SquareMeter aerodynamicDragArea) + { + return (from DataRow row in data.Rows + select new CrossWindCorrectionEntry { + Velocity = row.ParseDouble(Fields.Velocity).KMPHtoMeterPerSecond(), + EffectiveCrossSectionArea = row.ParseDouble(Fields.Cd) * aerodynamicDragArea + }).ToList(); + } + + private static bool HeaderIsValid(DataColumnCollection columns) + { + return columns.Contains(Fields.Velocity) && columns.Contains(Fields.Cd); + } + + public static CrossWindCorrectionCurve GetNoCorrectionCurve(SquareMeter aerodynamicDragArea) + { + return new CrossWindCorrectionCurve(new[] { + new CrossWindCorrectionEntry { + Velocity = 0.KMPHtoMeterPerSecond(), + EffectiveCrossSectionArea = aerodynamicDragArea + }, + new CrossWindCorrectionEntry { + Velocity = 100.KMPHtoMeterPerSecond(), + EffectiveCrossSectionArea = aerodynamicDragArea + } + }.ToList(), CrossWindCorrectionMode.NoCorrection); + } + + public SquareMeter EffectiveAirDragArea(MeterPerSecond x) + { + var p = Entries.GetSection(c => c.Velocity < x); + + if (x < p.Item1.Velocity || p.Item2.Velocity < x) { + //Log.Error(_data.CrossWindCorrectionMode == CrossWindCorrectionMode.VAirBetaLookupTable + // ? string.Format("CdExtrapol β = {0}", x) + // : string.Format("CdExtrapol v = {0}", x)); + Log.Error("CdExtrapol v = {0}", x); + } + + return VectoMath.Interpolate(p.Item1.Velocity, p.Item2.Velocity, + p.Item1.EffectiveCrossSectionArea, p.Item2.EffectiveCrossSectionArea, x); + } + + public class Fields + { + public static readonly string Velocity = "v"; + public static readonly string Cd = "Cd"; + } + + public class CrossWindCorrectionEntry + { + public SquareMeter EffectiveCrossSectionArea; + public MeterPerSecond Velocity; + } + } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/CycleData.cs b/VectoCore/Models/SimulationComponent/Data/CycleData.cs index 27eac5780579226c28d332055041c96f9b0164cd..76c9d656fb7cff153cf9c70addd46d43105677aa 100644 --- a/VectoCore/Models/SimulationComponent/Data/CycleData.cs +++ b/VectoCore/Models/SimulationComponent/Data/CycleData.cs @@ -5,23 +5,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data public class CycleData { /// <summary> - /// The left data sample of the current driving cycle position. (current start point) + /// The current absolute distance in the driving cycle. /// </summary> - public DrivingCycleData.DrivingCycleEntry LeftSample; + public Meter AbsDistance; /// <summary> - /// The right data sample of the current driving cycle position. (current end point) + /// The current absolute time in the driving cycle. /// </summary> - public DrivingCycleData.DrivingCycleEntry RightSample; + public Second AbsTime; /// <summary> - /// The current absolute distance in the driving cycle. + /// The left data sample of the current driving cycle position. (current start point) /// </summary> - public Meter AbsDistance; + public DrivingCycleData.DrivingCycleEntry LeftSample; /// <summary> - /// The current absolute time in the driving cycle. + /// The right data sample of the current driving cycle position. (current end point) /// </summary> - public Second AbsTime; + public DrivingCycleData.DrivingCycleEntry RightSample; } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/FullLoadCurve.cs b/VectoCore/Models/SimulationComponent/Data/FullLoadCurve.cs index 585cd4a813ec99320c5b5e1403477a305ee04379..20e11d446307824162b308a7b0bdd453b45dc38c 100644 --- a/VectoCore/Models/SimulationComponent/Data/FullLoadCurve.cs +++ b/VectoCore/Models/SimulationComponent/Data/FullLoadCurve.cs @@ -12,11 +12,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data { public class FullLoadCurve : SimulationComponentData { + protected Watt _maxPower; + protected PerSecond _ratedSpeed; internal List<FullLoadCurveEntry> FullLoadEntries; internal LookupData<PerSecond, Second> PT1Data; - protected PerSecond _ratedSpeed; - protected Watt _maxPower; + /// <summary> + /// Get the rated speed from the given full-load curve (i.e. speed with max. power) + /// </summary> + public PerSecond RatedSpeed + { + get { return (_ratedSpeed ?? ComputeRatedSpeed().Item1); } + } + + public Watt MaxPower + { + get { return (_maxPower ?? ComputeRatedSpeed().Item2); } + } public static FullLoadCurve ReadFromFile(string fileName, bool declarationMode = false) { @@ -70,7 +82,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data select new FullLoadCurveEntry { EngineSpeed = row.ParseDouble(Fields.EngineSpeed).RPMtoRad(), TorqueFullLoad = row.ParseDouble(Fields.TorqueFullLoad).SI<NewtonMeter>(), - TorqueDrag = row.ParseDouble(Fields.TorqueDrag).SI<NewtonMeter>(), + TorqueDrag = row.ParseDouble(Fields.TorqueDrag).SI<NewtonMeter>() //PT1 = row.ParseDouble(Fields.PT1).SI<Second>() }).ToList(); } @@ -82,27 +94,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data select new FullLoadCurveEntry { EngineSpeed = row.ParseDouble(0).RPMtoRad(), TorqueFullLoad = row.ParseDouble(1).SI<NewtonMeter>(), - TorqueDrag = row.ParseDouble(2).SI<NewtonMeter>(), + TorqueDrag = row.ParseDouble(2).SI<NewtonMeter>() //PT1 = row.ParseDouble(3).SI<Second>() }).ToList(); } /// <summary> - /// Get the rated speed from the given full-load curve (i.e. speed with max. power) - /// </summary> - public PerSecond RatedSpeed - { - get { return (_ratedSpeed ?? ComputeRatedSpeed().Item1); } - } - - public Watt MaxPower - { - get { return (_maxPower ?? ComputeRatedSpeed().Item2); } - } - - - /// <summary> - /// Compute the engine's rated speed from the given full-load curve (i.e. engine speed with max. power) + /// Compute the engine's rated speed from the given full-load curve (i.e. engine speed with max. power) /// </summary> protected Tuple<PerSecond, Watt> ComputeRatedSpeed() { @@ -182,11 +180,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data internal class FullLoadCurveEntry { public PerSecond EngineSpeed { get; set; } - public NewtonMeter TorqueFullLoad { get; set; } - public NewtonMeter TorqueDrag { get; set; } - //public Second PT1 { get; set; } #region Equality members diff --git a/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs b/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs index e2ca3c7519d7ea5593f80ca4474dc8b6cbf34a9c..cf98c784ce97de7c9f0ef639cc46a3991e01aabd 100644 --- a/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs +++ b/VectoCore/Models/SimulationComponent/Data/RetarderLossMap.cs @@ -6,102 +6,100 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data { - public class RetarderLossMap : SimulationComponentData - { - private List<RetarderLossEntry> _entries; + public class RetarderLossMap : SimulationComponentData + { + private List<RetarderLossEntry> _entries; + public static RetarderLossMap ReadFromFile(string fileName) + { + var data = VectoCSVFile.Read(fileName); - public static RetarderLossMap ReadFromFile(string fileName) - { - var data = VectoCSVFile.Read(fileName); + if (data.Columns.Count != 2) { + throw new VectoException("RetarderLossMap Data File must consist of 2 columns."); + } - if (data.Columns.Count != 2) { - throw new VectoException("RetarderLossMap Data File must consist of 2 columns."); - } + if (data.Rows.Count < 2) { + throw new VectoException("RetarderLossMap must consist of at least two entries."); + } - if (data.Rows.Count < 2) { - throw new VectoException("RetarderLossMap must consist of at least two entries."); - } + List<RetarderLossEntry> entries; + if (HeaderIsValid(data.Columns)) { + entries = CreateFromColumnNames(data); + } else { + Logger<RetarderLossMap>().Warn( + "RetarderLossMap: Header Line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.", + Fields.RetarderSpeed, Fields.TorqueLoss, + string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); + entries = CreateFromColumnIndizes(data); + } + return new RetarderLossMap { _entries = entries }; + } - List<RetarderLossEntry> entries; - if (HeaderIsValid(data.Columns)) { - entries = CreateFromColumnNames(data); - } else { - Logger<RetarderLossMap>().Warn( - "RetarderLossMap: Header Line is not valid. Expected: '{0}, {1}', Got: '{2}'. Falling back to column index.", - Fields.RetarderSpeed, Fields.TorqueLoss, - string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); - entries = CreateFromColumnIndizes(data); - } - return new RetarderLossMap { _entries = entries }; - } + public NewtonMeter RetarderLoss(PerSecond angularVelocity) + { + var idx = FindIndex(angularVelocity); + return VectoMath.Interpolate(_entries[idx - 1].RetarderSpeed, _entries[idx].RetarderSpeed, + _entries[idx - 1].TorqueLoss, _entries[idx].TorqueLoss, angularVelocity); + } - public NewtonMeter RetarderLoss(PerSecond angularVelocity) - { - var idx = FindIndex(angularVelocity); - return VectoMath.Interpolate(_entries[idx - 1].RetarderSpeed, _entries[idx].RetarderSpeed, - _entries[idx - 1].TorqueLoss, _entries[idx].TorqueLoss, angularVelocity); - } + protected int FindIndex(PerSecond angularVelocity) + { + int idx; + if (angularVelocity < _entries[0].RetarderSpeed) { + Log.Info("requested rpm below minimum rpm in retarder loss map - extrapolating. n: {0}, rpm_min: {1}", + angularVelocity.ConvertTo().Rounds.Per.Minute, + _entries[0].RetarderSpeed.ConvertTo().Rounds.Per.Minute); + idx = 1; + } else { + idx = _entries.FindIndex(x => x.RetarderSpeed > angularVelocity); + } + if (idx <= 0) { + idx = angularVelocity > _entries[0].RetarderSpeed ? _entries.Count - 1 : 1; + } + return idx; + } - protected int FindIndex(PerSecond angularVelocity) - { - int idx; - if (angularVelocity < _entries[0].RetarderSpeed) { - Log.Info("requested rpm below minimum rpm in retarder loss map - extrapolating. n: {0}, rpm_min: {1}", - angularVelocity.ConvertTo().Rounds.Per.Minute, - _entries[0].RetarderSpeed.ConvertTo().Rounds.Per.Minute); - idx = 1; - } else { - idx = _entries.FindIndex(x => x.RetarderSpeed > angularVelocity); - } - if (idx <= 0) { - idx = angularVelocity > _entries[0].RetarderSpeed ? _entries.Count - 1 : 1; - } - return idx; - } + private static List<RetarderLossEntry> CreateFromColumnNames(DataTable data) + { + return (from DataRow row in data.Rows + select new RetarderLossEntry { + RetarderSpeed = row.ParseDouble(Fields.RetarderSpeed).RPMtoRad(), + TorqueLoss = row.ParseDouble(Fields.TorqueLoss).SI<NewtonMeter>() + }).ToList(); + } - private static List<RetarderLossEntry> CreateFromColumnNames(DataTable data) - { - return (from DataRow row in data.Rows - select new RetarderLossEntry { - RetarderSpeed = row.ParseDouble(Fields.RetarderSpeed).RPMtoRad(), - TorqueLoss = row.ParseDouble(Fields.TorqueLoss).SI<NewtonMeter>() - }).ToList(); - } + private static bool HeaderIsValid(DataColumnCollection columns) + { + return columns.Contains(Fields.RetarderSpeed) && columns.Contains(Fields.TorqueLoss); + } - private static bool HeaderIsValid(DataColumnCollection columns) - { - return columns.Contains(Fields.RetarderSpeed) && columns.Contains(Fields.TorqueLoss); - } + private static List<RetarderLossEntry> CreateFromColumnIndizes(DataTable data) + { + return (from DataRow row in data.Rows + select + new RetarderLossEntry { + RetarderSpeed = row.ParseDouble(0).RPMtoRad(), + TorqueLoss = row.ParseDouble(1).SI<NewtonMeter>() + }).ToList(); + } - private static List<RetarderLossEntry> CreateFromColumnIndizes(DataTable data) - { - return (from DataRow row in data.Rows - select - new RetarderLossEntry { - RetarderSpeed = row.ParseDouble(0).RPMtoRad(), - TorqueLoss = row.ParseDouble(1).SI<NewtonMeter>() - }).ToList(); - } + private class RetarderLossEntry + { + public PerSecond RetarderSpeed { get; set; } + public NewtonMeter TorqueLoss { get; set; } + } - private class RetarderLossEntry - { - public PerSecond RetarderSpeed { get; set; } + private static class Fields + { + /// <summary> + /// [rpm] + /// </summary> + public const string RetarderSpeed = "Retarder Speed"; - public NewtonMeter TorqueLoss { get; set; } - } - - private static class Fields - { - /// <summary> - /// [rpm] - /// </summary> - public const string RetarderSpeed = "Retarder Speed"; - - /// <summary> - /// [Nm] - /// </summary> - public const string TorqueLoss = "Torque Loss"; - } - } + /// <summary> + /// [Nm] + /// </summary> + public const string TorqueLoss = "Torque Loss"; + } + } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/VehicleData.cs b/VectoCore/Models/SimulationComponent/Data/VehicleData.cs index 19e04a6d5bb656ce6808eaf9a7da9a1a237aeb1d..9791589edccb199933d22a6034d000dd829994cc 100644 --- a/VectoCore/Models/SimulationComponent/Data/VehicleData.cs +++ b/VectoCore/Models/SimulationComponent/Data/VehicleData.cs @@ -6,95 +6,81 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Data { - public class VehicleData : SimulationComponentData - { - public string BasePath { get; internal set; } - - public VehicleCategory VehicleCategory { get; internal set; } - - public VehicleClass VehicleClass { get; internal set; } - - //public CrossWindCorrectionMode CrossWindCorrectionMode { get; internal set; } - - public CrossWindCorrectionCurve CrossWindCorrectionCurve { get; internal set; } - - public RetarderData Retarder { get; internal set; } - - private List<Axle> _axleData; - - /// <summary> - /// Set the properties for all axles of the vehicle - /// </summary> - public List<Axle> AxleData - { - get { return _axleData; } - internal set - { - _axleData = value; - ComputeRollResistanceAndReducedMassWheels(); - } - } - - public AxleConfiguration AxleConfiguration { get; internal set; } - - public Kilogram CurbWeight { get; internal set; } - - public Kilogram CurbWeigthExtra { get; internal set; } - - public Kilogram Loading { get; internal set; } - - public Kilogram TotalVehicleWeight() - { - var retVal = 0.SI<Kilogram>(); - retVal += CurbWeight ?? 0.SI<Kilogram>(); - retVal += CurbWeigthExtra ?? 0.SI<Kilogram>(); - retVal += Loading ?? 0.SI<Kilogram>(); - return retVal; - } - - public Kilogram TotalCurbWeight() - { - var retVal = 0.SI<Kilogram>(); - retVal += CurbWeight ?? 0.SI<Kilogram>(); - retVal += CurbWeigthExtra ?? 0.SI<Kilogram>(); - return retVal; - } - - public Kilogram GrossVehicleMassRating { get; internal set; } - - public SquareMeter AerodynamicDragAera { get; internal set; } - - public Meter DynamicTyreRadius { get; internal set; } - - public Kilogram ReducedMassWheels { get; private set; } - - public string Rim { get; internal set; } - - public double TotalRollResistanceCoefficient { get; private set; } - - protected void ComputeRollResistanceAndReducedMassWheels() - { - if (TotalVehicleWeight() == 0.SI<Kilogram>()) { - throw new VectoException( - "Total vehicle weight must be greater than 0! Set CurbWeight and Loading before!"); - } - if (DynamicTyreRadius == null) { - throw new VectoException("Dynamic tyre radius must be set before axles!"); - } - - var RRC = 0.0; - var mRed0 = 0.SI<Kilogram>(); - foreach (var axle in _axleData) { - var nrWheels = axle.TwinTyres ? 4 : 2; - RRC += axle.AxleWeightShare * axle.RollResistanceCoefficient * - Math.Pow( - (axle.AxleWeightShare * TotalVehicleWeight() * Physics.GravityAccelleration / - axle.TyreTestLoad / - nrWheels).Value(), Physics.RollResistanceExponent - 1); - mRed0 += nrWheels * (axle.Inertia / DynamicTyreRadius / DynamicTyreRadius).Cast<Kilogram>(); - } - TotalRollResistanceCoefficient = RRC; - ReducedMassWheels = mRed0; - } - } + public class VehicleData : SimulationComponentData + { + private List<Axle> _axleData; + public string BasePath { get; internal set; } + public VehicleCategory VehicleCategory { get; internal set; } + public VehicleClass VehicleClass { get; internal set; } + //public CrossWindCorrectionMode CrossWindCorrectionMode { get; internal set; } + + public CrossWindCorrectionCurve CrossWindCorrectionCurve { get; internal set; } + public RetarderData Retarder { get; internal set; } + + /// <summary> + /// Set the properties for all axles of the vehicle + /// </summary> + public List<Axle> AxleData + { + get { return _axleData; } + internal set + { + _axleData = value; + ComputeRollResistanceAndReducedMassWheels(); + } + } + + public AxleConfiguration AxleConfiguration { get; internal set; } + public Kilogram CurbWeight { get; internal set; } + public Kilogram CurbWeigthExtra { get; internal set; } + public Kilogram Loading { get; internal set; } + public Kilogram GrossVehicleMassRating { get; internal set; } + public SquareMeter AerodynamicDragAera { get; internal set; } + public Meter DynamicTyreRadius { get; internal set; } + public Kilogram ReducedMassWheels { get; private set; } + public string Rim { get; internal set; } + public double TotalRollResistanceCoefficient { get; private set; } + + public Kilogram TotalVehicleWeight() + { + var retVal = 0.SI<Kilogram>(); + retVal += CurbWeight ?? 0.SI<Kilogram>(); + retVal += CurbWeigthExtra ?? 0.SI<Kilogram>(); + retVal += Loading ?? 0.SI<Kilogram>(); + return retVal; + } + + public Kilogram TotalCurbWeight() + { + var retVal = 0.SI<Kilogram>(); + retVal += CurbWeight ?? 0.SI<Kilogram>(); + retVal += CurbWeigthExtra ?? 0.SI<Kilogram>(); + return retVal; + } + + protected void ComputeRollResistanceAndReducedMassWheels() + { + if (TotalVehicleWeight() == 0.SI<Kilogram>()) { + throw new VectoException( + "Total vehicle weight must be greater than 0! Set CurbWeight and Loading before!"); + } + if (DynamicTyreRadius == null) { + throw new VectoException("Dynamic tyre radius must be set before axles!"); + } + + var RRC = 0.0; + var mRed0 = 0.SI<Kilogram>(); + foreach (var axle in _axleData) { + var nrWheels = axle.TwinTyres ? 4 : 2; + RRC += axle.AxleWeightShare * axle.RollResistanceCoefficient * + Math.Pow( + (axle.AxleWeightShare * TotalVehicleWeight() * Physics.GravityAccelleration / + axle.TyreTestLoad / + nrWheels).Value(), Physics.RollResistanceExponent - 1); + mRed0 += nrWheels * (axle.Inertia / DynamicTyreRadius / DynamicTyreRadius).Cast<Kilogram>(); + } + TotalRollResistanceCoefficient = RRC; + ReducedMassWheels = mRed0; + } + } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs index bf141f9a8bc3b6c4c043d6ca3ff1550481336abb..7ef951a3a7936f2127651f2caefad0e697b70074 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Runtime.InteropServices.WindowsRuntime; using TUGraz.VectoCore.Configuration; -using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation; @@ -13,254 +10,245 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - public class Vehicle : VectoSimulationComponent, IVehicle, IMileageCounter, IFvInPort, IDriverDemandOutPort - { - protected IFvOutPort NextComponent; - private VehicleState _previousState; - private VehicleState _currentState; - private readonly VehicleData _data; - - private readonly CrossWindCorrectionCurve _airResistanceCurve; - - public MeterPerSecond VehicleSpeed - { - get { return _previousState.Velocity; } - } - - public Kilogram VehicleMass - { - get { return _data.TotalCurbWeight(); } - } - - public Kilogram VehicleLoading - { - get { return _data.Loading; } - } - - public Kilogram TotalMass - { - get { return _data.TotalVehicleWeight(); } - } - - public Meter Distance - { - get { return _previousState.Distance; } - } - - - public Vehicle(IVehicleContainer container, VehicleData data) : base(container) - { - _data = data; - _previousState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = 0.SI<MeterPerSecond>() }; - _currentState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = 0.SI<MeterPerSecond>() }; - - var values = DeclarationData.AirDrag.Lookup(_data.VehicleCategory); - _airResistanceCurve = data.CrossWindCorrectionCurve; - } - - - public IFvInPort InPort() - { - return this; - } - - public IDriverDemandOutPort OutPort() - { - return this; - } - - public void Connect(IFvOutPort other) - { - NextComponent = other; - } - - public IResponse Initialize(MeterPerSecond vehicleSpeed, Radian roadGradient) - { - _previousState = new VehicleState { - Distance = DataBus.CycleStartDistance, - Velocity = vehicleSpeed, - RollingResistance = RollingResistance(roadGradient), - SlopeResistance = SlopeResistance(roadGradient) - }; - _previousState.AirDragResistance = AirDragResistance(0.SI<MeterPerSquareSecond>(), - Constants.SimulationSettings.TargetTimeInterval); - _previousState.VehicleAccelerationForce = _previousState.RollingResistance - + _previousState.AirDragResistance - + _previousState.SlopeResistance; - - _currentState = new VehicleState { - Distance = DataBus.CycleStartDistance, - Velocity = vehicleSpeed, - AirDragResistance = _previousState.AirDragResistance, - RollingResistance = _previousState.RollingResistance, - SlopeResistance = _previousState.SlopeResistance, - VehicleAccelerationForce = _previousState.VehicleAccelerationForce, - }; - - - return NextComponent.Initialize(_currentState.VehicleAccelerationForce, vehicleSpeed); - } - - public IResponse Initialize(MeterPerSecond vehicleSpeed, MeterPerSquareSecond startAcceleration, - Radian roadGradient) - { - var tmp = _previousState.Velocity; - // set vehicle speed to get accurate airdrag resistance - _previousState.Velocity = vehicleSpeed; - _currentState.Velocity = vehicleSpeed + startAcceleration * Constants.SimulationSettings.TargetTimeInterval; - var vehicleAccelerationForce = DriverAcceleration(startAcceleration) + RollingResistance(roadGradient) + - AirDragResistance(startAcceleration, - Constants.SimulationSettings.TargetTimeInterval) + - SlopeResistance(roadGradient); - - var retVal = NextComponent.Initialize(vehicleAccelerationForce, vehicleSpeed); - - _previousState.Velocity = tmp; - _currentState.Velocity = tmp; - return retVal; - } - - public IResponse Request(Second absTime, Second dt, MeterPerSquareSecond acceleration, Radian gradient, - bool dryRun = false) - { - Log.Debug("from Wheels: acceleration: {0}", acceleration); - _currentState.dt = dt; - _currentState.Acceleration = acceleration; - _currentState.Velocity = _previousState.Velocity + acceleration * dt; - if (_currentState.Velocity.IsEqual(0.SI<MeterPerSecond>(), - Constants.SimulationSettings.VehicleSpeedHaltTolerance)) { - _currentState.Velocity = 0.SI<MeterPerSecond>(); - } - _currentState.Distance = _previousState.Distance + _previousState.Velocity * dt + acceleration * dt * dt / 2; - - _currentState.DriverAcceleration = DriverAcceleration(acceleration); - _currentState.RollingResistance = RollingResistance(gradient); - _currentState.AirDragResistance = AirDragResistance(acceleration, dt); - _currentState.SlopeResistance = SlopeResistance(gradient); - - // DriverAcceleration = vehicleAccelerationForce - RollingResistance - AirDragResistance - SlopeResistance - _currentState.VehicleAccelerationForce = _currentState.DriverAcceleration - + _currentState.RollingResistance - + _currentState.AirDragResistance - + _currentState.SlopeResistance; - - var retval = NextComponent.Request(absTime, dt, _currentState.VehicleAccelerationForce, - _currentState.Velocity, - dryRun); - return retval; - } - - protected override void DoWriteModalResults(IModalDataWriter writer) - { - var averageVelocity = (_previousState.Velocity + _currentState.Velocity) / 2; - - writer[ModalResultField.v_act] = averageVelocity; - writer[ModalResultField.PaVeh] = ((_previousState.VehicleAccelerationForce * _previousState.Velocity + - _currentState.VehicleAccelerationForce * _currentState.Velocity) / 2.0) - .Cast<Watt>(); - writer[ModalResultField.Pgrad] = ((_previousState.SlopeResistance * _previousState.Velocity + - _currentState.SlopeResistance * _currentState.Velocity) / 2.0).Cast<Watt> - (); - writer[ModalResultField.Proll] = ((_previousState.RollingResistance * _previousState.Velocity + - _currentState.RollingResistance * _currentState.Velocity) / 2.0) - .Cast<Watt>(); - - writer[ModalResultField.Pair] = ComputeAirDragPowerLoss(_previousState.Velocity, _currentState.Velocity, - _currentState.dt); - - - // sanity check: is the vehicle in step with the cycle? - if (writer[ModalResultField.dist] == DBNull.Value) { - Log.Warn("distance field is not set!"); - } else { - var distance = (SI)writer[ModalResultField.dist]; - if (!distance.IsEqual(_currentState.Distance, 1e-12.SI<Meter>())) { - Log.Warn("distance diverges: {0}, distance: {1}", (distance - _currentState.Distance).Value(), - distance); - } - } - } - - - protected override void DoCommitSimulationStep() - { - _previousState = _currentState; - _currentState = new VehicleState(); - } - - protected Newton RollingResistance(Radian gradient) - { - var retVal = (Math.Cos(gradient.Value()) * _data.TotalVehicleWeight() * - Physics.GravityAccelleration * - _data.TotalRollResistanceCoefficient).Cast<Newton>(); - Log.Debug("RollingResistance: {0}", retVal); - return retVal; - } - - - protected Newton DriverAcceleration(MeterPerSquareSecond accelleration) - { - var retVal = ((_data.TotalVehicleWeight() + _data.ReducedMassWheels) * accelleration).Cast<Newton>(); - Log.Debug("DriverAcceleration: {0}", retVal); - return retVal; - } - - - protected internal Newton SlopeResistance(Radian gradient) - { - var retVal = - (_data.TotalVehicleWeight() * Physics.GravityAccelleration * Math.Sin(gradient.Value())).Cast<Newton>(); - Log.Debug("SlopeResistance: {0}", retVal); - return retVal; - } - - - protected internal Newton AirDragResistance(MeterPerSquareSecond acceleration, Second dt) - { - var vAverage = _previousState.Velocity + acceleration * dt / 2; - if (vAverage.IsEqual(0)) { - return 0.SI<Newton>(); - } - var result = - (ComputeAirDragPowerLoss(_previousState.Velocity, _previousState.Velocity + acceleration * dt, dt) / - vAverage).Cast<Newton>(); - - Log.Debug("AirDragResistance: {0}", result); - return result; - } - - private Watt ComputeAirDragPowerLoss(MeterPerSecond v1, MeterPerSecond v2, Second dt) - { - var vAverage = (v1 + v2) / 2; - var CdA = _airResistanceCurve.EffectiveAirDragArea(vAverage); - Watt averageAirDragPower; - if (v1.IsEqual(v2)) { - averageAirDragPower = (Physics.AirDensity / 2.0 * CdA * vAverage * vAverage * vAverage).Cast<Watt>(); - } else { - // compute the average force within the current simulation interval - // P(t) = k * v(t)^3 , v(t) = v0 + a * t // a != 0 - // => P_avg = (CdA * rho/2)/(4*a * dt) * (v2^4 - v1^4) - var acceleration = (v2 - v1) / dt; - averageAirDragPower = - (Physics.AirDensity / 2.0 * CdA * (v2 * v2 * v2 * v2 - v1 * v1 * v1 * v1) / (4 * acceleration * dt)) - .Cast<Watt>(); - } - return averageAirDragPower; - } - - - public class VehicleState - { - public MeterPerSecond Velocity; - public Second dt; - public Meter Distance; - - public Newton VehicleAccelerationForce; - public Newton DriverAcceleration; - public Newton SlopeResistance; - public Newton AirDragResistance; - public Newton RollingResistance; - public MeterPerSquareSecond Acceleration { get; set; } - } - } + public class Vehicle : VectoSimulationComponent, IVehicle, IMileageCounter, IFvInPort, IDriverDemandOutPort + { + private readonly CrossWindCorrectionCurve _airResistanceCurve; + private readonly VehicleData _data; + private VehicleState _currentState; + private VehicleState _previousState; + protected IFvOutPort NextComponent; + + public Vehicle(IVehicleContainer container, VehicleData data) : base(container) + { + _data = data; + _previousState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = 0.SI<MeterPerSecond>() }; + _currentState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = 0.SI<MeterPerSecond>() }; + + var values = DeclarationData.AirDrag.Lookup(_data.VehicleCategory); + _airResistanceCurve = data.CrossWindCorrectionCurve; + } + + public IResponse Initialize(MeterPerSecond vehicleSpeed, Radian roadGradient) + { + _previousState = new VehicleState { + Distance = DataBus.CycleStartDistance, + Velocity = vehicleSpeed, + RollingResistance = RollingResistance(roadGradient), + SlopeResistance = SlopeResistance(roadGradient) + }; + _previousState.AirDragResistance = AirDragResistance(0.SI<MeterPerSquareSecond>(), + Constants.SimulationSettings.TargetTimeInterval); + _previousState.VehicleAccelerationForce = _previousState.RollingResistance + + _previousState.AirDragResistance + + _previousState.SlopeResistance; + + _currentState = new VehicleState { + Distance = DataBus.CycleStartDistance, + Velocity = vehicleSpeed, + AirDragResistance = _previousState.AirDragResistance, + RollingResistance = _previousState.RollingResistance, + SlopeResistance = _previousState.SlopeResistance, + VehicleAccelerationForce = _previousState.VehicleAccelerationForce + }; + + + return NextComponent.Initialize(_currentState.VehicleAccelerationForce, vehicleSpeed); + } + + public IResponse Initialize(MeterPerSecond vehicleSpeed, MeterPerSquareSecond startAcceleration, + Radian roadGradient) + { + var tmp = _previousState.Velocity; + // set vehicle speed to get accurate airdrag resistance + _previousState.Velocity = vehicleSpeed; + _currentState.Velocity = vehicleSpeed + startAcceleration * Constants.SimulationSettings.TargetTimeInterval; + var vehicleAccelerationForce = DriverAcceleration(startAcceleration) + RollingResistance(roadGradient) + + AirDragResistance(startAcceleration, + Constants.SimulationSettings.TargetTimeInterval) + + SlopeResistance(roadGradient); + + var retVal = NextComponent.Initialize(vehicleAccelerationForce, vehicleSpeed); + + _previousState.Velocity = tmp; + _currentState.Velocity = tmp; + return retVal; + } + + public IResponse Request(Second absTime, Second dt, MeterPerSquareSecond acceleration, Radian gradient, + bool dryRun = false) + { + Log.Debug("from Wheels: acceleration: {0}", acceleration); + _currentState.dt = dt; + _currentState.Acceleration = acceleration; + _currentState.Velocity = _previousState.Velocity + acceleration * dt; + if (_currentState.Velocity.IsEqual(0.SI<MeterPerSecond>(), + Constants.SimulationSettings.VehicleSpeedHaltTolerance)) { + _currentState.Velocity = 0.SI<MeterPerSecond>(); + } + _currentState.Distance = _previousState.Distance + _previousState.Velocity * dt + acceleration * dt * dt / 2; + + _currentState.DriverAcceleration = DriverAcceleration(acceleration); + _currentState.RollingResistance = RollingResistance(gradient); + _currentState.AirDragResistance = AirDragResistance(acceleration, dt); + _currentState.SlopeResistance = SlopeResistance(gradient); + + // DriverAcceleration = vehicleAccelerationForce - RollingResistance - AirDragResistance - SlopeResistance + _currentState.VehicleAccelerationForce = _currentState.DriverAcceleration + + _currentState.RollingResistance + + _currentState.AirDragResistance + + _currentState.SlopeResistance; + + var retval = NextComponent.Request(absTime, dt, _currentState.VehicleAccelerationForce, + _currentState.Velocity, + dryRun); + return retval; + } + + public void Connect(IFvOutPort other) + { + NextComponent = other; + } + + public Meter Distance + { + get { return _previousState.Distance; } + } + + public MeterPerSecond VehicleSpeed + { + get { return _previousState.Velocity; } + } + + public Kilogram VehicleMass + { + get { return _data.TotalCurbWeight(); } + } + + public Kilogram VehicleLoading + { + get { return _data.Loading; } + } + + public Kilogram TotalMass + { + get { return _data.TotalVehicleWeight(); } + } + + public IFvInPort InPort() + { + return this; + } + + public IDriverDemandOutPort OutPort() + { + return this; + } + + protected override void DoWriteModalResults(IModalDataWriter writer) + { + var averageVelocity = (_previousState.Velocity + _currentState.Velocity) / 2; + + writer[ModalResultField.v_act] = averageVelocity; + writer[ModalResultField.PaVeh] = ((_previousState.VehicleAccelerationForce * _previousState.Velocity + + _currentState.VehicleAccelerationForce * _currentState.Velocity) / 2.0) + .Cast<Watt>(); + writer[ModalResultField.Pgrad] = ((_previousState.SlopeResistance * _previousState.Velocity + + _currentState.SlopeResistance * _currentState.Velocity) / 2.0).Cast<Watt> + (); + writer[ModalResultField.Proll] = ((_previousState.RollingResistance * _previousState.Velocity + + _currentState.RollingResistance * _currentState.Velocity) / 2.0) + .Cast<Watt>(); + + writer[ModalResultField.Pair] = ComputeAirDragPowerLoss(_previousState.Velocity, _currentState.Velocity, + _currentState.dt); + + + // sanity check: is the vehicle in step with the cycle? + if (writer[ModalResultField.dist] == DBNull.Value) { + Log.Warn("distance field is not set!"); + } else { + var distance = (SI)writer[ModalResultField.dist]; + if (!distance.IsEqual(_currentState.Distance, 1e-12.SI<Meter>())) { + Log.Warn("distance diverges: {0}, distance: {1}", (distance - _currentState.Distance).Value(), + distance); + } + } + } + + protected override void DoCommitSimulationStep() + { + _previousState = _currentState; + _currentState = new VehicleState(); + } + + protected Newton RollingResistance(Radian gradient) + { + var retVal = (Math.Cos(gradient.Value()) * _data.TotalVehicleWeight() * + Physics.GravityAccelleration * + _data.TotalRollResistanceCoefficient).Cast<Newton>(); + Log.Debug("RollingResistance: {0}", retVal); + return retVal; + } + + protected Newton DriverAcceleration(MeterPerSquareSecond accelleration) + { + var retVal = ((_data.TotalVehicleWeight() + _data.ReducedMassWheels) * accelleration).Cast<Newton>(); + Log.Debug("DriverAcceleration: {0}", retVal); + return retVal; + } + + protected internal Newton SlopeResistance(Radian gradient) + { + var retVal = + (_data.TotalVehicleWeight() * Physics.GravityAccelleration * Math.Sin(gradient.Value())).Cast<Newton>(); + Log.Debug("SlopeResistance: {0}", retVal); + return retVal; + } + + protected internal Newton AirDragResistance(MeterPerSquareSecond acceleration, Second dt) + { + var vAverage = _previousState.Velocity + acceleration * dt / 2; + if (vAverage.IsEqual(0)) { + return 0.SI<Newton>(); + } + var result = + (ComputeAirDragPowerLoss(_previousState.Velocity, _previousState.Velocity + acceleration * dt, dt) / + vAverage).Cast<Newton>(); + + Log.Debug("AirDragResistance: {0}", result); + return result; + } + + private Watt ComputeAirDragPowerLoss(MeterPerSecond v1, MeterPerSecond v2, Second dt) + { + var vAverage = (v1 + v2) / 2; + var CdA = _airResistanceCurve.EffectiveAirDragArea(vAverage); + Watt averageAirDragPower; + if (v1.IsEqual(v2)) { + averageAirDragPower = (Physics.AirDensity / 2.0 * CdA * vAverage * vAverage * vAverage).Cast<Watt>(); + } else { + // compute the average force within the current simulation interval + // P(t) = k * v(t)^3 , v(t) = v0 + a * t // a != 0 + // => P_avg = (CdA * rho/2)/(4*a * dt) * (v2^4 - v1^4) + var acceleration = (v2 - v1) / dt; + averageAirDragPower = + (Physics.AirDensity / 2.0 * CdA * (v2 * v2 * v2 * v2 - v1 * v1 * v1 * v1) / (4 * acceleration * dt)) + .Cast<Watt>(); + } + return averageAirDragPower; + } + + public class VehicleState + { + public Newton AirDragResistance; + public Meter Distance; + public Newton DriverAcceleration; + public Second dt; + public Newton RollingResistance; + public Newton SlopeResistance; + public Newton VehicleAccelerationForce; + public MeterPerSecond Velocity; + public MeterPerSquareSecond Acceleration { get; set; } + } + } } \ No newline at end of file diff --git a/VectoCore/Utils/VectoCSVFile.cs b/VectoCore/Utils/VectoCSVFile.cs index 2bfc54f5fc8a5483818dcfd6818c3f7651abf2c8..9ca70bc5ee025d5812cd50bf5031f7de440d9a18 100644 --- a/VectoCore/Utils/VectoCSVFile.cs +++ b/VectoCore/Utils/VectoCSVFile.cs @@ -31,7 +31,7 @@ namespace TUGraz.VectoCore.Utils private const char Comment = '#'; /// <summary> - /// Reads a CSV file which is stored in Vecto-CSV-Format. + /// Reads a CSV file which is stored in Vecto-CSV-Format. /// </summary> /// <param name="fileName"></param> /// <param name="ignoreEmptyColumns"></param> @@ -44,7 +44,7 @@ namespace TUGraz.VectoCore.Utils return ReadData(File.ReadAllLines(fileName), ignoreEmptyColumns, fullHeader); } catch (Exception e) { Logger<VectoCSVFile>().Error(e); - throw new VectoException(string.Format("File {0}: {1}", fileName, e.Message)); + throw new VectoException("File {0}: {1}", fileName, e.Message); } } @@ -143,8 +143,8 @@ namespace TUGraz.VectoCore.Utils } /// <summary> - /// Writes the datatable to the csv file. - /// Uses the column caption as header (with fallback to column name) for the csv header. + /// Writes the datatable to the csv file. + /// Uses the column caption as header (with fallback to column name) for the csv header. /// </summary> /// <param name="fileName">Path to the file.</param> /// <param name="table">The Datatable.</param> diff --git a/VectoCoreTest/Integration/CoachPowerTrain.cs b/VectoCoreTest/Integration/CoachPowerTrain.cs index a53e925901371a4490207ad1db2833127802beff..74efb5b4b24118463fc96761d1c75f9d5e19a624 100644 --- a/VectoCoreTest/Integration/CoachPowerTrain.cs +++ b/VectoCoreTest/Integration/CoachPowerTrain.cs @@ -14,167 +14,161 @@ using Wheels = TUGraz.VectoCore.Models.SimulationComponent.Impl.Wheels; namespace TUGraz.VectoCore.Tests.Integration { - public class CoachPowerTrain - { - public const string AccelerationFile = @"TestData\Components\Truck.vacc"; - - public const string EngineFile = @"TestData\Components\24t Coach.veng"; - - public const string AxleGearLossMap = @"TestData\Components\Axle.vtlm"; - public const string GearboxIndirectLoss = @"TestData\Components\Indirect Gear.vtlm"; - public const string GearboxDirectLoss = @"TestData\Components\Direct Gear.vtlm"; - - public const string GearboxShiftPolygonFile = @"TestData\Components\ShiftPolygons.vgbs"; - - public const string GearboxFullLoadCurveFile = @"TestData\Components\Gearbox.vfld"; - - public static VectoRun CreateEngineeringRun(DrivingCycleData cycleData, string modFileName, - bool overspeed = false) - { - var container = CreatePowerTrain(cycleData, modFileName, overspeed); - - return new DistanceRun("", container); - } - - - public static VehicleContainer CreatePowerTrain(DrivingCycleData cycleData, string modFileName, - bool overspeed = false) - { - var modalWriter = new ModalDataWriter(modFileName); - var container = new VehicleContainer(modalWriter); - - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - var axleGearData = CreateAxleGearData(); - var gearboxData = CreateGearboxData(); - var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); - var driverData = CreateDriverData(AccelerationFile, overspeed); - - var cycle = new DistanceBasedDrivingCycle(container, cycleData); - var engine = new CombustionEngine(container, engineData); - var clutch = new Clutch(container, engineData, engine.IdleController); - - dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); - tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); - tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); - tmp = Port.AddComponent(tmp, new Brakes(container)); - tmp = Port.AddComponent(tmp, new AxleGear(container, axleGearData)); - tmp = Port.AddComponent(tmp, - new Gearbox(container, gearboxData, new AMTShiftStrategy(gearboxData, container))); - tmp = Port.AddComponent(tmp, clutch); - - var aux = new Auxiliary(container); - aux.AddConstant("", 0.SI<Watt>()); - - tmp = Port.AddComponent(tmp, aux); - - Port.AddComponent(tmp, engine); - - engine.IdleController.RequestPort = clutch.IdleControlPort; - - return container; - } - - - private static GearboxData CreateGearboxData() - { - var ratios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; - - return new GearboxData { - Gears = ratios.Select((ratio, i) => - Tuple.Create((uint)i, - new GearData { - FullLoadCurve = FullLoadCurve.ReadFromFile(GearboxFullLoadCurveFile), - LossMap = (ratio != 1.0) - ? TransmissionLossMap.ReadFromFile(GearboxIndirectLoss, ratio, - string.Format("Gear {0}", i)) - : TransmissionLossMap.ReadFromFile(GearboxDirectLoss, ratio, - string.Format("Gear {0}", i)), - Ratio = ratio, - ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) - })) - .ToDictionary(k => k.Item1 + 1, v => v.Item2), - ShiftTime = 2.SI<Second>(), - Inertia = 0.SI<KilogramSquareMeter>(), - TractionInterruption = 1.SI<Second>(), - StartSpeed = 2.SI<MeterPerSecond>(), - StartAcceleration = 0.6.SI<MeterPerSquareSecond>(), - StartTorqueReserve = 0.2, - SkipGears = true, - TorqueReserve = 0.2, - }; - } - - private static GearData CreateAxleGearData() - { - const double ratio = 3.240355; - return new GearData { - Ratio = ratio, - LossMap = TransmissionLossMap.ReadFromFile(AxleGearLossMap, ratio, "AxleGear") - }; - } - - private static VehicleData CreateVehicleData(Kilogram loading) - { - var axles = new List<Axle> { - new Axle { - AxleWeightShare = 0.4375, - Inertia = 21.66667.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0055, - TwinTyres = false, - TyreTestLoad = 62538.75.SI<Newton>() - }, - new Axle { - AxleWeightShare = 0.375, - Inertia = 10.83333.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0065, - TwinTyres = true, - TyreTestLoad = 52532.55.SI<Newton>() - }, - new Axle { - AxleWeightShare = 0.1875, - Inertia = 21.66667.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0055, - TwinTyres = false, - TyreTestLoad = 62538.75.SI<Newton>() - } - }; - return new VehicleData { - AxleConfiguration = AxleConfiguration.AxleConfig_6x2, - AerodynamicDragAera = 3.2634.SI<SquareMeter>(), - //CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection, - CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), - CurbWeight = 15700.SI<Kilogram>(), - CurbWeigthExtra = 0.SI<Kilogram>(), - Loading = loading, - DynamicTyreRadius = 0.52.SI<Meter>(), - Retarder = new RetarderData { Type = RetarderData.RetarderType.None }, - AxleData = axles, - SavedInDeclarationMode = false, - }; - } - - private static DriverData CreateDriverData(string accelerationFile, bool overspeed = false) - { - return new DriverData { - AccelerationCurve = AccelerationCurveData.ReadFromFile(accelerationFile), - LookAheadCoasting = new DriverData.LACData { - Enabled = true, - MinSpeed = 50.KMPHtoMeterPerSecond(), - Deceleration = -0.5.SI<MeterPerSquareSecond>(), - }, - OverSpeedEcoRoll = overspeed - ? new DriverData.OverSpeedEcoRollData() { - Mode = DriverData.DriverMode.Overspeed, - MinSpeed = 50.KMPHtoMeterPerSecond(), - OverSpeed = 5.KMPHtoMeterPerSecond(), - } - : new DriverData.OverSpeedEcoRollData { - Mode = DriverData.DriverMode.Off - }, - StartStop = new VectoRunData.StartStopData { - Enabled = false, - } - }; - } - } + public class CoachPowerTrain + { + public const string AccelerationFile = @"TestData\Components\Truck.vacc"; + public const string EngineFile = @"TestData\Components\24t Coach.veng"; + public const string AxleGearLossMap = @"TestData\Components\Axle.vtlm"; + public const string GearboxIndirectLoss = @"TestData\Components\Indirect Gear.vtlm"; + public const string GearboxDirectLoss = @"TestData\Components\Direct Gear.vtlm"; + public const string GearboxShiftPolygonFile = @"TestData\Components\ShiftPolygons.vgbs"; + public const string GearboxFullLoadCurveFile = @"TestData\Components\Gearbox.vfld"; + + public static VectoRun CreateEngineeringRun(DrivingCycleData cycleData, string modFileName, + bool overspeed = false) + { + var container = CreatePowerTrain(cycleData, modFileName, overspeed); + + return new DistanceRun("", container); + } + + public static VehicleContainer CreatePowerTrain(DrivingCycleData cycleData, string modFileName, + bool overspeed = false) + { + var modalWriter = new ModalDataWriter(modFileName); + var container = new VehicleContainer(modalWriter); + + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + var axleGearData = CreateAxleGearData(); + var gearboxData = CreateGearboxData(); + var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); + var driverData = CreateDriverData(AccelerationFile, overspeed); + + var cycle = new DistanceBasedDrivingCycle(container, cycleData); + var engine = new CombustionEngine(container, engineData); + var clutch = new Clutch(container, engineData, engine.IdleController); + + dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); + tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); + tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); + tmp = Port.AddComponent(tmp, new Brakes(container)); + tmp = Port.AddComponent(tmp, new AxleGear(container, axleGearData)); + tmp = Port.AddComponent(tmp, + new Gearbox(container, gearboxData, new AMTShiftStrategy(gearboxData, container))); + tmp = Port.AddComponent(tmp, clutch); + + var aux = new Auxiliary(container); + aux.AddConstant("", 0.SI<Watt>()); + + tmp = Port.AddComponent(tmp, aux); + + Port.AddComponent(tmp, engine); + + engine.IdleController.RequestPort = clutch.IdleControlPort; + + return container; + } + + private static GearboxData CreateGearboxData() + { + var ratios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + return new GearboxData { + Gears = ratios.Select((ratio, i) => + Tuple.Create((uint)i, + new GearData { + FullLoadCurve = FullLoadCurve.ReadFromFile(GearboxFullLoadCurveFile), + LossMap = (ratio != 1.0) + ? TransmissionLossMap.ReadFromFile(GearboxIndirectLoss, ratio, + string.Format("Gear {0}", i)) + : TransmissionLossMap.ReadFromFile(GearboxDirectLoss, ratio, + string.Format("Gear {0}", i)), + Ratio = ratio, + ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) + })) + .ToDictionary(k => k.Item1 + 1, v => v.Item2), + ShiftTime = 2.SI<Second>(), + Inertia = 0.SI<KilogramSquareMeter>(), + TractionInterruption = 1.SI<Second>(), + StartSpeed = 2.SI<MeterPerSecond>(), + StartAcceleration = 0.6.SI<MeterPerSquareSecond>(), + StartTorqueReserve = 0.2, + SkipGears = true, + TorqueReserve = 0.2 + }; + } + + private static GearData CreateAxleGearData() + { + const double ratio = 3.240355; + return new GearData { + Ratio = ratio, + LossMap = TransmissionLossMap.ReadFromFile(AxleGearLossMap, ratio, "AxleGear") + }; + } + + private static VehicleData CreateVehicleData(Kilogram loading) + { + var axles = new List<Axle> { + new Axle { + AxleWeightShare = 0.4375, + Inertia = 21.66667.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0055, + TwinTyres = false, + TyreTestLoad = 62538.75.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.375, + Inertia = 10.83333.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0065, + TwinTyres = true, + TyreTestLoad = 52532.55.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.1875, + Inertia = 21.66667.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0055, + TwinTyres = false, + TyreTestLoad = 62538.75.SI<Newton>() + } + }; + return new VehicleData { + AxleConfiguration = AxleConfiguration.AxleConfig_6x2, + AerodynamicDragAera = 3.2634.SI<SquareMeter>(), + //CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection, + CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), + CurbWeight = 15700.SI<Kilogram>(), + CurbWeigthExtra = 0.SI<Kilogram>(), + Loading = loading, + DynamicTyreRadius = 0.52.SI<Meter>(), + Retarder = new RetarderData { Type = RetarderData.RetarderType.None }, + AxleData = axles, + SavedInDeclarationMode = false + }; + } + + private static DriverData CreateDriverData(string accelerationFile, bool overspeed = false) + { + return new DriverData { + AccelerationCurve = AccelerationCurveData.ReadFromFile(accelerationFile), + LookAheadCoasting = new DriverData.LACData { + Enabled = true, + MinSpeed = 50.KMPHtoMeterPerSecond(), + Deceleration = -0.5.SI<MeterPerSquareSecond>() + }, + OverSpeedEcoRoll = overspeed + ? new DriverData.OverSpeedEcoRollData { + Mode = DriverData.DriverMode.Overspeed, + MinSpeed = 50.KMPHtoMeterPerSecond(), + OverSpeed = 5.KMPHtoMeterPerSecond() + } + : new DriverData.OverSpeedEcoRollData { + Mode = DriverData.DriverMode.Off + }, + StartStop = new VectoRunData.StartStopData { + Enabled = false + } + }; + } + } } \ No newline at end of file diff --git a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs index df9bf23e01a344a334a591806525313baeb0b28a..0bba865a0ce1d725df17550d5ca54c3ea62ddc07 100644 --- a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs @@ -20,361 +20,356 @@ using Wheels = TUGraz.VectoCore.Models.SimulationComponent.Impl.Wheels; namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns { - [TestClass] - public class FullPowerTrain - { - private static Logger Log = LogManager.GetLogger(typeof(FullPowerTrain).ToString()); - - public const string CycleFile = @"TestData\Integration\FullPowerTrain\1-Gear-Test-dist.vdri"; - public const string CoachCycleFile = @"TestData\Integration\FullPowerTrain\Coach.vdri"; - public const string EngineFile = @"TestData\Components\24t Coach.veng"; - - public const string AccelerationFile = @"TestData\Components\Coach.vacc"; - - public const string GearboxLossMap = @"TestData\Components\Indirect Gear.vtlm"; - public const string GearboxShiftPolygonFile = @"TestData\Components\ShiftPolygons.vgbs"; - public const string GearboxFullLoadCurveFile = @"TestData\Components\Gearbox.vfld"; - - [TestMethod] - public void Test_FullPowertrain_SimpleGearbox() - { - var modalWriter = new ModalDataWriter("Coach_FullPowertrain_SimpleGearbox.vmod"); - var container = new VehicleContainer(modalWriter); - - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFile); - var axleGearData = CreateAxleGearData(); - var gearboxData = CreateSimpleGearboxData(); - var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); - var driverData = CreateDriverData(AccelerationFile); - - var cycle = new DistanceBasedDrivingCycle(container, cycleData); - var cyclePort = cycle.OutPort(); - dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); - tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); - tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); - tmp = Port.AddComponent(tmp, new Brakes(container)); - tmp = Port.AddComponent(tmp, new AxleGear(container, axleGearData)); - var gbx = new Gearbox(container, gearboxData, new AMTShiftStrategy(gearboxData, container)); - tmp = Port.AddComponent(tmp, gbx); - var engine = new CombustionEngine(container, engineData); - var clutch = new Clutch(container, engineData, engine.IdleController); - tmp = Port.AddComponent(tmp, clutch); - Port.AddComponent(tmp, engine); - engine.IdleController.RequestPort = clutch.IdleControlPort; - - cyclePort.Initialize(); - - var absTime = 0.SI<Second>(); - var ds = Constants.SimulationSettings.DriveOffDistance; - IResponse response; - - var cnt = 0; - do { - response = cyclePort.Request(absTime, ds); - response.Switch(). - Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). - Case<ResponseCycleFinished>(r => { }). - Case<ResponseSuccess>(r => { - container.CommitSimulationStep(absTime, r.SimulationInterval); - absTime += r.SimulationInterval; - - ds = container.VehicleSpeed.IsEqual(0) - ? Constants.SimulationSettings.DriveOffDistance - : Constants.SimulationSettings.TargetTimeInterval * container.VehicleSpeed; - - if (cnt++ % 100 == 0) { - modalWriter.Finish(VectoRun.Status.Success); - } - }). - Default(r => Assert.Fail("Unexpected Response: {0}", r)); - } while (!(response is ResponseCycleFinished)); - modalWriter.Finish(VectoRun.Status.Success); - Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); - } - - [TestMethod, Ignore] - public void Test_FullPowertrain() - { - var modalWriter = new ModalDataWriter("Coach_FullPowertrain.vmod"); - var container = new VehicleContainer(modalWriter); - - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CoachCycleFile); - var axleGearData = CreateAxleGearData(); - var gearboxData = CreateGearboxData(); - var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); - var driverData = CreateDriverData(AccelerationFile); - - var cycle = new DistanceBasedDrivingCycle(container, cycleData); - var cyclePort = cycle.OutPort(); - dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); - tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); - tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); - tmp = Port.AddComponent(tmp, new Brakes(container)); - tmp = Port.AddComponent(tmp, new AxleGear(container, axleGearData)); - var gbx = new Gearbox(container, gearboxData, new AMTShiftStrategy(gearboxData, container)); - tmp = Port.AddComponent(tmp, gbx); - var engine = new CombustionEngine(container, engineData); - var clutch = new Clutch(container, engineData, engine.IdleController); - tmp = Port.AddComponent(tmp, clutch); - Port.AddComponent(tmp, engine); - engine.IdleController.RequestPort = clutch.IdleControlPort; - - cyclePort.Initialize(); - - gbx.Gear = 0; - - var absTime = 0.SI<Second>(); - var ds = Constants.SimulationSettings.DriveOffDistance; - var response = cyclePort.Request(absTime, ds); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - container.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; - - gbx.Gear = 1; - var cnt = 0; - while (!(response is ResponseCycleFinished) && container.Distance < 17000) { - Log.Info("Test New Request absTime: {0}, ds: {1}", absTime, ds); - try { - response = cyclePort.Request(absTime, ds); - } catch (Exception) { - modalWriter.Finish(VectoRun.Status.Success); - throw; - } - Log.Info("Test Got Response: {0},", response); - - response.Switch(). - Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). - Case<ResponseCycleFinished>(r => { }). - Case<ResponseGearShift>(r => { Log.Debug("Gearshift"); }). - Case<ResponseSuccess>(r => { - container.CommitSimulationStep(absTime, r.SimulationInterval); - absTime += r.SimulationInterval; - - ds = container.VehicleSpeed.IsEqual(0) - ? Constants.SimulationSettings.DriveOffDistance - : Constants.SimulationSettings.TargetTimeInterval * container.VehicleSpeed; - - if (cnt++ % 100 == 0) { - modalWriter.Finish(VectoRun.Status.Success); - } - }). - Default(r => Assert.Fail("Unexpected Response: {0}", r)); - } - modalWriter.Finish(VectoRun.Status.Success); - Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); - } - - [TestMethod] - public void Test_FullPowertrain_LowSpeed() - { - var modalWriter = new ModalDataWriter("Coach_FullPowertrain_LowSpeed.vmod"); - var container = new VehicleContainer(modalWriter); - - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFile); - var axleGearData = CreateAxleGearData(); - var gearboxData = CreateGearboxData(); - var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); - var driverData = CreateDriverData(AccelerationFile); - - var cycle = new DistanceBasedDrivingCycle(container, cycleData); - var cyclePort = cycle.OutPort(); - dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); - tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); - tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); - tmp = Port.AddComponent(tmp, new Brakes(container)); - tmp = Port.AddComponent(tmp, new AxleGear(container, axleGearData)); - tmp = Port.AddComponent(tmp, - new Gearbox(container, gearboxData, new AMTShiftStrategy(gearboxData, container))); - var engine = new CombustionEngine(container, engineData); - var clutch = new Clutch(container, engineData, engine.IdleController); - tmp = Port.AddComponent(tmp, clutch); - Port.AddComponent(tmp, engine); - engine.IdleController.RequestPort = clutch.IdleControlPort; - - cyclePort.Initialize(); - - //container.Gear = 0; - var absTime = 0.SI<Second>(); - var ds = Constants.SimulationSettings.DriveOffDistance; - var response = cyclePort.Request(absTime, ds); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - container.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; - - //container.Gear = 1; - var cnt = 0; - while (!(response is ResponseCycleFinished) && container.Distance < 17000) { - Log.Info("Test New Request absTime: {0}, ds: {1}", absTime, ds); - try { - response = cyclePort.Request(absTime, ds); - } catch (Exception) { - modalWriter.Finish(VectoRun.Status.Success); - throw; - } - Log.Info("Test Got Response: {0},", response); - - response.Switch(). - Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). - Case<ResponseCycleFinished>(r => { }). - Case<ResponseGearShift>(r => { Log.Debug("Gearshift"); }). - Case<ResponseSuccess>(r => { - container.CommitSimulationStep(absTime, r.SimulationInterval); - absTime += r.SimulationInterval; - - ds = container.VehicleSpeed.IsEqual(0) - ? Constants.SimulationSettings.DriveOffDistance - : Constants.SimulationSettings.TargetTimeInterval * container.VehicleSpeed; - - if (cnt++ % 100 == 0) { - modalWriter.Finish(VectoRun.Status.Success); - } - }). - Default(r => { - modalWriter.Finish(VectoRun.Status.Success); - Assert.Fail("Unexpected Response: {0}", r); - }); - } - modalWriter.Finish(VectoRun.Status.Success); - Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); - } - - [TestMethod] - public void Test_FullPowerTrain_JobFile() - { - var sumWriter = new SummaryFileWriter(@"job.vsum"); - var jobContainer = new JobContainer(sumWriter); - - var factory = new SimulatorFactory(SimulatorFactory.FactoryMode.EngineeringMode, @"TestData\job.vecto"); - - jobContainer.AddRuns(factory); - jobContainer.Execute(); - - jobContainer.WaitFinished(); - ResultFileHelper.TestSumFile(@"TestData\Results\Integration\job.vsum", @"job.vsum"); - - ResultFileHelper.TestModFile(@"TestData\Results\Integration\job_1-Gear-Test-dist.vmod", - @"TestData\job_1-Gear-Test-dist.vmod", testRowCount: false); - } - - - // todo: add realistic FullLoadCurve - private static GearboxData CreateGearboxData() - { - var ratios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; - - return new GearboxData { - Gears = ratios.Select((ratio, i) => - Tuple.Create((uint)i, - new GearData { - FullLoadCurve = FullLoadCurve.ReadFromFile(GearboxFullLoadCurveFile), - LossMap = - TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, string.Format("Gear {0}", i)), - Ratio = ratio, - ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) - })) - .ToDictionary(k => k.Item1 + 1, v => v.Item2), - ShiftTime = 2.SI<Second>(), - Inertia = 0.SI<KilogramSquareMeter>(), - TractionInterruption = 1.SI<Second>(), - StartSpeed = 2.SI<MeterPerSecond>(), - StartAcceleration = 0.6.SI<MeterPerSquareSecond>(), - StartTorqueReserve = 0.2, - TorqueReserve = 0.2 - }; - } - - - private static GearData CreateAxleGearData() - { - var ratio = 3.240355; - return new GearData { - Ratio = ratio, - LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, "AxleGear") - }; - } - - private static GearboxData CreateSimpleGearboxData() - { - var ratio = 3.44; - return new GearboxData { - Gears = new Dictionary<uint, GearData> { - { - 1, new GearData { - FullLoadCurve = null, - LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, "Gear 1"), - Ratio = ratio, - ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) - } - } - }, - Inertia = 0.SI<KilogramSquareMeter>(), - TractionInterruption = 0.SI<Second>(), - ShiftTime = 2.SI<Second>(), - StartSpeed = 2.SI<MeterPerSecond>(), - StartAcceleration = 0.6.SI<MeterPerSquareSecond>(), - StartTorqueReserve = 0.2, - TorqueReserve = 0.2 - }; - } - - private static VehicleData CreateVehicleData(Kilogram loading) - { - var axles = new List<Axle> { - new Axle { - AxleWeightShare = 0.4375, - Inertia = 21.66667.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0055, - TwinTyres = false, - TyreTestLoad = 62538.75.SI<Newton>() - }, - new Axle { - AxleWeightShare = 0.375, - Inertia = 10.83333.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0065, - TwinTyres = true, - TyreTestLoad = 52532.55.SI<Newton>() - }, - new Axle { - AxleWeightShare = 0.1875, - Inertia = 21.66667.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0055, - TwinTyres = false, - TyreTestLoad = 62538.75.SI<Newton>() - } - }; - return new VehicleData { - AxleConfiguration = AxleConfiguration.AxleConfig_6x2, - AerodynamicDragAera = 3.2634.SI<SquareMeter>(), - //CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection, - CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), - CurbWeight = 15700.SI<Kilogram>(), - CurbWeigthExtra = 0.SI<Kilogram>(), - Loading = loading, - DynamicTyreRadius = 0.52.SI<Meter>(), - Retarder = new RetarderData { Type = RetarderData.RetarderType.None }, - AxleData = axles, - SavedInDeclarationMode = false, - }; - } - - private static DriverData CreateDriverData(string accelerationFile) - { - return new DriverData { - AccelerationCurve = AccelerationCurveData.ReadFromFile(accelerationFile), - LookAheadCoasting = new DriverData.LACData { - Enabled = false, - Deceleration = -0.5.SI<MeterPerSquareSecond>() - }, - OverSpeedEcoRoll = new DriverData.OverSpeedEcoRollData { - Mode = DriverData.DriverMode.Off - }, - StartStop = new VectoRunData.StartStopData { - Enabled = false, - } - }; - } - } + [TestClass] + public class FullPowerTrain + { + public const string CycleFile = @"TestData\Integration\FullPowerTrain\1-Gear-Test-dist.vdri"; + public const string CoachCycleFile = @"TestData\Integration\FullPowerTrain\Coach.vdri"; + public const string EngineFile = @"TestData\Components\24t Coach.veng"; + public const string AccelerationFile = @"TestData\Components\Coach.vacc"; + public const string GearboxLossMap = @"TestData\Components\Indirect Gear.vtlm"; + public const string GearboxShiftPolygonFile = @"TestData\Components\ShiftPolygons.vgbs"; + public const string GearboxFullLoadCurveFile = @"TestData\Components\Gearbox.vfld"; + private static readonly Logger Log = LogManager.GetLogger(typeof(FullPowerTrain).ToString()); + + [TestMethod] + public void Test_FullPowertrain_SimpleGearbox() + { + var modalWriter = new ModalDataWriter("Coach_FullPowertrain_SimpleGearbox.vmod"); + var container = new VehicleContainer(modalWriter); + + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFile); + var axleGearData = CreateAxleGearData(); + var gearboxData = CreateSimpleGearboxData(); + var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); + var driverData = CreateDriverData(AccelerationFile); + + var cycle = new DistanceBasedDrivingCycle(container, cycleData); + var cyclePort = cycle.OutPort(); + dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); + tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); + tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); + tmp = Port.AddComponent(tmp, new Brakes(container)); + tmp = Port.AddComponent(tmp, new AxleGear(container, axleGearData)); + var gbx = new Gearbox(container, gearboxData, new AMTShiftStrategy(gearboxData, container)); + tmp = Port.AddComponent(tmp, gbx); + var engine = new CombustionEngine(container, engineData); + var clutch = new Clutch(container, engineData, engine.IdleController); + tmp = Port.AddComponent(tmp, clutch); + Port.AddComponent(tmp, engine); + engine.IdleController.RequestPort = clutch.IdleControlPort; + + cyclePort.Initialize(); + + var absTime = 0.SI<Second>(); + var ds = Constants.SimulationSettings.DriveOffDistance; + IResponse response; + + var cnt = 0; + do { + response = cyclePort.Request(absTime, ds); + response.Switch(). + Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). + Case<ResponseCycleFinished>(r => { }). + Case<ResponseSuccess>(r => { + container.CommitSimulationStep(absTime, r.SimulationInterval); + absTime += r.SimulationInterval; + + ds = container.VehicleSpeed.IsEqual(0) + ? Constants.SimulationSettings.DriveOffDistance + : Constants.SimulationSettings.TargetTimeInterval * container.VehicleSpeed; + + if (cnt++ % 100 == 0) { + modalWriter.Finish(VectoRun.Status.Success); + } + }). + Default(r => Assert.Fail("Unexpected Response: {0}", r)); + } while (!(response is ResponseCycleFinished)); + modalWriter.Finish(VectoRun.Status.Success); + Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); + } + + [TestMethod, Ignore] + public void Test_FullPowertrain() + { + var modalWriter = new ModalDataWriter("Coach_FullPowertrain.vmod"); + var container = new VehicleContainer(modalWriter); + + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CoachCycleFile); + var axleGearData = CreateAxleGearData(); + var gearboxData = CreateGearboxData(); + var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); + var driverData = CreateDriverData(AccelerationFile); + + var cycle = new DistanceBasedDrivingCycle(container, cycleData); + var cyclePort = cycle.OutPort(); + dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); + tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); + tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); + tmp = Port.AddComponent(tmp, new Brakes(container)); + tmp = Port.AddComponent(tmp, new AxleGear(container, axleGearData)); + var gbx = new Gearbox(container, gearboxData, new AMTShiftStrategy(gearboxData, container)); + tmp = Port.AddComponent(tmp, gbx); + var engine = new CombustionEngine(container, engineData); + var clutch = new Clutch(container, engineData, engine.IdleController); + tmp = Port.AddComponent(tmp, clutch); + Port.AddComponent(tmp, engine); + engine.IdleController.RequestPort = clutch.IdleControlPort; + + cyclePort.Initialize(); + + gbx.Gear = 0; + + var absTime = 0.SI<Second>(); + var ds = Constants.SimulationSettings.DriveOffDistance; + var response = cyclePort.Request(absTime, ds); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + container.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; + + gbx.Gear = 1; + var cnt = 0; + while (!(response is ResponseCycleFinished) && container.Distance < 17000) { + Log.Info("Test New Request absTime: {0}, ds: {1}", absTime, ds); + try { + response = cyclePort.Request(absTime, ds); + } catch (Exception) { + modalWriter.Finish(VectoRun.Status.Success); + throw; + } + Log.Info("Test Got Response: {0},", response); + + response.Switch(). + Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). + Case<ResponseCycleFinished>(r => { }). + Case<ResponseGearShift>(r => { Log.Debug("Gearshift"); }). + Case<ResponseSuccess>(r => { + container.CommitSimulationStep(absTime, r.SimulationInterval); + absTime += r.SimulationInterval; + + ds = container.VehicleSpeed.IsEqual(0) + ? Constants.SimulationSettings.DriveOffDistance + : Constants.SimulationSettings.TargetTimeInterval * container.VehicleSpeed; + + if (cnt++ % 100 == 0) { + modalWriter.Finish(VectoRun.Status.Success); + } + }). + Default(r => Assert.Fail("Unexpected Response: {0}", r)); + } + modalWriter.Finish(VectoRun.Status.Success); + Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); + } + + [TestMethod] + public void Test_FullPowertrain_LowSpeed() + { + var modalWriter = new ModalDataWriter("Coach_FullPowertrain_LowSpeed.vmod"); + var container = new VehicleContainer(modalWriter); + + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFile); + var axleGearData = CreateAxleGearData(); + var gearboxData = CreateGearboxData(); + var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); + var driverData = CreateDriverData(AccelerationFile); + + var cycle = new DistanceBasedDrivingCycle(container, cycleData); + var cyclePort = cycle.OutPort(); + dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); + tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); + tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); + tmp = Port.AddComponent(tmp, new Brakes(container)); + tmp = Port.AddComponent(tmp, new AxleGear(container, axleGearData)); + tmp = Port.AddComponent(tmp, + new Gearbox(container, gearboxData, new AMTShiftStrategy(gearboxData, container))); + var engine = new CombustionEngine(container, engineData); + var clutch = new Clutch(container, engineData, engine.IdleController); + tmp = Port.AddComponent(tmp, clutch); + Port.AddComponent(tmp, engine); + engine.IdleController.RequestPort = clutch.IdleControlPort; + + cyclePort.Initialize(); + + //container.Gear = 0; + var absTime = 0.SI<Second>(); + var ds = Constants.SimulationSettings.DriveOffDistance; + var response = cyclePort.Request(absTime, ds); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + container.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; + + //container.Gear = 1; + var cnt = 0; + while (!(response is ResponseCycleFinished) && container.Distance < 17000) { + Log.Info("Test New Request absTime: {0}, ds: {1}", absTime, ds); + try { + response = cyclePort.Request(absTime, ds); + } catch (Exception) { + modalWriter.Finish(VectoRun.Status.Success); + throw; + } + Log.Info("Test Got Response: {0},", response); + + response.Switch(). + Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). + Case<ResponseCycleFinished>(r => { }). + Case<ResponseGearShift>(r => { Log.Debug("Gearshift"); }). + Case<ResponseSuccess>(r => { + container.CommitSimulationStep(absTime, r.SimulationInterval); + absTime += r.SimulationInterval; + + ds = container.VehicleSpeed.IsEqual(0) + ? Constants.SimulationSettings.DriveOffDistance + : Constants.SimulationSettings.TargetTimeInterval * container.VehicleSpeed; + + if (cnt++ % 100 == 0) { + modalWriter.Finish(VectoRun.Status.Success); + } + }). + Default(r => { + modalWriter.Finish(VectoRun.Status.Success); + Assert.Fail("Unexpected Response: {0}", r); + }); + } + modalWriter.Finish(VectoRun.Status.Success); + Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); + } + + [TestMethod] + public void Test_FullPowerTrain_JobFile() + { + var sumWriter = new SummaryFileWriter(@"job.vsum"); + var jobContainer = new JobContainer(sumWriter); + + var factory = new SimulatorFactory(SimulatorFactory.FactoryMode.EngineeringMode, @"TestData\job.vecto"); + + jobContainer.AddRuns(factory); + jobContainer.Execute(); + + jobContainer.WaitFinished(); + ResultFileHelper.TestSumFile(@"TestData\Results\Integration\job.vsum", @"job.vsum"); + + ResultFileHelper.TestModFile(@"TestData\Results\Integration\job_1-Gear-Test-dist.vmod", + @"TestData\job_1-Gear-Test-dist.vmod", testRowCount: false); + } + + // todo: add realistic FullLoadCurve + private static GearboxData CreateGearboxData() + { + var ratios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + return new GearboxData { + Gears = ratios.Select((ratio, i) => + Tuple.Create((uint)i, + new GearData { + FullLoadCurve = FullLoadCurve.ReadFromFile(GearboxFullLoadCurveFile), + LossMap = + TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, string.Format("Gear {0}", i)), + Ratio = ratio, + ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) + })) + .ToDictionary(k => k.Item1 + 1, v => v.Item2), + ShiftTime = 2.SI<Second>(), + Inertia = 0.SI<KilogramSquareMeter>(), + TractionInterruption = 1.SI<Second>(), + StartSpeed = 2.SI<MeterPerSecond>(), + StartAcceleration = 0.6.SI<MeterPerSquareSecond>(), + StartTorqueReserve = 0.2, + TorqueReserve = 0.2 + }; + } + + private static GearData CreateAxleGearData() + { + var ratio = 3.240355; + return new GearData { + Ratio = ratio, + LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, "AxleGear") + }; + } + + private static GearboxData CreateSimpleGearboxData() + { + var ratio = 3.44; + return new GearboxData { + Gears = new Dictionary<uint, GearData> { + { + 1, new GearData { + FullLoadCurve = null, + LossMap = TransmissionLossMap.ReadFromFile(GearboxLossMap, ratio, "Gear 1"), + Ratio = ratio, + ShiftPolygon = ShiftPolygon.ReadFromFile(GearboxShiftPolygonFile) + } + } + }, + Inertia = 0.SI<KilogramSquareMeter>(), + TractionInterruption = 0.SI<Second>(), + ShiftTime = 2.SI<Second>(), + StartSpeed = 2.SI<MeterPerSecond>(), + StartAcceleration = 0.6.SI<MeterPerSquareSecond>(), + StartTorqueReserve = 0.2, + TorqueReserve = 0.2 + }; + } + + private static VehicleData CreateVehicleData(Kilogram loading) + { + var axles = new List<Axle> { + new Axle { + AxleWeightShare = 0.4375, + Inertia = 21.66667.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0055, + TwinTyres = false, + TyreTestLoad = 62538.75.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.375, + Inertia = 10.83333.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0065, + TwinTyres = true, + TyreTestLoad = 52532.55.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.1875, + Inertia = 21.66667.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0055, + TwinTyres = false, + TyreTestLoad = 62538.75.SI<Newton>() + } + }; + return new VehicleData { + AxleConfiguration = AxleConfiguration.AxleConfig_6x2, + AerodynamicDragAera = 3.2634.SI<SquareMeter>(), + //CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection, + CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), + CurbWeight = 15700.SI<Kilogram>(), + CurbWeigthExtra = 0.SI<Kilogram>(), + Loading = loading, + DynamicTyreRadius = 0.52.SI<Meter>(), + Retarder = new RetarderData { Type = RetarderData.RetarderType.None }, + AxleData = axles, + SavedInDeclarationMode = false + }; + } + + private static DriverData CreateDriverData(string accelerationFile) + { + return new DriverData { + AccelerationCurve = AccelerationCurveData.ReadFromFile(accelerationFile), + LookAheadCoasting = new DriverData.LACData { + Enabled = false, + Deceleration = -0.5.SI<MeterPerSquareSecond>() + }, + OverSpeedEcoRoll = new DriverData.OverSpeedEcoRollData { + Mode = DriverData.DriverMode.Off + }, + StartStop = new VectoRunData.StartStopData { + Enabled = false + } + }; + } + } } \ No newline at end of file diff --git a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs index 5196af0a4de587e8b4f1f5193b674ca2fe53c7f7..2a0206f5ae60e46c791aab8e0e11af3b775545fc 100644 --- a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs @@ -3,7 +3,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.FileIO.Reader; using TUGraz.VectoCore.FileIO.Reader.Impl; -using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; @@ -17,268 +16,262 @@ using Wheels = TUGraz.VectoCore.Models.SimulationComponent.Impl.Wheels; namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns { - [TestClass] - public class MinimalPowertrain - { - public const string CycleFile = @"TestData\Integration\MinimalPowerTrain\1-Gear-Test-dist.vdri"; - public const string CycleFileStop = @"TestData\Integration\MinimalPowerTrain\1-Gear-StopTest-dist.vdri"; - public const string EngineFile = @"TestData\Integration\MinimalPowerTrain\24t Coach.veng"; - public const string GearboxFile = @"TestData\Integration\MinimalPowerTrain\24t Coach-1Gear.vgbx"; - public const string GbxLossMap = @"TestData\Integration\MinimalPowerTrain\NoLossGbxMap.vtlm"; + [TestClass] + public class MinimalPowertrain + { + public const string CycleFile = @"TestData\Integration\MinimalPowerTrain\1-Gear-Test-dist.vdri"; + public const string CycleFileStop = @"TestData\Integration\MinimalPowerTrain\1-Gear-StopTest-dist.vdri"; + public const string EngineFile = @"TestData\Integration\MinimalPowerTrain\24t Coach.veng"; + public const string GearboxFile = @"TestData\Integration\MinimalPowerTrain\24t Coach-1Gear.vgbx"; + public const string GbxLossMap = @"TestData\Integration\MinimalPowerTrain\NoLossGbxMap.vtlm"; + public const string AccelerationFile = @"TestData\Components\Coach.vacc"; + public const string AccelerationFile2 = @"TestData\Components\Truck.vacc"; + public const double Tolerance = 0.001; + [TestMethod] + public void TestWheelsAndEngineInitialize() + { + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - public const string AccelerationFile = @"TestData\Components\Coach.vacc"; - public const string AccelerationFile2 = @"TestData\Components\Truck.vacc"; + var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); - public const double Tolerance = 0.001; + var axleGearData = CreateAxleGearData(); + var driverData = CreateDriverData(AccelerationFile); - [TestMethod] - public void TestWheelsAndEngineInitialize() - { - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + var modalWriter = new ModalDataWriter("Coach_MinimalPowertrainOverload.vmod"); //new TestModalDataWriter(); + var vehicleContainer = new VehicleContainer(modalWriter); - var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); + dynamic tmp = Port.AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); + tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); + tmp = Port.AddComponent(tmp, new AxleGear(vehicleContainer, axleGearData)); - var axleGearData = CreateAxleGearData(); + var engine = new CombustionEngine(vehicleContainer, engineData); + var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); + tmp = Port.AddComponent(tmp, clutch); + Port.AddComponent(tmp, engine); + engine.IdleController.RequestPort = clutch.IdleControlPort; - var driverData = CreateDriverData(AccelerationFile); + var gbx = new MockGearbox(vehicleContainer); - var modalWriter = new ModalDataWriter("Coach_MinimalPowertrainOverload.vmod"); //new TestModalDataWriter(); - var vehicleContainer = new VehicleContainer(modalWriter); + var driverPort = driver.OutPort(); - var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); - dynamic tmp = Port.AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); - tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); - tmp = Port.AddComponent(tmp, new AxleGear(vehicleContainer, axleGearData)); + gbx.Gear = 1; - var engine = new CombustionEngine(vehicleContainer, engineData); - var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); - tmp = Port.AddComponent(tmp, clutch); - Port.AddComponent(tmp, engine); - engine.IdleController.RequestPort = clutch.IdleControlPort; + var response = driverPort.Initialize(18.KMPHtoMeterPerSecond(), + VectoMath.InclinationToAngle(2.842372037 / 100)); - var gbx = new MockGearbox(vehicleContainer); - var driverPort = driver.OutPort(); + var absTime = 0.SI<Second>(); - gbx.Gear = 1; - - var response = driverPort.Initialize(18.KMPHtoMeterPerSecond(), - VectoMath.InclinationToAngle(2.842372037 / 100)); - - - var absTime = 0.SI<Second>(); - - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); // time [s] , dist [m] , v_act [km/h] , v_targ [km/h] , acc [m/s²] , grad [%] , n [1/min] , Tq_eng [Nm] , Tq_clutch [Nm] , Tq_full [Nm] , Tq_drag [Nm] , Pe_eng [kW] , Pe_full [kW] , Pe_drag [kW] , Pe_clutch [kW] , Pa Eng [kW] , Paux [kW] , Gear [-] , Ploss GB [kW] , Ploss Diff [kW] , Ploss Retarder [kW] , Pa GB [kW] , Pa Veh [kW] , Proll [kW] , Pair [kW] , Pgrad [kW] , Pwheel [kW] , Pbrake [kW] , FC-Map [g/h] , FC-AUXc [g/h] , FC-WHTCc [g/h] // 1.5 , 5 , 18 , 18 , 0 , 2.842372 , 964.1117 , 323.7562 , 323.7562 , 2208.664 , -158.0261 , 32.68693 , 222.9902 , -15.95456 , 32.68693 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 5.965827 , 0.2423075 , 26.47879 , 32.68693 , 0 , 7574.113 , - , - - AssertHelper.AreRelativeEqual(964.1117.RPMtoRad().Value(), vehicleContainer.Engine.EngineSpeed.Value()); - Assert.AreEqual(2208.664, engine.PreviousState.StationaryFullLoadTorque.Value(), Tolerance); - Assert.AreEqual(-158.0261, engine.PreviousState.FullDragTorque.Value(), Tolerance); - - Assert.AreEqual(323.7562, engine.PreviousState.EngineTorque.Value(), Tolerance); - } + AssertHelper.AreRelativeEqual(964.1117.RPMtoRad().Value(), vehicleContainer.Engine.EngineSpeed.Value()); + Assert.AreEqual(2208.664, engine.PreviousState.StationaryFullLoadTorque.Value(), Tolerance); + Assert.AreEqual(-158.0261, engine.PreviousState.FullDragTorque.Value(), Tolerance); + Assert.AreEqual(323.7562, engine.PreviousState.EngineTorque.Value(), Tolerance); + } - [TestMethod] - public void TestWheelsAndEngine() - { - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFile); + [TestMethod] + public void TestWheelsAndEngine() + { + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFile); - var axleGearData = CreateAxleGearData(); + var axleGearData = CreateAxleGearData(); - var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); + var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); - var driverData = CreateDriverData(AccelerationFile); + var driverData = CreateDriverData(AccelerationFile); - var modalWriter = new ModalDataWriter("Coach_MinimalPowertrain.vmod"); //new TestModalDataWriter(); - var vehicleContainer = new VehicleContainer(modalWriter); + var modalWriter = new ModalDataWriter("Coach_MinimalPowertrain.vmod"); //new TestModalDataWriter(); + var vehicleContainer = new VehicleContainer(modalWriter); - var cycle = new DistanceBasedDrivingCycle(vehicleContainer, cycleData); + var cycle = new DistanceBasedDrivingCycle(vehicleContainer, cycleData); - dynamic tmp = Port.AddComponent(cycle, new Driver(vehicleContainer, driverData, new DefaultDriverStrategy())); - tmp = Port.AddComponent(tmp, new Vehicle(vehicleContainer, vehicleData)); - tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); - tmp = Port.AddComponent(tmp, new Brakes(vehicleContainer)); - tmp = Port.AddComponent(tmp, new AxleGear(vehicleContainer, axleGearData)); - var engine = new CombustionEngine(vehicleContainer, engineData); - var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); - tmp = Port.AddComponent(tmp, clutch); - Port.AddComponent(tmp, engine); - engine.IdleController.RequestPort = clutch.IdleControlPort; + dynamic tmp = Port.AddComponent(cycle, new Driver(vehicleContainer, driverData, new DefaultDriverStrategy())); + tmp = Port.AddComponent(tmp, new Vehicle(vehicleContainer, vehicleData)); + tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); + tmp = Port.AddComponent(tmp, new Brakes(vehicleContainer)); + tmp = Port.AddComponent(tmp, new AxleGear(vehicleContainer, axleGearData)); + var engine = new CombustionEngine(vehicleContainer, engineData); + var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); + tmp = Port.AddComponent(tmp, clutch); + Port.AddComponent(tmp, engine); + engine.IdleController.RequestPort = clutch.IdleControlPort; - var gbx = new MockGearbox(vehicleContainer); + var gbx = new MockGearbox(vehicleContainer); - var cyclePort = cycle.OutPort(); + var cyclePort = cycle.OutPort(); - cyclePort.Initialize(); + cyclePort.Initialize(); - gbx.Gear = 0; + gbx.Gear = 0; - var absTime = 0.SI<Second>(); - var ds = Constants.SimulationSettings.DriveOffDistance; - var response = cyclePort.Request(absTime, ds); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; + var absTime = 0.SI<Second>(); + var ds = Constants.SimulationSettings.DriveOffDistance; + var response = cyclePort.Request(absTime, ds); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; - gbx.Gear = 1; - var cnt = 0; - while (!(response is ResponseCycleFinished) && vehicleContainer.Distance < 17000) { - response = cyclePort.Request(absTime, ds); - response.Switch(). - Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). - Case<ResponseCycleFinished>(r => { }). - Case<ResponseSuccess>(r => { - vehicleContainer.CommitSimulationStep(absTime, r.SimulationInterval); - absTime += r.SimulationInterval; - - ds = vehicleContainer.VehicleSpeed.IsEqual(0) - ? Constants.SimulationSettings.DriveOffDistance - : (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed) - .Cast<Meter>(); - - if (cnt++ % 100 == 0) { - modalWriter.Finish(VectoRun.Status.Success); - } - }). - Default(r => Assert.Fail("Unexpected Response: {0}", r)); - } - - Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); - - modalWriter.Finish(VectoRun.Status.Success); - } - - [TestMethod] - public void TestWheelsAndEngineLookahead() - { - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFileStop); - - var axleGearData = CreateAxleGearData(); - - var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); - - var driverData = CreateDriverData(AccelerationFile2); - - var modalWriter = new ModalDataWriter("Coach_MinimalPowertrainOverload.vmod", - SimulatorFactory.FactoryMode.EngineeringMode); - var vehicleContainer = new VehicleContainer(modalWriter); - - var cycle = new DistanceBasedDrivingCycle(vehicleContainer, cycleData); - - dynamic tmp = Port.AddComponent(cycle, new Driver(vehicleContainer, driverData, new DefaultDriverStrategy())); - tmp = Port.AddComponent(tmp, new Vehicle(vehicleContainer, vehicleData)); - tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); - tmp = Port.AddComponent(tmp, new Brakes(vehicleContainer)); - tmp = Port.AddComponent(tmp, new AxleGear(vehicleContainer, axleGearData)); - var engine = new CombustionEngine(vehicleContainer, engineData); - var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); - tmp = Port.AddComponent(tmp, clutch); - Port.AddComponent(tmp, engine); - engine.IdleController.RequestPort = clutch.IdleControlPort; - - var gbx = new MockGearbox(vehicleContainer); - - var cyclePort = cycle.OutPort(); - - cyclePort.Initialize(); - - gbx.Gear = 0; - - var absTime = 0.SI<Second>(); - - gbx.Gear = 1; - var ds = Constants.SimulationSettings.DriveOffDistance; - while (vehicleContainer.Distance < 100) { - var response = cyclePort.Request(absTime, ds); - response.Switch(). - Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). - Case<ResponseSuccess>(r => { - vehicleContainer.CommitSimulationStep(absTime, r.SimulationInterval); - absTime += r.SimulationInterval; - - ds = vehicleContainer.VehicleSpeed.IsEqual(0) - ? Constants.SimulationSettings.DriveOffDistance - : (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed) - .Cast<Meter>(); - - modalWriter.Finish(VectoRun.Status.Success); - }); - } - - modalWriter.Finish(VectoRun.Status.Success); - } - - private static GearData CreateAxleGearData() - { - return new GearData { - Ratio = 3.0 * 3.5, - LossMap = TransmissionLossMap.ReadFromFile(GbxLossMap, 3.0 * 3.5, "AxleGear") - }; - } - - - private static VehicleData CreateVehicleData(Kilogram loading) - { - var axles = new List<Axle> { - new Axle { - AxleWeightShare = 0.4375, - Inertia = 21.66667.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0055, - TwinTyres = false, - TyreTestLoad = 62538.75.SI<Newton>() - }, - new Axle { - AxleWeightShare = 0.375, - Inertia = 10.83333.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0065, - TwinTyres = true, - TyreTestLoad = 52532.55.SI<Newton>() - }, - new Axle { - AxleWeightShare = 0.1875, - Inertia = 21.66667.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0055, - TwinTyres = false, - TyreTestLoad = 62538.75.SI<Newton>() - } - }; - return new VehicleData { - AxleConfiguration = AxleConfiguration.AxleConfig_6x2, - AerodynamicDragAera = 3.2634.SI<SquareMeter>(), - //CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection, - CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), - CurbWeight = 15700.SI<Kilogram>(), - CurbWeigthExtra = 0.SI<Kilogram>(), - Loading = loading, - DynamicTyreRadius = 0.52.SI<Meter>(), - Retarder = new RetarderData { Type = RetarderData.RetarderType.None }, - AxleData = axles, - SavedInDeclarationMode = false, - }; - } - - private static DriverData CreateDriverData(string accelerationFile) - { - return new DriverData { - AccelerationCurve = AccelerationCurveData.ReadFromFile(accelerationFile), - LookAheadCoasting = new DriverData.LACData { - Enabled = false, - Deceleration = -0.5.SI<MeterPerSquareSecond>() - }, - OverSpeedEcoRoll = new DriverData.OverSpeedEcoRollData { - Mode = DriverData.DriverMode.Off - }, - StartStop = new VectoRunData.StartStopData { - Enabled = false, - } - }; - } - } + gbx.Gear = 1; + var cnt = 0; + while (!(response is ResponseCycleFinished) && vehicleContainer.Distance < 17000) { + response = cyclePort.Request(absTime, ds); + response.Switch(). + Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). + Case<ResponseCycleFinished>(r => { }). + Case<ResponseSuccess>(r => { + vehicleContainer.CommitSimulationStep(absTime, r.SimulationInterval); + absTime += r.SimulationInterval; + + ds = vehicleContainer.VehicleSpeed.IsEqual(0) + ? Constants.SimulationSettings.DriveOffDistance + : (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed) + .Cast<Meter>(); + + if (cnt++ % 100 == 0) { + modalWriter.Finish(VectoRun.Status.Success); + } + }). + Default(r => Assert.Fail("Unexpected Response: {0}", r)); + } + + Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); + + modalWriter.Finish(VectoRun.Status.Success); + } + + [TestMethod] + public void TestWheelsAndEngineLookahead() + { + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFileStop); + + var axleGearData = CreateAxleGearData(); + + var vehicleData = CreateVehicleData(3300.SI<Kilogram>()); + + var driverData = CreateDriverData(AccelerationFile2); + + var modalWriter = new ModalDataWriter("Coach_MinimalPowertrainOverload.vmod", + SimulatorFactory.FactoryMode.EngineeringMode); + var vehicleContainer = new VehicleContainer(modalWriter); + + var cycle = new DistanceBasedDrivingCycle(vehicleContainer, cycleData); + + dynamic tmp = Port.AddComponent(cycle, new Driver(vehicleContainer, driverData, new DefaultDriverStrategy())); + tmp = Port.AddComponent(tmp, new Vehicle(vehicleContainer, vehicleData)); + tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); + tmp = Port.AddComponent(tmp, new Brakes(vehicleContainer)); + tmp = Port.AddComponent(tmp, new AxleGear(vehicleContainer, axleGearData)); + var engine = new CombustionEngine(vehicleContainer, engineData); + var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); + tmp = Port.AddComponent(tmp, clutch); + Port.AddComponent(tmp, engine); + engine.IdleController.RequestPort = clutch.IdleControlPort; + + var gbx = new MockGearbox(vehicleContainer); + + var cyclePort = cycle.OutPort(); + + cyclePort.Initialize(); + + gbx.Gear = 0; + + var absTime = 0.SI<Second>(); + + gbx.Gear = 1; + var ds = Constants.SimulationSettings.DriveOffDistance; + while (vehicleContainer.Distance < 100) { + var response = cyclePort.Request(absTime, ds); + response.Switch(). + Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). + Case<ResponseSuccess>(r => { + vehicleContainer.CommitSimulationStep(absTime, r.SimulationInterval); + absTime += r.SimulationInterval; + + ds = vehicleContainer.VehicleSpeed.IsEqual(0) + ? Constants.SimulationSettings.DriveOffDistance + : (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed) + .Cast<Meter>(); + + modalWriter.Finish(VectoRun.Status.Success); + }); + } + + modalWriter.Finish(VectoRun.Status.Success); + } + + private static GearData CreateAxleGearData() + { + return new GearData { + Ratio = 3.0 * 3.5, + LossMap = TransmissionLossMap.ReadFromFile(GbxLossMap, 3.0 * 3.5, "AxleGear") + }; + } + + private static VehicleData CreateVehicleData(Kilogram loading) + { + var axles = new List<Axle> { + new Axle { + AxleWeightShare = 0.4375, + Inertia = 21.66667.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0055, + TwinTyres = false, + TyreTestLoad = 62538.75.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.375, + Inertia = 10.83333.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0065, + TwinTyres = true, + TyreTestLoad = 52532.55.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.1875, + Inertia = 21.66667.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0055, + TwinTyres = false, + TyreTestLoad = 62538.75.SI<Newton>() + } + }; + return new VehicleData { + AxleConfiguration = AxleConfiguration.AxleConfig_6x2, + AerodynamicDragAera = 3.2634.SI<SquareMeter>(), + //CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection, + CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), + CurbWeight = 15700.SI<Kilogram>(), + CurbWeigthExtra = 0.SI<Kilogram>(), + Loading = loading, + DynamicTyreRadius = 0.52.SI<Meter>(), + Retarder = new RetarderData { Type = RetarderData.RetarderType.None }, + AxleData = axles, + SavedInDeclarationMode = false + }; + } + + private static DriverData CreateDriverData(string accelerationFile) + { + return new DriverData { + AccelerationCurve = AccelerationCurveData.ReadFromFile(accelerationFile), + LookAheadCoasting = new DriverData.LACData { + Enabled = false, + Deceleration = -0.5.SI<MeterPerSquareSecond>() + }, + OverSpeedEcoRoll = new DriverData.OverSpeedEcoRollData { + Mode = DriverData.DriverMode.Off + }, + StartStop = new VectoRunData.StartStopData { + Enabled = false + } + }; + } + } } \ No newline at end of file diff --git a/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs b/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs index 8ee88aab5355d2bc0b615f64d85ff38f71fc86ed..76252cfe08c4fcc0c1e50ced60697f38f938003d 100644 --- a/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs +++ b/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs @@ -12,531 +12,531 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Tests.Models.Declaration { - [TestClass] - public class DeclarationDataTest - { - public const double Tolerance = 0.0001; - public readonly MissionType[] Missions = Enum.GetValues(typeof(MissionType)).Cast<MissionType>().ToArray(); - - [TestMethod] - public void WheelDataTest() - { - var wheels = DeclarationData.Wheels; - - var tmp = wheels.Lookup("285/70 R19.5"); - - Assert.AreEqual(7.9, tmp.Inertia.Value(), Tolerance); - Assert.AreEqual(0.8943, tmp.DynamicTyreRadius.Value(), Tolerance); - Assert.AreEqual("b", tmp.SizeClass); - } - - [TestMethod] - public void RimsDataTest() - { - var rims = DeclarationData.Rims; - - var tmp = rims.Lookup("15° DC Rims"); - - Assert.AreEqual(3.03, tmp.F_a, Tolerance); - Assert.AreEqual(3.05, tmp.F_b, Tolerance); - } - - [TestMethod] - public void PT1Test() - { - var pt1 = DeclarationData.PT1; - - // FIXED POINTS - Assert.AreEqual(0, pt1.Lookup(400.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.47, pt1.Lookup(800.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.58, pt1.Lookup(1000.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.53, pt1.Lookup(1200.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.46, pt1.Lookup(1400.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.43, pt1.Lookup(1500.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.22, pt1.Lookup(1750.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.2, pt1.Lookup(1800.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.11, pt1.Lookup(2000.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.11, pt1.Lookup(2500.RPMtoRad()).Value(), Tolerance); - - // INTERPOLATE - Assert.AreEqual(0.235, pt1.Lookup(600.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.525, pt1.Lookup(900.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.555, pt1.Lookup(1100.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.495, pt1.Lookup(1300.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.445, pt1.Lookup(1450.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.325, pt1.Lookup(1625.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.21, pt1.Lookup(1775.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.155, pt1.Lookup(1900.RPMtoRad()).Value(), Tolerance); - Assert.AreEqual(0.11, pt1.Lookup(2250.RPMtoRad()).Value(), Tolerance); - - - // EXTRAPOLATE - Assert.AreEqual(0.11, pt1.Lookup(3000.RPMtoRad()).Value(), Tolerance); - AssertHelper.Exception<VectoException>(() => pt1.Lookup(200.RPMtoRad())); - AssertHelper.Exception<VectoException>(() => pt1.Lookup(0.RPMtoRad())); - } - - [TestMethod] - public void WHTCTest() - { - var whtc = DeclarationData.WHTCCorrection; - - var factors = new { - urban = new[] { 0.11, 0.17, 0.69, 0.98, 0.62, 1.0, 1.0, 1.0, 0.45, 0.0 }, - rural = new[] { 0.0, 0.3, 0.27, 0.0, 0.32, 0.0, 0.0, 0.0, 0.36, 0.22 }, - motorway = new[] { 0.89, 0.53, 0.04, 0.02, 0.06, 0.0, 0.0, 0.0, 0.19, 0.78 } - }; - - var r = new Random(); - for (var i = 0; i < Missions.Length; i++) { - var urban = r.NextDouble() * 2; - var rural = r.NextDouble() * 2; - var motorway = r.NextDouble() * 2; - var whtcValue = whtc.Lookup(Missions[i], urban, rural, motorway); - Assert.AreEqual(urban * factors.urban[i] + rural * factors.rural[i] + motorway * factors.motorway[i], - whtcValue); - } - } - - [TestMethod] - public void AirDragTest() - { - var airDrag = DeclarationData.AirDrag; - - var expected = new Dictionary<string, AirDrag.AirDragEntry> { - { "RigidSolo", new AirDrag.AirDragEntry { A1 = 0.013526, A2 = 0.017746, A3 = -0.000666 } }, - { "RigidTrailer", new AirDrag.AirDragEntry { A1 = 0.017125, A2 = 0.072275, A3 = -0.004148 } }, - { "TractorSemitrailer", new AirDrag.AirDragEntry { A1 = 0.034767, A2 = 0.039367, A3 = -0.001897 } }, - { "CoachBus", new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } } - }; - - foreach (var kv in expected) { - Assert.AreEqual(kv.Value, airDrag.Lookup(kv.Key)); - } - - var expectedCat = new Dictionary<VehicleCategory, AirDrag.AirDragEntry> { - { - VehicleCategory.RigidTruck, new AirDrag.AirDragEntry { A1 = 0.013526, A2 = 0.017746, A3 = -0.000666 } - }, - { VehicleCategory.Tractor, new AirDrag.AirDragEntry { A1 = 0.034767, A2 = 0.039367, A3 = -0.001897 } }, - { VehicleCategory.CityBus, new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } }, - { VehicleCategory.Coach, new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } }, { - VehicleCategory.InterurbanBus, - new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } - } - }; - - foreach (var kv in expectedCat) { - Assert.AreEqual(kv.Value, airDrag.Lookup(kv.Key)); - } - } - - [TestMethod] - public void CrossWindCorrectionTest() - { - var crossWindCorrectionCurve = - DeclarationDataAdapter.GetDeclarationAirResistanceCurve(VehicleCategory.Tractor, - 6.2985.SI<SquareMeter>()); - - var tmp = crossWindCorrectionCurve.EffectiveAirDragArea(0.KMPHtoMeterPerSecond()); - Assert.AreEqual(8.12204, tmp.Value(), Tolerance); - - tmp = crossWindCorrectionCurve.EffectiveAirDragArea(60.KMPHtoMeterPerSecond()); - Assert.AreEqual(8.12204, tmp.Value(), Tolerance); - - tmp = crossWindCorrectionCurve.EffectiveAirDragArea(75.KMPHtoMeterPerSecond()); - Assert.AreEqual(7.67058, tmp.Value(), Tolerance); - - tmp = crossWindCorrectionCurve.EffectiveAirDragArea(100.KMPHtoMeterPerSecond()); - Assert.AreEqual(7.23735, tmp.Value(), Tolerance); - - tmp = crossWindCorrectionCurve.EffectiveAirDragArea(52.1234.KMPHtoMeterPerSecond()); - Assert.AreEqual(8.12196, tmp.Value(), Tolerance); - - tmp = crossWindCorrectionCurve.EffectiveAirDragArea(73.5432.KMPHtoMeterPerSecond()); - Assert.AreEqual(7.70815, tmp.Value(), Tolerance); - - tmp = crossWindCorrectionCurve.EffectiveAirDragArea(92.8765.KMPHtoMeterPerSecond()); - Assert.AreEqual(7.33443, tmp.Value(), Tolerance); - } - - [TestMethod] - public void DefaultTCTest() - { - var tc = DeclarationData.TorqueConverter; - - var expected = new[] { - // fixed points - new { nu = 1.000, mu = 1.000, torque = 0.00 }, - new { nu = 1.005, mu = 1.000, torque = 0.00 }, - new { nu = 1.100, mu = 1.000, torque = -40.34 }, - new { nu = 1.222, mu = 1.000, torque = -80.34 }, - new { nu = 1.375, mu = 1.000, torque = -136.11 }, - new { nu = 1.571, mu = 1.000, torque = -216.52 }, - new { nu = 1.833, mu = 1.000, torque = -335.19 }, - new { nu = 2.200, mu = 1.000, torque = -528.77 }, - new { nu = 2.750, mu = 1.000, torque = -883.40 }, - new { nu = 4.400, mu = 1.000, torque = -2462.17 }, - new { nu = 11.000, mu = 1.000, torque = -16540.98 }, - - // interpolated points - new { nu = 1.0025, mu = 1.0, torque = 0.0 }, - new { nu = 1.0525, mu = 1.0, torque = -20.17 }, - new { nu = 1.161, mu = 1.0, torque = -60.34 }, - new { nu = 1.2985, mu = 1.0, torque = -108.225 }, - new { nu = 1.2985, mu = 1.0, torque = -108.225 }, - new { nu = 1.473, mu = 1.0, torque = -176.315 }, - new { nu = 1.702, mu = 1.0, torque = -275.855 }, - new { nu = 2.0165, mu = 1.0, torque = -431.98 }, - new { nu = 2.475, mu = 1.0, torque = -706.085 }, - new { nu = 3.575, mu = 1.0, torque = -1672.785 }, - new { nu = 7.7, mu = 1.0, torque = -9501.575 }, - - // extrapolated points - new { nu = 0.5, mu = 1.0, torque = 0.0 }, - new { nu = 12.0, mu = 1.0, torque = -18674.133 }, // = (12-4.4)*(-16540.98- -2462.17)/(11-4.4)+ -2462.17 - }; - - var referenceSpeed = 150.SI<PerSecond>(); - - var r = new Random(); - - foreach (var exp in expected) { - var mu = tc.LookupMu(exp.nu); - Assert.AreEqual(mu, exp.mu); - - var angularSpeed = r.Next(1000).SI<PerSecond>(); - var torque = tc.LookupTorque(exp.nu, angularSpeed, referenceSpeed); - AssertHelper.AreRelativeEqual( - exp.torque.SI<NewtonMeter>() * Math.Pow((angularSpeed / referenceSpeed).Cast<Scalar>(), 2), torque); - } - } - - [TestMethod] - public void AuxElectricSystemTest() - { - var es = DeclarationData.ElectricSystem; - - var expected = new[] { - new { Mission = MissionType.LongHaul, Base = 1240.SI<Watt>(), LED = 1190.SI<Watt>(), Efficiency = 0.7 }, - new { - Mission = MissionType.RegionalDelivery, - Base = 1055.SI<Watt>(), - LED = 1005.SI<Watt>(), - Efficiency = 0.7 - }, - new { - Mission = MissionType.UrbanDelivery, - Base = 974.SI<Watt>(), - LED = 924.SI<Watt>(), - Efficiency = 0.7 - }, - new { - Mission = MissionType.MunicipalUtility, - Base = 974.SI<Watt>(), - LED = 924.SI<Watt>(), - Efficiency = 0.7 - }, - new { - Mission = MissionType.Construction, - Base = 975.SI<Watt>(), - LED = 925.SI<Watt>(), - Efficiency = 0.7 - }, - new { Mission = MissionType.HeavyUrban, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 }, - new { Mission = MissionType.Urban, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 }, - new { Mission = MissionType.Suburban, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 }, - new { Mission = MissionType.Interurban, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 }, - new { Mission = MissionType.Coach, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 } - }; - Assert.AreEqual(expected.Length, Enum.GetValues(typeof(MissionType)).Length); - - foreach (var expectation in expected) { - var baseConsumption = es.Lookup(expectation.Mission, technologies: null); - var leds = es.Lookup(expectation.Mission, technologies: new[] { "LED lights" }); - - AssertHelper.AreRelativeEqual(expectation.Base / expectation.Efficiency, baseConsumption); - AssertHelper.AreRelativeEqual(expectation.LED / expectation.Efficiency, leds); - } - } - - [TestMethod] - public void AuxFanTechTest() - { - var fan = DeclarationData.Fan; - - const string defaultFan = "Crankshaft mounted - Electronically controlled visco clutch (Default)"; - var expected = new Dictionary<string, int[]> { - { - "Crankshaft mounted - Electronically controlled visco clutch (Default)", - new[] { 618, 671, 516, 566, 1037, 0, 0, 0, 0, 0 } - }, { - "Crankshaft mounted - Bimetallic controlled visco clutch", - new[] { 818, 871, 676, 766, 1277, 0, 0, 0, 0, 0 } - }, { - "Crankshaft mounted - Discrete step clutch", - new[] { 668, 721, 616, 616, 1157, 0, 0, 0, 0, 0 } - }, { - "Crankshaft mounted - On/Off clutch", - new[] { 718, 771, 666, 666, 1237, 0, 0, 0, 0, 0 } - }, { - "Belt driven or driven via transm. - Electronically controlled visco clutch", - new[] { 889, 944, 733, 833, 1378, 0, 0, 0, 0, 0 } - }, { - "Belt driven or driven via transm. - Bimetallic controlled visco clutch", - new[] { 1089, 1144, 893, 1033, 1618, 0, 0, 0, 0, 0 } - }, { - "Belt driven or driven via transm. - Discrete step clutch", - new[] { 939, 994, 883, 883, 1498, 0, 0, 0, 0, 0 } - }, { - "Belt driven or driven via transm. - On/Off clutch", - new[] { 989, 1044, 933, 933, 1578, 0, 0, 0, 0, 0 } - }, { - "Hydraulic driven - Variable displacement pump", - new[] { 738, 955, 632, 717, 1672, 0, 0, 0, 0, 0 } - }, { - "Hydraulic driven - Constant displacement pump", - new[] { 1000, 1200, 800, 900, 2100, 0, 0, 0, 0, 0 } - }, { - "Hydraulic driven - Electronically controlled", - new[] { 700, 800, 600, 600, 1400, 0, 0, 0, 0, 0 } - } - }; - - for (var i = 0; i < Missions.Length; i++) { - // default tech - Watt defaultValue = fan.Lookup(Missions[i], ""); - Assert.AreEqual(expected[defaultFan][i], defaultValue.Value(), Tolerance); - - // all fan techs - foreach (var expect in expected) { - Watt value = fan.Lookup(Missions[i], expect.Key); - Assert.AreEqual(expect.Value[i], value.Value(), Tolerance); - } - } - } - - [TestMethod] - public void AuxHeatingVentilationAirConditionTest() - { - var hvac = DeclarationData.HeatingVentilationAirConditioning; - - var expected = new Dictionary<VehicleClass, int[]> { - { VehicleClass.Class1, new[] { 0, 150, 150, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class2, new[] { 200, 200, 150, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class3, new[] { 0, 200, 150, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class4, new[] { 350, 200, 0, 300, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class5, new[] { 350, 200, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class7, new[] { 0, 0, 0, 0, 200, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class9, new[] { 350, 200, 0, 300, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class10, new[] { 350, 200, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class11, new[] { 0, 0, 0, 0, 200, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class12, new[] { 0, 0, 0, 0, 200, 0, 0, 0, 0, 0 } } - }; - - for (var i = 0; i < Missions.Length; i++) { - foreach (var expect in expected) { - Watt value = hvac.Lookup(Missions[i], expect.Key); - Assert.AreEqual(expect.Value[i], value.Value(), Tolerance); - } - } - } - - [TestMethod] - public void AuxPneumaticSystemTest() - { - var ps = DeclarationData.PneumaticSystem; - - var expected = new Dictionary<VehicleClass, int[]> { - { VehicleClass.Class1, new[] { 0, 1300, 1240, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class2, new[] { 1180, 1280, 1320, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class3, new[] { 0, 1360, 1380, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class4, new[] { 1300, 1340, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class5, new[] { 1340, 1820, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class7, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class9, new[] { 1340, 1540, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class10, new[] { 1340, 1820, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class11, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class12, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } - }; - - for (var i = 0; i < Missions.Length; i++) { - foreach (var expect in expected) { - Watt value = ps.Lookup(Missions[i], expect.Key); - Assert.AreEqual(expect.Value[i], value.Value(), Tolerance); - } - } - } - - [TestMethod] - public void AuxSteeringPumpTest() - { - var sp = DeclarationData.SteeringPump; - - var expected = new Dictionary<string, Dictionary<VehicleClass, int[]>> { - { - "Fixed displacement", new Dictionary<VehicleClass, int[]> { - { VehicleClass.Class1, new[] { 0, 260, 270, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class2, new[] { 370, 320, 310, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class3, new[] { 0, 340, 350, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class4, new[] { 610, 530, 0, 530, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class5, new[] { 720, 630, 620, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class7, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class9, new[] { 720, 550, 0, 550, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class10, new[] { 570, 530, 0, 0, 0, 0, 0, 0, 0, 0 } } - } - }, { - "Variable displacement", new Dictionary<VehicleClass, int[]> { - { VehicleClass.Class1, new[] { 0, 156, 162, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class2, new[] { 222, 192, 186, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class3, new[] { 0, 204, 210, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class4, new[] { 366, 318, 0, 318, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class5, new[] { 432, 378, 372, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class7, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class9, new[] { 432, 330, 0, 330, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class10, new[] { 342, 318, 0, 0, 0, 0, 0, 0, 0, 0 } } - } - }, { - "Hydraulic supported by electric", new Dictionary<VehicleClass, int[]> { - { VehicleClass.Class1, new[] { 0, 225, 235, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class2, new[] { 322, 278, 269, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class3, new[] { 0, 295, 304, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class4, new[] { 531, 460, 0, 460, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class5, new[] { 627, 546, 540, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class7, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class9, new[] { 627, 478, 0, 478, 0, 0, 0, 0, 0, 0 } }, - { VehicleClass.Class10, new[] { 498, 461, 0, 0, 0, 0, 0, 0, 0, 0 } } - } - } - }; - - foreach (var expect in expected) { - var technology = expect.Key; - foreach (var hdvClasses in expect.Value) { - var hdvClass = hdvClasses.Key; - for (var i = 0; i < Missions.Length; i++) { - Watt value = sp.Lookup(Missions[i], hdvClass, technology); - Assert.AreEqual(hdvClasses.Value[i], value.Value(), Tolerance); - } - } - } - } - - [TestMethod] - public void SegmentTest() - { - //mock vehicleData - var vehicleData = new { - VehicleCategory = VehicleCategory.RigidTruck, - AxleConfiguration = AxleConfiguration.AxleConfig_4x2, - GrossVehicleMassRating = 11900.SI<Kilogram>(), - CurbWeight = 5850.SI<Kilogram>() - }; - - var segment = DeclarationData.Segments.Lookup(vehicleData.VehicleCategory, vehicleData.AxleConfiguration, - vehicleData.GrossVehicleMassRating, vehicleData.CurbWeight); - - - Assert.AreEqual(VehicleClass.Class2, segment.VehicleClass); - - var data = AccelerationCurveData.ReadFromStream(segment.AccelerationFile); - TestAcceleration(data); - - Assert.AreEqual(3, segment.Missions.Length); - - var longHaulMission = segment.Missions[0]; - Assert.AreEqual(MissionType.LongHaul, longHaulMission.MissionType); - - Assert.AreEqual("RigidSolo", longHaulMission.CrossWindCorrection); - - Assert.IsTrue(new[] { 0.4, 0.6 }.SequenceEqual(longHaulMission.AxleWeightDistribution)); - Assert.IsTrue(new double[] { }.SequenceEqual(longHaulMission.TrailerAxleWeightDistribution)); - Assert.AreEqual(1900.SI<Kilogram>(), longHaulMission.MassExtra); - - Assert.IsNotNull(longHaulMission.CycleFile); - Assert.IsTrue(!string.IsNullOrEmpty(new StreamReader(longHaulMission.CycleFile).ReadLine())); - - Assert.AreEqual(0.SI<Kilogram>(), longHaulMission.MinLoad); - Assert.AreEqual(0.5882 * vehicleData.GrossVehicleMassRating - 2511.8.SI<Kilogram>(), longHaulMission.RefLoad); - Assert.AreEqual(vehicleData.GrossVehicleMassRating - longHaulMission.MassExtra - vehicleData.CurbWeight, - longHaulMission.MaxLoad); - - var regionalDeliveryMission = segment.Missions[1]; - Assert.AreEqual(MissionType.RegionalDelivery, regionalDeliveryMission.MissionType); - - Assert.AreEqual("RigidSolo", regionalDeliveryMission.CrossWindCorrection); - - Assert.IsTrue(new[] { 0.45, 0.55 }.SequenceEqual(regionalDeliveryMission.AxleWeightDistribution)); - Assert.IsTrue(new double[] { }.SequenceEqual(regionalDeliveryMission.TrailerAxleWeightDistribution)); - Assert.AreEqual(1900.SI<Kilogram>(), regionalDeliveryMission.MassExtra); - - Assert.IsNotNull(regionalDeliveryMission.CycleFile); - Assert.IsTrue(!string.IsNullOrEmpty(new StreamReader(regionalDeliveryMission.CycleFile).ReadLine())); - - Assert.AreEqual(0.SI<Kilogram>(), regionalDeliveryMission.MinLoad); - Assert.AreEqual(0.3941 * vehicleData.GrossVehicleMassRating - 1705.9.SI<Kilogram>(), - regionalDeliveryMission.RefLoad); - Assert.AreEqual( - vehicleData.GrossVehicleMassRating - regionalDeliveryMission.MassExtra - vehicleData.CurbWeight, - regionalDeliveryMission.MaxLoad); - - var urbanDeliveryMission = segment.Missions[2]; - Assert.AreEqual(MissionType.UrbanDelivery, urbanDeliveryMission.MissionType); - - Assert.AreEqual("RigidSolo", urbanDeliveryMission.CrossWindCorrection); - - Assert.IsTrue(new[] { 0.45, 0.55 }.SequenceEqual(urbanDeliveryMission.AxleWeightDistribution)); - Assert.IsTrue(new double[] { }.SequenceEqual(urbanDeliveryMission.TrailerAxleWeightDistribution)); - Assert.AreEqual(1900.SI<Kilogram>(), urbanDeliveryMission.MassExtra); - - Assert.IsNotNull(urbanDeliveryMission.CycleFile); - Assert.IsTrue(!string.IsNullOrEmpty(new StreamReader(urbanDeliveryMission.CycleFile).ReadLine())); - - Assert.AreEqual(0.SI<Kilogram>(), urbanDeliveryMission.MinLoad); - Assert.AreEqual(0.3941 * vehicleData.GrossVehicleMassRating - 1705.9.SI<Kilogram>(), - urbanDeliveryMission.RefLoad); - Assert.AreEqual( - vehicleData.GrossVehicleMassRating - urbanDeliveryMission.MassExtra - vehicleData.CurbWeight, - urbanDeliveryMission.MaxLoad); - } - - public void EqualAcceleration(AccelerationCurveData data, double velocity, double acceleration, - double deceleration) - { - var entry = data.Lookup(velocity.KMPHtoMeterPerSecond()); - Assert.AreEqual(entry.Acceleration.Value(), acceleration, Tolerance); - Assert.AreEqual(entry.Deceleration.Value(), deceleration, Tolerance); - } - - public void TestAcceleration(AccelerationCurveData data) - { - // FIXED POINTS - EqualAcceleration(data, 0, 1, -1); - EqualAcceleration(data, 25, 1, -1); - EqualAcceleration(data, 50, 0.642857143, -1); - EqualAcceleration(data, 60, 0.5, -0.5); - EqualAcceleration(data, 120, 0.5, -0.5); - - // INTERPOLATED POINTS - EqualAcceleration(data, 20, 1, -1); - EqualAcceleration(data, 40, 0.785714286, -1); - EqualAcceleration(data, 55, 0.571428572, -0.75); - EqualAcceleration(data, 80, 0.5, -0.5); - EqualAcceleration(data, 100, 0.5, -0.5); - - // EXTRAPOLATE - EqualAcceleration(data, -20, 1, -1); - EqualAcceleration(data, 140, 0.5, -0.5); - } - } + [TestClass] + public class DeclarationDataTest + { + public const double Tolerance = 0.0001; + public readonly MissionType[] Missions = Enum.GetValues(typeof(MissionType)).Cast<MissionType>().ToArray(); + + [TestMethod] + public void WheelDataTest() + { + var wheels = DeclarationData.Wheels; + + var tmp = wheels.Lookup("285/70 R19.5"); + + Assert.AreEqual(7.9, tmp.Inertia.Value(), Tolerance); + Assert.AreEqual(0.8943, tmp.DynamicTyreRadius.Value(), Tolerance); + Assert.AreEqual("b", tmp.SizeClass); + } + + [TestMethod] + public void RimsDataTest() + { + var rims = DeclarationData.Rims; + + var tmp = rims.Lookup("15° DC Rims"); + + Assert.AreEqual(3.03, tmp.F_a, Tolerance); + Assert.AreEqual(3.05, tmp.F_b, Tolerance); + } + + [TestMethod] + public void PT1Test() + { + var pt1 = DeclarationData.PT1; + + // FIXED POINTS + Assert.AreEqual(0, pt1.Lookup(400.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.47, pt1.Lookup(800.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.58, pt1.Lookup(1000.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.53, pt1.Lookup(1200.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.46, pt1.Lookup(1400.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.43, pt1.Lookup(1500.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.22, pt1.Lookup(1750.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.2, pt1.Lookup(1800.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.11, pt1.Lookup(2000.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.11, pt1.Lookup(2500.RPMtoRad()).Value(), Tolerance); + + // INTERPOLATE + Assert.AreEqual(0.235, pt1.Lookup(600.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.525, pt1.Lookup(900.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.555, pt1.Lookup(1100.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.495, pt1.Lookup(1300.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.445, pt1.Lookup(1450.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.325, pt1.Lookup(1625.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.21, pt1.Lookup(1775.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.155, pt1.Lookup(1900.RPMtoRad()).Value(), Tolerance); + Assert.AreEqual(0.11, pt1.Lookup(2250.RPMtoRad()).Value(), Tolerance); + + + // EXTRAPOLATE + Assert.AreEqual(0.11, pt1.Lookup(3000.RPMtoRad()).Value(), Tolerance); + AssertHelper.Exception<VectoException>(() => pt1.Lookup(200.RPMtoRad())); + AssertHelper.Exception<VectoException>(() => pt1.Lookup(0.RPMtoRad())); + } + + [TestMethod] + public void WHTCTest() + { + var whtc = DeclarationData.WHTCCorrection; + + var factors = new { + urban = new[] { 0.11, 0.17, 0.69, 0.98, 0.62, 1.0, 1.0, 1.0, 0.45, 0.0 }, + rural = new[] { 0.0, 0.3, 0.27, 0.0, 0.32, 0.0, 0.0, 0.0, 0.36, 0.22 }, + motorway = new[] { 0.89, 0.53, 0.04, 0.02, 0.06, 0.0, 0.0, 0.0, 0.19, 0.78 } + }; + + var r = new Random(); + for (var i = 0; i < Missions.Length; i++) { + var urban = r.NextDouble() * 2; + var rural = r.NextDouble() * 2; + var motorway = r.NextDouble() * 2; + var whtcValue = whtc.Lookup(Missions[i], urban, rural, motorway); + Assert.AreEqual(urban * factors.urban[i] + rural * factors.rural[i] + motorway * factors.motorway[i], + whtcValue); + } + } + + [TestMethod] + public void AirDragTest() + { + var airDrag = DeclarationData.AirDrag; + + var expected = new Dictionary<string, AirDrag.AirDragEntry> { + { "RigidSolo", new AirDrag.AirDragEntry { A1 = 0.013526, A2 = 0.017746, A3 = -0.000666 } }, + { "RigidTrailer", new AirDrag.AirDragEntry { A1 = 0.017125, A2 = 0.072275, A3 = -0.004148 } }, + { "TractorSemitrailer", new AirDrag.AirDragEntry { A1 = 0.034767, A2 = 0.039367, A3 = -0.001897 } }, + { "CoachBus", new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } } + }; + + foreach (var kv in expected) { + Assert.AreEqual(kv.Value, airDrag.Lookup(kv.Key)); + } + + var expectedCat = new Dictionary<VehicleCategory, AirDrag.AirDragEntry> { + { + VehicleCategory.RigidTruck, new AirDrag.AirDragEntry { A1 = 0.013526, A2 = 0.017746, A3 = -0.000666 } + }, + { VehicleCategory.Tractor, new AirDrag.AirDragEntry { A1 = 0.034767, A2 = 0.039367, A3 = -0.001897 } }, + { VehicleCategory.CityBus, new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } }, + { VehicleCategory.Coach, new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } }, { + VehicleCategory.InterurbanBus, + new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } + } + }; + + foreach (var kv in expectedCat) { + Assert.AreEqual(kv.Value, airDrag.Lookup(kv.Key)); + } + } + + [TestMethod] + public void CrossWindCorrectionTest() + { + var crossWindCorrectionCurve = + DeclarationDataAdapter.GetDeclarationAirResistanceCurve(VehicleCategory.Tractor, + 6.46.SI<SquareMeter>()); + + var tmp = crossWindCorrectionCurve.EffectiveAirDragArea(0.KMPHtoMeterPerSecond()); + Assert.AreEqual(8.12204, tmp.Value(), Tolerance); + + tmp = crossWindCorrectionCurve.EffectiveAirDragArea(60.KMPHtoMeterPerSecond()); + Assert.AreEqual(8.12204, tmp.Value(), Tolerance); + + tmp = crossWindCorrectionCurve.EffectiveAirDragArea(75.KMPHtoMeterPerSecond()); + Assert.AreEqual(7.67058, tmp.Value(), Tolerance); + + tmp = crossWindCorrectionCurve.EffectiveAirDragArea(100.KMPHtoMeterPerSecond()); + Assert.AreEqual(7.23735, tmp.Value(), Tolerance); + + tmp = crossWindCorrectionCurve.EffectiveAirDragArea(52.1234.KMPHtoMeterPerSecond()); + Assert.AreEqual(8.12196, tmp.Value(), Tolerance); + + tmp = crossWindCorrectionCurve.EffectiveAirDragArea(73.5432.KMPHtoMeterPerSecond()); + Assert.AreEqual(7.70815, tmp.Value(), Tolerance); + + tmp = crossWindCorrectionCurve.EffectiveAirDragArea(92.8765.KMPHtoMeterPerSecond()); + Assert.AreEqual(7.33443, tmp.Value(), Tolerance); + } + + [TestMethod] + public void DefaultTCTest() + { + var tc = DeclarationData.TorqueConverter; + + var expected = new[] { + // fixed points + new { nu = 1.000, mu = 1.000, torque = 0.00 }, + new { nu = 1.005, mu = 1.000, torque = 0.00 }, + new { nu = 1.100, mu = 1.000, torque = -40.34 }, + new { nu = 1.222, mu = 1.000, torque = -80.34 }, + new { nu = 1.375, mu = 1.000, torque = -136.11 }, + new { nu = 1.571, mu = 1.000, torque = -216.52 }, + new { nu = 1.833, mu = 1.000, torque = -335.19 }, + new { nu = 2.200, mu = 1.000, torque = -528.77 }, + new { nu = 2.750, mu = 1.000, torque = -883.40 }, + new { nu = 4.400, mu = 1.000, torque = -2462.17 }, + new { nu = 11.000, mu = 1.000, torque = -16540.98 }, + + // interpolated points + new { nu = 1.0025, mu = 1.0, torque = 0.0 }, + new { nu = 1.0525, mu = 1.0, torque = -20.17 }, + new { nu = 1.161, mu = 1.0, torque = -60.34 }, + new { nu = 1.2985, mu = 1.0, torque = -108.225 }, + new { nu = 1.2985, mu = 1.0, torque = -108.225 }, + new { nu = 1.473, mu = 1.0, torque = -176.315 }, + new { nu = 1.702, mu = 1.0, torque = -275.855 }, + new { nu = 2.0165, mu = 1.0, torque = -431.98 }, + new { nu = 2.475, mu = 1.0, torque = -706.085 }, + new { nu = 3.575, mu = 1.0, torque = -1672.785 }, + new { nu = 7.7, mu = 1.0, torque = -9501.575 }, + + // extrapolated points + new { nu = 0.5, mu = 1.0, torque = 0.0 }, + new { nu = 12.0, mu = 1.0, torque = -18674.133 } // = (12-4.4)*(-16540.98- -2462.17)/(11-4.4)+ -2462.17 + }; + + var referenceSpeed = 150.SI<PerSecond>(); + + var r = new Random(); + + foreach (var exp in expected) { + var mu = tc.LookupMu(exp.nu); + Assert.AreEqual(mu, exp.mu); + + var angularSpeed = r.Next(1000).SI<PerSecond>(); + var torque = tc.LookupTorque(exp.nu, angularSpeed, referenceSpeed); + AssertHelper.AreRelativeEqual( + exp.torque.SI<NewtonMeter>() * Math.Pow((angularSpeed / referenceSpeed).Cast<Scalar>(), 2), torque); + } + } + + [TestMethod] + public void AuxElectricSystemTest() + { + var es = DeclarationData.ElectricSystem; + + var expected = new[] { + new { Mission = MissionType.LongHaul, Base = 1240.SI<Watt>(), LED = 1190.SI<Watt>(), Efficiency = 0.7 }, + new { + Mission = MissionType.RegionalDelivery, + Base = 1055.SI<Watt>(), + LED = 1005.SI<Watt>(), + Efficiency = 0.7 + }, + new { + Mission = MissionType.UrbanDelivery, + Base = 974.SI<Watt>(), + LED = 924.SI<Watt>(), + Efficiency = 0.7 + }, + new { + Mission = MissionType.MunicipalUtility, + Base = 974.SI<Watt>(), + LED = 924.SI<Watt>(), + Efficiency = 0.7 + }, + new { + Mission = MissionType.Construction, + Base = 975.SI<Watt>(), + LED = 925.SI<Watt>(), + Efficiency = 0.7 + }, + new { Mission = MissionType.HeavyUrban, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 }, + new { Mission = MissionType.Urban, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 }, + new { Mission = MissionType.Suburban, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 }, + new { Mission = MissionType.Interurban, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 }, + new { Mission = MissionType.Coach, Base = 0.SI<Watt>(), LED = 0.SI<Watt>(), Efficiency = 1.0 } + }; + Assert.AreEqual(expected.Length, Enum.GetValues(typeof(MissionType)).Length); + + foreach (var expectation in expected) { + var baseConsumption = es.Lookup(expectation.Mission, null); + var leds = es.Lookup(expectation.Mission, new[] { "LED lights" }); + + AssertHelper.AreRelativeEqual(expectation.Base / expectation.Efficiency, baseConsumption); + AssertHelper.AreRelativeEqual(expectation.LED / expectation.Efficiency, leds); + } + } + + [TestMethod] + public void AuxFanTechTest() + { + var fan = DeclarationData.Fan; + + const string defaultFan = "Crankshaft mounted - Electronically controlled visco clutch (Default)"; + var expected = new Dictionary<string, int[]> { + { + "Crankshaft mounted - Electronically controlled visco clutch (Default)", + new[] { 618, 671, 516, 566, 1037, 0, 0, 0, 0, 0 } + }, { + "Crankshaft mounted - Bimetallic controlled visco clutch", + new[] { 818, 871, 676, 766, 1277, 0, 0, 0, 0, 0 } + }, { + "Crankshaft mounted - Discrete step clutch", + new[] { 668, 721, 616, 616, 1157, 0, 0, 0, 0, 0 } + }, { + "Crankshaft mounted - On/Off clutch", + new[] { 718, 771, 666, 666, 1237, 0, 0, 0, 0, 0 } + }, { + "Belt driven or driven via transm. - Electronically controlled visco clutch", + new[] { 889, 944, 733, 833, 1378, 0, 0, 0, 0, 0 } + }, { + "Belt driven or driven via transm. - Bimetallic controlled visco clutch", + new[] { 1089, 1144, 893, 1033, 1618, 0, 0, 0, 0, 0 } + }, { + "Belt driven or driven via transm. - Discrete step clutch", + new[] { 939, 994, 883, 883, 1498, 0, 0, 0, 0, 0 } + }, { + "Belt driven or driven via transm. - On/Off clutch", + new[] { 989, 1044, 933, 933, 1578, 0, 0, 0, 0, 0 } + }, { + "Hydraulic driven - Variable displacement pump", + new[] { 738, 955, 632, 717, 1672, 0, 0, 0, 0, 0 } + }, { + "Hydraulic driven - Constant displacement pump", + new[] { 1000, 1200, 800, 900, 2100, 0, 0, 0, 0, 0 } + }, { + "Hydraulic driven - Electronically controlled", + new[] { 700, 800, 600, 600, 1400, 0, 0, 0, 0, 0 } + } + }; + + for (var i = 0; i < Missions.Length; i++) { + // default tech + var defaultValue = fan.Lookup(Missions[i], ""); + Assert.AreEqual(expected[defaultFan][i], defaultValue.Value(), Tolerance); + + // all fan techs + foreach (var expect in expected) { + var value = fan.Lookup(Missions[i], expect.Key); + Assert.AreEqual(expect.Value[i], value.Value(), Tolerance); + } + } + } + + [TestMethod] + public void AuxHeatingVentilationAirConditionTest() + { + var hvac = DeclarationData.HeatingVentilationAirConditioning; + + var expected = new Dictionary<VehicleClass, int[]> { + { VehicleClass.Class1, new[] { 0, 150, 150, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class2, new[] { 200, 200, 150, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class3, new[] { 0, 200, 150, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class4, new[] { 350, 200, 0, 300, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class5, new[] { 350, 200, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class7, new[] { 0, 0, 0, 0, 200, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class9, new[] { 350, 200, 0, 300, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class10, new[] { 350, 200, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class11, new[] { 0, 0, 0, 0, 200, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class12, new[] { 0, 0, 0, 0, 200, 0, 0, 0, 0, 0 } } + }; + + for (var i = 0; i < Missions.Length; i++) { + foreach (var expect in expected) { + var value = hvac.Lookup(Missions[i], expect.Key); + Assert.AreEqual(expect.Value[i], value.Value(), Tolerance); + } + } + } + + [TestMethod] + public void AuxPneumaticSystemTest() + { + var ps = DeclarationData.PneumaticSystem; + + var expected = new Dictionary<VehicleClass, int[]> { + { VehicleClass.Class1, new[] { 0, 1300, 1240, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class2, new[] { 1180, 1280, 1320, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class3, new[] { 0, 1360, 1380, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class4, new[] { 1300, 1340, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class5, new[] { 1340, 1820, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class7, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class9, new[] { 1340, 1540, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class10, new[] { 1340, 1820, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class11, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class12, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } + }; + + for (var i = 0; i < Missions.Length; i++) { + foreach (var expect in expected) { + var value = ps.Lookup(Missions[i], expect.Key); + Assert.AreEqual(expect.Value[i], value.Value(), Tolerance); + } + } + } + + [TestMethod] + public void AuxSteeringPumpTest() + { + var sp = DeclarationData.SteeringPump; + + var expected = new Dictionary<string, Dictionary<VehicleClass, int[]>> { + { + "Fixed displacement", new Dictionary<VehicleClass, int[]> { + { VehicleClass.Class1, new[] { 0, 260, 270, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class2, new[] { 370, 320, 310, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class3, new[] { 0, 340, 350, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class4, new[] { 610, 530, 0, 530, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class5, new[] { 720, 630, 620, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class7, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class9, new[] { 720, 550, 0, 550, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class10, new[] { 570, 530, 0, 0, 0, 0, 0, 0, 0, 0 } } + } + }, { + "Variable displacement", new Dictionary<VehicleClass, int[]> { + { VehicleClass.Class1, new[] { 0, 156, 162, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class2, new[] { 222, 192, 186, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class3, new[] { 0, 204, 210, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class4, new[] { 366, 318, 0, 318, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class5, new[] { 432, 378, 372, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class7, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class9, new[] { 432, 330, 0, 330, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class10, new[] { 342, 318, 0, 0, 0, 0, 0, 0, 0, 0 } } + } + }, { + "Hydraulic supported by electric", new Dictionary<VehicleClass, int[]> { + { VehicleClass.Class1, new[] { 0, 225, 235, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class2, new[] { 322, 278, 269, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class3, new[] { 0, 295, 304, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class4, new[] { 531, 460, 0, 460, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class5, new[] { 627, 546, 540, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class6, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class7, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class8, new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class9, new[] { 627, 478, 0, 478, 0, 0, 0, 0, 0, 0 } }, + { VehicleClass.Class10, new[] { 498, 461, 0, 0, 0, 0, 0, 0, 0, 0 } } + } + } + }; + + foreach (var expect in expected) { + var technology = expect.Key; + foreach (var hdvClasses in expect.Value) { + var hdvClass = hdvClasses.Key; + for (var i = 0; i < Missions.Length; i++) { + var value = sp.Lookup(Missions[i], hdvClass, technology); + Assert.AreEqual(hdvClasses.Value[i], value.Value(), Tolerance); + } + } + } + } + + [TestMethod] + public void SegmentTest() + { + //mock vehicleData + var vehicleData = new { + VehicleCategory = VehicleCategory.RigidTruck, + AxleConfiguration = AxleConfiguration.AxleConfig_4x2, + GrossVehicleMassRating = 11900.SI<Kilogram>(), + CurbWeight = 5850.SI<Kilogram>() + }; + + var segment = DeclarationData.Segments.Lookup(vehicleData.VehicleCategory, vehicleData.AxleConfiguration, + vehicleData.GrossVehicleMassRating, vehicleData.CurbWeight); + + + Assert.AreEqual(VehicleClass.Class2, segment.VehicleClass); + + var data = AccelerationCurveData.ReadFromStream(segment.AccelerationFile); + TestAcceleration(data); + + Assert.AreEqual(3, segment.Missions.Length); + + var longHaulMission = segment.Missions[0]; + Assert.AreEqual(MissionType.LongHaul, longHaulMission.MissionType); + + Assert.AreEqual("RigidSolo", longHaulMission.CrossWindCorrection); + + Assert.IsTrue(new[] { 0.4, 0.6 }.SequenceEqual(longHaulMission.AxleWeightDistribution)); + Assert.IsTrue(new double[] { }.SequenceEqual(longHaulMission.TrailerAxleWeightDistribution)); + Assert.AreEqual(1900.SI<Kilogram>(), longHaulMission.MassExtra); + + Assert.IsNotNull(longHaulMission.CycleFile); + Assert.IsTrue(!string.IsNullOrEmpty(new StreamReader(longHaulMission.CycleFile).ReadLine())); + + Assert.AreEqual(0.SI<Kilogram>(), longHaulMission.MinLoad); + Assert.AreEqual(0.5882 * vehicleData.GrossVehicleMassRating - 2511.8.SI<Kilogram>(), longHaulMission.RefLoad); + Assert.AreEqual(vehicleData.GrossVehicleMassRating - longHaulMission.MassExtra - vehicleData.CurbWeight, + longHaulMission.MaxLoad); + + var regionalDeliveryMission = segment.Missions[1]; + Assert.AreEqual(MissionType.RegionalDelivery, regionalDeliveryMission.MissionType); + + Assert.AreEqual("RigidSolo", regionalDeliveryMission.CrossWindCorrection); + + Assert.IsTrue(new[] { 0.45, 0.55 }.SequenceEqual(regionalDeliveryMission.AxleWeightDistribution)); + Assert.IsTrue(new double[] { }.SequenceEqual(regionalDeliveryMission.TrailerAxleWeightDistribution)); + Assert.AreEqual(1900.SI<Kilogram>(), regionalDeliveryMission.MassExtra); + + Assert.IsNotNull(regionalDeliveryMission.CycleFile); + Assert.IsTrue(!string.IsNullOrEmpty(new StreamReader(regionalDeliveryMission.CycleFile).ReadLine())); + + Assert.AreEqual(0.SI<Kilogram>(), regionalDeliveryMission.MinLoad); + Assert.AreEqual(0.3941 * vehicleData.GrossVehicleMassRating - 1705.9.SI<Kilogram>(), + regionalDeliveryMission.RefLoad); + Assert.AreEqual( + vehicleData.GrossVehicleMassRating - regionalDeliveryMission.MassExtra - vehicleData.CurbWeight, + regionalDeliveryMission.MaxLoad); + + var urbanDeliveryMission = segment.Missions[2]; + Assert.AreEqual(MissionType.UrbanDelivery, urbanDeliveryMission.MissionType); + + Assert.AreEqual("RigidSolo", urbanDeliveryMission.CrossWindCorrection); + + Assert.IsTrue(new[] { 0.45, 0.55 }.SequenceEqual(urbanDeliveryMission.AxleWeightDistribution)); + Assert.IsTrue(new double[] { }.SequenceEqual(urbanDeliveryMission.TrailerAxleWeightDistribution)); + Assert.AreEqual(1900.SI<Kilogram>(), urbanDeliveryMission.MassExtra); + + Assert.IsNotNull(urbanDeliveryMission.CycleFile); + Assert.IsTrue(!string.IsNullOrEmpty(new StreamReader(urbanDeliveryMission.CycleFile).ReadLine())); + + Assert.AreEqual(0.SI<Kilogram>(), urbanDeliveryMission.MinLoad); + Assert.AreEqual(0.3941 * vehicleData.GrossVehicleMassRating - 1705.9.SI<Kilogram>(), + urbanDeliveryMission.RefLoad); + Assert.AreEqual( + vehicleData.GrossVehicleMassRating - urbanDeliveryMission.MassExtra - vehicleData.CurbWeight, + urbanDeliveryMission.MaxLoad); + } + + public void EqualAcceleration(AccelerationCurveData data, double velocity, double acceleration, + double deceleration) + { + var entry = data.Lookup(velocity.KMPHtoMeterPerSecond()); + Assert.AreEqual(entry.Acceleration.Value(), acceleration, Tolerance); + Assert.AreEqual(entry.Deceleration.Value(), deceleration, Tolerance); + } + + public void TestAcceleration(AccelerationCurveData data) + { + // FIXED POINTS + EqualAcceleration(data, 0, 1, -1); + EqualAcceleration(data, 25, 1, -1); + EqualAcceleration(data, 50, 0.642857143, -1); + EqualAcceleration(data, 60, 0.5, -0.5); + EqualAcceleration(data, 120, 0.5, -0.5); + + // INTERPOLATED POINTS + EqualAcceleration(data, 20, 1, -1); + EqualAcceleration(data, 40, 0.785714286, -1); + EqualAcceleration(data, 55, 0.571428572, -0.75); + EqualAcceleration(data, 80, 0.5, -0.5); + EqualAcceleration(data, 100, 0.5, -0.5); + + // EXTRAPOLATE + EqualAcceleration(data, -20, 1, -1); + EqualAcceleration(data, 140, 0.5, -0.5); + } + } } \ No newline at end of file diff --git a/VectoCoreTest/Models/SimulationComponent/DriverTest.cs b/VectoCoreTest/Models/SimulationComponent/DriverTest.cs index c8c172957767f2e7427399d8ff4f5cdd1e46c376..1c2d869fccccc71ee156a30851c4a82bcd0dc19f 100644 --- a/VectoCoreTest/Models/SimulationComponent/DriverTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/DriverTest.cs @@ -2,7 +2,6 @@ using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Configuration; -using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.FileIO.Reader.Impl; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; @@ -18,420 +17,410 @@ using Wheels = TUGraz.VectoCore.Models.SimulationComponent.Impl.Wheels; namespace TUGraz.VectoCore.Tests.Models.SimulationComponent { - [TestClass] - public class DriverTest - { - public const string JobFile = @"TestData\Jobs\24t Coach EngineOnly.vecto"; + [TestClass] + public class DriverTest + { + public const string JobFile = @"TestData\Jobs\24t Coach EngineOnly.vecto"; + public const string EngineFile = @"TestData\Components\24t Coach.veng"; + public const string AccelerationFile = @"TestData\Components\Coach.vacc"; + public const double Tolerance = 0.001; - public const string EngineFile = @"TestData\Components\24t Coach.veng"; + [TestMethod] + public void DriverCoastingTest() + { + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - public const string AccelerationFile = @"TestData\Components\Coach.vacc"; + var vehicleData = CreateVehicleData(33000.SI<Kilogram>()); + var driverData = CreateDriverData(); - public const double Tolerance = 0.001; + var modalWriter = new ModalDataWriter("Coach_MinimalPowertrain_Coasting.vmod", + SimulatorFactory.FactoryMode.EngineeringMode); //new TestModalDataWriter(); + var vehicleContainer = new VehicleContainer(modalWriter); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); + var engine = new CombustionEngine(vehicleContainer, engineData); + var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); + dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); + tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); + tmp = AddComponent(tmp, clutch); + AddComponent(tmp, engine); + engine.IdleController.RequestPort = clutch.IdleControlPort; - [TestMethod] - public void DriverCoastingTest() - { - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + var gbx = new MockGearbox(vehicleContainer) { Gear = 1 }; - var vehicleData = CreateVehicleData(33000.SI<Kilogram>()); + var driverPort = driver.OutPort(); - var driverData = CreateDriverData(); + var velocity = 5.SI<MeterPerSecond>(); + driverPort.Initialize(velocity, 0.SI<Radian>()); - var modalWriter = new ModalDataWriter("Coach_MinimalPowertrain_Coasting.vmod", - SimulatorFactory.FactoryMode.EngineeringMode); //new TestModalDataWriter(); - var vehicleContainer = new VehicleContainer(modalWriter); + var absTime = 0.SI<Second>(); - var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); - var engine = new CombustionEngine(vehicleContainer, engineData); - var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); - dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); - tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); - tmp = AddComponent(tmp, clutch); - AddComponent(tmp, engine); - engine.IdleController.RequestPort = clutch.IdleControlPort; + var response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, 0.SI<Radian>()); - var gbx = new MockGearbox(vehicleContainer) { Gear = 1 }; + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - var driverPort = driver.OutPort(); + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; - var velocity = 5.SI<MeterPerSecond>(); - driverPort.Initialize(velocity, 0.SI<Radian>()); + Assert.AreEqual(4.9812, vehicleContainer.VehicleSpeed.Value(), Tolerance); + Assert.AreEqual(0.2004, response.SimulationInterval.Value(), Tolerance); + Assert.AreEqual(engine.PreviousState.FullDragPower.Value(), engine.PreviousState.EnginePower.Value(), + Constants.SimulationSettings.EnginePowerSearchTolerance.Value()); - var absTime = 0.SI<Second>(); + while (vehicleContainer.VehicleSpeed > 1) { + response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, 0.SI<Radian>()); - var response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, 0.SI<Radian>()); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; + modalWriter.Finish(VectoRun.Status.Success); + } + modalWriter.Finish(VectoRun.Status.Success); + } - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; + [TestMethod] + public void DriverCoastingTest2() + { + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - Assert.AreEqual(4.9812, vehicleContainer.VehicleSpeed.Value(), Tolerance); - Assert.AreEqual(0.2004, response.SimulationInterval.Value(), Tolerance); - Assert.AreEqual(engine.PreviousState.FullDragPower.Value(), engine.PreviousState.EnginePower.Value(), - Constants.SimulationSettings.EnginePowerSearchTolerance.Value()); + var vehicleData = CreateVehicleData(33000.SI<Kilogram>()); - while (vehicleContainer.VehicleSpeed > 1) { - response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, 0.SI<Radian>()); + var driverData = CreateDriverData(); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + var modalWriter = new ModalDataWriter("Coach_MinimalPowertrain_Coasting.vmod"); + var vehicleContainer = new VehicleContainer(modalWriter); - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; - modalWriter.Finish(VectoRun.Status.Success); - } - modalWriter.Finish(VectoRun.Status.Success); - } + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); + var engine = new CombustionEngine(vehicleContainer, engineData); + var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); - [TestMethod] - public void DriverCoastingTest2() - { - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); + tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); + tmp = AddComponent(tmp, clutch); + AddComponent(tmp, engine); + engine.IdleController.RequestPort = clutch.IdleControlPort; - var vehicleData = CreateVehicleData(33000.SI<Kilogram>()); + var gbx = new MockGearbox(vehicleContainer); + gbx.Gear = 1; - var driverData = CreateDriverData(); + var driverPort = driver.OutPort(); - var modalWriter = new ModalDataWriter("Coach_MinimalPowertrain_Coasting.vmod"); - var vehicleContainer = new VehicleContainer(modalWriter); + var gradient = VectoMath.InclinationToAngle(-0.020237973 / 100.0); + var velocity = 5.SI<MeterPerSecond>(); + driverPort.Initialize(velocity, gradient); - var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); - var engine = new CombustionEngine(vehicleContainer, engineData); - var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); + var absTime = 0.SI<Second>(); - dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); - tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); - tmp = AddComponent(tmp, clutch); - AddComponent(tmp, engine); - engine.IdleController.RequestPort = clutch.IdleControlPort; + var response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, gradient); - var gbx = new MockGearbox(vehicleContainer); - gbx.Gear = 1; + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - var driverPort = driver.OutPort(); + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; - var gradient = VectoMath.InclinationToAngle(-0.020237973 / 100.0); - var velocity = 5.SI<MeterPerSecond>(); - driverPort.Initialize(velocity, gradient); + Assert.AreEqual(4.9812, vehicleContainer.VehicleSpeed.Value(), Tolerance); + Assert.AreEqual(0.2004, response.SimulationInterval.Value(), Tolerance); + Assert.AreEqual(engine.PreviousState.FullDragPower.Value(), engine.PreviousState.EnginePower.Value(), + Constants.SimulationSettings.EnginePowerSearchTolerance.Value()); - var absTime = 0.SI<Second>(); + while (vehicleContainer.VehicleSpeed > 1) { + response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, gradient); - var response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, gradient); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; + modalWriter.Finish(VectoRun.Status.Success); + } + modalWriter.Finish(VectoRun.Status.Success); + } - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; + [TestMethod] + public void DriverOverloadTest() + { + var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); - Assert.AreEqual(4.9812, vehicleContainer.VehicleSpeed.Value(), Tolerance); - Assert.AreEqual(0.2004, response.SimulationInterval.Value(), Tolerance); - Assert.AreEqual(engine.PreviousState.FullDragPower.Value(), engine.PreviousState.EnginePower.Value(), - Constants.SimulationSettings.EnginePowerSearchTolerance.Value()); + var vehicleData = CreateVehicleData(33000.SI<Kilogram>()); - while (vehicleContainer.VehicleSpeed > 1) { - response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, gradient); + var driverData = CreateDriverData(); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + var modalWriter = new ModalDataWriter("Coach_MinimalPowertrain.vmod", + SimulatorFactory.FactoryMode.EngineeringMode); + var vehicleContainer = new VehicleContainer(modalWriter); - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; - modalWriter.Finish(VectoRun.Status.Success); - } - modalWriter.Finish(VectoRun.Status.Success); - } + var cycle = new MockDrivingCycle(vehicleContainer, null); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); - [TestMethod] - public void DriverOverloadTest() - { - var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile); + dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); + tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); + var engine = new CombustionEngine(vehicleContainer, engineData); + var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); + engine.IdleController.RequestPort = clutch.IdleControlPort; + tmp = AddComponent(tmp, clutch); + AddComponent(tmp, engine); - var vehicleData = CreateVehicleData(33000.SI<Kilogram>()); + var gbx = new MockGearbox(vehicleContainer); - var driverData = CreateDriverData(); + var driverPort = driver.OutPort(); - var modalWriter = new ModalDataWriter("Coach_MinimalPowertrain.vmod", - SimulatorFactory.FactoryMode.EngineeringMode); - var vehicleContainer = new VehicleContainer(modalWriter); + driverPort.Initialize(0.SI<MeterPerSecond>(), 0.SI<Radian>()); - var cycle = new MockDrivingCycle(vehicleContainer, null); + var absTime = 0.SI<Second>(); - var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); + var response = driverPort.Request(absTime, 1.SI<Meter>(), 10.SI<MeterPerSecond>(), 0.SI<Radian>()); - dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); - tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); - var engine = new CombustionEngine(vehicleContainer, engineData); - var clutch = new Clutch(vehicleContainer, engineData, engine.IdleController); - engine.IdleController.RequestPort = clutch.IdleControlPort; - tmp = AddComponent(tmp, clutch); - AddComponent(tmp, engine); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - var gbx = new MockGearbox(vehicleContainer); + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; - var driverPort = driver.OutPort(); + Assert.AreEqual(0.955, modalWriter.GetValues<SI>(ModalResultField.acc).Last().Value(), Tolerance); - driverPort.Initialize(0.SI<MeterPerSecond>(), 0.SI<Radian>()); + response = driverPort.Request(absTime, 1.SI<Meter>(), 10.SI<MeterPerSecond>(), 0.SI<Radian>()); - var absTime = 0.SI<Second>(); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - var response = driverPort.Request(absTime, 1.SI<Meter>(), 10.SI<MeterPerSecond>(), 0.SI<Radian>()); + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + Assert.AreEqual(0.7914, modalWriter.GetValues<SI>(ModalResultField.acc).Last().Value(), Tolerance); + } - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; + [TestMethod] + public void DriverAccelerationTest() + { + var vehicleContainer = new VehicleContainer(); + var vehicle = new MockVehicle(vehicleContainer); - Assert.AreEqual(0.955, modalWriter.GetValues<SI>(ModalResultField.acc).Last().Value(), Tolerance); + var driverData = EngineeringModeSimulationDataReader.CreateDriverDataFromFile(JobFile); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); - response = driverPort.Request(absTime, 1.SI<Meter>(), 10.SI<MeterPerSecond>(), 0.SI<Radian>()); + var cycle = new MockDrivingCycle(vehicleContainer, null); - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; + driver.Connect(vehicle.OutPort()); - Assert.AreEqual(0.7914, modalWriter.GetValues<SI>(ModalResultField.acc).Last().Value(), Tolerance); - } + vehicle.MyVehicleSpeed = 0.SI<MeterPerSecond>(); + var absTime = 0.SI<Second>(); + var ds = 1.SI<Meter>(); + var gradient = 0.SI<Radian>(); - [TestMethod] - public void DriverAccelerationTest() - { - var vehicleContainer = new VehicleContainer(); - var vehicle = new MockVehicle(vehicleContainer); - - var driverData = EngineeringModeSimulationDataReader.CreateDriverDataFromFile(JobFile); - var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); - - var cycle = new MockDrivingCycle(vehicleContainer, null); - - - driver.Connect(vehicle.OutPort()); - - vehicle.MyVehicleSpeed = 0.SI<MeterPerSecond>(); - var absTime = 0.SI<Second>(); - var ds = 1.SI<Meter>(); - var gradient = 0.SI<Radian>(); - - var targetVelocity = 5.SI<MeterPerSecond>(); + var targetVelocity = 5.SI<MeterPerSecond>(); // var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); - var accelerations = new[] { - 1.01570922, 1.384540943, 1.364944972, 1.350793466, 1.331848649, 1.314995215, 1.2999934, - 1.281996392, 1.255462262 - }; - var simulationIntervals = new[] { - 1.403234648, 0.553054094, 0.405255346, 0.33653593, 0.294559444, 0.26555781, 0.243971311, 0.22711761, - 0.213554656 - }; - + var accelerations = new[] { + 1.01570922, 1.384540943, 1.364944972, 1.350793466, 1.331848649, 1.314995215, 1.2999934, + 1.281996392, 1.255462262 + }; + var simulationIntervals = new[] { + 1.403234648, 0.553054094, 0.405255346, 0.33653593, 0.294559444, 0.26555781, 0.243971311, 0.22711761, + 0.213554656 + }; - // accelerate from 0 to just below the target velocity and test derived simulation intervals & accelerations - for (var i = 0; i < accelerations.Length; i++) { - var tmpResponse = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); - Assert.IsInstanceOfType(tmpResponse, typeof(ResponseSuccess)); - Assert.AreEqual(accelerations[i], vehicle.LastRequest.acceleration.Value(), Tolerance); - Assert.AreEqual(simulationIntervals[i], tmpResponse.SimulationInterval.Value(), Tolerance); + // accelerate from 0 to just below the target velocity and test derived simulation intervals & accelerations + for (var i = 0; i < accelerations.Length; i++) { + var tmpResponse = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); - vehicleContainer.CommitSimulationStep(absTime, tmpResponse.SimulationInterval); - absTime += tmpResponse.SimulationInterval; - vehicle.MyVehicleSpeed += - (tmpResponse.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>(); - } + Assert.IsInstanceOfType(tmpResponse, typeof(ResponseSuccess)); + Assert.AreEqual(accelerations[i], vehicle.LastRequest.acceleration.Value(), Tolerance); + Assert.AreEqual(simulationIntervals[i], tmpResponse.SimulationInterval.Value(), Tolerance); - // full acceleration would exceed target velocity, driver should limit acceleration such that target velocity is reached... - var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); + vehicleContainer.CommitSimulationStep(absTime, tmpResponse.SimulationInterval); + absTime += tmpResponse.SimulationInterval; + vehicle.MyVehicleSpeed += + (tmpResponse.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>(); + } - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - Assert.AreEqual(0.899715479, vehicle.LastRequest.acceleration.Value(), Tolerance); - Assert.AreEqual(0.203734517, response.SimulationInterval.Value(), Tolerance); + // full acceleration would exceed target velocity, driver should limit acceleration such that target velocity is reached... + var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; - vehicle.MyVehicleSpeed += - (response.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>(); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + Assert.AreEqual(0.899715479, vehicle.LastRequest.acceleration.Value(), Tolerance); + Assert.AreEqual(0.203734517, response.SimulationInterval.Value(), Tolerance); - Assert.AreEqual(targetVelocity.Value(), vehicle.MyVehicleSpeed.Value(), Tolerance); + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; + vehicle.MyVehicleSpeed += + (response.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>(); + Assert.AreEqual(targetVelocity.Value(), vehicle.MyVehicleSpeed.Value(), Tolerance); - // vehicle has reached target velocity, no further acceleration necessary... - response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); + // vehicle has reached target velocity, no further acceleration necessary... - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - Assert.AreEqual(0, vehicle.LastRequest.acceleration.Value(), Tolerance); - Assert.AreEqual(0.2, response.SimulationInterval.Value(), Tolerance); - } + response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + Assert.AreEqual(0, vehicle.LastRequest.acceleration.Value(), Tolerance); + Assert.AreEqual(0.2, response.SimulationInterval.Value(), Tolerance); + } - [TestMethod] - public void DriverDecelerationTest() - { - var vehicleContainer = new VehicleContainer(); - var vehicle = new MockVehicle(vehicleContainer); + [TestMethod] + public void DriverDecelerationTest() + { + var vehicleContainer = new VehicleContainer(); + var vehicle = new MockVehicle(vehicleContainer); - var driverData = EngineeringModeSimulationDataReader.CreateDriverDataFromFile(JobFile); - var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); + var driverData = EngineeringModeSimulationDataReader.CreateDriverDataFromFile(JobFile); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); - var cycle = new MockDrivingCycle(vehicleContainer, null); + var cycle = new MockDrivingCycle(vehicleContainer, null); - driver.Connect(vehicle.OutPort()); + driver.Connect(vehicle.OutPort()); - vehicle.MyVehicleSpeed = 5.SI<MeterPerSecond>(); - var absTime = 0.SI<Second>(); - var ds = 1.SI<Meter>(); - var gradient = 0.SI<Radian>(); + vehicle.MyVehicleSpeed = 5.SI<MeterPerSecond>(); + var absTime = 0.SI<Second>(); + var ds = 1.SI<Meter>(); + var gradient = 0.SI<Radian>(); - var targetVelocity = 0.SI<MeterPerSecond>(); + var targetVelocity = 0.SI<MeterPerSecond>(); // var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); - var accelerations = new[] { - -0.68799597, -0.690581291, -0.693253225, -0.696020324, -0.698892653, -0.701882183, -0.695020765, - -0.677731071, - -0.660095846, -0.642072941, -0.623611107, -0.604646998, -0.58510078, -0.56497051, -0.547893288, - -0.529859078, - -0.510598641, -0.489688151, -0.466386685, -0.425121905 - }; - var simulationIntervals = new[] { - 0.202830428, 0.20884052, 0.215445127, 0.222749141, 0.230885341, 0.240024719, 0.250311822, 0.26182762, - 0.274732249, - 0.289322578, 0.305992262, 0.325276486, 0.34792491, 0.37502941, 0.408389927, 0.451003215, 0.5081108, - 0.590388012, - 0.724477573, 1.00152602 - }; - - - // accelerate from 0 to just below the target velocity and test derived simulation intervals & accelerations - for (var i = 0; i < accelerations.Length; i++) { - var tmpResponse = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); - - Assert.IsInstanceOfType(tmpResponse, typeof(ResponseSuccess)); - Assert.AreEqual(accelerations[i], vehicle.LastRequest.acceleration.Value(), Tolerance); - Assert.AreEqual(simulationIntervals[i], tmpResponse.SimulationInterval.Value(), Tolerance); - - vehicleContainer.CommitSimulationStep(absTime, tmpResponse.SimulationInterval); - absTime += tmpResponse.SimulationInterval; - vehicle.MyVehicleSpeed += - (tmpResponse.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>(); - } - - var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); - - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - Assert.AreEqual(-0.308576594, vehicle.LastRequest.acceleration.Value(), Tolerance); - Assert.AreEqual(2.545854078, response.SimulationInterval.Value(), Tolerance); - - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - //absTime += response.SimulationInterval; - vehicle.MyVehicleSpeed += - (response.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>(); - - Assert.AreEqual(targetVelocity.Value(), vehicle.MyVehicleSpeed.Value(), Tolerance); - } - - - //================== - - private static VehicleData CreateVehicleData(Kilogram loading) - { - var axles = new List<Axle> { - new Axle { - AxleWeightShare = 0.4375, - Inertia = 21.66667.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0055, - TwinTyres = false, - TyreTestLoad = 62538.75.SI<Newton>() - }, - new Axle { - AxleWeightShare = 0.375, - Inertia = 10.83333.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0065, - TwinTyres = false, - TyreTestLoad = 52532.55.SI<Newton>() - }, - new Axle { - AxleWeightShare = 0.1875, - Inertia = 21.66667.SI<KilogramSquareMeter>(), - RollResistanceCoefficient = 0.0055, - TwinTyres = false, - TyreTestLoad = 62538.75.SI<Newton>() - } - }; - return new VehicleData { - AxleConfiguration = AxleConfiguration.AxleConfig_4x2, - AerodynamicDragAera = 3.2634.SI<SquareMeter>(), - //CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection, - CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), - CurbWeight = 15700.SI<Kilogram>(), - CurbWeigthExtra = 0.SI<Kilogram>(), - Loading = loading, - DynamicTyreRadius = 0.52.SI<Meter>(), - Retarder = new RetarderData { Type = RetarderData.RetarderType.None }, - AxleData = axles, - SavedInDeclarationMode = false, - }; - } - - private static DriverData CreateDriverData() - { - return new DriverData { - AccelerationCurve = AccelerationCurveData.ReadFromFile(AccelerationFile), - LookAheadCoasting = new DriverData.LACData { - Enabled = false, - Deceleration = -0.5.SI<MeterPerSquareSecond>() - }, - OverSpeedEcoRoll = new DriverData.OverSpeedEcoRollData { - Mode = DriverData.DriverMode.Off - }, - StartStop = new VectoRunData.StartStopData { - Enabled = false, - } - }; - } - - - // ======================== - - protected virtual IDriver AddComponent(IDrivingCycle prev, IDriver next) - { - prev.InPort().Connect(next.OutPort()); - return next; - } - - protected virtual IVehicle AddComponent(IDriver prev, IVehicle next) - { - prev.InPort().Connect(next.OutPort()); - return next; - } - - protected virtual IWheels AddComponent(IFvInProvider prev, IWheels next) - { - prev.InPort().Connect(next.OutPort()); - return next; - } - - - protected virtual ITnOutProvider AddComponent(IWheels prev, ITnOutProvider next) - { - prev.InPort().Connect(next.OutPort()); - return next; - } - - protected virtual IPowerTrainComponent AddComponent(IPowerTrainComponent prev, IPowerTrainComponent next) - { - prev.InPort().Connect(next.OutPort()); - return next; - } - - protected virtual void AddComponent(IPowerTrainComponent prev, ITnOutProvider next) - { - prev.InPort().Connect(next.OutPort()); - } - } + var accelerations = new[] { + -0.68799597, -0.690581291, -0.693253225, -0.696020324, -0.698892653, -0.701882183, -0.695020765, + -0.677731071, + -0.660095846, -0.642072941, -0.623611107, -0.604646998, -0.58510078, -0.56497051, -0.547893288, + -0.529859078, + -0.510598641, -0.489688151, -0.466386685, -0.425121905 + }; + var simulationIntervals = new[] { + 0.202830428, 0.20884052, 0.215445127, 0.222749141, 0.230885341, 0.240024719, 0.250311822, 0.26182762, + 0.274732249, + 0.289322578, 0.305992262, 0.325276486, 0.34792491, 0.37502941, 0.408389927, 0.451003215, 0.5081108, + 0.590388012, + 0.724477573, 1.00152602 + }; + + + // accelerate from 0 to just below the target velocity and test derived simulation intervals & accelerations + for (var i = 0; i < accelerations.Length; i++) { + var tmpResponse = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); + + Assert.IsInstanceOfType(tmpResponse, typeof(ResponseSuccess)); + Assert.AreEqual(accelerations[i], vehicle.LastRequest.acceleration.Value(), Tolerance); + Assert.AreEqual(simulationIntervals[i], tmpResponse.SimulationInterval.Value(), Tolerance); + + vehicleContainer.CommitSimulationStep(absTime, tmpResponse.SimulationInterval); + absTime += tmpResponse.SimulationInterval; + vehicle.MyVehicleSpeed += + (tmpResponse.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>(); + } + + var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient); + + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + Assert.AreEqual(-0.308576594, vehicle.LastRequest.acceleration.Value(), Tolerance); + Assert.AreEqual(2.545854078, response.SimulationInterval.Value(), Tolerance); + + vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); + //absTime += response.SimulationInterval; + vehicle.MyVehicleSpeed += + (response.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>(); + + Assert.AreEqual(targetVelocity.Value(), vehicle.MyVehicleSpeed.Value(), Tolerance); + } + + //================== + + private static VehicleData CreateVehicleData(Kilogram loading) + { + var axles = new List<Axle> { + new Axle { + AxleWeightShare = 0.4375, + Inertia = 21.66667.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0055, + TwinTyres = false, + TyreTestLoad = 62538.75.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.375, + Inertia = 10.83333.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0065, + TwinTyres = false, + TyreTestLoad = 52532.55.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.1875, + Inertia = 21.66667.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.0055, + TwinTyres = false, + TyreTestLoad = 62538.75.SI<Newton>() + } + }; + return new VehicleData { + AxleConfiguration = AxleConfiguration.AxleConfig_4x2, + AerodynamicDragAera = 3.2634.SI<SquareMeter>(), + //CrossWindCorrectionMode = CrossWindCorrectionMode.NoCorrection, + CrossWindCorrectionCurve = CrossWindCorrectionCurve.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), + CurbWeight = 15700.SI<Kilogram>(), + CurbWeigthExtra = 0.SI<Kilogram>(), + Loading = loading, + DynamicTyreRadius = 0.52.SI<Meter>(), + Retarder = new RetarderData { Type = RetarderData.RetarderType.None }, + AxleData = axles, + SavedInDeclarationMode = false + }; + } + + private static DriverData CreateDriverData() + { + return new DriverData { + AccelerationCurve = AccelerationCurveData.ReadFromFile(AccelerationFile), + LookAheadCoasting = new DriverData.LACData { + Enabled = false, + Deceleration = -0.5.SI<MeterPerSquareSecond>() + }, + OverSpeedEcoRoll = new DriverData.OverSpeedEcoRollData { + Mode = DriverData.DriverMode.Off + }, + StartStop = new VectoRunData.StartStopData { + Enabled = false + } + }; + } + + // ======================== + + protected virtual IDriver AddComponent(IDrivingCycle prev, IDriver next) + { + prev.InPort().Connect(next.OutPort()); + return next; + } + + protected virtual IVehicle AddComponent(IDriver prev, IVehicle next) + { + prev.InPort().Connect(next.OutPort()); + return next; + } + + protected virtual IWheels AddComponent(IFvInProvider prev, IWheels next) + { + prev.InPort().Connect(next.OutPort()); + return next; + } + + protected virtual ITnOutProvider AddComponent(IWheels prev, ITnOutProvider next) + { + prev.InPort().Connect(next.OutPort()); + return next; + } + + protected virtual IPowerTrainComponent AddComponent(IPowerTrainComponent prev, IPowerTrainComponent next) + { + prev.InPort().Connect(next.OutPort()); + return next; + } + + protected virtual void AddComponent(IPowerTrainComponent prev, ITnOutProvider next) + { + prev.InPort().Connect(next.OutPort()); + } + } } \ No newline at end of file diff --git a/VectoCoreTest/Models/SimulationComponent/VehicleTest.cs b/VectoCoreTest/Models/SimulationComponent/VehicleTest.cs index 13cee11c4544f3e04d1cb7c562ad1688e986f9dd..2e9585604ecbb1a01080806c529703a8114b1ef1 100644 --- a/VectoCoreTest/Models/SimulationComponent/VehicleTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/VehicleTest.cs @@ -1,10 +1,12 @@ using System; +using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.FileIO.Reader.DataObjectAdaper; using TUGraz.VectoCore.FileIO.Reader.Impl; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Utils; @@ -121,5 +123,58 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent vehicle.CommitSimulationStep(writer); Assert.AreEqual(49735.26379, ((SI)writer[ModalResultField.Pair]).Value(), 0.1); } + + [TestMethod] + public void VehicleAirDragSpeedDependentTest() + { + var data = new[] { + "v_veh in km/h,Cd factor in -", + "0,1.173 ", + "5,1.173 ", + "10,1.173", + "15,1.173", + "20,1.173", + "25,1.173", + "30,1.173", + "35,1.173", + "40,1.173", + "45,1.173", + "50,1.173", + "55,1.173", + "60,1.173", + "65,1.153", + "70,1.136", + "75,1.121", + "80,1.109", + "85,1.099", + "90,1.090", + "95,1.082", + "100,1.075" + }; + var correctionData = new MemoryStream(); + var writer = new StreamWriter(correctionData); + foreach (var entry in data) { + writer.WriteLine(entry); + } + writer.Flush(); + correctionData.Seek(0, SeekOrigin.Begin); + + var crossSectionArea = 5.19.SI<SquareMeter>(); + var cwcc = CrossWindCorrectionCurve.ReadSpeedDependentCorrectionCurveFromStream(correctionData, crossSectionArea); + + Assert.AreEqual(crossSectionArea.Value() * 1.173, cwcc.EffectiveAirDragArea(0.KMPHtoMeterPerSecond()).Value(), + Tolerance); + Assert.AreEqual(crossSectionArea.Value() * 1.173, cwcc.EffectiveAirDragArea(40.KMPHtoMeterPerSecond()).Value(), + Tolerance); + Assert.AreEqual(crossSectionArea.Value() * 1.173, cwcc.EffectiveAirDragArea(60.KMPHtoMeterPerSecond()).Value(), + Tolerance); + Assert.AreEqual(crossSectionArea.Value() * 1.109, cwcc.EffectiveAirDragArea(80.KMPHtoMeterPerSecond()).Value(), + Tolerance); + Assert.AreEqual(crossSectionArea.Value() * 1.075, cwcc.EffectiveAirDragArea(100.KMPHtoMeterPerSecond()).Value(), + Tolerance); + + Assert.AreEqual(crossSectionArea.Value() * 1.163, cwcc.EffectiveAirDragArea(62.5.KMPHtoMeterPerSecond()).Value(), + Tolerance); + } } } \ No newline at end of file