← work
The headset's complete 3D model as a grey wireframe: the shell, the two lenses and their wheels, the side wheel and the adjustable strap.

● careerDec 2023 — Jun 2024

Infrared virtual reality headset

role
Software engineer and project lead (fixed-term)
company
Data Science Experts, for Lynred
location
Grenoble, France
tools
  • Python
  • OpenCV
  • Flask
  • Docker
  • Jetson Nano
  • React Native
  • ViroReact

Context

Lynred's application lab looks for new, sometimes playful uses of infrared: introduce the technology to a wide audience and show how easily its sensors integrate. Data Science Experts worked with Lynred on this project through one of its engineers: me, from December 2023 to June 2024.

The goal: a virtual reality headset that shows the world in thermal, in real time. The main constraint is latency: the slightest lag between head movement and image brings nausea and dizziness. The experience had to feel as smooth as a commercial VR headset.

Architecture

Three parts: Lynred's ATI320 camera (320 × 240 pixels, 7 g without its housing, shutterless, so it can film continuously), an NVIDIA Jetson Nano board for computing, and an Android smartphone inside the headset for display.

Overview infographic: the ATI320 camera streams to the Jetson Nano; at start-up the board launches a Docker container holding the Flask API and the Python image processing libraries; the Android smartphone fetches frames with GET requests and sends its settings with POST requests.
How the VR module works, from my technical report.

As soon as it is powered, the Jetson opens a USB tethering link with the phone: the board has neither Wi-Fi nor Bluetooth, and this isolated local link gets a new IP address on every connection. A Docker container then starts a multithreaded Flask server: the app fetches frames with GET requests and sends its settings with POST. A first approach, the Android Debug Bridge (ADB), was dropped: it could not keep up in real time.

Image processing

Frames arrive continuously through Lynred's SDK and are processed with OpenCV. Correction first relied on a custom chain; to gain speed, it now uses the camera's built-in shutterless correction. A colour map is then applied (greyscale by default, changeable from the app).

Diagram of the VR integration: the 320 × 240 infrared frame is copied and cropped by 40 pixels into a left eye and a right eye of 280 × 240, merged into 560 × 240 and sent to the smartphone; MobileNetV2 human detection fits in before, when on.
From camera to phone: the ATI320's integration in virtual reality.

With a single camera, there is no true depth: I built a fake stereoscopy. The frame is duplicated, each copy is cropped by 40 pixels on opposite sides, then both views are placed side by side, which is enough to give a sense of depth inside the headset.

Optionally, human detection draws boxes around people in the image: a MobileNetV2 model trained on infrared pedestrians, run by the DetectNet module of jetson-inference, optimised for the board. To keep things smooth, detection runs on one frame in five, and the boxes are reused in between.

The mobile app

The app is written in React Native. After a first 2D prototype, it was rebuilt in 3D with ViroReact: once the phone is in the headset, the touch screen is out of reach, so everything is driven with the head, using the gyroscope and a reticle that hovers and selects.

Screenshot of the phone in VR mode: two side-by-side views of a gridded 3D space, with the Lynred logo, the line “Observe the world in infrared” and the Start, Settings and Quit buttons.
The app's home screen, in its virtual reality space.

It finds the Jetson on its own by scanning the local network, welcomes the user in a 3D space with videos of industrial infrared applications, shows the stereo stream, and offers settings applied live on the board: spacing between the two images, colour map, human detection, camera calibration.

A second screen for trade shows

For demos, an HTML page served by Flask shows the infrared stream on a large screen plugged into the Jetson, alongside the headset, or on its own when no phone is connected. A script detects the screen at start-up, then keeps checking for it.

The second screen's web page: an “ATI320, 320 × 240, 12 µm” banner, a photo of the camera, a short description and the stereo infrared stream of a person sitting at a desk.
The infrared stream on the second screen's page.

The headset, with three students

In parallel, I was project lead for three ENSE3 students (Grenoble INP), Louis-Stéphane Assi, Jocelyn Ribes and Louis Métay-Peault, in charge of the mechanical design. The brief: survive a fall, protect the camera, run about four hours on a swappable battery, and fit every face.

“Requirements” slide: a 3D model of the headset and three numbered requirements, fall resistance, ergonomics and adaptability, four hours of battery life.
The brief, from the students' project review.

Starting from an open-source headset adapted in SolidWorks, they designed a ventilated housing for the camera, held by brackets, and a mount for the battery and the board.

3D models of the camera housing, a drilled and ventilated cube, and its mounting bracket.
The camera's ventilated housing and its bracket.
3D model of the battery and board mount, an open box.
The battery and Jetson mount.

With 702 g of components, when a complete commercial headset weighs about 600 g, wearing tests settled between three positions for the battery and board block (447 g): top, side or back. The top won, for weight distribution and cabling.

“Component layout” slide: the mount's model and a table of the pros and cons of the top, side and back positions, concluding on the top of the headset.
Position tests for the battery and board block.
The headset in profile: the red front that holds the phone, the white shell and the green mask, with a white adjustment wheel.
The 3D-printed prototype, in profile.
The red front seen from inside: the phone's slot, with its screws and holding clips.
The front that holds the phone.

The parts were printed in ABS and HIPS on Zortrax printers. Printing was the project's main hurdle: poor precision, parts lifting off the bed, parts broken and reprinted up to three times, then filed and drilled by hand.

“Printing difficulties” slide: poor precision, bed adhesion, hot-cold contact, with a preview of yellow parts being sliced.
Printing difficulties.

For battery life, a Python script logged the board's power and temperature live: the 10,000 mAh battery lasted 3 h 47 min, at steady power, 55 °C on average and 60 °C at most, below the materials' 80 °C deflection point.

Curve of power draw in milliwatts over the whole test: steady around 5,500 mW.
Power, steady over the whole discharge.
Curve of the board's temperature in degrees: it climbs to about 52 °C then settles near 60 °C.
The board's temperature.

Outcome

Working software that shows infrared in the headset in real time with minimal latency, and a first complete mechanical prototype. The technical report delivered in June 2024 sets out what comes next: a dedicated display instead of the phone, true stereoscopy with two cameras, mini-games that play with thermal vision, a fully autonomous headset and user testing.