Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS has been phased out. To see alternatives please check here

Skip to content
Snippets Groups Projects
Select Git revision
  • 66328e2e3a2d7ad1586d07e4146a75c70dfba6a5
  • stable default
  • feat-fchv-bus
  • fix-h2-ice-bus
  • powertrains-multiple-axles
  • amdm3/develop
  • issue-1039
  • amdm3/main
  • test/nuget_publish
  • IEPC-experiments
  • amdm2/main
  • amdm2/develop
  • aptngearbox-not-auto
  • playground
  • official/main
  • official/develop
  • issue-templates
  • pdf-reports
  • HEV-timeruns-dev
  • timerun-empower-hybrids
  • timerun-pwheel-hybrids
  • Release/v5.0.3
  • Release/v5.0.1
  • Release/5.0.0-RC
  • Nuget/v0.11.4-DEV
  • Release/v0.11.4-DEV
  • Release/4.3.4-DEV
  • Release/4.3.3
  • Release/4.3.2-RC
  • Release/v4.3.0-DEV
  • Release/4.2.7
  • XMLConverterTool/4.2.6.0
  • Release/4.2.6-RC
  • Release/v4.2.5
  • Release/v4.2.3
  • Release/v4.2.2.3539-RC
  • Release/v4.2.1.3469
  • Release/v0.11.2.3456-DEV
  • Release/v4.2.0.3448-RC
  • Release/v4.1.3.3415
  • Release/v4.1.1.3413
41 results

VehicleData.cs

Blame
  • Forked from VECTO / VECTO Sim
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    DeclarationData.cs 16.53 KiB
    /*
    * This file is part of VECTO.
    *
    * Copyright © 2012-2016 European Union
    *
    * Developed by Graz University of Technology,
    *              Institute of Internal Combustion Engines and Thermodynamics,
    *              Institute of Technical Informatics
    *
    * VECTO is licensed under the EUPL, Version 1.1 or - as soon they will be approved
    * by the European Commission - subsequent versions of the EUPL (the "Licence");
    * You may not use VECTO except in compliance with the Licence.
    * You may obtain a copy of the Licence at:
    *
    * https://joinup.ec.europa.eu/community/eupl/og_page/eupl
    *
    * Unless required by applicable law or agreed to in writing, VECTO
    * distributed under the Licence is distributed on an "AS IS" basis,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the Licence for the specific language governing permissions and
    * limitations under the Licence.
    *
    * Authors:
    *   Stefan Hausberger, hausberger@ivt.tugraz.at, IVT, Graz University of Technology
    *   Christian Kreiner, christian.kreiner@tugraz.at, ITI, Graz University of Technology
    *   Michael Krisper, michael.krisper@tugraz.at, ITI, Graz University of Technology
    *   Raphael Luz, luz@ivt.tugraz.at, IVT, Graz University of Technology
    *   Markus Quaritsch, markus.quaritsch@tugraz.at, IVT, Graz University of Technology
    *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
    */
    
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using TUGraz.VectoCommon.Exceptions;
    using TUGraz.VectoCommon.InputData;
    using TUGraz.VectoCommon.Models;
    using TUGraz.VectoCommon.Utils;
    using TUGraz.VectoCore.InputData.Reader.ComponentData;
    using TUGraz.VectoCore.Models.SimulationComponent.Data;
    using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine;
    using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox;
    using TUGraz.VectoCore.Utils;
    
    namespace TUGraz.VectoCore.Models.Declaration
    {
    	public static class DeclarationData
    	{
    		public const string DeclarationDataResourcePrefix = "TUGraz.VectoCore.Resources.Declaration";
    
    		public static readonly Watt MinEnginePowerForEMS = 300e3.SI<Watt>();
    
    		public static readonly Segments Segments = new Segments();
    		public static readonly Wheels Wheels = new Wheels();
    		public static readonly PT1 PT1 = new PT1();
    		public static readonly FuelData FuelData = FuelData.Instance();
    		public static readonly ElectricSystem ElectricSystem = new ElectricSystem();
    		public static readonly Fan Fan = new Fan();
    
    		public static readonly HeatingVentilationAirConditioning HeatingVentilationAirConditioning =
    			new HeatingVentilationAirConditioning();
    
    		public static readonly PneumaticSystem PneumaticSystem = new PneumaticSystem();
    		public static readonly SteeringPump SteeringPump = new SteeringPump();
    		public static readonly WHTCCorrection WHTCCorrection = new WHTCCorrection();
    		public static readonly AirDrag AirDrag = new AirDrag();
    		public static readonly StandardBodies StandardBodies = new StandardBodies();
    		public static readonly Payloads Payloads = new Payloads();
    		public static readonly PTOTransmission PTOTransmission = new PTOTransmission();
    
    		/// <summary>
    		/// Formula for calculating the payload for a given gross vehicle weight.
    		/// (so called "pc-formula", Whitebook Apr 2016, Part 1, p.187)
    		/// </summary>
    		public static Kilogram GetPayloadForGrossVehicleWeight(Kilogram grossVehicleWeight, string equationName)
    		{
    			if (equationName.ToLower().StartsWith("pc10")) {
    				return Payloads.Lookup10Percent(grossVehicleWeight);
    			}
    			if (equationName.ToLower().StartsWith("pc75")) {
    				return Payloads.Lookup75Percent(grossVehicleWeight);
    			}
    			return Payloads.Lookup50Percent(grossVehicleWeight);
    		}
    
    		/// <summary>
    		/// Returns the payload for a trailer. This is 75% of (GVW-CurbWeight).
    		/// </summary>
    		public static Kilogram GetPayloadForTrailerWeight(Kilogram grossVehicleWeight, Kilogram curbWeight, bool lowLoading)
    		{
    			return Payloads.LookupTrailer(grossVehicleWeight, curbWeight) / (lowLoading ? 7.5 : 1);
    		}
    
    		public static int PoweredAxle()
    		{
    			return 1;
    		}
    
    
    		public static class Driver
    		{
    			public static class LookAhead
    			{
    				public const bool Enabled = true;
    
    				public const double DecisionFactorCoastingOffset = 2.5;
    				public const double DecisionFactorCoastingScaling = 1.5;
    				public const double LookAheadDistanceFactor = 10;
    				public static readonly MeterPerSecond MinimumSpeed = 50.KMPHtoMeterPerSecond();
    			}
    
    			public static class OverSpeedEcoRoll
    			{
    				public static readonly IList<DriverMode> AllowedModes = new List<DriverMode> {
    					DriverMode.EcoRoll,
    					DriverMode.Overspeed
    				};
    
    				public static readonly MeterPerSecond MinSpeed = 50.KMPHtoMeterPerSecond();
    				public static readonly MeterPerSecond OverSpeed = 5.KMPHtoMeterPerSecond();
    				public static readonly MeterPerSecond UnderSpeed = 5.KMPHtoMeterPerSecond();
    			}
    
    			//public static class StartStop
    			//{
    			//	public static readonly MeterPerSecond MaxSpeed = 5.KMPHtoMeterPerSecond();
    			//	public static readonly Second Delay = 5.SI<Second>();
    			//	public static readonly Second MinTime = 5.SI<Second>();
    			//}
    		}
    
    		public static class Trailer
    		{
    			public const double RollResistanceCoefficient = 0.0055;
    			public const double TyreTestLoad = 37500;
    
    			public const bool TwinTyres = false;
    			//public const string WheelsType = "385/65 R 22.5";
    		}
    
    		public static class Engine
    		{
    			public static readonly KilogramSquareMeter ClutchInertia = 1.3.SI<KilogramSquareMeter>();
    			public static readonly KilogramSquareMeter TorqueConverterInertia = 1.2.SI<KilogramSquareMeter>();
    
    			public static readonly KilogramSquareMeter EngineBaseInertia = 0.41.SI<KilogramSquareMeter>();
    			public static readonly SI EngineDisplacementInertia = (0.27 * 1000).SI().Kilo.Gramm.Per.Meter; // [kg/m]
    
    			public const double TorqueLimitGearboxFactor = 0.9;
    			public const double TorqueLimitVehicleFactor = 0.95;
    
    			public static KilogramSquareMeter EngineInertia(CubicMeter displacement, GearboxType gbxType)
    			{
    				// VB Code:    Return 1.3 + 0.41 + 0.27 * (Displ / 1000)
    				return (gbxType.AutomaticTransmission() ? TorqueConverterInertia : ClutchInertia) + EngineBaseInertia +
    						EngineDisplacementInertia * displacement;
    			}
    		}
    
    		public static class Gearbox
    		{
    			public const double TorqueReserve = 0.2;
    			public const double TorqueReserveStart = 0.2;
    			public static readonly MeterPerSecond StartSpeed = 1.3.SI<MeterPerSecond>();
    			public static readonly MeterPerSquareSecond StartAcceleration = 0.6.SI<MeterPerSquareSecond>();
    			public static readonly KilogramSquareMeter Inertia = 0.SI<KilogramSquareMeter>();
    
    			public static readonly MeterPerSecond TruckMaxAllowedSpeed = 85.KMPHtoMeterPerSecond();
    			public const double ShiftPolygonRPMMargin = 7; // %
    			private const double ShiftPolygonEngineFldMargin = 0.98;
    
    			public static readonly Second MinTimeBetweenGearshifts = 1.5.SI<Second>();
    			public static readonly Second DownshiftAfterUpshiftDelay = 10.SI<Second>();
    			public static readonly Second UpshiftAfterDownshiftDelay = 10.SI<Second>();
    
    			public static readonly MeterPerSquareSecond UpshiftMinAcceleration = 0.1.SI<MeterPerSquareSecond>();
    
    			//public static readonly PerSecond TorqueConverterSpeedLimit = 1600.RPMtoRad();
    			public static readonly double TorqueConverterSecondGearThreshold = 1.8;
    
    			/// <summary>
    			/// computes the shift polygons for a single gear according to the whitebook 2016
    			/// </summary>
    			/// <param name="gearIdx">index of the gear to compute the shift polygons for  -- gear number - 1!</param>
    			/// <param name="fullLoadCurve">engine full load curve, potentially limited by the gearbox</param>
    			/// <param name="gears">list of gears</param>
    			/// <param name="engine">engine data</param>
    			/// <param name="axlegearRatio"></param>
    			/// <param name="dynamicTyreRadius"></param>
    			/// <returns></returns>
    			public static ShiftPolygon ComputeShiftPolygon(int gearIdx, EngineFullLoadCurve fullLoadCurve,
    				IList<ITransmissionInputData> gears, CombustionEngineData engine, double axlegearRatio, Meter dynamicTyreRadius)
    			{
    				if (gears.Count < 2) {
    					throw new VectoException("ComputeShiftPolygon needs at least 2 gears. {0} gears given.", gears.Count);
    				}
    
    				// ReSharper disable once InconsistentNaming
    				var engineSpeed85kmhLastGear = ComputeEngineSpeed85kmh(gears[gears.Count - 1], axlegearRatio, dynamicTyreRadius);
    
    				var nVHigh = VectoMath.Min(engineSpeed85kmhLastGear, engine.FullLoadCurves[0].RatedSpeed);
    
    				var diffRatio = gears[gears.Count - 2].Ratio / gears[gears.Count - 1].Ratio - 1;
    
    				var maxDragTorque = fullLoadCurve.MaxDragTorque * 1.1;
    
    				var p1 = new Point(engine.IdleSpeed.Value() / 2, 0);
    				var p2 = new Point(engine.IdleSpeed.Value() * 1.1, 0);
    				var p3 = new Point(nVHigh.Value() * 0.9,
    					fullLoadCurve.FullLoadStationaryTorque(nVHigh * 0.9).Value());
    
    				var p4 =
    					new Point((nVHigh * (1 + diffRatio / 3)).Value(), 0);
    				var p5 = new Point(fullLoadCurve.N95hSpeed.Value(), fullLoadCurve.MaxTorque.Value());
    
    				var p6 = new Point(p2.X, VectoMath.Interpolate(p1, p3, p2.X));
    				var p7 = new Point(p4.X, VectoMath.Interpolate(p2, p5, p4.X));
    
    				var fldMargin = ShiftPolygonFldMargin(fullLoadCurve.FullLoadEntries, (p3.X * 0.95).SI<PerSecond>());
    				var downshiftCorr = MoveDownshiftBelowFld(Edge.Create(p6, p3), fldMargin, 1.1 * fullLoadCurve.MaxTorque);
    
    				var downShift = new List<ShiftPolygon.ShiftPolygonEntry>();
    				if (gearIdx > 0) {
    					downShift =
    						new[] { p2, downshiftCorr.P1, downshiftCorr.P2 }.Select(
    							point => new ShiftPolygon.ShiftPolygonEntry() {
    								AngularSpeed = point.X.SI<PerSecond>(),
    								Torque = point.Y.SI<NewtonMeter>()
    							})
    							.ToList();
    
    					downShift[0].Torque = maxDragTorque;
    				}
    				var upShift = new List<ShiftPolygon.ShiftPolygonEntry>();
    				if (gearIdx >= gears.Count - 1) {
    					return new ShiftPolygon(downShift, upShift);
    				}
    
    				var gearRatio = gears[gearIdx].Ratio / gears[gearIdx + 1].Ratio;
    				var rpmMarginFactor = 1 + ShiftPolygonRPMMargin / 100.0;
    
    				// ReSharper disable InconsistentNaming
    				var p2p = new Point(p2.X * gearRatio * rpmMarginFactor, p2.Y / gearRatio);
    				var p3p = new Point(p3.X * gearRatio * rpmMarginFactor, p3.Y / gearRatio);
    				var p6p = new Point(p6.X * gearRatio * rpmMarginFactor, p6.Y / gearRatio);
    				var edgeP6pP3p = new Edge(p6p, p3p);
    				var p3pExt = new Point((1.1 * p5.Y - edgeP6pP3p.OffsetXY) / edgeP6pP3p.SlopeXY, 1.1 * p5.Y);
    				// ReSharper restore InconsistentNaming
    
    				upShift = IntersectShiftPolygon(new[] { p4, p7, p5 }.ToList(), new[] { p2p, p6p, p3pExt }.ToList())
    					.Select(point => new ShiftPolygon.ShiftPolygonEntry() {
    						AngularSpeed = point.X.SI<PerSecond>(),
    						Torque = point.Y.SI<NewtonMeter>()
    					})
    					.ToList();
    				upShift[0].Torque = maxDragTorque;
    				return new ShiftPolygon(downShift, upShift);
    			}
    
    			/// <summary>
    			/// ensures the original downshift line is below the (already reduced) full-load curve
    			/// </summary>
    			/// <param name="shiftLine">second part of the shift polygon (slope)</param>
    			/// <param name="fldMargin">reduced full-load curve</param>
    			/// <param name="maxTorque">max torque</param>
    			/// <returns>returns a corrected shift polygon segment (slope) that is below the full load curve and reaches given maxTorque. the returned segment has the same slope</returns>
    			internal static Edge MoveDownshiftBelowFld(Edge shiftLine, IEnumerable<Point> fldMargin, NewtonMeter maxTorque)
    			{
    				var slope = shiftLine.SlopeXY;
    				var d = shiftLine.P2.Y - slope * shiftLine.P2.X;
    
    				d = fldMargin.Select(point => point.Y - slope * point.X).Concat(new[] { d }).Min();
    				var p6Corr = new Point(shiftLine.P1.X, shiftLine.P1.X * slope + d);
    				var p3Corr = new Point((maxTorque.Value() - d) / slope, maxTorque.Value());
    				return Edge.Create(p6Corr, p3Corr);
    			}
    
    			/// <summary>
    			/// reduce the torque of the full load curve up to the given rpms
    			/// </summary>
    			/// <param name="fullLoadCurve"></param>
    			/// <param name="rpmLimit"></param>
    			/// <returns></returns>
    			internal static IEnumerable<Point> ShiftPolygonFldMargin(List<FullLoadCurve.FullLoadCurveEntry> fullLoadCurve,
    				PerSecond rpmLimit)
    			{
    				return
    					fullLoadCurve.TakeWhile(fldEntry => fldEntry.EngineSpeed < rpmLimit)
    						.Select(
    							fldEntry =>
    								new Point(fldEntry.EngineSpeed.Value(), fldEntry.TorqueFullLoad.Value() * ShiftPolygonEngineFldMargin))
    						.ToList();
    			}
    
    			// ReSharper disable once InconsistentNaming
    			private static PerSecond ComputeEngineSpeed85kmh(ITransmissionInputData gear, double axleRatio,
    				Meter dynamicTyreRadius)
    			{
    				var engineSpeed = TruckMaxAllowedSpeed / dynamicTyreRadius * axleRatio * gear.Ratio;
    				return engineSpeed;
    			}
    
    			internal static List<Point> IntersectShiftPolygon(List<Point> orig, List<Point> transformedDownshift)
    			{
    				var intersections = new List<Point>();
    				// compute all intersection points between both line segments
    				// ReSharper disable once LoopCanBeConvertedToQuery
    				foreach (var origLine in orig.Pairwise(Edge.Create)) {
    					// ReSharper disable once LoopCanBeConvertedToQuery
    					foreach (var transformedLine in transformedDownshift.Pairwise(Edge.Create)) {
    						var isect = VectoMath.Intersect(origLine, transformedLine);
    						if (isect != null) {
    							intersections.Add(isect);
    						}
    					}
    				}
    
    				// add all points (i.e. intersecting points and both line segments) to a single list
    				var pointSet = new List<Point>(orig);
    				pointSet.AddRange(transformedDownshift);
    				pointSet.AddRange(intersections);
    				pointSet.AddRange(ProjectPointsToLineSegments(orig, transformedDownshift));
    				pointSet.AddRange(ProjectPointsToLineSegments(transformedDownshift, orig));
    
    				// line sweeping from max_X to 0: select point with lowest Y coordinate, abort if a point has Y = 0
    				var shiftPolygon = new List<Point>();
    				foreach (var xCoord in pointSet.Select(pt => pt.X).Distinct().OrderBy(x => x).Reverse()) {
    					var coord = xCoord;
    					var xPoints = pointSet.Where(pt => pt.X.IsEqual(coord) && !pt.Y.IsEqual(0)).ToList();
    					shiftPolygon.Add(xPoints.MinBy(pt => pt.Y));
    					var tmp = pointSet.Where(pt => pt.X.IsEqual(coord)).Where(pt => pt.Y.IsEqual(0)).ToList();
    					if (!tmp.Any()) {
    						continue;
    					}
    					shiftPolygon.Add(tmp.First());
    					break;
    				}
    
    				// find and remove colinear points
    				var toRemove = new List<Point>();
    				for (var i = 0; i < shiftPolygon.Count - 2; i++) {
    					var edge = new Edge(shiftPolygon[i], shiftPolygon[i + 2]);
    					if (edge.ContainsXY(shiftPolygon[i + 1])) {
    						toRemove.Add(shiftPolygon[i + 1]);
    					}
    				}
    				foreach (var point in toRemove) {
    					shiftPolygon.Remove(point);
    				}
    
    				// order points first by x coordinate and the by Y coordinate ASC
    				return shiftPolygon.OrderBy(pt => pt.X).ThenBy(pt => pt.Y).ToList();
    			}
    
    			private static List<Point> ProjectPointsToLineSegments(List<Point> lineSegments, List<Point> points)
    			{
    				var pointSet = new List<Point>();
    				foreach (var segment in lineSegments.Pairwise(Edge.Create)) {
    					if (segment.P1.X.IsEqual(segment.P2.X)) {
    						continue;
    					}
    					var k = segment.SlopeXY;
    					var d = segment.P1.Y - segment.P1.X * k;
    					pointSet.AddRange(points.Select(point => new Point(point.X, point.X * k + d)));
    				}
    				return pointSet;
    			}
    
    			public static IEnumerable<TorqueConverterEntry> GetTorqueConverterDragCurve(double ratio)
    			{
    				var resourceId = DeclarationData.DeclarationDataResourcePrefix + ".TorqueConverter.csv";
    				var data = VectoCSVFile.ReadStream(RessourceHelper.ReadStream(resourceId), source: resourceId);
    				var characteristicTorque = (from DataRow row in data.Rows
    					select
    						new TorqueConverterEntry() {
    							SpeedRatio = row.ParseDouble(TorqueConverterDataReader.Fields.SpeedRatio),
    							Torque = row.ParseDouble(TorqueConverterDataReader.Fields.CharacteristicTorque).SI<NewtonMeter>(),
    							TorqueRatio = row.ParseDouble(TorqueConverterDataReader.Fields.TorqueRatio)
    						}).ToArray();
    				foreach (var torqueConverterEntry in characteristicTorque) {
    					torqueConverterEntry.SpeedRatio = torqueConverterEntry.SpeedRatio * ratio;
    					torqueConverterEntry.TorqueRatio = torqueConverterEntry.TorqueRatio / ratio;
    				}
    				return characteristicTorque.Where(x => x.SpeedRatio >= ratio).ToArray();
    			}
    		}
    
    		public static class PTO
    		{
    			public const string DefaultPTOTechnology =
    				"only the drive shaft of the PTO - shift claw, synchronizer, sliding gearwheel";
    
    			public const string DefaultPTOIdleLosses =
    				DeclarationDataResourcePrefix + ".MissionCycles.MunicipalUtility_PTO_generic.vptol";
    
    			public const string DefaultPTOActivationCycle =
    				DeclarationDataResourcePrefix + ".MissionCycles.MunicipalUtility_PTO_generic.vptoc";
    		}
    	}
    }