Code development platform for open source projects from the European Union institutions

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

Merge pull request #66 in VECTO/vecto-sim from...

Merge pull request #66 in VECTO/vecto-sim from ~EMQUARIMA/vecto-sim:feature/VECTO-70-wheels-engine-only-driving-cycle to develop

* commit '4f9f344c': (21 commits)
  update repository
  driving the whole test-cycle works (~17km), results are similar to vecto 2.2
  disabled logging to file in test environment
  simple cycle works for 11km and result is simiar to vecto2
  use new SI functionality
  bugfix in transmission loss map: wrong torque limit!
  additional component in powertrain (breaks) - correct testcase
  more debugging, difference vecto2?
  add powerdemand of main components in response object add ClutchInfo Interface add Breaks (also to PowertrainBuilder)
  - refactor Dry-Run Response to use SI Units - introduce Breaks, IBreaks interface - bugfix gearbox transmissionlossmap lookup - add tons of logging to trace driving behavior - Driver: handling of lookahead info - Driver: breaking (to be tested!)
  more work on driver model: lookahead
  drivingcycle lookahead
  include method to calculate deceleration distance for lookahead (breaking)
  testcase to show bug in SI-unit (VECTO-111)
  some testcases to improve coverage
  introduce combustion engine model for engine-only cycles (handling of overload situations) introduce minimum acceleration in driver model (abort otherwise) interpretation of driving cycle (stop-time + increase distance), altitude computation make all testcases green...
  abort simulation if a minimum acceleration can not be reached
  move constant to SimulationSettings class
  coasting test works until almost halt of vehicle (<1m/s)
  implemented coasting in driver model (point of operation search) testcase for coasting
  ...
parents 4966b5c9 4f9f344c
No related branches found
No related tags found
No related merge requests found
Showing
with 278 additions and 61 deletions
......@@ -54,13 +54,20 @@ namespace TUGraz.VectoCore.Configuration
/// threshold for changes in the road gradient. changes below this threshold will be considered to be equal for filtering out the driving cycle.
/// altitude computation is done before filtering!
/// </summary>
public static readonly double DrivingCycleRoadGradientTolerance = 0;
public static readonly double DrivingCycleRoadGradientTolerance = 1E-12;
//VectoMath.InclinationToAngle(0.25 / 100.0).Value();
public const int DriverSearchLoopThreshold = 100;
public const double EngineFLDPowerTolerance = 0.50; // Watt
public const double CluchNormSpeed = 0.03;
public static readonly MeterPerSquareSecond MinimumAcceleration = 0.1.SI<MeterPerSquareSecond>();
public static Meter DriverActionDistanceTolerance = 0.25.SI<Meter>();
}
}
}
\ No newline at end of file
......@@ -14,43 +14,44 @@ namespace TUGraz.VectoCore.FileIO.Reader
public class DrivingCycleDataReader
{
// --- Factory Methods
public static DrivingCycleData ReadFromStream(Stream stream, DrivingCycleData.CycleType type)
public static DrivingCycleData ReadFromStream(Stream stream, CycleType type)
{
return DoReadCycleData(type, VectoCSVFile.ReadStream(stream));
}
public static DrivingCycleData ReadFromFileEngineOnly(string fileName)
{
return ReadFromFile(fileName, DrivingCycleData.CycleType.EngineOnly);
return ReadFromFile(fileName, CycleType.EngineOnly);
}
public static DrivingCycleData ReadFromFileDistanceBased(string fileName)
{
return ReadFromFile(fileName, DrivingCycleData.CycleType.DistanceBased);
return ReadFromFile(fileName, CycleType.DistanceBased);
}
public static DrivingCycleData ReadFromFileTimeBased(string fileName)
{
return ReadFromFile(fileName, DrivingCycleData.CycleType.TimeBased);
return ReadFromFile(fileName, CycleType.TimeBased);
}
public static DrivingCycleData ReadFromFile(string fileName, DrivingCycleData.CycleType type)
public static DrivingCycleData ReadFromFile(string fileName, CycleType type)
{
var retVal = DoReadCycleData(type, VectoCSVFile.Read(fileName));
retVal.Name = Path.GetFileNameWithoutExtension(fileName);
return retVal;
}
private static DrivingCycleData DoReadCycleData(DrivingCycleData.CycleType type, DataTable data)
private static DrivingCycleData DoReadCycleData(CycleType type, DataTable data)
{
var parser = CreateDataParser(type);
var entries = parser.Parse(data).ToList();
if (type == DrivingCycleData.CycleType.DistanceBased) {
if (type == CycleType.DistanceBased) {
entries = FilterDrivingCycleEntries(entries);
}
var cycle = new DrivingCycleData {
Entries = entries,
CycleType = type
};
return cycle;
}
......@@ -69,16 +70,29 @@ namespace TUGraz.VectoCore.FileIO.Reader
filtered.Add(current);
var distance = current.Distance;
var altitude = current.Altitude;
foreach (var entry in entries) {
//foreach (var entry in entries) {
for (var i = 0; i < entries.Count; i++) {
var entry = entries[i];
if (i > 0) {
altitude += (entry.Distance - distance) * entries[i - 1].RoadGradientPercent / 100.0;
}
entry.Altitude = altitude;
if (!CycleEntriesAreEqual(current, entry)) {
// if something changes in the cycle, add it to the filtered cycle but always add last entry
if (!CycleEntriesAreEqual(current, entry) || i == entries.Count - 1) {
entry.Altitude = altitude;
filtered.Add(entry);
current = entry;
}
if (entry.StoppingTime.IsEqual(0) && !entry.VehicleTargetSpeed.IsEqual(0)) {
altitude += (entry.Distance - distance) * entry.RoadGradientPercent / 100.0;
if (!entry.StoppingTime.IsEqual(0) && entry.VehicleTargetSpeed.IsEqual(0)) {
// vehicle stops. duplicate current distance entry with 0 waiting time
var tmp = new DrivingCycleData.DrivingCycleEntry(entry) {
StoppingTime = 0.SI<Second>(),
VehicleTargetSpeed = i < entries.Count - 1 ? entries[i + 1].VehicleTargetSpeed : 0.SI<MeterPerSecond>()
};
filtered.Add(tmp);
current = tmp;
}
distance = entry.Distance;
}
log.Info(string.Format("Data loaded. Number of Entries: {0}, filtered Entries: {1}", entries.Count, filtered.Count));
......@@ -128,14 +142,14 @@ namespace TUGraz.VectoCore.FileIO.Reader
return retVal;
}
private static IDataParser CreateDataParser(DrivingCycleData.CycleType type)
private static IDataParser CreateDataParser(CycleType type)
{
switch (type) {
case DrivingCycleData.CycleType.EngineOnly:
case CycleType.EngineOnly:
return new EngineOnlyDataParser();
case DrivingCycleData.CycleType.TimeBased:
case CycleType.TimeBased:
return new TimeBasedDataParser();
case DrivingCycleData.CycleType.DistanceBased:
case CycleType.DistanceBased:
return new DistanceBasedDataParser();
default:
throw new ArgumentOutOfRangeException("type");
......
......@@ -33,7 +33,7 @@ namespace TUGraz.VectoCore.FileIO.Reader.Impl
var driverdata = dao.CreateDriverData(Job);
driverdata.AccelerationCurve = AccelerationCurveData.ReadFromStream(segment.AccelerationFile);
foreach (var mission in segment.Missions) {
var cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, DrivingCycleData.CycleType.DistanceBased);
var cycle = DrivingCycleDataReader.ReadFromStream(mission.CycleFile, CycleType.DistanceBased);
foreach (var loading in mission.Loadings) {
var engineData = dao.CreateEngineData(Engine);
......
......@@ -109,7 +109,7 @@ namespace TUGraz.VectoCore.FileIO.Reader.Impl
Aux = Aux,
// TODO: distance or time-based cycle!
Cycle =
DrivingCycleDataReader.ReadFromFile(Path.Combine(job.BasePath, cycle), DrivingCycleData.CycleType.DistanceBased),
DrivingCycleDataReader.ReadFromFile(Path.Combine(job.BasePath, cycle), CycleType.DistanceBased),
IsEngineOnly = IsEngineOnly
};
yield return simulationRunData;
......
......@@ -23,5 +23,17 @@ namespace TUGraz.VectoCore.Models.Connector.Ports
Second SimulationInterval { get; set; }
ResponseType ResponseType { get; }
Watt EnginePowerRequest { get; set; }
Watt ClutchPowerRequest { get; set; }
Watt GearboxPowerRequest { get; set; }
Watt AxlegearPowerRequest { get; set; }
Watt WheelsPowerRequest { get; set; }
Watt VehiclePowerRequest { get; set; }
}
}
\ No newline at end of file
......@@ -8,6 +8,18 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl
public Second SimulationInterval { get; set; }
public abstract ResponseType ResponseType { get; }
public Watt EnginePowerRequest { get; set; }
public Watt ClutchPowerRequest { get; set; }
public Watt GearboxPowerRequest { get; set; }
public Watt AxlegearPowerRequest { get; set; }
public Watt WheelsPowerRequest { get; set; }
public Watt VehiclePowerRequest { get; set; }
}
/// <summary>
......@@ -37,7 +49,7 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl
/// </summary>
public class ResponseFailOverload : AbstractResponse
{
public double Delta { get; set; }
public Watt Delta { get; set; }
public double Gradient { get; set; }
public override ResponseType ResponseType
......@@ -71,8 +83,8 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl
internal class ResponseDryRun : AbstractResponse
{
public double DeltaFullLoad { get; set; }
public double DeltaDragLoad { get; set; }
public Watt EngineDeltaFullLoad { get; set; }
public Watt EngineDeltaDragLoad { get; set; }
public override ResponseType ResponseType
{
......
......@@ -130,7 +130,7 @@ namespace TUGraz.VectoCore.Models.Declaration
public static class LookAhead
{
public const bool Enabled = true;
public static readonly MeterPerSquareSecond Deceleration = 0.5.SI<MeterPerSquareSecond>();
public static readonly MeterPerSquareSecond Deceleration = -0.5.SI<MeterPerSquareSecond>();
public static readonly MeterPerSecond MinimumSpeed = 50.KMPHtoMeterPerSecond();
}
......
......@@ -174,7 +174,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
/// <summary>
/// [km/h] Target vehicle speed.
/// </summary>
[ModalResultField(typeof(SI))] v_targ,
[ModalResultField(typeof(SI), outputFactor: 3.6)] v_targ,
/// <summary>
/// [m/s2] Vehicle acceleration.
......
using System.Security.Cryptography.X509Certificates;
using TUGraz.VectoCore.Models.SimulationComponent;
namespace TUGraz.VectoCore.Models.Simulation.DataBus
{
public interface IClutchInfo
{
ClutchState ClutchState();
}
}
\ No newline at end of file
namespace TUGraz.VectoCore.Models.Simulation.DataBus
using TUGraz.VectoCore.Models.SimulationComponent;
namespace TUGraz.VectoCore.Models.Simulation.DataBus
{
/// <summary>
/// Defines interfaces for all different cockpits to access shared data of the powertrain.
/// </summary>
public interface IDataBus : IGearboxInfo, IEngineInfo, IVehicleInfo, IMileageCounter, IRoadLookAhead {}
public interface IDataBus : IGearboxInfo, IEngineInfo, IVehicleInfo, IMileageCounter, IClutchInfo, IBreaks,
IRoadLookAhead {}
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ namespace TUGraz.VectoCore.Models.Simulation.DataBus
{
public interface IRoadLookAhead
{
IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Meter distance);
IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Meter lookaheadDistance);
IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Second time);
}
......
......@@ -16,10 +16,30 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
var ds = (Container.VehicleSpeed() * Constants.SimulationSettings.TargetTimeInterval).Cast<Meter>();
if (ds.IsEqual(0)) {
// vehicle stands still, drive a certain distance...
ds = Constants.SimulationSettings.DriveOffDistance;
}
var response = CyclePort.Request(AbsTime, ds);
IResponse response;
var requestDone = false;
do {
response = CyclePort.Request(AbsTime, ds);
switch (response.ResponseType) {
case ResponseType.Success:
requestDone = true;
break;
case ResponseType.CycleFinished:
requestDone = true;
break;
case ResponseType.DrivingCycleDistanceExceeded:
var distanceResponse = response as ResponseDrivingCycleDistanceExceeded;
if (distanceResponse != null) {
ds = distanceResponse.MaxDistance;
}
break;
}
} while (!requestDone);
//while (response is ResponseFailTimeInterval) {
// _dt = (response as ResponseFailTimeInterval).DeltaT;
......
using System.Collections;
using TUGraz.VectoCore.Exceptions;
using TUGraz.VectoCore.Models.Connector.Ports;
using TUGraz.VectoCore.Models.Simulation.Data;
......@@ -32,21 +33,24 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
private VehicleContainer BuildFullPowertrain(VectoRunData data)
{
IDrivingCycle cycle;
if (_engineOnly) {
cycle = new TimeBasedDrivingCycle(_container, data.Cycle);
} else {
if (data.IsEngineOnly) {
cycle = new TimeBasedDrivingCycle(_container, data.Cycle);
} else {
//todo: make distinction between time based and distance based driving cycle!
switch (data.Cycle.CycleType) {
case CycleType.EngineOnly:
throw new VectoSimulationException("Engine-Only cycle File for full PowerTrain not allowed!");
case CycleType.DistanceBased:
cycle = new DistanceBasedDrivingCycle(_container, data.Cycle);
}
break;
case CycleType.TimeBased:
cycle = new TimeBasedDrivingCycle(_container, data.Cycle);
break;
default:
throw new VectoSimulationException("Unhandled Cycle Type");
}
// cycle --> driver --> vehicle --> wheels --> axleGear --> retarder --> gearBox
var driver = AddComponent(cycle, new Driver(_container, data.DriverData));
var vehicle = AddComponent(driver, new Vehicle(_container, data.VehicleData));
var wheels = AddComponent(vehicle, new Wheels(_container, data.VehicleData.DynamicTyreRadius));
var tmp = AddComponent(wheels, new AxleGear(_container, data.GearboxData.AxleGearData));
var breaks = AddComponent(wheels, new Breaks(_container));
var tmp = AddComponent(breaks, new AxleGear(_container, data.GearboxData.AxleGearData));
switch (data.VehicleData.Retarder.Type) {
case RetarderData.RetarderType.Primary:
......@@ -142,7 +146,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
private VehicleContainer BuildEngineOnly(VectoRunData data)
{
var cycle = new EngineOnlySimulation(_container, data.Cycle);
var cycle = new EngineOnlyDrivingCycle(_container, data.Cycle);
var gearbox = new EngineOnlyGearbox(_container);
cycle.InPort().Connect(gearbox.OutPort());
......@@ -152,7 +156,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
directAux.AddDirect(cycle);
gearbox.InPort().Connect(directAux.OutPort());
var engine = new CombustionEngine(_container, data.EngineData);
var engine = new EngineOnlyCombustionEngine(_container, data.EngineData);
directAux.InPort().Connect(engine.OutPort());
return _container;
......
......@@ -18,9 +18,12 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
internal IEngineInfo Engine;
internal IGearboxInfo Gearbox;
internal IVehicleInfo Vehicle;
internal IBreaks Breaks;
internal IMileageCounter MilageCounter;
internal IClutchInfo Clutch;
internal IRoadLookAhead Road;
internal ISimulationOutPort Cycle;
......@@ -121,10 +124,20 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
MilageCounter = milage;
}
var breaks = component as IBreaks;
if (breaks != null) {
Breaks = breaks;
}
var road = component as IRoadLookAhead;
if (road != null) {
Road = road;
}
var clutch = component as IClutchInfo;
if (clutch != null) {
Clutch = clutch;
}
}
......@@ -162,14 +175,25 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
return MilageCounter.Distance();
}
public IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Meter distance)
public IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Meter lookaheadDistance)
{
return Road.LookAhead(distance);
return Road.LookAhead(lookaheadDistance);
}
public IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Second time)
{
return Road.LookAhead(time);
}
public Watt BreakPower
{
get { return Breaks.BreakPower; }
set { Breaks.BreakPower = value; }
}
public ClutchState ClutchState()
{
return Clutch.ClutchState();
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
......@@ -47,6 +48,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
}
public AccelerationEntry Lookup(MeterPerSecond key)
{
var index = FindIndex(key);
return new AccelerationEntry {
Acceleration =
VectoMath.Interpolate(_entries[index - 1].Key, _entries[index].Key, _entries[index - 1].Value.Acceleration,
_entries[index].Value.Acceleration, key),
Deceleration =
VectoMath.Interpolate(_entries[index - 1].Key, _entries[index].Key, _entries[index - 1].Value.Deceleration,
_entries[index].Value.Deceleration, key)
};
}
protected int FindIndex(MeterPerSecond key)
{
var index = 1;
if (key < _entries[0].Key) {
......@@ -58,15 +73,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
index = (key > _entries[0].Key) ? _entries.Count - 1 : 1;
}
}
return new AccelerationEntry {
Acceleration =
VectoMath.Interpolate(_entries[index - 1].Key, _entries[index].Key, _entries[index - 1].Value.Acceleration,
_entries[index].Value.Acceleration, key),
Deceleration =
VectoMath.Interpolate(_entries[index - 1].Key, _entries[index].Key, _entries[index - 1].Value.Deceleration,
_entries[index].Value.Deceleration, key)
};
return index;
}
public class AccelerationEntry
......@@ -74,5 +81,65 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
public MeterPerSquareSecond Acceleration { get; set; }
public MeterPerSquareSecond Deceleration { get; set; }
}
/// <summary>
///
/// </summary>
/// <param name="v1">current speed of the vehicle</param>
/// <param name="v2">desired speed of the vehicle at the end of acceleration/deceleration phase</param>
/// <returns>distance required to accelerate/decelerate the vehicle from v1 to v2 according to the acceleration curve</returns>
public Meter ComputeAccelerationDistance(MeterPerSecond v1, MeterPerSecond v2)
{
var index1 = FindIndex(v1);
var index2 = FindIndex(v2);
var distance = 0.SI<Meter>();
for (var i = index2; i <= index1; i++) {
distance += ComputeAccelerationSegmentDistance(i, v1, v2);
}
return distance;
}
/// <summary>
///
/// </summary>
/// <param name="i">segment of the acceleration curve to use [(i-1) ... i]</param>
/// <param name="v1">current speed of the vehicle</param>
/// <param name="v2">desired speed of the vehicle at the end of acceleration/deceleration phase</param>
/// <returns>distance required to accelerate/decelerate the vehicle from v1 to v2 according to the acceleration curve</returns>
private Meter ComputeAccelerationSegmentDistance(int i, MeterPerSecond v1, MeterPerSecond v2)
{
var leftEntry = _entries[i - 1]; // entry with lower velocity
var rightEntry = _entries[i]; // entry with higher velocity
v2 = VectoMath.Max(v2, leftEntry.Key); // min. velocity within current segment
v1 = VectoMath.Min(v1, rightEntry.Key); // max. velocity within current segment
if (leftEntry.Value.Deceleration.IsEqual(rightEntry.Value.Deceleration)) {
// v(t) = a * t + v1 => t = (v2 - v1) / a
// s(t) = a/2 * t^2 + v1 * t + s0 {s0 == 0} => s(t)
var acceleration = v2 > v1 ? leftEntry.Value.Acceleration : leftEntry.Value.Deceleration;
return ((v2 - v1) * (v2 - v1) / 2.0 / acceleration + v1 * (v2 - v1) / acceleration).Cast<Meter>();
}
// a(v) = k * v + d
// dv/dt = a(v) = d * v + d ==> v(t) = sgn(k * v1 + d) * exp(-k * c) / k * exp(t * k) - d / k
// v(0) = v1 => c = - ln(|v1 * k + d|) / k
// v(t) = (v1 + d / k) * exp(t * k) - d / k => t = 1 / k * ln((v2 * k + d) / (v1 * k + d))
// s(t) = m / k* exp(t * k) + b * t + c' {m = v1 + d / k, b = -d / k}
var k = (leftEntry.Value.Deceleration - rightEntry.Value.Deceleration) / (leftEntry.Key - rightEntry.Key);
var d = leftEntry.Value.Deceleration - k * leftEntry.Key;
if (v2 > v1) {
k = (leftEntry.Value.Acceleration - rightEntry.Value.Acceleration) / (leftEntry.Key - rightEntry.Key);
d = leftEntry.Value.Acceleration - k * leftEntry.Key;
}
var m = v1 + d / k;
var b = -d / k;
var c = 0.SI<Meter>() - m / k;
var t = Math.Log(((v2 * k + d) / (v1 * k + d)).Cast<Scalar>()) / k;
return m / k * Math.Exp((k * t).Value()) + b * t + c;
}
}
}
\ No newline at end of file
......@@ -6,22 +6,36 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
{
public class DrivingCycleData : SimulationComponentData
{
public enum CycleType
{
EngineOnly,
TimeBased,
DistanceBased
}
internal DrivingCycleData() {}
public List<DrivingCycleEntry> Entries { get; internal set; }
public string Name { get; internal set; }
public CycleType CycleType { get; internal set; }
public class DrivingCycleEntry
{
public DrivingCycleEntry() {}
public DrivingCycleEntry(DrivingCycleEntry entry)
{
Distance = entry.Distance;
Time = entry.Time;
VehicleTargetSpeed = entry.VehicleTargetSpeed;
RoadGradient = entry.RoadGradient;
Altitude = entry.Altitude;
StoppingTime = entry.StoppingTime;
EngineSpeed = entry.EngineSpeed;
Gear = entry.Gear;
AdditionalAuxPowerDemand = entry.AdditionalAuxPowerDemand;
AirSpeedRelativeToVehicle = entry.AirSpeedRelativeToVehicle;
WindYawAngle = entry.WindYawAngle;
EngineTorque = entry.EngineTorque;
Drag = entry.Drag;
AuxiliarySupplyPower = new Dictionary<string, Watt>(entry.AuxiliarySupplyPower);
}
/// <summary>
/// [m] Travelled distance used for distance-based cycles. If "t"
/// is also defined this column will be ignored.
......@@ -115,4 +129,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
#endregion
}
public enum CycleType
{
EngineOnly,
TimeBased,
DistanceBased
}
}
\ No newline at end of file
......@@ -51,7 +51,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
log.WarnFormat(
"FullLoadCurve: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: '{3}'. Falling back to column index.",
Fields.EngineSpeed, Fields.TorqueFullLoad, Fields.TorqueDrag,
string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()));
string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
entriesFld = CreateFromColumnIndizes(data);
}
......
......@@ -4,6 +4,7 @@ using System.Data;
using System.Linq;
using Common.Logging;
using Newtonsoft.Json;
using NLog.Fluent;
using TUGraz.VectoCore.Exceptions;
using TUGraz.VectoCore.Utils;
......@@ -13,6 +14,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
{
[JsonProperty] private readonly List<GearLossMapEntry> _entries;
private readonly double _ratio;
private readonly DelauneyMap _lossMap; // Input Speed, Output Torque (to Wheels) => Input Torque (Engine)
//private readonly DelauneyMap _reverseLossMap; // Input Speed, Input Torque (Engine) => Output Torque (Wheels)
......@@ -80,11 +83,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
private TransmissionLossMap(List<GearLossMapEntry> entries, double gearRatio)
{
_ratio = gearRatio;
_entries = entries;
_lossMap = new DelauneyMap();
//_reverseLossMap = new DelauneyMap();
foreach (var entry in _entries) {
_lossMap.AddPoint(entry.InputSpeed.Value(), (entry.InputTorque.Value() - entry.TorqueLoss.Value()) * gearRatio,
_lossMap.AddPoint(entry.InputSpeed.Value(), (entry.InputTorque.Value() - entry.TorqueLoss.Value()) * _ratio,
entry.InputTorque.Value());
// @@@quam: according to Raphael, not needed for now...
//_reverseLossMap.AddPoint(entry.InputSpeed.Double(), entry.InputTorque.Double(),
......@@ -103,8 +107,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
public NewtonMeter GearboxInTorque(PerSecond angularVelocity, NewtonMeter gbxOutTorque)
{
try {
return VectoMath.Max(_lossMap.Interpolate(angularVelocity.Value(), gbxOutTorque.Value()).SI<NewtonMeter>(),
0.SI<NewtonMeter>());
var gbxInTorque = _lossMap.Interpolate(angularVelocity.Value(), gbxOutTorque.Value()).SI<NewtonMeter>();
LogManager.GetLogger(this.GetType()).DebugFormat("GearboxLoss: {0}", gbxInTorque);
// Torque at input of the geabox must be greater than or equal to the torque at the output
// (i.e. no 'torque-gain' in the transmission due to interpolation etc.)
return VectoMath.Max(gbxInTorque, gbxOutTorque / _ratio);
} catch (Exception e) {
throw new VectoSimulationException(
string.Format("Failed to interpolate in TransmissionLossMap. angularVelocity: {0}, torque: {1}", angularVelocity,
......
using TUGraz.VectoCore.Utils;
namespace TUGraz.VectoCore.Models.SimulationComponent
{
public interface IBreaks
{
Watt BreakPower { get; set; }
}
}
\ No newline at end of file
namespace TUGraz.VectoCore.Models.SimulationComponent
{
public enum ClutchState
{
ClutchClosed,
ClutchOpened,
ClutchSlipping
}
public interface IClutch : IPowerTrainComponent {}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment