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

Skip to content
Snippets Groups Projects
Forked from VECTO / VECTO Sim
5221 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
DriverTest.cs 20.11 KiB
/*
* This file is part of VECTO.
*
* Copyright © 2012-2019 European Union
*
* Developed by Graz University of Technology,
*              Institute of Internal Combustion Engines and Thermodynamics,
*              Institute of Technical Informatics
*
* VECTO is licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use VECTO except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* https://joinup.ec.europa.eu/community/eupl/og_page/eupl
*
* Unless required by applicable law or agreed to in writing, VECTO
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* Authors:
*   Stefan Hausberger, hausberger@ivt.tugraz.at, IVT, Graz University of Technology
*   Christian Kreiner, christian.kreiner@tugraz.at, ITI, Graz University of Technology
*   Michael Krisper, michael.krisper@tugraz.at, ITI, Graz University of Technology
*   Raphael Luz, luz@ivt.tugraz.at, IVT, Graz University of Technology
*   Markus Quaritsch, markus.quaritsch@tugraz.at, IVT, Graz University of Technology
*   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using TUGraz.VectoCommon.Models;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Configuration;
using TUGraz.VectoCore.InputData.Reader.ComponentData;
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.Impl;
using TUGraz.VectoCore.Models.SimulationComponent;
using TUGraz.VectoCore.Models.SimulationComponent.Data;
using TUGraz.VectoCore.Models.SimulationComponent.Impl;
using TUGraz.VectoCore.OutputData;
using TUGraz.VectoCore.OutputData.FileIO;
using TUGraz.VectoCore.Tests.Utils;
using Wheels = TUGraz.VectoCore.Models.SimulationComponent.Impl.Wheels;
using NUnit.Framework;
using TUGraz.VectoCommon.InputData;

namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
{
	[TestFixture]
	public class DriverTest
	{
		public const string JobFile = @"TestData\Jobs\24t Coach EngineOnly.vecto";
		public const string EngineFile = @"TestData\Components\24t Coach.veng";
		public const string EngineFileHigh = @"TestData\Components\24t Coach_high.veng";
		public const string AccelerationFile = @"TestData\Components\Coach.vacc";
		public const double Tolerance = 0.001;

		[OneTimeSetUp]
		public void RunBeforeAnyTests()
		{
			Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory);
		}


		[TestCase]
		public void DriverCoastingTest()
		{
			var engineData = MockSimulationDataFactory.CreateEngineDataFromFile(EngineFile, 1);

			var vehicleData = CreateVehicleData(33000.SI<Kilogram>());
			var airdragData = CreateAirdragData();
			vehicleData.DynamicTyreRadius = 0.026372213.SI<Meter>(); // take into account axle ratio, gear ratio

			var driverData = CreateDriverData();

			var fileWriter = new FileOutputWriter("Coach_MinimalPowertrain_Coasting");
			var runData = new VectoRunData() {
				JobName = "Coach_MinimalPowertrain_Coasting",
				VehicleData = vehicleData,
				AirdragData = airdragData,
				EngineData = engineData,
				ElectricMachinesData = new List<Tuple<PowertrainPosition, ElectricMotorData>>()
            };
			var modData = new ModalDataContainer(runData, fileWriter, null);
			var vehicleContainer = new VehicleContainer(ExecutionMode.Engineering, modData) {
				RunData = runData
			};
			var mockCycle = new MockDrivingCycle(vehicleContainer, null);

			var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy(vehicleContainer));
			var engine = new CombustionEngine(vehicleContainer, engineData);
			var clutch = new Clutch(vehicleContainer, engineData);
			dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData, airdragData));
			tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius, vehicleData.WheelsInertia));
			tmp = AddComponent(tmp, clutch);
			AddComponent(tmp, engine);
			clutch.IdleController = engine.IdleController;

			var gbx = new MockGearbox(vehicleContainer) { Gear = 1 };

			var driverPort = driver.OutPort();

			var velocity = 5.SI<MeterPerSecond>();
			driverPort.Initialize(velocity, 0.SI<Radian>());

			var absTime = 0.SI<Second>();

			var response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, 0.SI<Radian>());

			Assert.IsInstanceOf<ResponseSuccess>(response);

			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
			absTime += response.SimulationInterval;

			Assert.AreEqual(4.9877, vehicleContainer.VehicleInfo.VehicleSpeed.Value(), Tolerance);
			Assert.AreEqual(0.2004, response.SimulationInterval.Value(), Tolerance);
			Assert.AreEqual(engine.PreviousState.FullDragTorque.Value(), engine.PreviousState.EngineTorque.Value(),
				Constants.SimulationSettings.LineSearchTolerance);

			while (vehicleContainer.VehicleInfo.VehicleSpeed > 1.7) {
				response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, 0.SI<Radian>());

				Assert.IsInstanceOf<ResponseSuccess>(response);

				vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
				absTime += response.SimulationInterval;
				modData.Finish(VectoRun.Status.Success);
			}
			modData.Finish(VectoRun.Status.Success);
		}

		[TestCase]
		public void DriverCoastingTest2()
		{
			var engineData = MockSimulationDataFactory.CreateEngineDataFromFile(EngineFile, 1);

			var vehicleData = CreateVehicleData(33000.SI<Kilogram>());
			vehicleData.DynamicTyreRadius = 0.026372213.SI<Meter>(); // take into account axle ratio, gear ratio
			var airdragData = CreateAirdragData();
			var driverData = CreateDriverData();

			var fileWriter = new FileOutputWriter("Coach_MinimalPowertrain_Coasting");
			var runData = new VectoRunData()
			{
				JobName = "Coach_MinimalPowertrain_Coasting",
				VehicleData = vehicleData,
				EngineData = engineData,
			};
			var modData = new ModalDataContainer(runData, fileWriter, null);
            var vehicleContainer = new VehicleContainer(ExecutionMode.Engineering, modData) {
				RunData = runData
			};
			var mockCycle = new MockDrivingCycle(vehicleContainer, null);

			var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy(vehicleContainer));
			var engine = new CombustionEngine(vehicleContainer, engineData);
			var clutch = new Clutch(vehicleContainer, engineData);

			dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData, airdragData));
			tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius, vehicleData.WheelsInertia));
			tmp = AddComponent(tmp, clutch);
			AddComponent(tmp, engine);
			clutch.IdleController = engine.IdleController;

			var gbx = new MockGearbox(vehicleContainer);
			gbx.Gear = 1;

			var driverPort = driver.OutPort();

			var gradient = VectoMath.InclinationToAngle(-0.020237973 / 100.0);
			var velocity = 5.SI<MeterPerSecond>();
			driverPort.Initialize(velocity, gradient);

			var absTime = 0.SI<Second>();

			var response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, gradient);

			Assert.IsInstanceOf<ResponseSuccess>(response);

			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
			absTime += response.SimulationInterval;

			Assert.AreEqual(4.9878, vehicleContainer.VehicleInfo.VehicleSpeed.Value(), Tolerance);
			Assert.AreEqual(0.2004, response.SimulationInterval.Value(), Tolerance);
			Assert.AreEqual(engine.PreviousState.FullDragTorque.Value(), engine.PreviousState.EngineTorque.Value(),
				Constants.SimulationSettings.LineSearchTolerance);

			while (vehicleContainer.VehicleInfo.VehicleSpeed > 1.7) {
				response = driver.DrivingActionCoast(absTime, 1.SI<Meter>(), velocity, gradient);

				Assert.IsInstanceOf<ResponseSuccess>(response);

				vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
				absTime += response.SimulationInterval;
				modData.Finish(VectoRun.Status.Success);
			}
			modData.Finish(VectoRun.Status.Success);
		}

		[TestCase]
		public void DriverOverloadTest()
		{
			var engineData = MockSimulationDataFactory.CreateEngineDataFromFile(EngineFileHigh, 1);

			var vehicleData = CreateVehicleData(33000.SI<Kilogram>());
			var airdragData = CreateAirdragData();

			// take into account the axle ratio and 1st-gear ratio
			vehicleData.DynamicTyreRadius /= (3.24 * 6.38);

			var driverData = CreateDriverData();

			var fileWriter = new FileOutputWriter("Coach_MinimalPowertrain");
			var runData = new VectoRunData()
			{
				JobName = "Coach_MinimalPowertrain",
				VehicleData = vehicleData,
				AirdragData = airdragData,
				EngineData = engineData,
				ElectricMachinesData = new List<Tuple<PowertrainPosition, ElectricMotorData>>()
			};
			var modData = new ModalDataContainer(runData, fileWriter, null);
            var vehicleContainer = new VehicleContainer(ExecutionMode.Engineering, modData) {
				RunData = runData
			};

			var cycle = new MockDrivingCycle(vehicleContainer, null);
			var brakes = new Brakes(vehicleContainer);
			var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy(vehicleContainer));

			dynamic tmp = AddComponent(driver, new Vehicle(vehicleContainer, vehicleData, airdragData));
			tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius, vehicleData.WheelsInertia));
			var engine = new CombustionEngine(vehicleContainer, engineData);
			var clutch = new Clutch(vehicleContainer, engineData);
			clutch.IdleController = engine.IdleController;
			tmp = AddComponent(tmp, clutch);
			AddComponent(tmp, engine);

			var gbx = new MockGearbox(vehicleContainer);
			gbx.Gear = 1;

			var driverPort = driver.OutPort();

			driverPort.Initialize(0.SI<MeterPerSecond>(), 0.SI<Radian>());

			var absTime = 0.SI<Second>();

			var response = driverPort.Request(absTime, 1.SI<Meter>(), 20.SI<MeterPerSecond>(), 0.SI<Radian>());

			Assert.IsInstanceOf<ResponseSuccess>(response);

			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
			absTime += response.SimulationInterval;

			Assert.AreEqual(0.24182, modData.GetValues<SI>(ModalResultField.acc).Last().Value(), Tolerance);

			response = driverPort.Request(absTime, 1.SI<Meter>(), 20.SI<MeterPerSecond>(), 0.SI<Radian>());

			Assert.IsInstanceOf<ResponseSuccess>(response);

			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
			absTime += response.SimulationInterval;

			Assert.AreEqual(0.2900, modData.GetValues<SI>(ModalResultField.acc).Last().Value(), Tolerance);
		}

		[TestCase]
		public void DriverAccelerationTest()
		{
			var vehicleContainer = new VehicleContainer(ExecutionMode.Engineering) {
				RunData = new VectoRunData() {
					VehicleData = new VehicleData() { VehicleCategory = VehicleCategory.RigidTruck},
				}
			};
			var vehicle = new MockVehicle(vehicleContainer);

			var driverData = MockSimulationDataFactory.CreateDriverDataFromFile(JobFile);
			var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy(vehicleContainer));

			new MockEngine(vehicleContainer);
			new EngineOnlyGearboxInfo(vehicleContainer);
			new ATClutchInfo(vehicleContainer);

			var cycle = new MockDrivingCycle(vehicleContainer, null);
			var brakes = new Brakes(vehicleContainer);
			driver.Connect(vehicle.OutPort());

			vehicle.MyVehicleSpeed = 0.SI<MeterPerSecond>();
			var absTime = 0.SI<Second>();
			var ds = 1.SI<Meter>();
			var gradient = 0.SI<Radian>();

			var targetVelocity = 5.SI<MeterPerSecond>();

			//			var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient);

			var accelerations = new[] {
				1.01570922, 1.384540943, 1.364944972, 1.350793466, 1.331848649, 1.314995215, 1.2999934,
				1.281996392, 1.255462262
			};
			var simulationIntervals = new[] {
				1.403234648, 0.553054094, 0.405255346, 0.33653593, 0.294559444, 0.26555781, 0.243971311, 0.22711761,
				0.213554656
			};

			// accelerate from 0 to just below the target velocity and test derived simulation intervals & accelerations
			for (var i = 0; i < accelerations.Length; i++) {
				var tmpResponse = driver.OutPort().Request(absTime, ds, targetVelocity, gradient);

				Assert.IsInstanceOf<ResponseSuccess>(tmpResponse);
				Assert.AreEqual(accelerations[i], vehicle.LastRequest.acceleration.Value(), Tolerance);
				Assert.AreEqual(simulationIntervals[i], tmpResponse.SimulationInterval.Value(), Tolerance);

				vehicleContainer.CommitSimulationStep(absTime, tmpResponse.SimulationInterval);
				absTime += tmpResponse.SimulationInterval;
				vehicle.MyVehicleSpeed +=
					(tmpResponse.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>();
			}

			// full acceleration would exceed target velocity, driver should limit acceleration such that target velocity is reached...
			var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient);

			Assert.IsInstanceOf<ResponseSuccess>(response);
			Assert.AreEqual(0.899715479, vehicle.LastRequest.acceleration.Value(), Tolerance);
			Assert.AreEqual(0.203734517, response.SimulationInterval.Value(), Tolerance);

			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
			absTime += response.SimulationInterval;
			vehicle.MyVehicleSpeed +=
				(response.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>();

			Assert.AreEqual(targetVelocity.Value(), vehicle.MyVehicleSpeed.Value(), Tolerance);

			// vehicle has reached target velocity, no further acceleration necessary...

			response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient);

			Assert.IsInstanceOf<ResponseSuccess>(response);
			Assert.AreEqual(0, vehicle.LastRequest.acceleration.Value(), Tolerance);
			Assert.AreEqual(0.2, response.SimulationInterval.Value(), Tolerance);
		}
		[TestCase]
		public void DriverDecelerationTest()
		{
			var vehicleContainer = new VehicleContainer(ExecutionMode.Engineering) {
				RunData = new VectoRunData() {
					VehicleData = new VehicleData() { VehicleCategory = VehicleCategory.RigidTruck }
				}
			};
			var vehicle = new MockVehicle(vehicleContainer);
			new MockEngine(vehicleContainer);
			new EngineOnlyGearboxInfo(vehicleContainer);
			new ATClutchInfo(vehicleContainer);

			var driverData = MockSimulationDataFactory.CreateDriverDataFromFile(JobFile);
			var driver = new Driver(vehicleContainer, driverData, new DefaultDriverStrategy(vehicleContainer));

			var cycle = new MockDrivingCycle(vehicleContainer, null);
			var brakes = new Brakes(vehicleContainer);
			driver.Connect(vehicle.OutPort());

			vehicle.MyVehicleSpeed = 5.SI<MeterPerSecond>();
			var absTime = 0.SI<Second>();
			var ds = 1.SI<Meter>();
			var gradient = 0.SI<Radian>();

			var targetVelocity = 0.SI<MeterPerSecond>();

			//			var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient);

			var accelerations = new[] {
				-0.68799597, -0.690581291, -0.693253225, -0.696020324, -0.698892653, -0.701882183, -0.695020765,
				-0.677731071,
				-0.660095846, -0.642072941, -0.623611107, -0.604646998, -0.58510078, -0.56497051, -0.547893288,
				-0.529859078,
				-0.510598641, -0.489688151, -0.466386685, -0.425121905
			};
			var simulationIntervals = new[] {
				0.202830428, 0.20884052, 0.215445127, 0.222749141, 0.230885341, 0.240024719, 0.250311822, 0.26182762,
				0.274732249,
				0.289322578, 0.305992262, 0.325276486, 0.34792491, 0.37502941, 0.408389927, 0.451003215, 0.5081108,
				0.590388012,
				0.724477573, 1.00152602
			};

			// accelerate from 0 to just below the target velocity and test derived simulation intervals & accelerations
			for (var i = 0; i < accelerations.Length; i++) {
				var tmpResponse = driver.OutPort().Request(absTime, ds, targetVelocity, gradient);

				Assert.IsInstanceOf<ResponseSuccess>(tmpResponse);
				Assert.AreEqual(accelerations[i], vehicle.LastRequest.acceleration.Value(), Tolerance);
				Assert.AreEqual(simulationIntervals[i], tmpResponse.SimulationInterval.Value(), Tolerance);

				vehicleContainer.CommitSimulationStep(absTime, tmpResponse.SimulationInterval);
				absTime += tmpResponse.SimulationInterval;
				vehicle.MyVehicleSpeed +=
					(tmpResponse.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>();
			}

			var response = driver.OutPort().Request(absTime, ds, targetVelocity, gradient);

			Assert.IsInstanceOf<ResponseSuccess>(response);
			Assert.AreEqual(-0.308576594, vehicle.LastRequest.acceleration.Value(), Tolerance);
			Assert.AreEqual(2.545854078, response.SimulationInterval.Value(), Tolerance);

			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
			//absTime += response.SimulationInterval;
			vehicle.MyVehicleSpeed +=
				(response.SimulationInterval * vehicle.LastRequest.acceleration).Cast<MeterPerSecond>();

			Assert.AreEqual(targetVelocity.Value(), vehicle.MyVehicleSpeed.Value(), Tolerance);
		}

		//==================

		private static VehicleData CreateVehicleData(Kilogram loading)
		{
			var axles = new List<Axle> {
				new Axle {
					AxleWeightShare = 0.4375,
					Inertia = 21.66667.SI<KilogramSquareMeter>(),
					RollResistanceCoefficient = 0.0055,
					TwinTyres = false,
					TyreTestLoad = 62538.75.SI<Newton>()
				},
				new Axle {
					AxleWeightShare = 0.375,
					Inertia = 10.83333.SI<KilogramSquareMeter>(),
					RollResistanceCoefficient = 0.0065,
					TwinTyres = false,
					TyreTestLoad = 52532.55.SI<Newton>()
				},
				new Axle {
					AxleWeightShare = 0.1875,
					Inertia = 21.66667.SI<KilogramSquareMeter>(),
					RollResistanceCoefficient = 0.0055,
					TwinTyres = false,
					TyreTestLoad = 62538.75.SI<Newton>()
				}
			};
			return new VehicleData {
				AxleConfiguration = AxleConfiguration.AxleConfig_4x2,
				AirDensity = DeclarationData.AirDensity,
				CurbMass = 15700.SI<Kilogram>(),
				Loading = loading,
				DynamicTyreRadius = 0.52.SI<Meter>(),
				AxleData = axles,
				SavedInDeclarationMode = false
			};
		}

		private static AirdragData CreateAirdragData()
		{
			return new AirdragData() {
				CrossWindCorrectionCurve =
					new CrosswindCorrectionCdxALookup(3.2634.SI<SquareMeter>(),
						CrossWindCorrectionCurveReader.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()),
						CrossWindCorrectionMode.NoCorrection),
			};
		}

		private static DriverData CreateDriverData()
		{
			return new DriverData {
				AccelerationCurve = AccelerationCurveReader.ReadFromFile(AccelerationFile),
				LookAheadCoasting = new DriverData.LACData {
					Enabled = false,
					//Deceleration = -0.5.SI<MeterPerSquareSecond>()
				},
				OverSpeed = new DriverData.OverSpeedData {
					Enabled = false
				},
			};
		}

		// ========================

		protected virtual IDriver AddComponent(IDrivingCycle prev, IDriver next)
		{
			prev.InPort().Connect(next.OutPort());
			return next;
		}

		protected virtual IVehicle AddComponent(IDriver prev, IVehicle next)
		{
			prev.InPort().Connect(next.OutPort());
			return next;
		}

		protected virtual IWheels AddComponent(IFvInProvider prev, IWheels next)
		{
			prev.InPort().Connect(next.OutPort());
			return next;
		}

		protected virtual ITnOutProvider AddComponent(IWheels prev, ITnOutProvider next)
		{
			prev.InPort().Connect(next.OutPort());
			return next;
		}

		protected virtual IPowerTrainComponent AddComponent(IPowerTrainComponent prev, IPowerTrainComponent next)
		{
			prev.InPort().Connect(next.OutPort());
			return next;
		}

		protected virtual void AddComponent(IPowerTrainComponent prev, ITnOutProvider next)
		{
			prev.InPort().Connect(next.OutPort());
		}
	}
}