Functional Reactive Virtual RealityThe FRVR Yampa-Extensions
The Yampa FRP system is the current state of the art in Functional Reactive Programming systems. It is written in Haskell using the Arrow extensions to the language. FRP and Yampa in particular enable the creation of hybrid systems, composed of continuous time behaviors and reactive switching between behaviors. The Yampa system is powerful and can be used to create very interesting systems. However, Yampa is also mostly an academic exercise to date, though always tested with applications of relevance. Its usage for programming a "Space Invaders" style game and even a First Person Shooter, show its potential. Unfortunately, many aspects that are required of the FRVR system are simply not met. These are functionalities identified in the investigation of Dynamic, Interactive Virtual Environments (DIVEs). Other issues are that several issue arrise with the simulation method, when the update rate is tied to the VR system. VR systems have significantly slower update rates than standard simulation timings and are often quite erratic. FRVR, therefore, modifies and extends the functionalities of Yampa.
Although these are not the only functionalities incorporated, the most crucial of these are:
ExtensibilityThe most important change to Yampa, is a restructuring of the code basis. One reason was simply to organize the functionalities better,. The main reason was that Yampa was specifically designed to disallow user extensibility. Users could write all kinds of behaviors, as long as the basic functionalities provided were enough. The actual implementation details were hidden from the user. One of the goals of FRVR was extensibility, which suffers tremendously through this restriction. Following an example of the AFRPUtitilies already present, FRVR's Yampa version strikes a compromise by allowing the advanced user at the internals, but they have to import an extra module to do it. Using this interface, AFRPInternal, some of the more VR specific extensions are implemented in the FRVR module space instead of the Yampa space. Future users can extend Yampa, without having to recompile the entire source.
Time Resolution FixesMany simulations of continuous-based system are dependent on the time resolution of the simulation. If the simulation isn't sampled at a high enough frequency, the simulation becomes unstable. Even something as simple as a pendulum requires a 100Hz refresh rate. Since FRVR currently couples the simulation to the VR system frame rate, 30 Hz is doing well and 15Hz might well happen. To combat this, FRVR introduces a number of different functionalities that work at different levels and solve different aspects of the problem.
- simulation kernel level: Special versions of the simulation kernel, reactminimate and reactsubimate, reduce the simulation step size by sub-sampling the entire simulation ever frame. reactminimate is the preferred version of the kernel level solutions. The user simply specifies the minimum step size for the simulation. The kernel assures the simulation kernel is run enough every VR frame so that this is met.
- sub-hierarchy level: These special SFs perform the same job as the kernel level functionalities, but only for a sub-branch. In this way ,a portion of the environment that needs to be sampled at a higher rate can be done so, without hurting the rest of the simulation speed. It is also very useful in combination with the time scaling functionality.
- sub-sampled switches: Many simulations involve changes to the simulation parameters at higher-orders, e.g. a pendulum changes velocity from positive to negative at the high point of the arc. Achieving a stable simulation is dependent on the sampling of the transition at exactly this point. A series of newly developed switches that are based on the originals extend their functionality to sub-sampled the first SF to find the actual time of the Event. After finding the actual event time, the new SF is run with the remaining time, a full step before the classic switches get to it.
However, Yampa's continuation-based stream implementation facilitates the implementation of an undo that works appropriate even in these hard situations. The only thing the programmer has to decide is when the saves should be triggered. The special undo SFs take care of the rest for the programmer. They just hand over the behaviors that should be "undoable" to the undoSF. Events trigger the save and undo actions.