Project

Adrian Josan

2024:7




VR Bike

The VR bike system is a project combining virtual reality with cycling. Streaming the data from a spinning bike to a Unity project rendered on a VR headset allows users to immerse themselves in virtual environments while cycling, potentially providing more engaging and interactive experiences. This document explains how the system works and how to run it with the associated Unity Project.

Hardware:

  • VR-Bike
  • Sufficiently powerful PC (supporting Unity and Visual Studio)
  • VR headset (e.g. Meta Quest 3)

Software:

  • Unity version 2020.3.18f1
  • Visual Studio 2022
    • .NET Framework 4.8

The VR-Bike system was conceptualized and built by Tom Onderwater as a tool for his research project, titled: “Investigating the Effect of Visual Information and Optic Flow on Interception Adequacy using a VR-Bike”. Tom visualized the VR bike as “a new research tool which interfaces with a virtual environment, enabling research into the effect of optic flow.”

After Tom had finished his research, he kindly offered the VR bike and the source code to the Interaction Lab.

The main physical component of the system is the VR-Bike [fig ref], which was developed to interface with the VR environment and consists of the following two sub-systems, which are both connected to the host PC via USB [fig ref]:

  • Praxtour spinning bike is a commercially available spinning bike with a USB interface. The bike has a flywheel the resistance of which can be programmatically adjusted to simulate braking, riding on an inclined surface, or with increased drag, etc. The spinning bike generates the following data: cycling speed; left brake and right brake intensity; gear; and cadence.
  • Rotating Handlebar that can rotate and is used to turn inside the virtual environment. The rotation of the handlebar is measured by a sensor connected to an Arduino board [fig ref].

The readings from the Praxtour bike and the Arduino are aggregated together before being streamed to the virtual environment over a web socket connection at 50 Hz. There's a fixed 0.1-second delay between action and perception by the system.

This functionality is implemented through a controller program called *MinimalController,* written in C# using .NET 4.8. The primary classes are:

  • InputControl - which connects to the Praxtour bike and the Arduino Uno and reads the data from both devices.
  • Program - which uses InputControl and SocketServer to read and send the data through a web socket.

The virtual environment consists of a scene within the BikeMan Unity project. It contains the bike, a plain ground surface, trees, and a target ball, which moves and is to be intercepted by the player. The headset’s position is fixed relative to the cyclist model but head movement is allowed.

The behavior of the bike in the Unity Project is enabled by multiple scripts, mainly Bike, BikePhysics, and BikeSocketClient which use a web socket client to connect to the controller’s socket server, read the aggregated data, and based on this data implement the bike’s dynamics within the Unity scene.

The flywheel's resistance, which makes the pedals feel heavier, is calculated by adding a predefined Normal Resistance and the braking intensity from the brake levers, streamed back to the Praxtour bike through the controller via the web socket connection.

Note: Since the readings from the sensors on the bike need to be streamed to the Unity scene via a PC, the Unity project has to run in PCVR mode. Therefore, you can connect any VR headset supporting PCVR to render the scene.

Note: The script to read the handlebar rotation has already been loaded on the Arduino Uno board. In case you need to modify or reload it, the script can be found in the BikeSteer directory in the repository.

TIP: the readings from the Arduino board can be checked directly in Arduino IDE.

TIP: if you use a Meta Quest headset and have a laptop with hybrid graphics (e.g. Lenovo Legion 5), make sure to set the discrete graphics mode from the bios, otherwise, the Quest Link might get stuck in the loading screen.