diff --git a/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs index d5bfb2792f74f9f69ed8bd2734ec331a5e6905b0..a3b322b17eb6642ea8bd3cfa2efa699aaadaf8f6 100644 --- a/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs +++ b/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs @@ -46,7 +46,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl throw new VectoSimulationException("Unhandled Cycle Type"); } // cycle --> driver --> vehicle --> wheels --> axleGear --> retarder --> gearBox - var driver = AddComponent(cycle, new Driver(_container, data.DriverData)); + var driver = AddComponent(cycle, new Driver(_container, data.DriverData, new DefaultDriverStrategy())); var vehicle = AddComponent(driver, new Vehicle(_container, data.VehicleData)); var wheels = AddComponent(vehicle, new Wheels(_container, data.VehicleData.DynamicTyreRadius)); var breaks = AddComponent(wheels, new Breaks(_container)); diff --git a/VectoCore/Models/SimulationComponent/IDriverActions.cs b/VectoCore/Models/SimulationComponent/IDriverActions.cs new file mode 100644 index 0000000000000000000000000000000000000000..a56d36b7808b87d632e0fcfc62cfd407b1a6e8e1 --- /dev/null +++ b/VectoCore/Models/SimulationComponent/IDriverActions.cs @@ -0,0 +1,76 @@ +using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Simulation.DataBus; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Models.SimulationComponent +{ + public interface IDriverActions + { + /// <summary> + /// perform an 'acceleration driving action', i.e., accelerate the vehicle to the given target velocity but limit the + /// acceleration by the driver model (acceleration/deceleration curve). The acceleration is adjusted such that the engine + /// is not overloaded + /// </summary> + /// <param name="absTime"></param> + /// <param name="ds"></param> + /// <param name="targetVelocity"></param> + /// <param name="gradient"></param> + /// <returns></returns> + IResponse DrivingActionAccelerate(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient); + + /// <summary> + /// perform a 'coasting driving action', i.e., the engine is operating at the full drag load. adjust the acceleration such that + /// this operating point is reached + /// </summary> + /// <param name="absTime"></param> + /// <param name="ds"></param> + /// <param name="gradient"></param> + /// <returns></returns> + IResponse DrivingActionCoast(Second absTime, Meter ds, Radian gradient); + + /// <summary> + /// perform a 'brake driving action', i.e. decelerate the vehicle by using the mechanical brakes to the next target speed + /// the deceleration is limited by the driver's acceleration/deceleration curve. + /// </summary> + /// <param name="absTime"></param> + /// <param name="ds"></param> + /// <param name="gradient"></param> + /// <param name="nextTargetSpeed"></param> + /// <returns></returns> + IResponse DrivingActionBrake(Second absTime, Meter ds, Radian gradient, MeterPerSecond nextTargetSpeed); + + /// <summary> + /// perform a 'roll driving action', i.e., the clutch is open and the vehicle rolls without motoring. adjust the acceleration + /// such that the torque at the gearbox' input (engine side) is zero + /// </summary> + /// <param name="absTime"></param> + /// <param name="ds"></param> + /// <param name="gradient"></param> + /// <returns></returns> + IResponse DrivingActionRoll(Second absTime, Meter ds, Radian gradient); + + + /// <summary> + /// perform a 'halt driving action', i.e., the vehicle stops for the given amount of time. + /// </summary> + /// <param name="absTime"></param> + /// <param name="dt"></param> + /// <param name="targetVelocity"></param> + /// <param name="gradient"></param> + /// <returns></returns> + IResponse DrivingActionHalt(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient); + + /// <summary> + /// Compute the distance required to decelerate the vehicle from the current velocity to the given target velocity + /// considering the driver's acceleration/deceleration curve + /// </summary> + /// <param name="targetSpeed"></param> + /// <returns></returns> + Meter ComputeDecelerationDistance(MeterPerSecond targetSpeed); + + /// <summary> + /// access the vehicle's data bus to get information from other components. + /// </summary> + IDataBus DataBus { get; } + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/IDriverStrategy.cs b/VectoCore/Models/SimulationComponent/IDriverStrategy.cs new file mode 100644 index 0000000000000000000000000000000000000000..222162ba95424cdc1af79f47dee682ea4ec706a5 --- /dev/null +++ b/VectoCore/Models/SimulationComponent/IDriverStrategy.cs @@ -0,0 +1,14 @@ +using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Models.SimulationComponent +{ + public interface IDriverStrategy + { + IDriverActions Driver { get; set; } + + IResponse Request(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient); + + IResponse Request(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient); + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs b/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs new file mode 100644 index 0000000000000000000000000000000000000000..9d3de106912b316d42c462fe57a46710d3d0ea54 --- /dev/null +++ b/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Models.SimulationComponent.Impl +{ + public class DefaultDriverStrategy : LoggingObject, IDriverStrategy + { + public enum DrivingMode + { + DrivingModeDrive, + DrivingModeBrake, + } + + public enum DrivingBehavior + { + //Stopped, + Accelerating, + Drive, + Coasting, + Braking, + //EcoRoll, + //OverSpeed, + } + + protected DrivingMode CurrentDrivingMode; + protected Dictionary<DrivingMode, IDriverMode> DrivingModes = new Dictionary<DrivingMode, IDriverMode>(); + + public DefaultDriverStrategy() + { + DrivingModes.Add(DrivingMode.DrivingModeDrive, new DriverModeDrive()); + DrivingModes.Add(DrivingMode.DrivingModeBrake, new DriverModeBrake()); + CurrentDrivingMode = DrivingMode.DrivingModeDrive; + } + + public IDriverActions Driver { get; set; } + + public IResponse Request(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient) + { + throw new NotImplementedException(); + } + + public IResponse Request(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) + { + return Driver.DrivingActionHalt(absTime, dt, targetVelocity, gradient); + } + + + protected IList<DrivingBehaviorEntry> GetNextDrivingActions(Meter minDistance) + { + var currentSpeed = Driver.DataBus.VehicleSpeed(); + + // distance until halt + var lookaheadDistance = Formulas.DecelerationDistance(currentSpeed, 0.SI<MeterPerSecond>(), + DeclarationData.Driver.LookAhead.Deceleration); + + var lookaheadData = Driver.DataBus.LookAhead(1.2 * lookaheadDistance); + + Log.Debug("Lookahead distance: {0} @ current speed {1}", lookaheadDistance, currentSpeed); + var nextActions = new List<DrivingBehaviorEntry>(); + for (var i = 0; i < lookaheadData.Count; i++) { + var entry = lookaheadData[i]; + if (entry.VehicleTargetSpeed < currentSpeed) { + var breakingDistance = Driver.ComputeDecelerationDistance(entry.VehicleTargetSpeed); + Log.Debug("distance to decelerate from {0} to {1}: {2}", currentSpeed, entry.VehicleTargetSpeed, + breakingDistance); + Log.Debug("adding 'Braking' starting at distance {0}", entry.Distance - breakingDistance); + nextActions.Add( + new DrivingBehaviorEntry { + Action = DefaultDriverStrategy.DrivingBehavior.Braking, + ActionDistance = entry.Distance - breakingDistance, + TriggerDistance = entry.Distance, + NextTargetSpeed = entry.VehicleTargetSpeed + }); + var coastingDistance = Formulas.DecelerationDistance(currentSpeed, entry.VehicleTargetSpeed, + DeclarationData.Driver.LookAhead.Deceleration); + Log.Debug("adding 'Coasting' starting at distance {0}", entry.Distance - coastingDistance); + nextActions.Add( + new DrivingBehaviorEntry { + Action = DefaultDriverStrategy.DrivingBehavior.Coasting, + ActionDistance = entry.Distance - coastingDistance, + TriggerDistance = entry.Distance, + NextTargetSpeed = entry.VehicleTargetSpeed + }); + } + if (entry.VehicleTargetSpeed > currentSpeed) { + nextActions.Add(new DrivingBehaviorEntry { + Action = DefaultDriverStrategy.DrivingBehavior.Accelerating, + NextTargetSpeed = entry.VehicleTargetSpeed, + TriggerDistance = entry.Distance, + ActionDistance = entry.Distance + }); + } + } + + return nextActions.OrderBy(x => x.ActionDistance).ToList(); + } + } + + //===================================== + + + public interface IDriverMode + { + IDriverActions Driver { get; set; } + + IResponse Request(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient); + } + + //===================================== + + public class DriverModeDrive : IDriverMode + { + public IDriverActions Driver { get; set; } + + public IResponse Request(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient) + { + throw new System.NotImplementedException(); + } + } + + //===================================== + + public class DriverModeBrake : IDriverMode + { + public IDriverActions Driver { get; set; } + + public IResponse Request(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient) + { + throw new System.NotImplementedException(); + } + } + + //===================================== + + [DebuggerDisplay("ActionDistance: {ActionDistance}, TriggerDistance: {TriggerDistance}, Action: {Action}")] + public class DrivingBehaviorEntry + { + public DefaultDriverStrategy.DrivingBehavior Action; + public MeterPerSecond NextTargetSpeed; + public Meter TriggerDistance; + public Meter ActionDistance; + } +} \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/Models/SimulationComponent/Impl/Driver.cs index 0aa47c30f36d871412cfa2ca8091aa1969c9800e..d0a3169ce88fe0ced5a5c56e2e1734c42228f446 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Driver.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Driver.cs @@ -9,13 +9,14 @@ using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.DataBus; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - public class Driver : VectoSimulationComponent, IDriver, IDrivingCycleOutPort, IDriverDemandInPort + public class Driver : VectoSimulationComponent, IDriver, IDrivingCycleOutPort, IDriverDemandInPort, IDriverActions { internal DriverState CurrentState = new DriverState(); @@ -23,29 +24,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected DriverData DriverData; - public enum DrivingBehavior - { - Stopped, - Accelerating, - Drive, - Coasting, - Braking, - //EcoRoll, - //OverSpeed, - } + protected IDriverStrategy DriverStrategy; - [DebuggerDisplay("ActionDistance: {ActionDistance}, TriggerDistance: {TriggerDistance}, Action: {Action}")] - public class DrivingBehaviorEntry - { - public DrivingBehavior Action; - public MeterPerSecond NextTargetSpeed; - public Meter TriggerDistance; - public Meter ActionDistance; - } - public Driver(VehicleContainer container, DriverData driverData) : base(container) + public Driver(VehicleContainer container, DriverData driverData, IDriverStrategy strategy) : base(container) { DriverData = driverData; + DriverStrategy = strategy; } public IDriverDemandInPort InPort() @@ -72,7 +57,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl "Request: absTime: {0}, ds: {1}, targetVelocity: {2}, gradient: {3} | distance: {4}, velocity: {5}", absTime, ds, targetVelocity, gradient, DataBus.Distance(), DataBus.VehicleSpeed()); - var retVal = DoHandleRequest(absTime, ds, targetVelocity, gradient); + var retVal = DriverStrategy.Request(absTime, ds, targetVelocity, gradient); + //DoHandleRequest(absTime, ds, targetVelocity, gradient); CurrentState.Response = retVal; return retVal; @@ -84,73 +70,86 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Log.Debug("==== DRIVER Request ===="); Log.Debug("Request: absTime: {0}, dt: {1}, targetVelocity: {2}, gradient: {3}", absTime, dt, targetVelocity, gradient); - var retVal = DoHandleRequest(absTime, dt, targetVelocity, gradient); + + var retVal = DriverStrategy.Request(absTime, dt, targetVelocity, gradient); + //DoHandleRequest(absTime, dt, targetVelocity, gradient); CurrentState.Response = retVal; return retVal; } - protected IResponse DoHandleRequest(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient) + //protected IResponse DoHandleRequest(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient) + //{ + // var currentDistance = DataBus.Distance(); + // var nextDrivingActions = GetNextDrivingActions(currentDistance); + + // Log.Debug(", ".Join(nextDrivingActions.Select(x => string.Format("({0}: {1})", x.ActionDistance, x.Action)))); + + + // if (CurrentState.DrivingAction.Action == DefaultDriverStrategy.DrivingBehavior.Stopped && targetVelocity >= DataBus.VehicleSpeed()) { + // CurrentState.DrivingAction.Action = DefaultDriverStrategy.DrivingBehavior.Drive; + // } + + // if (nextDrivingActions.Count > 0) { + // // if we exceeded the previous action (by accident), set the action anyway in case there is no 'next action'... + // CurrentState.DrivingAction = nextDrivingActions.LastOrDefault(x => x.ActionDistance < currentDistance) ?? + // CurrentState.DrivingAction; + + // var nextActions = nextDrivingActions.Where(x => x.ActionDistance >= currentDistance).ToList(); + // var nextDrivingAction = nextActions.GetEnumerator(); + // nextDrivingAction.MoveNext(); + // var hasNextEntry = true; + + // // if the current position matches the next action - set new action. + // if (nextDrivingAction.Current.ActionDistance <= + // currentDistance + Constants.SimulationSettings.DriverActionDistanceTolerance) { + // CurrentState.DrivingAction = nextDrivingAction.Current; + // hasNextEntry = nextDrivingAction.MoveNext(); // the current action has already been processed, look at next one... + // } + + // // check if desired distance exceeds next action point + // if (hasNextEntry && nextDrivingAction.Current.ActionDistance < currentDistance + ds) { + // Log.Debug( + // "current Distance: {3} -- Simulation Distance {0} exceeds next DrivingAction at {1}, reducing interval to {2}", ds, + // nextDrivingAction.Current.ActionDistance, nextDrivingAction.Current.ActionDistance - currentDistance, + // currentDistance); + // return new ResponseDrivingCycleDistanceExceeded { + // MaxDistance = nextDrivingAction.Current.ActionDistance - currentDistance + // }; + // } + // } else { + // if (targetVelocity > DataBus.VehicleSpeed()) { + // CurrentState.DrivingAction.Action = DefaultDriverStrategy.DrivingBehavior.Accelerating; + // } + // } + // Log.Debug("DrivingAction: {0}", CurrentState.DrivingAction.Action); + // //CurrentState.DrivingAction = nextAction; + // switch (CurrentState.DrivingAction.Action) { + // case DefaultDriverStrategy.DrivingBehavior.Accelerating: + // return DrivingActionAccelerate(absTime, ds, targetVelocity, gradient); + // case DefaultDriverStrategy.DrivingBehavior.Drive: + // return DrivingActionAccelerate(absTime, ds, targetVelocity, gradient); + // case DefaultDriverStrategy.DrivingBehavior.Coasting: + // return DrivingActionCoast(absTime, ds, gradient); + // case DefaultDriverStrategy.DrivingBehavior.Braking: + // return DoBreak(absTime, ds, gradient, CurrentState.DrivingAction.NextTargetSpeed); + // } + // throw new VectoSimulationException("unhandled driving action " + CurrentState.DrivingAction); + //} + + public IResponse DrivingActionRoll(Second absTime, Meter ds, Radian gradient) { - var currentDistance = DataBus.Distance(); - var nextDrivingActions = GetNextDrivingActions(currentDistance); - - Log.Debug(", ".Join(nextDrivingActions.Select(x => string.Format("({0}: {1})", x.ActionDistance, x.Action)))); - - - if (CurrentState.DrivingAction.Action == DrivingBehavior.Stopped && targetVelocity >= DataBus.VehicleSpeed()) { - CurrentState.DrivingAction.Action = DrivingBehavior.Drive; - } - - if (nextDrivingActions.Count > 0) { - // if we exceeded the previous action (by accident), set the action anyway in case there is no 'next action'... - CurrentState.DrivingAction = nextDrivingActions.LastOrDefault(x => x.ActionDistance < currentDistance) ?? - CurrentState.DrivingAction; - - var nextActions = nextDrivingActions.Where(x => x.ActionDistance >= currentDistance).ToList(); - var nextDrivingAction = nextActions.GetEnumerator(); - nextDrivingAction.MoveNext(); - var hasNextEntry = true; - - // if the current position matches the next action - set new action. - if (nextDrivingAction.Current.ActionDistance <= - currentDistance + Constants.SimulationSettings.DriverActionDistanceTolerance) { - CurrentState.DrivingAction = nextDrivingAction.Current; - hasNextEntry = nextDrivingAction.MoveNext(); // the current action has already been processed, look at next one... - } + throw new NotImplementedException(); + } - // check if desired distance exceeds next action point - if (hasNextEntry && nextDrivingAction.Current.ActionDistance < currentDistance + ds) { - Log.Debug( - "current Distance: {3} -- Simulation Distance {0} exceeds next DrivingAction at {1}, reducing interval to {2}", ds, - nextDrivingAction.Current.ActionDistance, nextDrivingAction.Current.ActionDistance - currentDistance, - currentDistance); - return new ResponseDrivingCycleDistanceExceeded { - MaxDistance = nextDrivingAction.Current.ActionDistance - currentDistance - }; - } - } else { - if (targetVelocity > DataBus.VehicleSpeed()) { - CurrentState.DrivingAction.Action = DrivingBehavior.Accelerating; - } - } - Log.Debug("DrivingAction: {0}", CurrentState.DrivingAction.Action); - //CurrentState.DrivingAction = nextAction; - switch (CurrentState.DrivingAction.Action) { - case DrivingBehavior.Accelerating: - return DriveOrAccelerate(absTime, ds, targetVelocity, gradient); - case DrivingBehavior.Drive: - return DriveOrAccelerate(absTime, ds, targetVelocity, gradient); - case DrivingBehavior.Coasting: - return DoCoast(absTime, ds, gradient); - case DrivingBehavior.Braking: - return DoBreak(absTime, ds, gradient, CurrentState.DrivingAction.NextTargetSpeed); - } - throw new VectoSimulationException("unhandled driving action " + CurrentState.DrivingAction); + IDataBus IDriverActions.DataBus + { + get { return DataBus; } } - private IResponse DoBreak(Second absTime, Meter ds, Radian gradient, MeterPerSecond nextTargetSpeed) + + public IResponse DrivingActionBrake(Second absTime, Meter ds, Radian gradient, MeterPerSecond nextTargetSpeed) { ComputeAcceleration(ref ds, nextTargetSpeed); @@ -167,7 +166,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } var newDs = ds; - SearchBreakingPower(absTime, ref newDs, gradient, dryRun, true); + SearchBreakingPower(absTime, ref newDs, gradient, dryRun); if (!ds.IsEqual(newDs)) { Log.Debug( @@ -188,7 +187,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; //new ResponseDrivingCycleDistanceExceeded() { SimulationInterval = CurrentState.dt }; } - private void SearchBreakingPower(Second absTime, ref Meter ds, Radian gradient, ResponseDryRun response, bool coasting) + private void SearchBreakingPower(Second absTime, ref Meter ds, Radian gradient, ResponseDryRun response) { var debug = new List<dynamic>(); // only used while testing var breakingPower = (DataBus.ClutchState() != ClutchState.ClutchClosed) @@ -241,7 +240,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl throw new VectoSimulationException("Failed to find operating point for breaking!"); } - private IResponse DriveOrAccelerate(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient) + public IResponse DrivingActionAccelerate(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient) { ComputeAcceleration(ref ds, targetVelocity); if (CurrentState.dt <= 0) { @@ -259,7 +258,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Case<ResponseEngineOverload>(r => { if (r != null && r.Delta < 0) { // if Delta is negative we are already below the Drag-load curve. activate breaks - retVal = DoBreak(absTime, ds, gradient, targetVelocity); + retVal = DrivingActionBrake(absTime, ds, gradient, targetVelocity); } else { var doAccelerate = (DataBus.VehicleSpeed() - targetVelocity).Abs() > 0.1 * targetVelocity; @@ -272,7 +271,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Case<ResponseGearboxOverload>(r => { if (r != null && r.Delta < 0) { // if Delta is negative we are below the Drag-load curve: activate breaks - retVal = DoBreak(absTime, ds, gradient, targetVelocity); + retVal = DrivingActionBrake(absTime, ds, gradient, targetVelocity); } else { var doAccelerate = (DataBus.VehicleSpeed() - targetVelocity).Abs() > 0.1 * targetVelocity; @@ -290,62 +289,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return new ResponseDrivingCycleDistanceExceeded { SimulationInterval = CurrentState.dt }; } - protected IList<DrivingBehaviorEntry> GetNextDrivingActions(Meter minDistance) - { - var currentSpeed = DataBus.VehicleSpeed(); - - // distance until halt - var lookaheadDistance = Formulas.DecelerationDistance(currentSpeed, 0.SI<MeterPerSecond>(), - DeclarationData.Driver.LookAhead.Deceleration); - - var lookaheadData = DataBus.LookAhead(1.2 * lookaheadDistance); - - Log.Debug("Lookahead distance: {0} @ current speed {1}", lookaheadDistance, currentSpeed); - var nextActions = new List<DrivingBehaviorEntry>(); - for (var i = 0; i < lookaheadData.Count; i++) { - var entry = lookaheadData[i]; - if (entry.VehicleTargetSpeed < currentSpeed) { - var breakingDistance = ComputeDecelerationDistance(entry.VehicleTargetSpeed); - Log.Debug("distance to decelerate from {0} to {1}: {2}", currentSpeed, entry.VehicleTargetSpeed, - breakingDistance); - Log.Debug("adding 'Braking' starting at distance {0}", entry.Distance - breakingDistance); - nextActions.Add( - new DrivingBehaviorEntry { - Action = DrivingBehavior.Braking, - ActionDistance = entry.Distance - breakingDistance, - TriggerDistance = entry.Distance, - NextTargetSpeed = entry.VehicleTargetSpeed - }); - var coastingDistance = Formulas.DecelerationDistance(currentSpeed, entry.VehicleTargetSpeed, - DeclarationData.Driver.LookAhead.Deceleration); - Log.Debug("adding 'Coasting' starting at distance {0}", entry.Distance - coastingDistance); - nextActions.Add( - new DrivingBehaviorEntry { - Action = DrivingBehavior.Coasting, - ActionDistance = entry.Distance - coastingDistance, - TriggerDistance = entry.Distance, - NextTargetSpeed = entry.VehicleTargetSpeed - }); - } - if (entry.VehicleTargetSpeed > currentSpeed) { - nextActions.Add(new DrivingBehaviorEntry { - Action = DrivingBehavior.Accelerating, - NextTargetSpeed = entry.VehicleTargetSpeed, - TriggerDistance = entry.Distance, - ActionDistance = entry.Distance - }); - } - } - - return nextActions.OrderBy(x => x.ActionDistance).ToList(); - } - - protected internal Meter ComputeDecelerationDistance(MeterPerSecond targetSpeed) - { - return DriverData.AccelerationCurve.ComputeAccelerationDistance(DataBus.VehicleSpeed(), targetSpeed); - } - - protected internal IResponse DoCoast(Second absTime, Meter ds, Radian gradient) + public IResponse DrivingActionCoast(Second absTime, Meter ds, Radian gradient) { ComputeAcceleration(ref ds, 0.SI<MeterPerSecond>()); @@ -480,7 +424,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// </summary> /// <param name="ds"></param> /// <param name="targetVelocity"></param> - private void ComputeAcceleration(ref Meter ds, MeterPerSecond targetVelocity) + public void ComputeAcceleration(ref Meter ds, MeterPerSecond targetVelocity) { var currentSpeed = DataBus.VehicleSpeed(); @@ -507,6 +451,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } } + + /// <summary> + /// computes the distance required to decelerate from the current velocity to the given target velocity considering + /// the drivers acceleration/deceleration curve. + /// </summary> + /// <param name="targetSpeed"></param> + /// <returns></returns> + public Meter ComputeDecelerationDistance(MeterPerSecond targetSpeed) + { + return DriverData.AccelerationCurve.ComputeAccelerationDistance(DataBus.VehicleSpeed(), targetSpeed); + } + + /// <summary> /// Computes the time interval for driving the given distance ds with the vehicle's current speed and the given acceleration. /// If the distance ds can not be reached (i.e., the vehicle would halt before ds is reached) then the distance parameter is adjusted. @@ -556,8 +513,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return solutions.Min().SI<Second>(); } - - protected IResponse DoHandleRequest(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) + /// <summary> + /// simulate a certain time interval where the vehicle is stopped. + /// </summary> + /// <param name="absTime"></param> + /// <param name="dt"></param> + /// <param name="targetVelocity"></param> + /// <param name="gradient"></param> + /// <returns></returns> + public IResponse DrivingActionHalt(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) { if (!targetVelocity.IsEqual(0) || !DataBus.VehicleSpeed().IsEqual(0)) { throw new NotImplementedException("TargetVelocity or VehicleVelocity is not zero!"); @@ -590,31 +554,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl CurrentState.RetryCount = 0; CurrentState.Response = null; - if (CurrentState.DrivingAction.NextTargetSpeed != null && - DataBus.VehicleSpeed().IsEqual(CurrentState.DrivingAction.NextTargetSpeed)) { - Log.Debug("reached target Speed {0} - set Driving action to {1}", CurrentState.DrivingAction.NextTargetSpeed, - DrivingBehavior.Drive); - CurrentState.DrivingAction.Action = DrivingBehavior.Drive; - } - if (DataBus.VehicleSpeed().IsEqual(0)) { - Log.Debug("vehicle stopped {0} - set Driving action to {1}", DataBus.VehicleSpeed(), DrivingBehavior.Stopped); - CurrentState.DrivingAction.Action = DrivingBehavior.Stopped; - } + //if (CurrentState.DrivingAction.NextTargetSpeed != null && + // DataBus.VehicleSpeed().IsEqual(CurrentState.DrivingAction.NextTargetSpeed)) { + // Log.Debug("reached target Speed {0} - set Driving action to {1}", CurrentState.DrivingAction.NextTargetSpeed, + // DefaultDriverStrategy.DrivingBehavior.Drive); + // CurrentState.DrivingAction.Action = DefaultDriverStrategy.DrivingBehavior.Drive; + //} + //if (DataBus.VehicleSpeed().IsEqual(0)) { + // Log.Debug("vehicle stopped {0}", DataBus.VehicleSpeed()); + // CurrentState.DrivingAction.Action = DefaultDriverStrategy.DrivingBehavior.Stopped; + //} } public class DriverState { - public DriverState() - { - DrivingAction = new DrivingBehaviorEntry(); - } - public Second dt; public MeterPerSquareSecond Acceleration; public IResponse Response; public int RetryCount; - public DrivingBehaviorEntry DrivingAction; } } } \ No newline at end of file diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj index e53ac9b8b2f4f20b0956db954947eb981d476711..b8ee413b92bf87c99afe5cb38ea0bca2dc70627a 100644 --- a/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore.csproj @@ -153,9 +153,12 @@ <Compile Include="Models\LoggingObject.cs" /> <Compile Include="Models\SimulationComponent\Data\GearboxType.cs" /> <Compile Include="Models\SimulationComponent\IBreaks.cs" /> + <Compile Include="Models\SimulationComponent\IDriverActions.cs" /> + <Compile Include="Models\SimulationComponent\IDriverStrategy.cs" /> <Compile Include="Models\SimulationComponent\IDrivingCycleInfo.cs" /> <Compile Include="Models\SimulationComponent\Impl\AuxiliaryData.cs" /> <Compile Include="Models\SimulationComponent\Impl\Breaks.cs" /> + <Compile Include="Models\SimulationComponent\Impl\DefaultDriverStrategy.cs" /> <Compile Include="Models\SimulationComponent\Impl\EngineOnlyCombustionEngine.cs" /> <Compile Include="Models\Simulation\DataBus\IClutchInfo.cs" /> <Compile Include="Models\Simulation\Data\AuxiliaryDemandType.cs" /> diff --git a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs index a22537390eb18fc87897d834e4d4c6b0a75caf9e..c598ad8e37e5ff58f62202f3f1f4587894fb3ea3 100644 --- a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs @@ -50,7 +50,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns var cycle = new DistanceBasedDrivingCycle(container, cycleData); var cyclePort = cycle.OutPort(); - dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData)); + dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); tmp = Port.AddComponent(tmp, new Breaks(container)); @@ -111,7 +111,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns var cycle = new DistanceBasedDrivingCycle(container, cycleData); var cyclePort = cycle.OutPort(); - dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData)); + dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); tmp = Port.AddComponent(tmp, new Breaks(container)); @@ -181,7 +181,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns var cycle = new DistanceBasedDrivingCycle(container, cycleData); var cyclePort = cycle.OutPort(); - dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData)); + dynamic tmp = Port.AddComponent(cycle, new Driver(container, driverData, new DefaultDriverStrategy())); tmp = Port.AddComponent(tmp, new Vehicle(container, vehicleData)); tmp = Port.AddComponent(tmp, new Wheels(container, vehicleData.DynamicTyreRadius)); tmp = Port.AddComponent(tmp, new Breaks(container)); diff --git a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs index d864d963daa982f2f2075a03e52c4414e38f0534..6288b959e5f3ad602a0727783caef5a3f6ddeb8c 100644 --- a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs @@ -48,7 +48,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns var sumWriter = new TestSumWriter(); var vehicleContainer = new VehicleContainer(modalWriter, sumWriter); - var driver = new Driver(vehicleContainer, driverData); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); dynamic tmp = Port.AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); tmp = Port.AddComponent(tmp, new AxleGear(vehicleContainer, axleGearData)); @@ -99,7 +99,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns var cycle = new DistanceBasedDrivingCycle(vehicleContainer, cycleData); - dynamic tmp = Port.AddComponent(cycle, new Driver(vehicleContainer, driverData)); + dynamic tmp = Port.AddComponent(cycle, new Driver(vehicleContainer, driverData, new DefaultDriverStrategy())); tmp = Port.AddComponent(tmp, new Vehicle(vehicleContainer, vehicleData)); tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); tmp = Port.AddComponent(tmp, new Breaks(vehicleContainer)); @@ -161,13 +161,14 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns var driverData = CreateDriverData(AccelerationFile2); - var modalWriter = new ModalDataWriter("Coach_MinimalPowertrainOverload.vmod", SimulatorFactory.FactoryMode.EngineeringMode); + var modalWriter = new ModalDataWriter("Coach_MinimalPowertrainOverload.vmod", + SimulatorFactory.FactoryMode.EngineeringMode); var sumWriter = new TestSumWriter(); var vehicleContainer = new VehicleContainer(modalWriter, sumWriter); var cycle = new DistanceBasedDrivingCycle(vehicleContainer, cycleData); - dynamic tmp = Port.AddComponent(cycle, new Driver(vehicleContainer, driverData)); + dynamic tmp = Port.AddComponent(cycle, new Driver(vehicleContainer, driverData, new DefaultDriverStrategy())); tmp = Port.AddComponent(tmp, new Vehicle(vehicleContainer, vehicleData)); tmp = Port.AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); tmp = Port.AddComponent(tmp, new Breaks(vehicleContainer)); diff --git a/VectoCoreTest/Models/SimulationComponent/DriverTest.cs b/VectoCoreTest/Models/SimulationComponent/DriverTest.cs index aa88e2044546e5022e38835b8b6dfa3f28a65ae2..28b9691e45e1c21eff0c707257132fc8e850c958 100644 --- a/VectoCoreTest/Models/SimulationComponent/DriverTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/DriverTest.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.Exceptions; -using TUGraz.VectoCore.FileIO.Reader; using TUGraz.VectoCore.FileIO.Reader.Impl; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; @@ -47,7 +45,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var sumWriter = new TestSumWriter(); var vehicleContainer = new VehicleContainer(modalWriter, sumWriter); - var driver = new Driver(vehicleContainer, driverData); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); var engine = new CombustionEngine(vehicleContainer, engineData); dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); @@ -64,7 +62,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var absTime = 0.SI<Second>(); - var response = driver.DoCoast(absTime, 1.SI<Meter>(), 0.SI<Radian>()); + var response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), 0.SI<Radian>()); Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); @@ -77,7 +75,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent Constants.SimulationSettings.EngineFLDPowerTolerance); while (vehicleContainer.VehicleSpeed() > 1) { - response = driver.DoCoast(absTime, 1.SI<Meter>(), 0.SI<Radian>()); + response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), 0.SI<Radian>()); Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); @@ -102,7 +100,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var sumWriter = new TestSumWriter(); var vehicleContainer = new VehicleContainer(modalWriter, sumWriter); - var driver = new Driver(vehicleContainer, driverData); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); var engine = new CombustionEngine(vehicleContainer, engineData); dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); @@ -120,7 +118,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var absTime = 0.SI<Second>(); - var response = driver.DoCoast(absTime, 1.SI<Meter>(), gradient); + var response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), gradient); Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); @@ -133,7 +131,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent Constants.SimulationSettings.EngineFLDPowerTolerance); while (vehicleContainer.VehicleSpeed() > 1) { - response = driver.DoCoast(absTime, 1.SI<Meter>(), gradient); + response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), gradient); Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); @@ -158,7 +156,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var sumWriter = new TestSumWriter(); var vehicleContainer = new VehicleContainer(modalWriter, sumWriter); - var driver = new Driver(vehicleContainer, driverData); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData)); tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius)); @@ -211,7 +209,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var vehicle = new MockVehicle(vehicleContainer); var driverData = EngineeringModeSimulationDataReader.CreateDriverDataFromFile(JobFile); - var driver = new Driver(vehicleContainer, driverData); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); driver.Connect(vehicle.OutPort()); @@ -277,7 +275,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var vehicle = new MockVehicle(vehicleContainer); var driverData = EngineeringModeSimulationDataReader.CreateDriverDataFromFile(JobFile); - var driver = new Driver(vehicleContainer, driverData); + var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy()); driver.Connect(vehicle.OutPort()); @@ -322,7 +320,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent Assert.AreEqual(2.545854078, response.SimulationInterval.Value(), Tolerance); vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; + //absTime += response.SimulationInterval; vehicle.MyVehicleSpeed += (response.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>();