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

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

refactoring: computation of airdrag resistance (force, power) - more accurate

parent 87c4a759
No related branches found
No related tags found
No related merge requests found
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using TUGraz.VectoCore.Configuration;
using TUGraz.VectoCore.Exceptions;
using TUGraz.VectoCore.Models.Connector.Ports;
using TUGraz.VectoCore.Models.Declaration;
......@@ -18,6 +20,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
private VehicleState _currentState;
private readonly VehicleData _data;
private readonly Point[] _airResistanceCurve;
public MeterPerSecond VehicleSpeed
{
get { return _previousState.Velocity; }
......@@ -53,6 +57,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
public Vehicle(IVehicleContainer container, VehicleData data, double initialVelocity) : this(container, data)
{
var values = DeclarationData.AirDrag.Lookup(_data.VehicleCategory);
_airResistanceCurve = CalculateAirResistanceCurve(values);
_previousState.Velocity = initialVelocity.SI<MeterPerSecond>();
}
......@@ -76,7 +83,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
_previousState = new VehicleState {
Distance = 0.SI<Meter>(),
Velocity = vehicleSpeed,
AirDragResistance = AirDragResistance(),
AirDragResistance = AirDragResistance(0.SI<MeterPerSquareSecond>(), Constants.SimulationSettings.TargetTimeInterval),
RollingResistance = RollingResistance(roadGradient),
SlopeResistance = SlopeResistance(roadGradient)
};
......@@ -99,22 +106,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
public IResponse Initialize(MeterPerSecond vehicleSpeed, MeterPerSquareSecond startAcceleration, Radian roadGradient)
{
var tmp = _previousState.Velocity;
// set vehicle speed to get accurate airdrag resistance
_previousState.Velocity = vehicleSpeed;
_currentState.Velocity = vehicleSpeed + startAcceleration * Constants.SimulationSettings.TargetTimeInterval;
var vehicleAccelerationForce = DriverAcceleration(startAcceleration) + RollingResistance(roadGradient) +
AirDragResistance() + SlopeResistance(roadGradient);
return NextComponent.Initialize(vehicleAccelerationForce, vehicleSpeed);
AirDragResistance(startAcceleration, Constants.SimulationSettings.TargetTimeInterval) +
SlopeResistance(roadGradient);
var retVal = NextComponent.Initialize(vehicleAccelerationForce, vehicleSpeed);
_previousState.Velocity = tmp;
_currentState.Velocity = tmp;
return retVal;
}
public IResponse Request(Second absTime, Second dt, MeterPerSquareSecond accelleration, Radian gradient,
public IResponse Request(Second absTime, Second dt, MeterPerSquareSecond acceleration, Radian gradient,
bool dryRun = false)
{
Log.Debug("from Wheels: acceleration: {0}", accelleration);
Log.Debug("from Wheels: acceleration: {0}", acceleration);
_currentState.dt = dt;
_currentState.Velocity = _previousState.Velocity + accelleration * dt;
_currentState.Acceleration = acceleration;
_currentState.Velocity = _previousState.Velocity + acceleration * dt;
_currentState.Distance = _previousState.Distance + dt * (_previousState.Velocity + _currentState.Velocity) / 2;
_currentState.DriverAcceleration = DriverAcceleration(accelleration);
_currentState.DriverAcceleration = DriverAcceleration(acceleration);
_currentState.RollingResistance = RollingResistance(gradient);
_currentState.AirDragResistance = AirDragResistance();
_currentState.AirDragResistance = AirDragResistance(acceleration, dt);
_currentState.SlopeResistance = SlopeResistance(gradient);
// DriverAcceleration = vehicleAccelerationForce - RollingResistance - AirDragResistance - SlopeResistance
......@@ -140,8 +158,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
writer[ModalResultField.Proll] = (_previousState.RollingResistance * _previousState.Velocity +
_currentState.RollingResistance * _currentState.Velocity) / 2;
// TODO: comptuation of AirResistancePower is wrong!
writer[ModalResultField.Pair] = (_previousState.AirDragResistance * _previousState.Velocity +
_currentState.AirDragResistance * _currentState.Velocity) / 2;
Watt averageAirDragPower;
if (_currentState.Acceleration.IsEqual(0)) {
var vAverage = (_previousState.Velocity + _currentState.Velocity) / 2;
averageAirDragPower = (ComputeAirDragForce(vAverage) * vAverage).Cast<Watt>();
} else {
// compute the average force within the current simulation interval
// P(t) = k * v(t)^3 , v(t) = v0 + a * t // a != 0
// => P_avg = 1/T * k/(4*a) * (v1^4 - v0^4) = 1/(4*a*T)(F1*v1^2 - F0*v0^2)
var force0 = ComputeAirDragForce(_previousState.Velocity);
var force1 = ComputeAirDragForce(_currentState.Velocity);
averageAirDragPower = ((force1 * _currentState.Velocity * _currentState.Velocity -
force0 * _previousState.Velocity * _previousState.Velocity) /
(4 * _currentState.Acceleration * _currentState.dt)).Cast<Watt>();
}
writer[ModalResultField.Pair] = averageAirDragPower;
// sanity check: is the vehicle in step with the cycle?
......@@ -171,49 +203,55 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
}
protected Newton AirDragResistance()
protected Newton AirDragResistance(MeterPerSquareSecond acceleration, Second dt)
{
var vAverage = (_previousState.Velocity + _currentState.Velocity) / 2;
if (acceleration.IsEqual(0)) {
var vAverage = (_previousState.Velocity + _currentState.Velocity) / 2;
var retVal = ComputeAirDragForce(vAverage);
Log.Debug("AirDragResistance: {0}", retVal);
return retVal;
}
var vAir = vAverage;
// compute the average force within the current simulation interval
// F(t) = k * v(t)^2 , v(t) = v0 + a * t // a != 0
// => F_avg = 1/T * k/(3*a) * (v1^3 - v0^3) = 1/(3*a*T)(F1*v1 - F0*v0)
var force0 = ComputeAirDragForce(_previousState.Velocity);
var force1 = ComputeAirDragForce(_currentState.Velocity);
// todo: different CdA in different file versions!
var CdA = _data.CrossSectionArea * _data.DragCoefficient;
var result =
((force1 * _currentState.Velocity - force0 * _previousState.Velocity) / (3.0 * acceleration * dt)).Cast<Newton>();
Log.Debug("AirDragResistance: {0}", result);
return result;
}
protected Newton ComputeAirDragForce(MeterPerSecond velocity)
{
var CdA = ComputeEffectiveAirDragArea(velocity);
return (Physics.AirDensity / 2.0 * CdA * velocity * velocity).Cast<Newton>();
}
private SquareMeter ComputeEffectiveAirDragArea(MeterPerSecond velocity)
{
var CdA = _data.AerodynamicDragAera;
switch (_data.CrossWindCorrectionMode) {
case CrossWindCorrectionMode.NoCorrection:
break;
case CrossWindCorrectionMode.SpeedDependent:
var values = DeclarationData.AirDrag.Lookup(_data.VehicleCategory);
var curve = CalculateAirResistanceCurve(values);
CdA *= AirDragInterpolate(curve, vAverage);
case CrossWindCorrectionMode.DeclarationModeCorrection:
CdA = AirDragInterpolate(velocity);
break;
// todo ask raphael: What is the air cd decl mode?
//case tCdMode.CdOfVdecl
// CdA = AirDragInterpolate(curve, vAverage);
// break;
case CrossWindCorrectionMode.VAirBeta:
//todo: get data from driving cycle
//vAir = DrivingCycleData.DrivingCycleEntry.AirSpeedRelativeToVehicle;
//CdA *= AirDragInterpolate(Math.Abs(DrivingCycleData.DrivingCycleEntry.WindYawAngle))
throw new NotImplementedException("VAirBeta is not implemented");
//break;
default:
throw new NotImplementedException(string.Format(" is not implemented", _data.CrossWindCorrectionMode));
}
var retVal = (CdA * Physics.AirDensity / 2 * vAir * vAir).Cast<Newton>();
Log.Debug("AirDragResistance: {0}", retVal);
return retVal;
return CdA;
}
private double AirDragInterpolate(IEnumerable<Point> curve, MeterPerSecond x)
private SquareMeter AirDragInterpolate(MeterPerSecond x)
{
var p = curve.GetSection(c => c.X < x);
var p = _airResistanceCurve.GetSection(c => c.X < x);
if (x < p.Item1.X || p.Item2.X < x) {
Log.Error(_data.CrossWindCorrectionMode == CrossWindCorrectionMode.VAirBeta
Log.Error(_data.CrossWindCorrectionMode == CrossWindCorrectionMode.VAirBetaLookupTable
? string.Format("CdExtrapol β = {0}", x)
: string.Format("CdExtrapol v = {0}", x));
}
......@@ -224,24 +262,24 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
public class Point
{
public MeterPerSecond X;
public double Y;
public SquareMeter Y;
}
protected Point[] CalculateAirResistanceCurve(AirDrag.AirDragEntry values)
{
// todo: get from vehicle or move whole procedure to vehicle
var cdA0Actual = 0;
var cdA0Actual = _data.AerodynamicDragAera;
var betaValues = new Dictionary<int, double>();
var betaValues = new Dictionary<int, SquareMeter>();
for (var beta = 0; beta <= 12; beta++) {
var deltaCdA = values.A1 * beta + values.A2 * beta * beta + values.A3 * beta * beta * beta;
betaValues[beta] = deltaCdA;
betaValues[beta] = deltaCdA.SI<SquareMeter>();
}
var points = new List<Point> { new Point { X = 0.SI<MeterPerSecond>(), Y = 0 } };
var points = new List<Point> { new Point { X = 0.SI<MeterPerSecond>(), Y = 0.SI<SquareMeter>() } };
for (var vVeh = 60.KMPHtoMeterPerSecond(); vVeh <= 100; vVeh += 5.SI<MeterPerSecond>()) {
var cdASum = 0.0;
for (var vVeh = 60.KMPHtoMeterPerSecond(); vVeh <= 100.KMPHtoMeterPerSecond(); vVeh += 5.KMPHtoMeterPerSecond()) {
var cdASum = 0.0.SI<SquareMeter>();
for (var alpha = 0; alpha <= 180; alpha += 10) {
var vWindX = Physics.BaseWindSpeed * Math.Cos(alpha.ToRadian());
var vWindY = Physics.BaseWindSpeed * Math.Sin(alpha.ToRadian());
......@@ -292,6 +330,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
public Newton SlopeResistance;
public Newton AirDragResistance;
public Newton RollingResistance;
public MeterPerSquareSecond Acceleration { get; set; }
}
}
}
\ No newline at end of file
......@@ -8,6 +8,6 @@
public static readonly double RollResistanceExponent = 0.9;
public static readonly MeterPerSecond BaseWindSpeed = 3.SI().Kilo.Meter.Per.Hour.Cast<MeterPerSecond>();
public static readonly MeterPerSecond BaseWindSpeed = 3.KMPHtoMeterPerSecond();
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment