Route simulation and playback
Simulating routes and playing back route data
Route simulation and playbacks
We provide support for the simulation of route data, and for controlling the playback of route data
In this section:
What is a simulation session?
Given a route, it should be possible to use it to drive a simulation, such that it is possible to follow a point on the route, play back travel along a route, reverse and fast-forward this travel, and bind an interesting visual representation to this route playback. The RouteSimulationSession class is the mechanism provided to achieve this. A RouteSimulationSession acts as a controller bound to a route. Using the session you can start, stop, pause, change speed, and reverse the playback along the route. The session can be queried for the current playback point (in ECEF) and direction. A view can be bound to the session, such that the playback can be visualised with a 3D model. A camera controller can also be bound to the session, so as to follow the playback of the session along the route.
Lifetime of a simulation session
Once a Route has been built and submitted, simulations can be run on the route. These simulations are represented by the RouteSimulationSession class. An arbitrary number of sessions can be bound to a given route, and have no effect on each other. Route simulation sessions are created and destroyed using the RouteSimulationService, as demonstrated in the following example;
// Assume that m_pRoute is a valid Route*.
// We can use m_pRoute to create a route simulation session.
RouteSimulationSession* pSession = m_routeSimulationService.BeginRouteSimulationSession(*m_pRoute);
// ... some code in which the pSession object is used ...
// Destroy the route simulation session - note that we should not delete the RouteSimulationSession*.
// pSession is no longer valid to use after the call to EndRouteSimulationSession,
// so we can simply set it to NULL
pSession = NULL;
Controlling a simulation session
The RouteSimulationSession acts as a controller for the session. Playback can be controlled with the StartPlaybackFromBeginning, EndPlayback, Pause and Unpause methods. A session is considered to be in an Active, Inactive or Paused state (sessions are Inactive when created). Playback on an Inactive session may be started with the StartPlaybackFromBeginning method; XXXX calling EndPlayback on an Active session will stop playback and set the state to inactive. The Pause and Unpause methods will alternate between Active and Paused states. The state of a session can be queried with the GetSessionState method.
When an active session playback completes (i.e., the playback reaches the end of the route), the state becomes Paused. This state can be queried via the IsRouteCompleted method.
The playback direction of a session can be modified using the SetReversePlaybackDirection and SetForwardPlaybackDirection methods, such that ‘rewind’ can be implemented. The current direction of a session can be queried using the GetPlaybackDirection method. A helper method TogglePlaybackDirection is provided to change the current playback direction.
The session can be in one of three playback speed states; these states are PlaybackSpeedUseLinkSpeedValue, PlaybackSpeedUseLinkSpeedMultiplier, and PlaybackSpeedUseCustomSpeed. The PlaybackSpeedUseLinkSpeedValue state means that the session should inspect the route data, and use the speed of the current link. This means that, if the route has been built using known speed limit values (via link attributes in the RouteBuilder), the session will obey these speed values. The PlaybackSpeedUseLinkSpeedMultiplier is similar, but can be used to speed up or slow down overall playback while keeping the relative link speeds consistent. For example, if a multiplier of 2.0 is used, the playback time will be halved; if a multiplier of 0.5 is used, the playback time will be doubled. In both cases, ratio of time spent on each link of the overall time for the route will be the same. Finally, the PlaybackSpeedUseCustomSpeed state means that the link speeds should be ignored, and that the playback speed should just use the absolute value provided (in meters per second).
The default playback speed state is PlaybackSpeedUseLinkSpeedValue; to enter this state explicitly, the UseLinkSpeedValue method can be used. To use a link speed multiplier, the UseLinkSpeedValueWithMultiplier method should be used. Finally, the UseCustomSpeedValue method with an absolute value in meters per second should be used to enter the PlaybackSpeedUseCustomSpeed state. These states can be combined with the RouteSimulationPlaybackDirection to implement fast-forward, rewind, etc., with varying playback speeds.
To allow the implementation of camera controllers, and the computation of view transforms, etc., the session exposes the current focal location on the route via the GetCurrentPositionEcef method, and the current direction (based on the current link) via the GetCurrentDirection method.
Finally, the session can be used to implement the projection of an arbitrary point on to the route. The SetCurrentPositionSnappedToRoute method accepts an ECEF position, computes the projection of this position to the closest available point on the route. This position can then be queried for via the GetCurrentPositionEcef method. Bounded views and camera controllers (described below) will be able to make use of this projected point. The example code uses this method to project the nearest point to the camera interest point on to the route, and the view binding for this session renders a vehicle on the route at the computed nearest point.
The Example code demonstrates all of these methods in a practical scenario, using three independent sessions bound to a route, and a simple UI to manipulate the playback.
Binding a view to a simulation session
Once a RouteSimulationService has been created, a view can be bound to session using the RouteSimulationViewService. The only view supported for route binding are SceneModels created from POD Files; see the model loading documentation for an explanation of the model API.
Once a model has been loaded, a SceneModel can be bound to a route simulation session with an arbitrary local transformation. The model can be updated via the binding, as can the local transformation. The binding with an identity transformation is demonstrated in the following example;
// Assume that pSession is a valid RouteSimulationSession*, and that pModel
// is a valid SceneModel* loaded from a .pod file.
pSessionViewBinding = m_routeSimulationViewService.CreateBinding(*pSession, pModel, transform);
// ...later, when we want to update the view and transform.
// We change the bound model, and create a transform to double the scale of the view.
// ...later still, when we are finshed with the view binding
// pSessionViewBinding is no longer valid to use after the call to DestroyBinding,
// so we can simply set it to NULL
pSessionViewBinding = NULL;
Binding a camera controller to a simulation session
A camera controller is provided for binding to a route simulation session, RouteSimulationGlobeCameraController. This controller wraps an instance of the regular GlobeCameraController, updating it to follow the simulation session playback point. It can be configured to permit or restrict input by locking to a heading or distance, or the view parameters can be set explicitly. A typical use case for this type would be to configure some desired follow behaviour (such as automatically rotating to face the session link direction, and/or locked to a specified distance, etc.), then to call use the StartFollowingSession method to begin following the session focal point. The example application demonstrates using a RouteSimulationGlobeCameraController combined with a set of UI buttons to control the camera behaviour.
RouteSimulationExample – This example illustrates how to use the RouteSimulationSession to control simulations, and RouteSimulationService to create and destroy sessions. The example also demonstrates binding a view to the session using the RouteSimulationModelBinding, and binding a RouteSimulationGlobeCameraController to the session.
The example is available here.