Time handling – real time faking

This post is part of the SATF work.

Proper time handling within MRDS turned out to be an absolutely non-trivial task. But its nice part is an opportunity to demonstrate and exploit some of the advanced MRDS features. Namely, the service “polymorphism”, touched in the timer generic service contract; the Observer pattern DSS implementation employed in the timer subscriptions and notifications; and the pattern of interaction between a simulation entity and a service.

The problems arise when you step aside from the real time simulation mode (when the simulator tunes simulation quality so that it could proceed in real time). There are two such treacherous use cases in the simulation testing framework for MRDS: simulation with the fixed time delta (meaning the small fixed time delta, higher simulation quality and slower than real time processing) and the simulation pause (meaning the simulation time freeze). The first occurs when some test demands the higher simulation quality, the second – on a test’s result assessing when the simulation entities state is deserialized (slow operation) and afterwards compared with some services’ states. If simulation time is not frozen the things under comparison get unsynchronized and diverge. Not heeded (i.e the real time instead of simulation were used in the involved services) these cases could lead to, for example, the Monte Carlo localization service update firing twenty times more often (with regard to the “physical time”) than intended (because the “physical” simulation time is twenty times slower than real, of which the MC localization service knows nothing) effectively rendering all the simulation useless. The capability “to fake” the real time management tools, to substitute the simulation time for real if needed, would solve the issue. However, the MRDS package does not provide facilities for dealing with the simulation time at all. What it provides is only the real time tools. Hence, the task is to implement the time handling tools with sufficient functionality and capable of seamless dealing with the simulation time if needed.

Actually, the “sufficient” functionality occurred to be the simple timer functionality: time interval setting, timer commencing, notifying after each elapsed interval and turning the timer off. The final solution for the client service looks like this:

public class TimerClient{
	...
	TimerFacade _timerFacade;
	
	void Start(){
		...
		_timerFacade = new TimerFacade(this, 100);
		MainPortInterleave.CombineWith(new Interleave(new ExclusiveReceiverGroup(), new ConcurrentReceiverGroup(
				Arbiter.ReceiveWithIterator(true, _timerFacade.TickPort, Update))));
		_timerFacade.Set();
	}

	IEnumerator Update(TimeSpan dt){
		...
	}

	public void OnDropDown(DsspDefaultDrop dropDownRq){
		_timerFacade.Dispose();
		...
	}
}

As a single peculiarity, the TimerFacade constructor takes a reference to the client service as a handle to DSS API. The TimerFacade name emphasizes that some complex logics lurks behind, otherwise externally, it has no differences from the conventional timer. It is not the case internally: the picture shows different modules participating in the TimerFacade solution.


TimerFacade design

To expose the MRDS simulation time to the clients you have to go to great lengths, since the only place (as far as I know) where it can be merely acquired is a simulation entity’s Update handler. So, the first component is the special simulation entity, called TimerEntity, which literally does nothing (it has neither the physical nor visual body) but sitting inside of the simulation universe and exposing the simulation time. It does so by firing its public Tick event on every call to its Update handler (executed by the simulation engine). This entity is automatically inserted into each test’s environment on each test try. The correspondent entity service (whose breed was described briefly in the “MRDS review” section) SimulatedTimerService implements the Subscribe operation for timer notifications of the generic Timer contract and Pause operation for the time freeze. Different services (AtomicClockTimerService, for example) could implement the Timer contract making for the service polymorphic behavior. The Subscribe method is implemented via the built-in DSS subscription-notification infrastructure which is the other name for the Observer pattern. The SimulatedTimerService is supposed to be a singleton: all other services in need of the timer functionality could locate and use it. That makes it responsible for tracking elapsed time intervals for all of its clients. For that purpose, SimulatedTimerService uses the MultiTimer class, providing its own Subscribe method, which stores a record for each client with its demanded interval and id, and Update method, which updates elapsed time for every client and triggers the Tick event for those, whose time has come. With that, all the necessary functionality of the simulation time timer is implemented. What is left is transparency: in ideal world a service would not have to bother inside of what environment exactly, simulated or real, it is working. The TimerFacade class takes care of it. On the call to its Set method, it determines if any service complying to the Timer contract is present in the DSS directory, if so, TimerFacade uses it, otherwise it employs the standard real time MRDS facilities. And the client knows nothing about these complications.

This architecture with the suspicious centralized SimulatedTimerService hub for all the timer clients needs some justification. First, the MRDS architecture suggests a one-to-one correspondence between a simulation entity (the sole source of the simulation time) and a simulation entity service. Thus, the more appealing and insulated architecture without the centralized timer hub would require this simulation entity-service pair for each timer client, and this pair is really heavy-weighted compared to a record in the MultiTimer object. Second, given required functionality of a pause applied simultaneously to all timers in the system, the centralized architecture looks very expedient. The last consideration is the reasonably small number of needed timers and their trivial processing logics: even hundred of them hardly strain the actual design.

By and large, the described staff solves the problem. It provides the timer synchronised properly with either the simulation or real time. The timer possesses all the needed functionality. The client does not have to know about any of the things above. The inevitable downside of the real time substitution is relaxing of the performance constraints: if the simulation time is ten times slower than real, than the service under test has ten times more real time between updates. This issue is entirely on developer’s conscience, but could be controlled relatively easily with the help of a profiler.

Previous Next

Leave a Reply

Your email address will not be published. Required fields are marked *