From 24cce7b6e5b12891ad270ae1904a6a03eef7ec8c Mon Sep 17 00:00:00 2001
From: Michael Krisper <michael.krisper@tugraz.at>
Date: Mon, 18 Jul 2022 11:33:38 +0200
Subject: [PATCH] Many Changes: Squashed all IUpdateable Changes together to
 merge it with develop branch again.

---
 VectoCommon/VectoCommon/Utils/SI.cs           | 26 +++++++++++-
 .../Impl/Electrics/SimpleBattery.cs           | 18 ++++++++
 .../Electrics/ISimpleBattery.cs               |  3 +-
 .../Simulation/Impl/PowertrainBuilder.cs      | 20 ++++++++-
 .../Simulation/Impl/VehicleContainer.cs       | 37 ++++++++++++++++
 .../Models/Simulation/Impl/WHRCharger.cs      | 15 ++++++-
 .../SimulationComponent/DCDCConverter.cs      | 14 ++++++-
 .../SimulationComponent/ElectricSystem.cs     | 18 +++++++-
 .../Models/SimulationComponent/IAuxPort.cs    |  2 +-
 .../Models/SimulationComponent/IUpdateable.cs | 42 +++++++++++++++++++
 .../Impl/AMTShiftStrategyOptimized.cs         |  5 +--
 .../SimulationComponent/Impl/ATGearbox.cs     | 32 +++++++++++++-
 .../Impl/ATShiftStrategyOptimized.cs          |  2 +-
 .../Impl/AbstractGearbox.cs                   |  2 +
 .../SimulationComponent/Impl/AxleGear.cs      | 15 ++++++-
 .../SimulationComponent/Impl/Battery.cs       | 15 ++++++-
 .../SimulationComponent/Impl/BatterySystem.cs | 29 ++++++++++++-
 .../Models/SimulationComponent/Impl/Brakes.cs | 16 ++++++-
 .../Impl/BusAuxiliariesAdapter.cs             | 15 +++++++
 .../Models/SimulationComponent/Impl/Clutch.cs | 18 ++++++--
 .../Impl/DistanceBasedDrivingCycle.cs         | 19 ++++++++-
 .../SimulationComponent/Impl/ElectricMotor.cs | 21 +++++++++-
 .../Impl/EngineAuxiliary.cs                   | 15 +++++++
 .../SimulationComponent/Impl/Gearbox.cs       | 35 +++++++++++++++-
 .../Impl/GensetChargerAdapter.cs              | 15 ++++++-
 .../Impl/PEVAMTShiftStrategy.cs               | 11 ++---
 .../Impl/SimplePowertrainContainer.cs         |  2 +
 .../Impl/StopStartCombustionEngine.cs         | 15 ++++++-
 .../SimulationComponent/Impl/SuperCap.cs      | 17 +++++++-
 .../Impl/TorqueConverter.cs                   | 16 ++++++-
 .../Impl/TransmissionComponent.cs             |  1 +
 .../SimulationComponent/Impl/Vehicle.cs       | 18 +++++++-
 .../Models/SimulationComponent/Impl/Wheels.cs | 16 ++++++-
 .../Strategies/TestPowertrain.cs              |  6 +++
 .../SimulationComponent/SwitchableClutch.cs   | 15 ++++++-
 .../VectoSimulationComponent.cs               |  2 +
 36 files changed, 527 insertions(+), 41 deletions(-)
 create mode 100644 VectoCore/VectoCore/Models/SimulationComponent/IUpdateable.cs

diff --git a/VectoCommon/VectoCommon/Utils/SI.cs b/VectoCommon/VectoCommon/Utils/SI.cs
index 38faea4cd4..6776282cbb 100644
--- a/VectoCommon/VectoCommon/Utils/SI.cs
+++ b/VectoCommon/VectoCommon/Utils/SI.cs
@@ -850,7 +850,7 @@ namespace TUGraz.VectoCommon.Utils
 	/// <summary>
 	/// SI Class for one per second [1/s].
 	/// </summary>
-	[DebuggerDisplay("{Val.ToString(\"F1\"),nq} [rad/s] ({AsRPM.ToString(\"F1\"),nq} [rpm)")]
+	[DebuggerDisplay("{Val.ToString(\"F1\"),nq} [rad/s] ({AsRPM.ToString(\"F1\"),nq} [rpm])")]
 	public class PerSecond : SIBase<PerSecond>
 	{
 		private static readonly int[] Units = { 0, 0, -1, 0, 0, 0, 0 };
@@ -864,14 +864,36 @@ namespace TUGraz.VectoCommon.Utils
 			return SIBase<PerSquareSecond>.Create(perSecond.Val / second.Value());
 		}
 
+		public static PerMeter operator /(PerSecond perSecond, MeterPerSecond second)
+		{
+			return SIBase<PerMeter>.Create(perSecond.Val / second.Value());
+		}
+
 		public static MeterPerSecond operator *(PerSecond perSecond, Meter meter)
 		{
 			return SIBase<MeterPerSecond>.Create(perSecond.Val * meter.Value());
 		}
-		
+
 		public double AsRPM => Val * 60 / (2 * Math.PI);
 	}
 
+	/// <summary>
+	/// SI Class for one per meter [1/m].
+	/// </summary>
+	[DebuggerDisplay("{Val.ToString(\"F1\"),nq} [1/m]")]
+	public class PerMeter : SIBase<PerMeter>
+	{
+		private static readonly int[] Units = { 0, -1, 0, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private PerMeter(double val) : base(val, Units) { }
+
+		public static PerSecond operator *(PerMeter perMeter, MeterPerSecond meterPerSecond) => 
+			SIBase<PerSecond>.Create(perMeter.Val * meterPerSecond.Value());
+
+		public static PerSecond operator *(MeterPerSecond meterPerSecond, PerMeter perMeter) => perMeter * meterPerSecond;
+	}
+	
 	/// <summary>
 	/// SI Class for Meter per second [m/s].
 	/// </summary>
diff --git a/VectoCore/VectoCore/Models/BusAuxiliaries/DownstreamModules/Impl/Electrics/SimpleBattery.cs b/VectoCore/VectoCore/Models/BusAuxiliaries/DownstreamModules/Impl/Electrics/SimpleBattery.cs
index 6fff2a8be4..2a7375c231 100644
--- a/VectoCore/VectoCore/Models/BusAuxiliaries/DownstreamModules/Impl/Electrics/SimpleBattery.cs
+++ b/VectoCore/VectoCore/Models/BusAuxiliaries/DownstreamModules/Impl/Electrics/SimpleBattery.cs
@@ -56,6 +56,12 @@ namespace TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Electric
 		}
 
 		#endregion
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) => false;
+
+		#endregion
 	}
 
 	// ########################################
@@ -114,6 +120,8 @@ namespace TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Electric
 				ConsumedEnergy = 0.SI<WattSecond>();
 			}
 			public WattSecond ConsumedEnergy { get; set; }
+
+			public State Clone() => (State)MemberwiseClone();
 		}
 
 		#region Overrides of VectoSimulationComponent
@@ -136,7 +144,17 @@ namespace TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Electric
 			}
 			AdvanceState();
 		}
+		#endregion
 
+		#region Implementation of IUpdateable
+		public bool UpdateFrom(object other) {
+			if (other is SimpleBattery b) {
+				PreviousState = b.PreviousState.Clone();
+				SOC = b.SOC;
+				return true;
+			}
+			return false;
+		}
 		#endregion
 	}
 }
diff --git a/VectoCore/VectoCore/Models/BusAuxiliaries/Interfaces/DownstreamModules/Electrics/ISimpleBattery.cs b/VectoCore/VectoCore/Models/BusAuxiliaries/Interfaces/DownstreamModules/Electrics/ISimpleBattery.cs
index 2afae59c4b..1c615da59f 100644
--- a/VectoCore/VectoCore/Models/BusAuxiliaries/Interfaces/DownstreamModules/Electrics/ISimpleBattery.cs
+++ b/VectoCore/VectoCore/Models/BusAuxiliaries/Interfaces/DownstreamModules/Electrics/ISimpleBattery.cs
@@ -1,4 +1,5 @@
 using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Models.SimulationComponent;
 
 namespace TUGraz.VectoCore.Models.BusAuxiliaries.Interfaces.DownstreamModules.Electrics {
 
@@ -9,7 +10,7 @@ namespace TUGraz.VectoCore.Models.BusAuxiliaries.Interfaces.DownstreamModules.El
 
 	}
 
-	public interface ISimpleBattery  : ISimpleBatteryInfo
+	public interface ISimpleBattery  : ISimpleBatteryInfo, IUpdateable
 	{
 		WattSecond ConsumedEnergy { get; }
 
diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
index 0fae92d631..c4f3fb4794 100644
--- a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
@@ -1636,7 +1636,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 		}
 	}
 
-	public class SimpleCharger : IElectricChargerPort
+	public class SimpleCharger : IElectricChargerPort, IUpdateable
 	{
 		#region Implementation of IElectricChargerPort
 
@@ -1659,6 +1659,24 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 		}
 
 		#endregion
+
+		#region Implementation of IUpdateable
+		public bool UpdateFrom(object other)
+		{
+			if (other is IElectricSystemInfo es) {
+				_chargingPower = es.ChargePower;
+				return true;
+			}
+
+			if (other is Watt w) {
+				_chargingPower = w;
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 
 	internal class DummyEngineInfo : VectoSimulationComponent, IEngineInfo, IEngineControl
diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/VehicleContainer.cs b/VectoCore/VectoCore/Models/Simulation/Impl/VehicleContainer.cs
index 182243953c..e951a3e2dd 100644
--- a/VectoCore/VectoCore/Models/Simulation/Impl/VehicleContainer.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Impl/VehicleContainer.cs
@@ -198,8 +198,45 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 			//todo mk20210617 use sorted list with inverse commitPriority (-commitPriority)
 			_components = _components.OrderBy(x => x.Item1).Reverse().ToList();
 		}
+		private List<(IUpdateable, object)> ComponentUpdateList = new List<(IUpdateable, object)>();
 
+		protected void UpdateComponentsInternal(IDataBus realContainer)
+		{
+			if (ComponentUpdateList.Any()) {
+				foreach (var (target, source) in ComponentUpdateList) {
+					target.UpdateFrom(source);
+				}
+			} else {
+				foreach (var (_, c) in _components) {
+					var found = false;
+					if (c is IUpdateable target) {
+						foreach (var (_, source) in (realContainer as VehicleContainer)._components) {
+							if (target.UpdateFrom(source)) {
+								ComponentUpdateList.Add((target, source));
+								found = true;
+							}
+						}
+					}
+
+					#if DEBUG
+					if (!found) {
+						Console.WriteLine("Test Component is not updateable: " + c.GetType());
+					}
+					#endif
+				}
+				
+				#if DEBUG
+				var sourceList = ComponentUpdateList.Select(st => st.Item2).ToArray();
+				foreach (var (_, source) in (realContainer as VehicleContainer)._components) {
+					if (!sourceList.Contains(source)){
+						Console.WriteLine("Real Component is not used for update: " + source.GetType());
+					}
+				}
+				#endif
 
+				ComponentUpdateList = ComponentUpdateList.Distinct().ToList();
+			}
+		}
 
 		public virtual void CommitSimulationStep(Second time, Second simulationInterval)
 		{
diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/WHRCharger.cs b/VectoCore/VectoCore/Models/Simulation/Impl/WHRCharger.cs
index 979140c4bf..6ee398a33c 100644
--- a/VectoCore/VectoCore/Models/Simulation/Impl/WHRCharger.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Impl/WHRCharger.cs
@@ -5,7 +5,7 @@ using TUGraz.VectoCore.OutputData;
 
 namespace TUGraz.VectoCore.Models.Simulation.Impl
 {
-	public class WHRCharger : StatefulVectoSimulationComponent<WHRCharger.State>, IElectricChargerPort
+	public class WHRCharger : StatefulVectoSimulationComponent<WHRCharger.State>, IElectricChargerPort, IUpdateable
 	{
 		public double Efficiency { get; }
 
@@ -71,7 +71,20 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 			public WattSecond GeneratedEnergy { get; set; }
 
 			public WattSecond ExcessiveEnergy { get; set; }
+
+			public State Clone() => (State)MemberwiseClone();
+		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is WHRCharger c) {
+				PreviousState = c.PreviousState.Clone();
+				return true;
+			}
+			return false;
 		}
 
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/DCDCConverter.cs b/VectoCore/VectoCore/Models/SimulationComponent/DCDCConverter.cs
index c42d792ece..34559dde4a 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/DCDCConverter.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/DCDCConverter.cs
@@ -8,7 +8,7 @@ using TUGraz.VectoCore.OutputData;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent
 {
-	public class DCDCConverter : StatefulVectoSimulationComponent<DCDCConverter.State>, IDCDCConverter
+	public class DCDCConverter : StatefulVectoSimulationComponent<DCDCConverter.State>, IDCDCConverter, IUpdateable
 	{
 		public double Efficiency { get; protected set; }
 
@@ -90,6 +90,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent
 
 			public WattSecond ConsumedEnergy { get; set; }
 			public WattSecond MissingEnergy { get; set; }
+			
+			public State Clone() => (State)MemberwiseClone();
 		}
+
+		#region Implementation of IUpdateable
+		public bool UpdateFrom(object other) {
+			if (other is DCDCConverter d) {
+				PreviousState = d.PreviousState.Clone();
+				return true;
+			}
+			return false;
+		}
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/ElectricSystem.cs b/VectoCore/VectoCore/Models/SimulationComponent/ElectricSystem.cs
index d4903f8f0b..66338c293e 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/ElectricSystem.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/ElectricSystem.cs
@@ -6,11 +6,13 @@ using TUGraz.VectoCore.Configuration;
 using TUGraz.VectoCore.Models.Connector.Ports.Impl;
 using TUGraz.VectoCore.Models.Simulation;
 using TUGraz.VectoCore.Models.Simulation.Data;
+using TUGraz.VectoCore.Models.SimulationComponent.Impl;
 using TUGraz.VectoCore.OutputData;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent
 {
-	public class ElectricSystem : StatefulVectoSimulationComponent<ElectricSystem.State>, IElectricSystem, IElectricAuxConnecor, IElectricChargerConnector, IBatteryConnector
+	public class ElectricSystem : StatefulVectoSimulationComponent<ElectricSystem.State>, IElectricSystem, IElectricAuxConnecor, 
+		IElectricChargerConnector, IBatteryConnector, IUpdateable
 	{
 
 		protected readonly List<IElectricAuxPort> Consumers = new List<IElectricAuxPort>();
@@ -141,7 +143,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent
 				ConsumerPower = powerDemand;
 				BatteryPower = batteryPower;
 			}
+
+			public State Clone() => (State)MemberwiseClone();
 		}
 
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is ElectricSystem s) {
+				PreviousState = s.PreviousState.Clone();
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IAuxPort.cs b/VectoCore/VectoCore/Models/SimulationComponent/IAuxPort.cs
index 8ffddbf456..04a22c88b3 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/IAuxPort.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/IAuxPort.cs
@@ -43,7 +43,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent
 		void Connect(IAuxPort aux);
 	}
 
-	public interface IAuxPort
+	public interface IAuxPort: IUpdateable
 	{
 		NewtonMeter Initialize(NewtonMeter torque, PerSecond angularSpeed);
 
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IUpdateable.cs b/VectoCore/VectoCore/Models/SimulationComponent/IUpdateable.cs
new file mode 100644
index 0000000000..f60db9bb59
--- /dev/null
+++ b/VectoCore/VectoCore/Models/SimulationComponent/IUpdateable.cs
@@ -0,0 +1,42 @@
+/*
+* 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
+*/
+
+namespace TUGraz.VectoCore.Models.SimulationComponent
+{
+	public interface IUpdateable
+	{
+		/// <summary>
+		/// Tries to update the internal state of this object from the other object.
+		/// </summary>
+		/// <returns>True if the update was possible. False if the update is not possible.</returns>
+		bool UpdateFrom(object other);
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyOptimized.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyOptimized.cs
index 55b9974e75..d63082eec1 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyOptimized.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyOptimized.cs
@@ -130,9 +130,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					continue;
 				}
 
-				var estimatedEngineSpeed = (vehicleSpeedPostShift * (totalTransmissionRatio /
-						GearboxModelData.Gears[currentGear.Gear].Ratio * GearboxModelData.Gears[tryNextGear.Gear].Ratio))
-					.Cast<PerSecond>();
+				var estimatedEngineSpeed = vehicleSpeedPostShift * (totalTransmissionRatio /
+						GearboxModelData.Gears[currentGear.Gear].Ratio * GearboxModelData.Gears[tryNextGear.Gear].Ratio);
 				if (estimatedEngineSpeed.IsSmaller(shiftStrategyParameters.MinEngineSpeedPostUpshift)) {
 					continue;
 				}
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs
index 1de8dd3d0c..794bcf3a57 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs
@@ -45,7 +45,7 @@ using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class ATGearbox : AbstractGearbox<ATGearbox.ATGearboxState>, IHybridControlledGearbox
+	public class ATGearbox : AbstractGearbox<ATGearbox.ATGearboxState>, IHybridControlledGearbox, IUpdateable
 	{
 		protected internal readonly IShiftStrategy _strategy;
 		protected internal readonly TorqueConverter TorqueConverter;
@@ -581,8 +581,38 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public bool Disengaged = true;
 			public WattSecond PowershiftLossEnergy;
 			public NewtonMeter PowershiftLoss;
+
+			public ATGearboxState Clone() => (ATGearboxState)MemberwiseClone();
+
 		}
 
 		public bool SwitchToNeutral { get; set; }
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other)
+		{
+			if (other is ATGearbox g) {
+				PreviousState = g.PreviousState.Clone();
+				_powershiftLossEnergy = g._powershiftLossEnergy;
+				EngineInertia = g.EngineInertia;
+				Disengaged = g.Disengaged;
+				SwitchToNeutral = g.SwitchToNeutral;
+				RequestAfterGearshift = g.RequestAfterGearshift;
+				LastShift = g.LastShift;
+				return true;
+			}
+
+			if (other is GearshiftPosition p) {
+				Gear = p;
+				DisengageGearbox = !p.Engaged;
+				Disengaged = !p.Engaged;
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATShiftStrategyOptimized.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATShiftStrategyOptimized.cs
index 472d7b0ecc..dbda13c068 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATShiftStrategyOptimized.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATShiftStrategyOptimized.cs
@@ -250,7 +250,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 				var inAngularVelocity = GearboxModelData.Gears[next.Gear].Ratio * outAngularVelocity;
 				var totalTransmissionRatio = inAngularVelocity / (DataBus.VehicleInfo.VehicleSpeed + DataBus.DriverInfo.DriverAcceleration * dt);
-				var estimatedEngineSpeed = (vehicleSpeedPostShift * totalTransmissionRatio).Cast<PerSecond>();
+				var estimatedEngineSpeed = vehicleSpeedPostShift * totalTransmissionRatio;
 				if (estimatedEngineSpeed.IsSmaller(shiftStrategyParameters.MinEngineSpeedPostUpshift)) {
 					continue;
 				}
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AbstractGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AbstractGearbox.cs
index e7b845bf73..14028b6418 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AbstractGearbox.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AbstractGearbox.cs
@@ -170,5 +170,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		public GearshiftPosition Gear;
 		public TransmissionLossMap.LossMapResult TorqueLossResult;
 		public DrivingBehavior DrivingBehavior;
+
+		public new GearboxState Clone() => (GearboxState)base.Clone();
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AxleGear.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AxleGear.cs
index b8c9d95da0..dc0116d06b 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AxleGear.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AxleGear.cs
@@ -39,7 +39,7 @@ using TUGraz.VectoCore.OutputData;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class AxleGear : TransmissionComponent, IAxlegear
+	public class AxleGear : TransmissionComponent, IAxlegear, IUpdateable
 	{
 		public AxleGear(IVehicleContainer container, AxleGearData modelData) : base(container, modelData.AxleGear) { }
 
@@ -81,5 +81,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				(PreviousState.InAngularVelocity + CurrentState.InAngularVelocity) / 2.0, CurrentState.InTorque);
 
 		public double Ratio => ModelData.Ratio;
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is AxleGear g) {
+				PreviousState = g.PreviousState.Clone();
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 }
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Battery.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Battery.cs
index 2d131e2d61..c18f5f57e0 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Battery.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Battery.cs
@@ -14,7 +14,7 @@ using TUGraz.VectoCore.OutputData;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class Battery : StatefulVectoSimulationComponent<Battery.State>, IElectricEnergyStorage, IElectricEnergyStoragePort
+	public class Battery : StatefulVectoSimulationComponent<Battery.State>, IElectricEnergyStorage, IElectricEnergyStoragePort, IUpdateable
 	{
 		protected readonly BatteryData ModelData;
 
@@ -274,8 +274,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public Watt MaxDischargePower;
 			public Watt BatteryLoss;
 			public Second PulseDuration;
+			public State Clone() => (State)MemberwiseClone();
 		}
 
 
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is Battery b) {
+				PreviousState = b.PreviousState.Clone();
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatterySystem.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatterySystem.cs
index 556b71c828..0e3475ba42 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatterySystem.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatterySystem.cs
@@ -14,9 +14,9 @@ using TUGraz.VectoCore.OutputData;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class BatterySystem : StatefulVectoSimulationComponent<BatterySystem.State>, IElectricEnergyStorage, IElectricEnergyStoragePort
+	public class BatterySystem : StatefulVectoSimulationComponent<BatterySystem.State>, IElectricEnergyStorage, IElectricEnergyStoragePort, IUpdateable
 	{
-		public class BatteryString
+		public class BatteryString: IUpdateable
 		{
 			protected readonly List<Battery> _batteries;
 			
@@ -111,6 +111,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					: MaxChargeCurrent(dt);
 				return solutions.Where(x => Math.Sign(sign) == Math.Sign(x) && Math.Abs(x).IsSmallerOrEqual(Math.Abs(maxCurrent.Value()), 1e-3)).Min().SI<Ampere>();
 			}
+
+			#region Implementation of IUpdateable
+
+			public bool UpdateFrom(object other) {
+				if (other is BatteryString bs) {
+					return _batteries.ZipAll(bs._batteries).All(ts => ts.Item1.UpdateFrom(ts.Item2));
+				}
+				return false;
+			}
+
+			#endregion
 		}
 
 		protected internal readonly Dictionary<int, BatteryString> Batteries = new Dictionary<int, BatteryString>();
@@ -377,6 +388,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public Watt MaxDischargePower;
 			public Watt BatteryLoss;
 			public Second PulseDuration;
+			public State Clone() => (State)MemberwiseClone();
+		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is BatterySystem b) {
+				PreviousState = b.PreviousState.Clone();
+				return Batteries.All(kv => kv.Value.UpdateFrom(b.Batteries[kv.Key]));
+			}
+
+			return false;
 		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Brakes.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Brakes.cs
index bf6ef7e401..738460f4cf 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Brakes.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Brakes.cs
@@ -41,8 +41,7 @@ using TUGraz.VectoCore.OutputData;
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
 	public class Brakes : StatefulProviderComponent<SimpleComponentState, ITnOutPort, ITnInPort, ITnOutPort>,
-		IPowerTrainComponent, ITnOutPort,
-		ITnInPort, IBrakes
+		IPowerTrainComponent, ITnOutPort, ITnInPort, IBrakes, IUpdateable
 	{
 		public Watt BrakePower { get; set; }
 
@@ -93,5 +92,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			BrakePower = 0.SI<Watt>();
 			base.DoCommitSimulationStep(time, simulationInterval);
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is Brakes b) {
+				PreviousState = b.PreviousState.Clone();
+				BrakePower = b.BrakePower;
+				return true;
+			}
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs
index 3465fa90b6..f8f1527f75 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs
@@ -396,6 +396,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public WattSecond MissingElectricEnergy { get; set; }
 
 			public Watt ExcessiveDragPower = 0.SI<Watt>();
+
+			public BusAuxState Clone() => (BusAuxState)MemberwiseClone();
 		}
 
 		public class ElectricStorageWrapper : ISimpleBatteryInfo
@@ -433,5 +435,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			#endregion
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is BusAuxiliariesAdapter b) {
+				PreviousState = b.PreviousState.Clone();
+				return ElectricStorage.UpdateFrom(b.ElectricStorage);
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 }
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Clutch.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Clutch.cs
index 668e1523b3..83b97ab25e 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Clutch.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Clutch.cs
@@ -43,9 +43,8 @@ using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class
-		Clutch : StatefulProviderComponent<Clutch.ClutchState, ITnOutPort, ITnInPort, ITnOutPort>, IClutch,
-		ITnOutPort, ITnInPort
+	public class Clutch : StatefulProviderComponent<Clutch.ClutchState, ITnOutPort, ITnInPort, ITnOutPort>, IClutch, 
+		ITnOutPort, ITnInPort, IUpdateable
 	{
 		protected readonly PerSecond _idleSpeed;
 		protected readonly PerSecond _ratedSpeed;
@@ -252,6 +251,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public Watt ClutchLoss { get; set; }
 			public bool ICEOn { get; set; }
 			public PerSecond ICEOnSpeed { get; set; }
+			public new ClutchState Clone() => (ClutchState)base.Clone();
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is Clutch c) {
+				PreviousState = c.PreviousState.Clone();
+				return true;
+			}
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
index 4f623cfa45..a61d012880 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
@@ -52,11 +52,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 	/// </summary>
 	public sealed class DistanceBasedDrivingCycle : StatefulProviderComponent
 		<DistanceBasedDrivingCycle.DrivingCycleState, ISimulationOutPort, IDrivingCycleInPort, IDrivingCycleOutPort>,
-		IDrivingCycle, ISimulationOutPort, IDrivingCycleInPort, IDisposable
+		IDrivingCycle, ISimulationOutPort, IDrivingCycleInPort, IDisposable, IUpdateable
 	{
 		private const double LookaheadTimeSafetyMargin = 1.5;
 		internal readonly IDrivingCycleData Data;
-		internal readonly DrivingCycleEnumerator CycleIntervalIterator;
+		internal DrivingCycleEnumerator CycleIntervalIterator;
 		private bool _intervalProlonged;
 		internal IdleControllerSwitcher IdleController;
 		private Meter CycleEndDistance;
@@ -579,5 +579,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			CycleIntervalIterator.Dispose();
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is DistanceBasedDrivingCycle c) {
+				PreviousState = c.PreviousState.Clone();
+				CycleIntervalIterator = c.CycleIntervalIterator;
+				//TODO MK-20220523 also allow updating from measuredspeeddrivingcycle?
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 }
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
index 69ad5fe4a1..be9862dd99 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
@@ -14,7 +14,8 @@ using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class ElectricMotor : StatefulProviderComponent<ElectricMotorState, ITnOutPort, ITnInPort, ITnOutPort>, IPowerTrainComponent, IElectricMotor, ITnOutPort, ITnInPort
+	public class ElectricMotor : StatefulProviderComponent<ElectricMotorState, ITnOutPort, ITnInPort, ITnOutPort>, 
+		IPowerTrainComponent, IElectricMotor, ITnOutPort, ITnInPort, IUpdateable
 	{
 
 		protected internal IElectricSystem ElectricPower;
@@ -576,6 +577,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			return emSpeed / ModelData.RatioADC;
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is ElectricMotor e) {
+				PreviousState = e.PreviousState.Clone();
+				ElectricPower = e.ElectricPower;
+				ThermalBuffer = e.ThermalBuffer;
+				DeRatingActive = e.DeRatingActive;
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 
 	public class ElectricMotorState // : SimpleComponentState
@@ -603,5 +620,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 
 		public Watt ElectricPowerToBattery;
+
+		public ElectricMotorState Clone() => (ElectricMotorState)MemberwiseClone();
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/EngineAuxiliary.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/EngineAuxiliary.cs
index e7f82a552c..18ee0611a9 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/EngineAuxiliary.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/EngineAuxiliary.cs
@@ -244,6 +244,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			public PerSecond AngularSpeed;
 			public Dictionary<string, Watt> PowerDemands;
+
+			public State Clone() => (State)MemberwiseClone();
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is EngineAuxiliary a) {
+				PreviousState = a.PreviousState.Clone();
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
index aa931e68de..3b0ce5332a 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
@@ -43,7 +43,7 @@ using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class Gearbox : AbstractGearbox<GearboxState>, IHybridControlledGearbox
+	public class Gearbox : AbstractGearbox<GearboxState>, IHybridControlledGearbox, IUpdateable
 	{
 		/// <summary>
 		/// The shift strategy.
@@ -565,5 +565,38 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		}
 
 		public override Second LastShift => EngageTime;
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is Gearbox g) {
+				PreviousState = g.PreviousState.Clone();
+				Disengaged = g.Disengaged;
+				DisengageGearbox = g.DisengageGearbox;
+				_nextGear = g.NextGear;
+				Gear = g.Gear;
+
+				if (DataBus.VehicleInfo.VehicleStopped) {
+					Gear = _nextGear;
+				}
+				
+				return true;
+			}
+
+			if (other is GearshiftPosition p) {
+				_nextGear = p;
+				DisengageGearbox = !p.Engaged;
+				Disengaged = !p.Engaged;
+				return true;
+			}
+
+			if (other is GearboxState s) {
+				PreviousState = s.Clone();
+			}
+			
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/GensetChargerAdapter.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/GensetChargerAdapter.cs
index 0a38a67fde..1a43cf6239 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/GensetChargerAdapter.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/GensetChargerAdapter.cs
@@ -1,10 +1,11 @@
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.Models.Connector.Ports.Impl;
+using TUGraz.VectoCore.Models.SimulationComponent.Strategies;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class GensetChargerAdapter : IElectricChargerPort
+	public class GensetChargerAdapter : IElectricChargerPort, IUpdateable
 	{
 		protected IElectricSystem es;
 		protected Watt PowerGenerated;
@@ -75,5 +76,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			#endregion
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is GenSetOperatingPoint p) {
+				ChargingPower = p.ElectricPower;
+				return true;
+			}
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs
index 26501658c3..c441b6e66c 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs
@@ -352,10 +352,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					continue;
 				}
 
-				var estimatedEngineSpeed = (vehicleSpeedPostShift * (totalTransmissionRatio /
-						GearboxModelData.Gears[currentGear.Gear].Ratio *
-						GearboxModelData.Gears[tryNextGear.Gear].Ratio))
-					.Cast<PerSecond>();
+				var estimatedEngineSpeed = vehicleSpeedPostShift * (totalTransmissionRatio /
+						GearboxModelData.Gears[currentGear.Gear].Ratio * GearboxModelData.Gears[tryNextGear.Gear].Ratio);
 				if (estimatedEngineSpeed.IsSmaller(shiftStrategyParameters.MinEngineSpeedPostUpshift)) {
 					continue;
 				}
@@ -597,9 +595,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 			TestContainerSuperCap?.Initialize(DataBus.BatteryInfo.StateOfCharge);
 
-			if (TestContainerElectricSystemCharger != null) {
-				TestContainerElectricSystemCharger.ChargingPower = (DataBus.ElectricSystemInfo.ChargePower);
-			}
+			TestContainerElectricSystemCharger?.UpdateFrom(DataBus.ElectricSystemInfo.ChargePower);
+
 
 			//var pos = ModelData.ElectricMachinesData.FirstOrDefault().Item1;
 			TestContainerElectricMotor.ThermalBuffer =
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimplePowertrainContainer.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimplePowertrainContainer.cs
index b50f7d7e46..2696b49047 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimplePowertrainContainer.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimplePowertrainContainer.cs
@@ -36,5 +36,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl {
 		public MeterPerSecond NextBrakeTriggerSpeed => 0.SI<MeterPerSecond>();
 
 		#endregion
+
+		public void UpdateComponents(IDataBus realContainer) => UpdateComponentsInternal(realContainer);
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/StopStartCombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/StopStartCombustionEngine.cs
index 96aba3d63c..767422c91a 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/StopStartCombustionEngine.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/StopStartCombustionEngine.cs
@@ -12,7 +12,7 @@ using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class StopStartCombustionEngine : CombustionEngine
+	public class StopStartCombustionEngine : CombustionEngine, IUpdateable
 	{
 		private WattSecond EngineStartEnergy;
 
@@ -230,6 +230,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			container[ModalResultField.P_WHR_mech_map] = 0.SI<Watt>();
 			container[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>();
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other)
+		{
+			if (other is CombustionEngine e) {
+				PreviousState = e.PreviousState;
+				return EngineAux.UpdateFrom(e.EngineAux);
+			}
+			return false;
+		}
+
+		#endregion
 	}
 
 	public class SimplePowerrtrainCombustionEngine : StopStartCombustionEngine
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/SuperCap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/SuperCap.cs
index 041129065c..bd0aa3e00d 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/SuperCap.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/SuperCap.cs
@@ -13,7 +13,7 @@ using TUGraz.VectoCore.OutputData;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
-	public class SuperCap : StatefulVectoSimulationComponent<SuperCap.State>, IElectricEnergyStorage, IElectricEnergyStoragePort
+	public class SuperCap : StatefulVectoSimulationComponent<SuperCap.State>, IElectricEnergyStorage, IElectricEnergyStoragePort, IUpdateable
 	{
 		private SuperCapData ModelData;
 
@@ -199,6 +199,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public Watt MaxChargePower;
 			public Watt MaxDischargePower;
 			public Watt InternalLoss;
+
+			public State Clone() => (State)MemberwiseClone();
 		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is SuperCap o) {
+				PreviousState = o.PreviousState.Clone();
+				return true;
+			}
+
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs
index 54955db39f..a623f26eed 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs
@@ -49,7 +49,7 @@ using TUGraz.VectoCore.Utils;
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
 	public class TorqueConverter : StatefulVectoSimulationComponent<TorqueConverter.TorqueConverterComponentState>,
-		ITnInPort, ITnOutPort, ITorqueConverter
+		ITnInPort, ITnOutPort, ITorqueConverter, IUpdateable
 	{
 		protected readonly IGearboxInfo Gearbox;
 		protected readonly IShiftStrategy ShiftStrategy;
@@ -506,6 +506,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			public TorqueConverterOperatingPoint OperatingPoint;
 			public bool IgnitionOn;
+
+			public new TorqueConverterComponentState Clone() => (TorqueConverterComponentState)base.Clone();
 		}
 
 		#region Implementation of ITorqueConverterControl
@@ -520,6 +522,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		public TorqueConverterOperatingPoint SetOperatingPoint { get; set; }
 
 
+		#endregion
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is TorqueConverter tc) {
+				PreviousState = tc.PreviousState.Clone();
+				return true;
+			}
+			return false;
+		}
+
 		#endregion
 	}
 }
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TransmissionComponent.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TransmissionComponent.cs
index adf81d3165..8c7603946f 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TransmissionComponent.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TransmissionComponent.cs
@@ -49,6 +49,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			public TransmissionLossMap.LossMapResult TorqueLossResult;
 			//public NewtonMeter TorqueLoss = 0.SI<NewtonMeter>();
+			public new TransmissionState Clone() => (TransmissionState)MemberwiseClone();
 		}
 
 		protected TransmissionComponent(IVehicleContainer container, TransmissionData modelData) : base(container)
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs
index 1ea0ef778e..3d5576124f 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs
@@ -47,8 +47,7 @@ using TUGraz.VectoCore.Utils;
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
 	public class Vehicle : StatefulProviderComponent<Vehicle.VehicleState, IDriverDemandOutPort, IFvInPort, IFvOutPort>,
-		IVehicle, IMileageCounter, IFvInPort,
-		IDriverDemandOutPort
+		IVehicle, IMileageCounter, IFvInPort, IDriverDemandOutPort, IUpdateable
 	{
 		internal readonly VehicleData ModelData;
 
@@ -280,6 +279,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				$"slope_res: {SlopeResistance}, " +
 				$"air_drag: {AirDragResistance}, " +
 				$"traction force: {VehicleTractionForce}";
+
+			public VehicleState Clone() => (VehicleState)MemberwiseClone();
+		}
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is Vehicle v) {
+				PreviousState = v.PreviousState.Clone();
+				MaxVehicleSpeed = v.MaxVehicleSpeed;
+				return true;
+			}
+			return false;
 		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Wheels.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Wheels.cs
index 6afaf44cc2..fa96f336de 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Wheels.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Wheels.cs
@@ -40,7 +40,7 @@ using TUGraz.VectoCore.Utils;
 namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 {
 	public class Wheels : StatefulProviderComponent<Wheels.WheelsState, IFvOutPort, ITnInPort, ITnOutPort>, IWheels,
-		IFvOutPort, ITnInPort
+		IFvOutPort, ITnInPort, IUpdateable
 	{
 		private readonly KilogramSquareMeter _totalWheelsInertia;
 
@@ -49,6 +49,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public PerSecond AngularVelocity;
 			public NewtonMeter TorqueIn;
 			public NewtonMeter InertiaTorqueLoss;
+
+			public WheelsState Clone() => (WheelsState)MemberwiseClone();
 		}
 
 		public Wheels(IVehicleContainer cockpit, Meter rdyn, KilogramSquareMeter totalWheelsInertia)
@@ -96,5 +98,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		public Kilogram ReducedMassWheels => (_totalWheelsInertia / DynamicTyreRadius / DynamicTyreRadius).Cast<Kilogram>();
 
 		public Meter DynamicTyreRadius { get; }
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is Wheels w) {
+				PreviousState = w.PreviousState.Clone();
+				return true;
+			}
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/TestPowertrain.cs b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/TestPowertrain.cs
index 42c94ada79..9f93aba3f9 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/TestPowertrain.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/TestPowertrain.cs
@@ -43,6 +43,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 	public class TestPowertrain<T> where T: class, IHybridControlledGearbox, IGearbox
 	{
 		public SimplePowertrainContainer Container;
+		public IDataBus RealContainer;
+
 		public T Gearbox;
 		
 		public SimpleHybridController HybridController;
@@ -63,6 +65,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 		public TestPowertrain(SimplePowertrainContainer container, IDataBus realContainer)
 		{
 			Container = container;
+			RealContainer = realContainer;
+
 			Gearbox = Container.GearboxCtl as T;
 			
 			HybridController = Container.HybridController as SimpleHybridController;
@@ -110,6 +114,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies
 			}
 			//Brakes = new MockBrakes(container);
 		}
+
+		public void UpdateComponents() => Container.UpdateComponents(RealContainer);
 	}
 
 	public class MockBrakes : VectoSimulationComponent, IBrakes
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/SwitchableClutch.cs b/VectoCore/VectoCore/Models/SimulationComponent/SwitchableClutch.cs
index 9b8d9bbe85..dd5b241a79 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/SwitchableClutch.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/SwitchableClutch.cs
@@ -9,7 +9,7 @@ using TUGraz.VectoCore.Models.SimulationComponent.Impl;
 
 namespace TUGraz.VectoCore.Models.SimulationComponent
 {
-	public class SwitchableClutch : Clutch
+	public class SwitchableClutch : Clutch, IUpdateable
 	{
 		public SwitchableClutch(IVehicleContainer container, CombustionEngineData engineData) : base(container, engineData) { }
 
@@ -142,5 +142,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent
 		#endregion
 
 		#endregion
+
+		#region Implementation of IUpdateable
+
+		public bool UpdateFrom(object other) {
+			if (other is SwitchableClutch c) {
+				PreviousState = c.PreviousState.Clone();
+				ClutchOpen = c.ClutchOpen;
+				return true;
+			}
+			return false;
+		}
+
+		#endregion
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/VectoSimulationComponent.cs b/VectoCore/VectoCore/Models/SimulationComponent/VectoSimulationComponent.cs
index 6034fcc178..584ab68d22 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/VectoSimulationComponent.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/VectoSimulationComponent.cs
@@ -145,5 +145,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent
 			OutTorque = outTorque;
 			OutAngularVelocity = outAngularVelocity;
 		}
+
+		public SimpleComponentState Clone() => (SimpleComponentState)MemberwiseClone();
 	}
 }
\ No newline at end of file
-- 
GitLab