diff --git a/VectoCore/Configuration/Constants.cs b/VectoCore/Configuration/Constants.cs index 525928ee188808b91c834d7b9b6436bdc5679b56..076772cc9b3a15316639a5a87a02614f0c7554ed 100644 --- a/VectoCore/Configuration/Constants.cs +++ b/VectoCore/Configuration/Constants.cs @@ -86,6 +86,10 @@ namespace TUGraz.VectoCore.Configuration public static readonly PerSecond EngineIdlingSearchInterval = 10.SI<PerSecond>(); public const int EngineSearchLoopThreshold = 100; + + public const int MaximumIterationCountForSimulationStep = 30; + + public static readonly MeterPerSecond VehicleStopClutchDisengageSpeed = 10.KMPHtoMeterPerSecond(); } } } \ No newline at end of file diff --git a/VectoCore/Exceptions/VectoExceptions.cs b/VectoCore/Exceptions/VectoExceptions.cs index 108e13935205d2aa00d2bb8ccfa7a41c08c999f1..3019e44a73a2981d9d4dff0dba3237e1170d2f58 100644 --- a/VectoCore/Exceptions/VectoExceptions.cs +++ b/VectoCore/Exceptions/VectoExceptions.cs @@ -1,21 +1,35 @@ using System; using System.IO; using JetBrains.Annotations; +using NLog; namespace TUGraz.VectoCore.Exceptions { public class VectoException : Exception { - public VectoException(string message) : base(message) {} - public VectoException(string message, Exception innerException) : base(message, innerException) {} + public VectoException(string message) : base(message) + { + LogManager.Flush(); + } + + public VectoException(string message, Exception innerException) : base(message, innerException) + { + LogManager.Flush(); + } [StringFormatMethod("message")] public VectoException(string message, params object[] args) - : base(string.Format(message, args)) {} + : base(string.Format(message, args)) + { + LogManager.Flush(); + } [StringFormatMethod("message")] protected VectoException(string message, Exception inner, params object[] args) - : base(string.Format(message, args), inner) {} + : base(string.Format(message, args), inner) + { + LogManager.Flush(); + } } public abstract class FileIOException : VectoException diff --git a/VectoCore/Exceptions/VectoSimulationException.cs b/VectoCore/Exceptions/VectoSimulationException.cs index 4b56d68f7220ce33cd02a2d7f9f39487336390e0..ebbd9c00f76416c21c29e3771d3c45bff98b484b 100644 --- a/VectoCore/Exceptions/VectoSimulationException.cs +++ b/VectoCore/Exceptions/VectoSimulationException.cs @@ -26,4 +26,9 @@ namespace TUGraz.VectoCore.Exceptions Response = resp; } } + + public class VectoSearchFailedException : VectoException + { + public VectoSearchFailedException(string message, params object[] args) : base(message, args) {} + } } \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/Impl/Response.cs b/VectoCore/Models/Connector/Ports/Impl/Response.cs index 61b70770f523fca10516ff25a1fe511adebd6424..f7bd2afe1e9a97dcb4517b0a54c387ab1074335a 100644 --- a/VectoCore/Models/Connector/Ports/Impl/Response.cs +++ b/VectoCore/Models/Connector/Ports/Impl/Response.cs @@ -87,4 +87,6 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl } internal class ResponseGearShift : AbstractResponse {} + + internal class ResponseEngineSpeedTooLow : ResponseDryRun {} } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/DataBus/IDataBus.cs b/VectoCore/Models/Simulation/DataBus/IDataBus.cs index e5549e05378f62b67661e80fe3556d13eead1f91..39f00f8e768e7484ae8b6242697d3b9cb81bdc1c 100644 --- a/VectoCore/Models/Simulation/DataBus/IDataBus.cs +++ b/VectoCore/Models/Simulation/DataBus/IDataBus.cs @@ -1,4 +1,5 @@ using TUGraz.VectoCore.Models.SimulationComponent; +using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Simulation.DataBus { diff --git a/VectoCore/Models/Simulation/DataBus/IDriverInfo.cs b/VectoCore/Models/Simulation/DataBus/IDriverInfo.cs index ae113cce4e5a44aad44203ca5435f7c464da4ef1..938284fb97afee720ae3decacf57b0304bddc637 100644 --- a/VectoCore/Models/Simulation/DataBus/IDriverInfo.cs +++ b/VectoCore/Models/Simulation/DataBus/IDriverInfo.cs @@ -1,7 +1,20 @@ +using TUGraz.VectoCore.Utils; + namespace TUGraz.VectoCore.Models.Simulation.DataBus { + public enum DrivingBehavior + { + Halted, + Accelerating, + Driving, + Coasting, + Braking, + } + public interface IDriverInfo { bool VehicleStopped { get; } + + DrivingBehavior DrivingBehavior { get; } } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/DataBus/IRoadLookAhead.cs b/VectoCore/Models/Simulation/DataBus/IRoadLookAhead.cs index 438dc0de58305d372a13f5c3af86ffe12293e286..04f1d1f8b06bdc07c1449155757b7d1aac0996d0 100644 --- a/VectoCore/Models/Simulation/DataBus/IRoadLookAhead.cs +++ b/VectoCore/Models/Simulation/DataBus/IRoadLookAhead.cs @@ -6,6 +6,8 @@ namespace TUGraz.VectoCore.Models.Simulation.DataBus { public interface IRoadLookAhead { + Meter CycleStartDistance { get; } + IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Meter lookaheadDistance); IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Second time); diff --git a/VectoCore/Models/Simulation/Impl/DistanceRun.cs b/VectoCore/Models/Simulation/Impl/DistanceRun.cs index beb13565ffcc6a87af7c101a8ed693f60f3177ef..971248cedf10480cc8d78f91d5f7c01a673d52fb 100644 --- a/VectoCore/Models/Simulation/Impl/DistanceRun.cs +++ b/VectoCore/Models/Simulation/Impl/DistanceRun.cs @@ -9,7 +9,12 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl { public class DistanceRun : VectoRun { - public DistanceRun(IVehicleContainer container) : base(container) {} + public string Name { get; protected set; } + + public DistanceRun(string name, IVehicleContainer container) : base(container) + { + Name = name; + } protected override IResponse DoSimulationStep() { @@ -18,6 +23,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl ? Constants.SimulationSettings.DriveOffDistance : Constants.SimulationSettings.TargetTimeInterval * Container.VehicleSpeed; + var loopCount = 0; IResponse response; do { response = CyclePort.Request(AbsTime, ds); @@ -37,6 +43,9 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl Default(r => { throw new VectoException("DistanceRun got an unexpected response: {0}", r); }); + if (loopCount++ > Constants.SimulationSettings.MaximumIterationCountForSimulationStep) { + throw new VectoSimulationException("Maximum iteration count for a single simulation interval reached! Aborting!"); + } } while (!(response is ResponseSuccess || response is ResponseCycleFinished)); return response; @@ -44,6 +53,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl protected override IResponse Initialize() { + Log.Info("Starting {0}", Name); return CyclePort.Initialize(); } } diff --git a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs index d60fba5a64bd8ea175cc7b17bcdb8951a1c103db..655f14e2117cb1fff5287786162477cff738d250 100644 --- a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs +++ b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs @@ -71,7 +71,8 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl if (data.IsEngineOnly) { run = new TimeRun(builder.Build(data)); } else { - run = new DistanceRun(builder.Build(data)); + var runCaption = string.Format("Cycle: {0} Loading: {1}", data.Cycle.Name, data.ModFileSuffix); + run = new DistanceRun(runCaption, builder.Build(data)); } yield return run; diff --git a/VectoCore/Models/Simulation/Impl/VectoRun.cs b/VectoCore/Models/Simulation/Impl/VectoRun.cs index 98168cf489898c2d0e7aabd9b3dae327b862e346..ca4e0d5c182d80955afe3d5cdad2675cb43ce4db 100644 --- a/VectoCore/Models/Simulation/Impl/VectoRun.cs +++ b/VectoCore/Models/Simulation/Impl/VectoRun.cs @@ -44,7 +44,6 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl response = DoSimulationStep(); if (response is ResponseSuccess) { Container.CommitSimulationStep(AbsTime, dt); - AbsTime += dt; } } while (response is ResponseSuccess); diff --git a/VectoCore/Models/Simulation/Impl/VehicleContainer.cs b/VectoCore/Models/Simulation/Impl/VehicleContainer.cs index 1cf98b9484b08a139236a3ac6a6e6df1daabffa0..e49344a5e635bc5bf7a6f5d968909d47a712b4db 100644 --- a/VectoCore/Models/Simulation/Impl/VehicleContainer.cs +++ b/VectoCore/Models/Simulation/Impl/VehicleContainer.cs @@ -259,5 +259,15 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl { get { return Driver.VehicleStopped; } } + + public DrivingBehavior DrivingBehavior + { + get { return Driver.DrivingBehavior; } + } + + public Meter CycleStartDistance + { + get { return Road.CycleStartDistance; } + } } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/IDriverStrategy.cs b/VectoCore/Models/SimulationComponent/IDriverStrategy.cs index 222162ba95424cdc1af79f47dee682ea4ec706a5..8728f1603045fdea08cd3beb1ac0b6c3f70a9439 100644 --- a/VectoCore/Models/SimulationComponent/IDriverStrategy.cs +++ b/VectoCore/Models/SimulationComponent/IDriverStrategy.cs @@ -1,4 +1,6 @@ using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Simulation.DataBus; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent @@ -7,6 +9,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent { IDriverActions Driver { get; set; } + DrivingBehavior DriverBehavior { get; } + IResponse Request(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient); IResponse Request(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient); diff --git a/VectoCore/Models/SimulationComponent/Impl/Clutch.cs b/VectoCore/Models/SimulationComponent/Impl/Clutch.cs index 76ec4161601b7a2b5ab5dbc9246be9811603c2e4..410adf931ecb660dbf688f5e805351b5a7c4886b 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Clutch.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Clutch.cs @@ -66,6 +66,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { if (angularVelocity == null) { //var retval = NextComponent.Request(absTime, dt, torque, null, dryRun); + Log.Debug("Invoking IdleController..."); var retval = IdleController.Request(absTime, dt, torque, null, dryRun); retval.ClutchPowerRequest = 0.SI<Watt>(); return retval; diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index 34680b8cc4db67c80f0231f04607c9755d8aed73..9bde9e84de516f4a13bfe4dc136fd9bd0f93fa37 100644 --- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Resources; +using NLog; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Connector.Ports; @@ -45,7 +46,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl internal EngineState PreviousState = new EngineState(); - protected readonly CombustionEngineData Data; + protected internal readonly CombustionEngineData Data; public CombustionEngine(IVehicleContainer cockpit, CombustionEngineData data) : base(cockpit) @@ -495,7 +496,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var auxDemandResponse = RequestPort.Request(absTime, dt, torque, prevEngineSpeed, true); - var deltaEnginePower = nextEnginePower - auxDemandResponse.AuxiliariesPowerDemand; + var deltaEnginePower = nextEnginePower - (auxDemandResponse.AuxiliariesPowerDemand ?? 0.SI<Watt>()); var deltaTorque = deltaEnginePower / prevEngineSpeed; var deltaAngularSpeed = (deltaTorque / Engine.Data.Inertia * dt).Cast<PerSecond>(); @@ -508,10 +509,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl nextAngularSpeed = prevEngineSpeed + deltaAngularSpeed; if (nextAngularSpeed < Engine.Data.IdleSpeed) { - // search for EnginePower such that nextAngularSpeed == Engine.Data.IdleSpeed - var tmp = RequestPort.Request(absTime, dt, torque, Engine.Data.IdleSpeed); - return tmp; - //throw new NotImplementedException("Search for PE s.t. n2 = n_idle"); + nextAngularSpeed = Engine.Data.IdleSpeed; } retVal = RequestPort.Request(absTime, dt, torque, nextAngularSpeed); @@ -531,6 +529,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private IResponse SearchIdlingSpeed(Second absTime, Second dt, NewtonMeter torque, PerSecond angularSpeed, ResponseUnderload responseUnderload) { + Log.Info("Disabling logging during search idling speed"); + LogManager.DisableLogging(); + var prevEngineSpeed = Engine.PreviousState.EngineSpeed; var searchInterval = Constants.SimulationSettings.EngineIdlingSearchInterval; @@ -552,6 +553,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl delta = response.DeltaDragLoad; debug.Add(new { engineSpeed = nextAngularSpeed, searchInterval, delta }); if (delta.IsEqual(0.SI<Watt>(), Constants.SimulationSettings.EnginePowerSearchTolerance)) { + LogManager.EnableLogging(); Log.Debug("found operating point in {0} iterations. engine speed: {1}, delta: {2}", retryCount, nextAngularSpeed, delta); return RequestPort.Request(absTime, dt, torque, nextAngularSpeed); @@ -563,6 +565,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl searchInterval *= intervalFactor; } while (retryCount++ < Constants.SimulationSettings.EngineSearchLoopThreshold); + LogManager.EnableLogging(); Log.Warn("Exceeded max iterations when searching for idling point!"); Log.Warn("acceleration: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.acceleration)), ", ".Join(debug.Slice(-6).Select(x => x.acceleration))); diff --git a/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs b/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs index 55d39fa46e482c0f03960100a312e7611d45c8dd..7f1a20eb9fceb0b0b9e0e2bc54223d40fc532a47 100644 --- a/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs +++ b/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs @@ -23,14 +23,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl DrivingModeBrake, } - public enum DrivingBehavior - { - Accelerating, - Drive, - Coasting, - Braking, - } - protected DrivingMode CurrentDrivingMode; protected Dictionary<DrivingMode, IDriverMode> DrivingModes = new Dictionary<DrivingMode, IDriverMode>(); @@ -100,22 +92,36 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (v2 <= nextAction.NextTargetSpeed) { return retVal; } - var coastingDistance = Formulas.DecelerationDistance(v2, nextAction.NextTargetSpeed, - Driver.DriverData.LookAheadCoasting.Deceleration); - //if (Driver.DataBus.Distance.IsEqual(nextAction.TriggerDistance - coastingDistance, - // Constants.SimulationSettings.DriverActionDistanceTolerance.Value())) { - // return retVal; - //} - // if the distance at the end of the simulation interval is smaller than the new ActionDistance - // we are safe - go ahead... - if ((Driver.DataBus.Distance + ds).IsSmallerOrEqual(nextAction.TriggerDistance - coastingDistance, - Constants.SimulationSettings.DriverActionDistanceTolerance)) { + Meter newds; + switch (nextAction.Action) { + case DrivingBehavior.Coasting: + var coastingDistance = Formulas.DecelerationDistance(v2, nextAction.NextTargetSpeed, + Driver.DriverData.LookAheadCoasting.Deceleration); + + // if the distance at the end of the simulation interval is smaller than the new ActionDistance + // we are safe - go ahead... + if ((Driver.DataBus.Distance + ds).IsSmallerOrEqual(nextAction.TriggerDistance - coastingDistance, + Constants.SimulationSettings.DriverActionDistanceTolerance)) { + return retVal; + } + newds = EstimateAccelerationDistanceBeforeBrake(retVal, nextAction); + break; + case DrivingBehavior.Braking: + var brakingDistance = Driver.DriverData.AccelerationCurve.ComputeAccelerationDistance(v2, + nextAction.NextTargetSpeed); + if ((Driver.DataBus.Distance + ds).IsSmaller(nextAction.TriggerDistance - brakingDistance)) { + return retVal; + } + newds = (nextAction.TriggerDistance - brakingDistance) - Driver.DataBus.Distance; + break; + default: + return retVal; + } + if (ds.IsEqual(newds, 1e-3.SI<Meter>())) { return retVal; } - - var newds = EstimateAccelerationDistanceBeforeBrake(retVal, nextAction); Log.Debug("Exceeding next ActionDistance at {0}. Reducing max Distance to {1}", nextAction.ActionDistance, newds); return new ResponseDrivingCycleDistanceExceeded() { Source = this, @@ -123,22 +129,31 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl }; } + + public IResponse Request(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) + { + DriverBehavior = DrivingBehavior.Halted; + return Driver.DrivingActionHalt(absTime, dt, targetVelocity, gradient); + } + + + public DrivingBehavior DriverBehavior { get; internal set; } + private Meter EstimateAccelerationDistanceBeforeBrake(IResponse retVal, DrivingBehaviorEntry nextAction) { // estimate the distance to drive when accelerating with the current acceleration (taken from retVal) and then // coasting with the dirver's LookaheadDeceleration. // TriggerDistance - CurrentDistance = s_accelerate + s_lookahead - // s_coast(dt) = - (currentSpeed + a * dt)^2 / (2 * a_lookahead + // s_coast(dt) = - (currentSpeed + a * dt + nextTargetSpeed) * (nextTargetSpeed - (currentSpeed + a * dt)) / (2 * a_lookahead) // s_acc(dt) = currentSpeed * dt + a / 2 * dt^2 // => solve for dt, compute ds = currentSpeed * dt + a / 2 * dt^2 var dtList = VectoMath.QuadraticEquationSolver( (retVal.Acceleration / 2 - retVal.Acceleration * retVal.Acceleration / 2 / Driver.DriverData.LookAheadCoasting.Deceleration).Value(), (Driver.DataBus.VehicleSpeed - - Driver.DataBus.VehicleSpeed * retVal.Acceleration / Driver.DriverData.LookAheadCoasting.Deceleration) - .Value - (), - (-Driver.DataBus.VehicleSpeed * Driver.DataBus.VehicleSpeed / 2 / Driver.DriverData.LookAheadCoasting.Deceleration - + Driver.DataBus.VehicleSpeed * retVal.Acceleration / Driver.DriverData.LookAheadCoasting.Deceleration).Value(), + (nextAction.NextTargetSpeed * nextAction.NextTargetSpeed / 2 / Driver.DriverData.LookAheadCoasting.Deceleration - + Driver.DataBus.VehicleSpeed * Driver.DataBus.VehicleSpeed / 2 / Driver.DriverData.LookAheadCoasting.Deceleration - (nextAction.TriggerDistance - Driver.DataBus.Distance)).Value()); dtList.Sort(); var dt = dtList.First(x => x > 0).SI<Second>(); @@ -146,13 +161,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return newds; } - - public IResponse Request(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) - { - return Driver.DrivingActionHalt(absTime, dt, targetVelocity, gradient); - } - - protected DrivingBehaviorEntry GetNextDrivingAction(Meter minDistance) { var currentSpeed = Driver.DataBus.VehicleSpeed; @@ -166,52 +174,52 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Log.Debug("Lookahead distance: {0} @ current speed {1}", lookaheadDistance, currentSpeed); var nextActions = new List<DrivingBehaviorEntry>(); foreach (var entry in lookaheadData) { - if (entry.VehicleTargetSpeed < currentSpeed) { + var nextTargetSpeed = OverspeedAllowed(entry.RoadGradient, entry.VehicleTargetSpeed) + ? entry.VehicleTargetSpeed + Driver.DriverData.OverSpeedEcoRoll.OverSpeed + : entry.VehicleTargetSpeed; + if (nextTargetSpeed < currentSpeed) { if (!Driver.DriverData.LookAheadCoasting.Enabled || - currentSpeed < Driver.DriverData.LookAheadCoasting.MinSpeed) { - var brakingDistance = Driver.ComputeDecelerationDistance(entry.VehicleTargetSpeed); - Log.Debug("adding 'Braking' starting at distance {0}", entry.Distance - brakingDistance); + entry.VehicleTargetSpeed < Driver.DriverData.LookAheadCoasting.MinSpeed) { + var brakingDistance = Driver.ComputeDecelerationDistance(nextTargetSpeed); + Log.Debug("adding 'Braking' starting at distance {0}. brakingDistance: {1}, triggerDistance: {2}", + entry.Distance - brakingDistance, brakingDistance, entry.Distance); nextActions.Add(new DrivingBehaviorEntry { Action = DrivingBehavior.Braking, ActionDistance = entry.Distance - brakingDistance, TriggerDistance = entry.Distance, - NextTargetSpeed = - OverspeedAllowed(entry.RoadGradient) - ? entry.VehicleTargetSpeed + Driver.DriverData.OverSpeedEcoRoll.OverSpeed - : entry.VehicleTargetSpeed + NextTargetSpeed = nextTargetSpeed }); } else { - var coastingDistance = Formulas.DecelerationDistance(currentSpeed, entry.VehicleTargetSpeed, + var coastingDistance = Formulas.DecelerationDistance(currentSpeed, nextTargetSpeed, Driver.DriverData.LookAheadCoasting.Deceleration); - Log.Debug("adding 'Coasting' starting at distance {0}", entry.Distance - coastingDistance); + Log.Debug("adding 'Coasting' starting at distance {0}. coastingDistance: {1}, triggerDistance: {2}", + entry.Distance - coastingDistance, coastingDistance, entry.Distance); nextActions.Add( new DrivingBehaviorEntry { - Action = DefaultDriverStrategy.DrivingBehavior.Coasting, + Action = DrivingBehavior.Coasting, ActionDistance = entry.Distance - coastingDistance, TriggerDistance = entry.Distance, - NextTargetSpeed = OverspeedAllowed(entry.RoadGradient) - ? entry.VehicleTargetSpeed + Driver.DriverData.OverSpeedEcoRoll.OverSpeed - : entry.VehicleTargetSpeed + NextTargetSpeed = nextTargetSpeed }); } } - if (entry.VehicleTargetSpeed > currentSpeed) { - nextActions.Add(new DrivingBehaviorEntry { - Action = DefaultDriverStrategy.DrivingBehavior.Accelerating, - NextTargetSpeed = entry.VehicleTargetSpeed, - TriggerDistance = entry.Distance, - ActionDistance = entry.Distance - }); - } + //if (nextTargetSpeed > currentSpeed) { + // nextActions.Add(new DrivingBehaviorEntry { + // Action = DefaultDriverStrategy.DrivingBehavior.Accelerating, + // NextTargetSpeed = entry.VehicleTargetSpeed, + // TriggerDistance = entry.Distance, + // ActionDistance = entry.Distance + // }); + //} } return nextActions.Count == 0 ? null : nextActions.OrderBy(x => x.ActionDistance).First(); } - public bool OverspeedAllowed(Radian gradient) + public bool OverspeedAllowed(Radian gradient, MeterPerSecond velocity) { return Driver.DriverData.OverSpeedEcoRoll.Mode == DriverData.DriverMode.Overspeed && - gradient < 0 && Driver.DataBus.VehicleSpeed > Driver.DriverData.OverSpeedEcoRoll.MinSpeed; + gradient < 0 && velocity > Driver.DriverData.OverSpeedEcoRoll.MinSpeed; } } @@ -268,12 +276,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl IResponse response = null; var velocity = targetVelocity; - if (DriverStrategy.OverspeedAllowed(gradient)) { + if (DriverStrategy.OverspeedAllowed(gradient, targetVelocity)) { velocity += DriverData.OverSpeedEcoRoll.OverSpeed; } if (DataBus.ClutchClosed(absTime)) { // drive along - if (DriverStrategy.OverspeedAllowed(gradient) && DataBus.VehicleSpeed.IsEqual(targetVelocity)) { + if (DriverStrategy.OverspeedAllowed(gradient, targetVelocity) && DataBus.VehicleSpeed.IsEqual(targetVelocity)) { response = Driver.DrivingActionCoast(absTime, ds, velocity, gradient); if (response is ResponseSuccess && response.Acceleration < 0) { response = Driver.DrivingActionAccelerate(absTime, ds, targetVelocity, gradient); @@ -294,7 +302,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl }); }). Case<ResponseUnderload>(r => { - if (DriverStrategy.OverspeedAllowed(gradient)) { + if (DriverStrategy.OverspeedAllowed(gradient, targetVelocity)) { response = Driver.DrivingActionCoast(absTime, ds, velocity, gradient); if (response is ResponseUnderload || response is ResponseSpeedLimitExceeded) { response = Driver.DrivingActionBrake(absTime, ds, velocity, gradient); @@ -387,6 +395,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } switch (Phase) { case BrakingPhase.Coast: + DriverStrategy.DriverBehavior = DrivingBehavior.Coasting; response = DataBus.ClutchClosed(absTime) ? Driver.DrivingActionCoast(absTime, ds, targetVelocity, gradient) : Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); @@ -397,6 +406,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl gradient, r); Phase = BrakingPhase.Brake; }). + Case<ResponseOverload>(r => { + // limiting deceleration while coast may result in an overload => issue brakes to decelerate with driver's max deceleration + response = Driver.DrivingActionAccelerate(absTime, ds, targetVelocity, gradient); + //Phase = BrakingPhase.Brake; + }). Case<ResponseGearShift>(r => { response = Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); }). @@ -415,6 +429,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var targetDistance = DataBus.VehicleSpeed < Constants.SimulationSettings.MinVelocityForCoast ? DriverStrategy.BrakeTrigger.TriggerDistance : null; + DriverStrategy.DriverBehavior = DrivingBehavior.Braking; response = Driver.DrivingActionBrake(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient, targetDistance: targetDistance); response.Switch(). @@ -442,7 +457,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl [DebuggerDisplay("ActionDistance: {ActionDistance}, TriggerDistance: {TriggerDistance}, Action: {Action}")] public class DrivingBehaviorEntry { - public DefaultDriverStrategy.DrivingBehavior Action; + public DrivingBehavior Action; public MeterPerSecond NextTargetSpeed; public Meter TriggerDistance; public Meter ActionDistance; diff --git a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs index 60574bb09c06588240e641f793c8cc972471ce28..f32fc8e0dca155930ffbd6b00cccec9b68f0a3bd 100644 --- a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs @@ -111,25 +111,24 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return new ResponseCycleFinished(); } - if ((PreviousState.Distance + ds).IsGreater(CycleIntervalIterator.RightSample.Distance)) { - // only drive until next sample point in cycle - Log.Debug("Limiting distance to next sample point {0}", - CycleIntervalIterator.RightSample.Distance - PreviousState.Distance); - return new ResponseDrivingCycleDistanceExceeded { - Source = this, - MaxDistance = CycleIntervalIterator.RightSample.Distance - PreviousState.Distance - }; + var nextSpeedChange = GetSpeedChangeWithinSimulationInterval(ds); + if (nextSpeedChange == null || ds.IsSmallerOrEqual(nextSpeedChange - PreviousState.Distance)) { + return DriveDistance(absTime, ds); } - - - return DriveDistance(absTime, ds); + // only drive until next sample point in cycle with speed change + Log.Debug("Limiting distance to next sample point {0}", + CycleIntervalIterator.RightSample.Distance - PreviousState.Distance); + return new ResponseDrivingCycleDistanceExceeded { + Source = this, + MaxDistance = nextSpeedChange - PreviousState.Distance + }; } private IResponse DriveTimeInterval(Second absTime, Second dt) { CurrentState.AbsTime = PreviousState.AbsTime + dt; CurrentState.WaitTime = PreviousState.WaitTime + dt; - CurrentState.Gradient = ComputeGradient(); + CurrentState.Gradient = ComputeGradient(0.SI<Meter>()); CurrentState.VehicleTargetSpeed = CycleIntervalIterator.LeftSample.VehicleTargetSpeed; return NextComponent.Request(absTime, dt, CycleIntervalIterator.LeftSample.VehicleTargetSpeed, CurrentState.Gradient); @@ -137,42 +136,62 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private IResponse DriveDistance(Second absTime, Meter ds) { - if (!CurrentState.RequestToNextSamplePointDone && - (CycleIntervalIterator.RightSample.Distance - PreviousState.Distance) < - Constants.SimulationSettings.BrakeNextTargetDistance) { + var nextSpeedChanges = LookAhead(Constants.SimulationSettings.BrakeNextTargetDistance); + if (nextSpeedChanges.Count > 0 && !CurrentState.RequestToNextSamplePointDone) { CurrentState.RequestToNextSamplePointDone = true; Log.Debug("current distance is close to the next speed change: {0}", - CycleIntervalIterator.RightSample.Distance - PreviousState.Distance); + nextSpeedChanges.First().Distance - PreviousState.Distance); return new ResponseDrivingCycleDistanceExceeded { Source = this, MaxDistance = Constants.SimulationSettings.BrakeNextTargetDistance }; } + CurrentState.Distance = PreviousState.Distance + ds; CurrentState.VehicleTargetSpeed = CycleIntervalIterator.LeftSample.VehicleTargetSpeed; - CurrentState.Gradient = ComputeGradient(); + CurrentState.Gradient = ComputeGradient(ds); return NextComponent.Request(absTime, ds, CurrentState.VehicleTargetSpeed, CurrentState.Gradient); } - private Radian ComputeGradient() + private Radian ComputeGradient(Meter ds) { var leftSamplePoint = CycleIntervalIterator.LeftSample; - var rightSamplePoint = CycleIntervalIterator.RightSample; - var gradient = leftSamplePoint.RoadGradient; + var cycleIterator = CycleIntervalIterator.Clone(); + while (cycleIterator.RightSample.Distance < PreviousState.Distance + ds && !cycleIterator.LastEntry) { + cycleIterator.MoveNext(); + } + var rightSamplePoint = cycleIterator.RightSample; - if (!leftSamplePoint.Distance.IsEqual(rightSamplePoint.Distance)) { - CurrentState.Altitude = VectoMath.Interpolate(leftSamplePoint.Distance, rightSamplePoint.Distance, - leftSamplePoint.Altitude, rightSamplePoint.Altitude, CurrentState.Distance); + var gradient = leftSamplePoint.RoadGradient; - gradient = VectoMath.InclinationToAngle(((CurrentState.Altitude - PreviousState.Altitude) / - (CurrentState.Distance - PreviousState.Distance)).Value()); + if (leftSamplePoint.Distance.IsEqual(rightSamplePoint.Distance)) { + return gradient; } + + CurrentState.Altitude = VectoMath.Interpolate(leftSamplePoint.Distance, rightSamplePoint.Distance, + leftSamplePoint.Altitude, rightSamplePoint.Altitude, PreviousState.Distance + ds); + + gradient = VectoMath.InclinationToAngle(((CurrentState.Altitude - PreviousState.Altitude) / + (ds)).Value()); //return 0.SI<Radian>(); return gradient; } + private Meter GetSpeedChangeWithinSimulationInterval(Meter ds) + { + var leftSamplePoint = CycleIntervalIterator.LeftSample; + var cycleIterator = CycleIntervalIterator.Clone(); + + do { + if (!leftSamplePoint.VehicleTargetSpeed.IsEqual(cycleIterator.RightSample.VehicleTargetSpeed)) { + return cycleIterator.RightSample.Distance; + } + } while (cycleIterator.RightSample.Distance < PreviousState.Distance + ds && cycleIterator.MoveNext()); + return null; + } + IResponse ISimulationOutPort.Request(Second absTime, Second dt) { throw new NotImplementedException(); @@ -201,6 +220,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl CycleIntervalIterator.LeftSample.RoadGradient); } + public Meter CycleStartDistance + { + get { return Data.Entries.Count > 0 ? Data.Entries.First().Distance : 0.SI<Meter>(); } + } + #endregion protected IResponse ProcessResponse(IResponse response) @@ -234,10 +258,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } // separately test for equality and greater than to have tolerance for equality comparison - if (CycleIntervalIterator.LeftSample.StoppingTime.IsEqual(0) && - CurrentState.Distance.IsGreaterOrEqual(CycleIntervalIterator.RightSample.Distance)) { - // we have reached the end of the current interval in the cycle, move on... - CycleIntervalIterator.MoveNext(); + if (CycleIntervalIterator.LeftSample.StoppingTime.IsEqual(0)) { + while (CurrentState.Distance.IsGreaterOrEqual(CycleIntervalIterator.RightSample.Distance) && + !CycleIntervalIterator.LastEntry) { + // we have reached the end of the current interval in the cycle, move on... + CycleIntervalIterator.MoveNext(); + } + } else { + if (CycleIntervalIterator.LeftSample.StoppingTime.IsEqual(PreviousState.WaitTime)) { + // we needed to stop at the current interval in the cycle and have already waited enough time, move on.. + CycleIntervalIterator.MoveNext(); + } } } @@ -248,10 +279,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var retVal = new List<DrivingCycleData.DrivingCycleEntry>(); var cycleIterator = CycleIntervalIterator.Clone(); + var velocity = cycleIterator.LeftSample.VehicleTargetSpeed; do { + if (cycleIterator.RightSample.VehicleTargetSpeed.IsEqual(velocity)) { + continue; + } retVal.Add(cycleIterator.RightSample); + velocity = cycleIterator.RightSample.VehicleTargetSpeed; } while (cycleIterator.MoveNext() && cycleIterator.RightSample.Distance < PreviousState.Distance + lookaheadDistance); + if (retVal.Count > 0) { + retVal = retVal.Where(x => x.Distance <= PreviousState.Distance + lookaheadDistance).ToList(); + retVal.Sort((x, y) => x.Distance.CompareTo(y.Distance)); + } return retVal; } diff --git a/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/Models/SimulationComponent/Impl/Driver.cs index bf7e41b5851d1ec759bd1debc668fff0127e0c97..1616ce94117f6ed41c8ce6ce726566e7d403bda2 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Driver.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Driver.cs @@ -148,8 +148,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl }); if (retVal == null) { - // unhandled response (overload, delta > 0) - we need to search for a valid operating point.. - var nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, response); + // unhandled response (overload, delta > 0) - we need to search for a valid operating point.. + + OperatingPoint nextOperatingPoint; + try { + nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, response); + } catch (VectoSimulationException) { + // in case of an exception during search the engine-speed got too low - gear disengaged, try roll action. + nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, response); + } var limitedOperatingPoint = LimitAccelerationByDriverModel(nextOperatingPoint, LimitationMode.LimitDecelerationDriver); @@ -255,9 +262,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // return response; //} - operatingPoint = SearchOperatingPoint(absTime, operatingPoint.SimulationDistance, gradient, - operatingPoint.Acceleration, response, coasting: true); - + try { + operatingPoint = SearchOperatingPoint(absTime, operatingPoint.SimulationDistance, gradient, + operatingPoint.Acceleration, response, coasting: true); + } catch (VectoSimulationException) { + // in case of an exception during search the engine-speed got too low - gear disengaged, try roll action. + operatingPoint = SearchOperatingPoint(absTime, operatingPoint.SimulationDistance, gradient, + operatingPoint.Acceleration, response, coasting: true); + } if (!ds.IsEqual(operatingPoint.SimulationDistance)) { // vehicle is at low speed, coasting would lead to stop before ds is reached. Log.Debug("SearchOperatingPoint reduced the max. distance: {0} -> {1}. Issue new request from driving cycle!", @@ -293,7 +305,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Case<ResponseSuccess>(). Case<ResponseUnderload>(). // driver limits acceleration, operating point may be below engine's //drag load resp. below 0 - //Case<ResponseOverload>(). // driver limits acceleration, operating point may be above 0 (GBX), use brakes + Case<ResponseOverload>(). // driver limits acceleration, operating point may be above 0 (GBX), use brakes Case<ResponseGearShift>(). Case<ResponseFailTimeInterval>(r => { retVal = new ResponseDrivingCycleDistanceExceeded() { @@ -381,8 +393,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl }; } - Log.Debug("Found operating point for breaking. dt: {0}, acceleration: {1}", operatingPoint.SimulationInterval, - operatingPoint.Acceleration); + Log.Debug("Found operating point for breaking. dt: {0}, acceleration: {1} brakingPower: {2}", + operatingPoint.SimulationInterval, + operatingPoint.Acceleration, DataBus.BreakPower); + if (DataBus.BreakPower < 0) { + DataBus.BreakPower = 0.SI<Watt>(); + return new ResponseOverload { Source = this }; + } retVal = NextComponent.Request(absTime, operatingPoint.SimulationInterval, operatingPoint.Acceleration, gradient); @@ -488,7 +505,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var response = (ResponseDryRun) NextComponent.Request(absTime, operatingPoint.SimulationInterval, operatingPoint.Acceleration, gradient, true); - var delta = DataBus.ClutchClosed(absTime) ? response.DeltaDragLoad : response.GearboxPowerRequest; + var delta = DataBus.ClutchClosed(absTime) ? response.DeltaDragLoad : response.GearboxPowerRequest; if (delta.IsEqual(0.SI<Watt>(), Constants.SimulationSettings.EnginePowerSearchTolerance)) { LogManager.EnableLogging(); @@ -516,7 +533,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Log.Warn("Exceeded max iterations when searching for operating point!"); Log.Warn("exceeded: {0} ... {1}", ", ".Join(debug.Take(5)), ", ".Join(debug.Slice(-6))); Log.Error("Failed to find operating point for breaking!"); - throw new VectoSimulationException("Failed to find operating point for breaking!exceeded: {0} ... {1}", + throw new VectoSearchFailedException("Failed to find operating point for breaking!exceeded: {0} ... {1}", ", ".Join(debug.Take(5)), ", ".Join(debug.Slice(-6))); } @@ -607,6 +624,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl (ResponseDryRun)NextComponent.Request(absTime, retVal.SimulationInterval, retVal.Acceleration, gradient, true); delta = actionRoll ? response.GearboxPowerRequest : (coasting ? response.DeltaDragLoad : response.DeltaFullLoad); + if (response is ResponseEngineSpeedTooLow) { + LogManager.EnableLogging(); + Log.Debug("Got EngineSpeedTooLow during SearchOperatingPoint. Aborting!"); + throw new VectoSimulationException("EngineSpeed too low during search."); + } + if (delta.IsEqual(0.SI<Watt>(), Constants.SimulationSettings.EnginePowerSearchTolerance)) { LogManager.EnableLogging(); Log.Debug("found operating point in {0} iterations. Engine Power req: {2}, Gearbox Power req: {3} delta: {1}", @@ -622,7 +645,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Log.Warn("exceeded: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.delta)), ", ".Join(debug.Slice(-6).Select(x => x.delta))); Log.Error("Failed to find operating point! absTime: {0}", absTime); - throw new VectoSimulationException("Failed to find operating point! exceeded: {0} ... {1}", + throw new VectoSearchFailedException("Failed to find operating point! exceeded: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.delta)), ", ".Join(debug.Slice(-6).Select(x => x.delta))); } @@ -751,10 +774,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// <returns></returns> public IResponse DrivingActionHalt(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) { - if (!targetVelocity.IsEqual(0) || !DataBus.VehicleSpeed.IsEqual(0)) { + if (!targetVelocity.IsEqual(0) || !DataBus.VehicleSpeed.IsEqual(0, 1e-3)) { throw new NotImplementedException("TargetVelocity or VehicleVelocity is not zero!"); } - DataBus.BreakPower = double.PositiveInfinity.SI<Watt>(); + DataBus.BreakPower = Double.PositiveInfinity.SI<Watt>(); var retVal = NextComponent.Request(absTime, dt, 0.SI<MeterPerSquareSecond>(), gradient); retVal.Switch(). Case<ResponseGearShift>(r => { @@ -809,6 +832,16 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl LimitDecelerationLookahead = 0x4 } + public DrivingBehavior DriverBehavior + { + get { return DriverStrategy.DriverBehavior; } + } + public bool VehicleStopped { get; protected set; } + + public DrivingBehavior DrivingBehavior + { + get { return DriverStrategy.DriverBehavior; } + } } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs index 397f38c4b45351030083b315ed549640042bc0c8..7f7016162042e10a0dc9a2205a621f5de882bd88 100644 --- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs @@ -75,6 +75,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return NextComponent.Initialize(Data.Entries[index].EngineTorque, Data.Entries[index].EngineSpeed); } + public Meter StartDistance + { + get { throw new NotImplementedException(); } + } + #endregion #region ITnInPort diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs index eedbdaeda2a9d6884a8f6247e022025ca4d4d141..b528cbe88a3b911140c45f4167627b97a9732ed8 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs @@ -186,6 +186,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// </returns> public IResponse Request(Second absTime, Second dt, NewtonMeter torque, PerSecond angularVelocity, bool dryRun) { + Log.Debug("Gearbox Power Request: torque: {0}, angularVelocity: {1}", torque, angularVelocity); if (DataBus.VehicleStopped) { _shiftTime = absTime; } @@ -293,6 +294,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } if (dryRun) { + if ((DataBus.DrivingBehavior == DrivingBehavior.Braking || DataBus.DrivingBehavior == DrivingBehavior.Coasting) && + inEngineSpeed < DataBus.EngineIdleSpeed && + DataBus.VehicleSpeed < Constants.SimulationSettings.VehicleStopClutchDisengageSpeed) { + _disengaged = true; + _shiftTime = absTime + dt; + _strategy.Disengage(absTime, dt, outTorque, outAngularVelocity); + Log.Debug("EngineSpeed is below IdleSpeed, Gearbox disengage!"); + return new ResponseEngineSpeedTooLow() { Source = this, GearboxPowerRequest = outTorque * outAngularVelocity }; + } var dryRunResponse = NextComponent.Request(absTime, dt, inTorque, inEngineSpeed, true); dryRunResponse.GearboxPowerRequest = outTorque * outAngularVelocity; return dryRunResponse; diff --git a/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs b/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs index 7261ffba83022f26917342a65ddaeb23975cffc6..3c0cb58e8dc87154e5c444b0b6ef09f712811638 100644 --- a/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs +++ b/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs @@ -289,18 +289,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Gearbox.Gear = tryNextGear; var response = (ResponseDryRun)Gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); Gearbox.Gear = tmpGear; - - inAngularVelocity = Data.Gears[tryNextGear].Ratio * outAngularVelocity; - inTorque = response.ClutchPowerRequest / inAngularVelocity; - - // if next gear supplied enough power reserve: take it - // otherwise take - if (!IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity)) { - var fullLoadPower = response.EnginePowerRequest - response.DeltaFullLoad; - var reserve = 1 - (response.EnginePowerRequest / fullLoadPower).Cast<Scalar>(); - - if (reserve >= Data.TorqueReserve) { - NextGear = tryNextGear; + if (!(response is ResponseEngineSpeedTooLow)) { + inAngularVelocity = Data.Gears[tryNextGear].Ratio * outAngularVelocity; + inTorque = response.ClutchPowerRequest / inAngularVelocity; + + // if next gear supplied enough power reserve: take it + // otherwise take + if (!IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity)) { + var fullLoadPower = response.EnginePowerRequest - response.DeltaFullLoad; + var reserve = 1 - (response.EnginePowerRequest / fullLoadPower).Cast<Scalar>(); + + if (reserve >= Data.TorqueReserve) { + NextGear = tryNextGear; + } } } } diff --git a/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs index 1fa19a646fc91702baac7fd713e4862de02c5c14..49c2374a056e88e6416760d3a48a36b44210c3dc 100644 --- a/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs @@ -69,6 +69,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl throw new NotImplementedException(); } + public Meter StartDistance + { + get { return 0.SI<Meter>(); } + } + #endregion #region IDrivingCycleInPort diff --git a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs index 581d1a8bf86c1108edfb789b51c49b2fb17dd23d..1472ab894312eea87f5be8fc2b5eaae5ec5ce70f 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs @@ -77,7 +77,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IResponse Initialize(MeterPerSecond vehicleSpeed, Radian roadGradient) { _previousState = new VehicleState { - Distance = 0.SI<Meter>(), + Distance = DataBus.CycleStartDistance, Velocity = vehicleSpeed, RollingResistance = RollingResistance(roadGradient), SlopeResistance = SlopeResistance(roadGradient) @@ -89,7 +89,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl + _previousState.SlopeResistance; _currentState = new VehicleState { - Distance = 0.SI<Meter>(), + Distance = DataBus.CycleStartDistance, Velocity = vehicleSpeed, AirDragResistance = _previousState.AirDragResistance, RollingResistance = _previousState.RollingResistance, diff --git a/VectoCoreTest/Integration/CoachPowerTrain.cs b/VectoCoreTest/Integration/CoachPowerTrain.cs index f4636825f6a8e1775f1da5e1fdf97a4e9aa53a4e..f84820d81015c7ee2e60fbde046e80d8f543c841 100644 --- a/VectoCoreTest/Integration/CoachPowerTrain.cs +++ b/VectoCoreTest/Integration/CoachPowerTrain.cs @@ -32,7 +32,7 @@ namespace TUGraz.VectoCore.Tests.Integration { var container = CreatePowerTrain(cycleData, modFileName, overspeed); - return new DistanceRun(container); + return new DistanceRun("", container); } diff --git a/VectoCoreTest/Integration/DriverStrategy/DriverStrategyTestTruck.cs b/VectoCoreTest/Integration/DriverStrategy/DriverStrategyTestTruck.cs index a506e47089b58552fbb830afd0a954e3aa342b22..7d68a0ba7968631a3f7f7fbdb9e0f744ff3a54b0 100644 --- a/VectoCoreTest/Integration/DriverStrategy/DriverStrategyTestTruck.cs +++ b/VectoCoreTest/Integration/DriverStrategy/DriverStrategyTestTruck.cs @@ -10,7 +10,7 @@ namespace TUGraz.VectoCore.Tests.Integration.DriverStrategy [TestInitialize] public void DisableLogging() { - LogManager.DisableLogging(); + //LogManager.DisableLogging(); //GraphWriter.Disable(); } @@ -814,6 +814,49 @@ namespace TUGraz.VectoCore.Tests.Integration.DriverStrategy @"..\..\TestData\Integration\DriverStrategy\Vecto2.2\40t Truck_Overspeed\40t_Long_Haul_Truck_Cycle_Accelerate_0_40_downhill_1.vmod"); } + [TestMethod] + public void Truck_Accelerate_Decelerate_Downhill_overspeed() + { + var cycleData = new string[] { + // <s>,<v>,<grad>,<stop> + " 0, 60, 0, 0", + " 10, 60, -6, 0", + "100, 55, -6, 0", + "300, 55, -6, 0" + }; + var cycle = SimpleDrivingCycles.CreateCycleData(cycleData); + + Truck40tPowerTrain.CreateEngineeringRun(cycle, "Truck_DriverStrategy_Accelerate_Decelerate-overspeed.vmod", true) + .Run(); + } + + [TestMethod] + public void Truck_SlopeChangeBeforeStop() + { + var cycleData = new string[] { + // <s>,<v>,<grad>,<stop> + " 0, 60, -1.4, 0", + "198, 60, -1.7, 0", + "200, 0, -1.7, 4", + }; + var cycle = SimpleDrivingCycles.CreateCycleData(cycleData); + + Truck40tPowerTrain.CreateEngineeringRun(cycle, "Truck_DriverStrategy_SlopeChangeBeforeStop.vmod") + .Run(); + } + + [TestMethod] + public void Truck_FrequentSlopeChanges() + { + var cycleData = new string[] { + // <s>,<v>,<grad>,<stop> + " 0, 60, 0, 0", + " 10, 60, -6, 0", + "100, 55, -6, 0", + "300, 55, -6, 0" + }; + } + #endregion } } \ No newline at end of file diff --git a/VectoCoreTest/Integration/FullCycleDeclarationTest.cs b/VectoCoreTest/Integration/FullCycleDeclarationTest.cs index 5ec6e05684aa54b21760e0f06ac67df4753bfc44..654f193d225713abefb6dd80198f22906d01a9a0 100644 --- a/VectoCoreTest/Integration/FullCycleDeclarationTest.cs +++ b/VectoCoreTest/Integration/FullCycleDeclarationTest.cs @@ -1,7 +1,31 @@ -namespace TUGraz.VectoCore.Tests.Integration +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NLog; +using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.FileIO.Reader.Impl; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.Impl; + +namespace TUGraz.VectoCore.Tests.Integration { + [TestClass] public class FullCycleDeclarationTest { - + public const string TruckDeclarationJob = @"TestData\Integration\DeclarationMode\40t Truck\40t_Long_Haul_Truck.vecto"; + + [TestMethod] + public void Truck40tDeclarationTest() + { + //LogManager.DisableLogging(); + + var factory = new SimulatorFactory(SimulatorFactory.FactoryMode.DeclarationMode, TruckDeclarationJob); + var sumFileName = Path.GetFileNameWithoutExtension(TruckDeclarationJob) + Constants.FileExtensions.SumFile; + var sumWriter = new SummaryFileWriter(sumFileName); + var jobContainer = new JobContainer(sumWriter); + + jobContainer.AddRuns(factory); + + jobContainer.Execute(); + } } } \ No newline at end of file diff --git a/VectoCoreTest/Integration/Truck40tPowerTrain.cs b/VectoCoreTest/Integration/Truck40tPowerTrain.cs index b3d3daa92c93979b9e864c1ffbbcbe8d1a1dc753..841500e4020fb3471eb8901c79b6f121e1d3c294 100644 --- a/VectoCoreTest/Integration/Truck40tPowerTrain.cs +++ b/VectoCoreTest/Integration/Truck40tPowerTrain.cs @@ -31,7 +31,7 @@ namespace TUGraz.VectoCore.Tests.Integration { var container = CreatePowerTrain(cycleData, modFileName, 7500.SI<Kilogram>(), 19300.SI<Kilogram>(), overspeed); - return new DistanceRun(container); + return new DistanceRun("", container); } public static VectoRun CreateEngineeringRun(DrivingCycleData cycleData, string modFileName, Kilogram massExtra, @@ -39,7 +39,7 @@ namespace TUGraz.VectoCore.Tests.Integration { var container = CreatePowerTrain(cycleData, modFileName, massExtra, loading); - return new DistanceRun(container); + return new DistanceRun("", container); } public static VehicleContainer CreatePowerTrain(DrivingCycleData cycleData, string modFileName, Kilogram massExtra, diff --git a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs index 577cc66758923033820191bbbe894a801e341af7..7a52652f53aeb457fe0a9006a374972a1dcbf654 100644 --- a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs @@ -391,6 +391,66 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent //dataWriter.Finish(); } + [TestMethod] + public void EngineIdleControllerTest2Truck() + { + VehicleContainer container; + CombustionEngine engine; + ITnOutPort requestPort; + VehicleContainer(TruckEngine, out container, out engine, out requestPort); + + //var dataWriter = new ModalDataWriter("EngienIdle.vmod"); + //container.DataWriter = dataWriter; + + var absTime = 0.SI<Second>(); + var dt = Constants.SimulationSettings.TargetTimeInterval; + + var angularVelocity = 95.5596.SI<PerSecond>(); + var torque = (engine.Data.FullLoadCurve.DragLoadStationaryPower(angularVelocity) - 5000.SI<Watt>()) / angularVelocity; + + var response = requestPort.Initialize(torque, angularVelocity); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + response = requestPort.Request(absTime, dt, torque, angularVelocity); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + Assert.AreEqual(-14829.79713, response.EnginePowerRequest.Value(), Tolerance); + container.CommitSimulationStep(absTime, dt); + absTime += dt; + + var engineSpeed = new PerSecond[] { + 1680.RPMtoRad(), 1680.RPMtoRad(), 1467.014.RPMtoRad(), 1272.8658.RPMtoRad(), 1090.989.RPMtoRad(), + 915.3533.RPMtoRad(), 738.599.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), + 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), 560.RPMtoRad(), + 560.RPMtoRad() + }; + var enginePower = new Watt[] { + 5000.SI<Watt>(), 5000.SI<Watt>(), -32832.8834.SI<Watt>(), -25025.1308.SI<Watt>(), -19267.0360.SI<Watt>(), + -14890.1962.SI<Watt>(), -11500.7991.SI<Watt>(), -8091.0577.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), + 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), + 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>(), 5000.SI<Watt>() + }; + + var engSpeedResults = new List<dynamic>(); + torque = 0.SI<NewtonMeter>(); + for (var i = 0; i < engineSpeed.Count(); i++) { + response = requestPort.Request(absTime, dt, torque, null); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + container.CommitSimulationStep(absTime, dt); + + engSpeedResults.Add(new { + absTime, + engine.PreviousState.EngineSpeed, + engine.PreviousState.EnginePower + }); + //Assert.AreEqual(engineSpeed[i].Value(), engine.PreviousState.EngineSpeed.Value(), Tolerance); + //Assert.AreEqual(enginePower[i].Value(), engine.PreviousState.EnginePower.Value(), Tolerance); + + absTime += dt; + } + //dataWriter.Finish(); + } + [TestMethod, Ignore] public void TestWriteToFile() { diff --git a/VectoCoreTest/Models/SimulationComponent/DistanceBasedDrivingCycleTest.cs b/VectoCoreTest/Models/SimulationComponent/DistanceBasedDrivingCycleTest.cs index adcb0c8ee4d107ee6880a45d3fc45b3a42532231..467c740219df90c8c1f1ac54123479e02cf3b9bc 100644 --- a/VectoCoreTest/Models/SimulationComponent/DistanceBasedDrivingCycleTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/DistanceBasedDrivingCycleTest.cs @@ -6,6 +6,7 @@ using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Tests.Integration; using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Utils; @@ -18,6 +19,97 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent public const double Tolerance = 0.0001; + + [TestMethod] + public void TestLimitRequst() + { + var data = new string[] { + // <s>,<v>,<grad>,<stop> + " 0, 20, 0, 0", + " 1, 20, -0.1, 0", + " 2, 20, -0.3, 0", + " 10, 40, -0.3, 0", + " 19, 40, -0.2, 0", + " 20, 30, -0.1, 0" + }; + var cycleData = SimpleDrivingCycles.CreateCycleData(data); + var container = new VehicleContainer(); + var cycle = new DistanceBasedDrivingCycle(container, cycleData); + + var gbx = new MockGearbox(container); + + var driver = new MockDriver(container); + cycle.InPort().Connect(driver.OutPort()); + + cycle.OutPort().Initialize(); + + // just in test mock driver + driver.VehicleStopped = false; + + var absTime = 0.SI<Second>(); + + // a request up to 10m succeeds, no speed change for the next 10m + + var response = cycle.OutPort().Request(absTime, 0.3.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + response = cycle.OutPort().Request(absTime, 1.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + response = cycle.OutPort().Request(absTime, 1.3.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + response = cycle.OutPort().Request(absTime, 2.7.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + response = cycle.OutPort().Request(absTime, 3.5.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + // a request with 12m exceeds the speed change at 10m -> maxDistance == 10m + + response = cycle.OutPort().Request(absTime, 12.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseDrivingCycleDistanceExceeded)); + Assert.AreEqual(10, ((ResponseDrivingCycleDistanceExceeded)response).MaxDistance.Value()); + + response = cycle.OutPort().Request(absTime, 10.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + // drive 10m + container.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; + + // - - - - - - - - + // request with 8m succeeds + + response = cycle.OutPort().Request(absTime, 8.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + + container.CommitSimulationStep(absTime, response.SimulationInterval); + absTime += response.SimulationInterval; + + // - - - - - - - - + // request with 3m more -> distance exceeded. maxDistance == 2m (approach next speed change, we are within 5m radius) + + response = cycle.OutPort().Request(absTime, 3.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseDrivingCycleDistanceExceeded)); + Assert.AreEqual(2, ((ResponseDrivingCycleDistanceExceeded)response).MaxDistance.Value()); + + // - - - - - - - - + // request with 1m (18 -> 19m) => response exceeded, drive up to next sample point (at least 5m) + response = cycle.OutPort().Request(absTime, 1.SI<Meter>()); + Assert.IsInstanceOfType(response, typeof(ResponseDrivingCycleDistanceExceeded)); + Assert.AreEqual(5, ((ResponseDrivingCycleDistanceExceeded)response).MaxDistance.Value()); + + // next request with 5m, as suggested => distance exceeded. maxDistance == 2m (next speed change).... + response = cycle.OutPort().Request(absTime, ((ResponseDrivingCycleDistanceExceeded)response).MaxDistance); + Assert.IsInstanceOfType(response, typeof(ResponseDrivingCycleDistanceExceeded)); + Assert.AreEqual(2, ((ResponseDrivingCycleDistanceExceeded)response).MaxDistance.Value()); + + // ok + response = cycle.OutPort().Request(absTime, ((ResponseDrivingCycleDistanceExceeded)response).MaxDistance); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); + } + [TestMethod] public void TestDistanceRequest() { @@ -36,7 +128,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent // just in test mock driver driver.VehicleStopped = false; - var startDistance = cycleData.Entries.First().Distance.Value(); + var startDistance = container.CycleStartDistance.Value(); var absTime = 0.SI<Second>(); // waiting time of 40 seconds is split up to 3 steps: 0.5, 39, 0.5 @@ -74,7 +166,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent container.CommitSimulationStep(absTime, response.SimulationInterval); absTime += response.SimulationInterval; - + response = cycle.OutPort().Request(absTime, 1.SI<Meter>()); Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); diff --git a/VectoCoreTest/Utils/MockAuxiliaryDemand.cs b/VectoCoreTest/Utils/MockAuxiliaryDemand.cs index 08f4e274ade8310741478578aa679bad64fa23a2..b193adf3c54732c7d6d7683bff23a01d73de9e13 100644 --- a/VectoCoreTest/Utils/MockAuxiliaryDemand.cs +++ b/VectoCoreTest/Utils/MockAuxiliaryDemand.cs @@ -47,6 +47,11 @@ namespace TUGraz.VectoCore.Tests.Utils _right.MoveNext(); } + public Meter CycleStartDistance + { + get { return _left.Current.Distance; } + } + public IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Meter lookaheadDistance) { return new List<DrivingCycleData.DrivingCycleEntry>(); diff --git a/VectoCoreTest/Utils/MockDriver.cs b/VectoCoreTest/Utils/MockDriver.cs index 4fe7209ad379a6afa1b6366230efcf92b78ce569..971d6f394cb576e16bdd9c185c78e8308982e1be 100644 --- a/VectoCoreTest/Utils/MockDriver.cs +++ b/VectoCoreTest/Utils/MockDriver.cs @@ -80,6 +80,13 @@ namespace TUGraz.VectoCore.Tests.Utils public Radian Gradient; } + //public MeterPerSquareSecond DriverAcceleration { get; set; } + public bool VehicleStopped { get; set; } + + public DrivingBehavior DrivingBehavior + { + get { throw new NotImplementedException(); } + } } } \ No newline at end of file diff --git a/VectoCoreTest/VectoCoreTest.csproj b/VectoCoreTest/VectoCoreTest.csproj index f1c7a4b6259d31b49e1df1a876bd2c04e7c3da07..43fc0f262540fa66aa7e60c95e4c9a7ea9effb3b 100644 --- a/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCoreTest/VectoCoreTest.csproj @@ -283,6 +283,40 @@ <None Include="TestData\EngineFullLoadJumps.csv"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\40t_Long_Haul_Truck.pdf" /> + <None Include="TestData\Integration\DeclarationMode\40t Truck\40t_Long_Haul_Truck.vecto"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\40t_Long_Haul_Truck.veng"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\40t_Long_Haul_Truck.vfld"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\40t_Long_Haul_Truck.vgbx"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\40t_Long_Haul_Truck.vmap"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\40t_Long_Haul_Truck.vveh"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\Axle 40t Truck.vtlm"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\Axle.vtlm"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\Direct Gear.vtlm"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\Indirect Gear.vtlm"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="TestData\Integration\DeclarationMode\40t Truck\Retarder.vrlm"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> <None Include="TestData\Integration\FullPowerTrain\1-Gear-StopTest-dist.vdri" /> <None Include="TestData\Integration\FullPowerTrain\1-Gear-Test-dist.vdri"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> diff --git a/VectoCoreTest/app.config b/VectoCoreTest/app.config index 4edb0c1d6051cbf5e7b88f11c753e5dcf05645fd..105d7a285960193a9b156bbc46ab5a8819b2192e 100644 --- a/VectoCoreTest/app.config +++ b/VectoCoreTest/app.config @@ -16,7 +16,7 @@ <targets async="true"> <target xsi:type="Console" name="ConsoleLogger" error="true" /> <target xsi:type="File" name="LogFile" fileName="${basedir}/logs/log.txt" - layout="${longdate} [${processid}@${machinename}] ${callsite} ${level:uppercase=true}: ${message}" /> + layout="${longdate} [${processid}:${threadid}@${machinename}] ${callsite} ${level:uppercase=true}: ${message}" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="LogFile" />