PiVR has been developed by David Tadres and Matthieu Louis (`Louis Lab
`__).
.. _Benchmark:
PiVR Benchmark
***************
.. _Concepts:
Concepts
========
When creating a virtual reality two different measurements of time
are relevant:
#. The **loop time**: How often per second does the system take input
from the subject? This is usually expressed in **Hz**.
#. The **latency**: How long between taking the input and presenting the
subject with the updated stimulus that makes the virtual reality?
This is usually expressed in milliseconds (**ms**).
Next, how can one measure time on a computer? Most operating systems
(Windows, MacOS and Linux) are *non-real time operating systems*.
This means that the OS can **not** guarantee that a given line of
code is executed at a fixed interval. If one asks the system to
simply record the time to measure *loop time* and *latency* on
introduces uncertainty, possibly in the order of milliseconds.
Luckily PiVR has a real-time operating system - on the GPU:
Digital cameras work by reading out lines on their sensor and the
camera used by PiVR is no different. (Read `here
`__ for a
fantastic introduction).
For example at 90 frames per second at 640x480 the camera must read
out 480 lines in ~11ms. It must therefore spend no more than 2.3^-5s
or 23.1us per line. This means every 23.1us the camera is pushing one
frame line to the GPU (see `here
`__
for detailed information).
The GPU records the timestamp of when the first line of a new frame
is received based on its real-time hardware clock. We
take advantage of this while doing the PiVR measurements. This timestamp
is called presentation timestamps (**PTS**). (More info `here
`__).
.. _Benchmark_loop_time:
PiVR loop time
==============
PiVR loop time has been tested by recording the PTS while doing
real-time tracking at 640x480 resolution and a variety of framerates
using a Raspberry Pi 3.
.. figure:: Figures/benchmarking/1_loop_time_640x480.jpg
:width: 100 %
:alt: 1_loop_time_640x480.jpg
For example at 30fps each camera timestamp should be 1/30 = 0.033s
which of course is 33ms.
The reported timestamps are perfect for 30 and 40fps. At 50, 60 and
70fps we start loosing a few frames (6/5,598, 25/7,198 and 16/8,398,
respectively) meaning PiVR could not keep up with the images coming
in therefore the loop time was larger than 1/fps.
For more detail please see `Timing Performance of PiVR
`__
.. _Benchmark_latency:
PiVR latency
=============
To measure latency we turned the LED on at a defined frame and asked
how long it takes for PiVR to detect the change in light intensity.
This was based on the excellent suggestion of `Reviewer #1
`__:
#. Run closed loop tracking at 70fps at 640x480 with a facsimile larva.
#. At each 50th frame of a trial (and multiples thereof), turn the red
LED on.
#. Take the median of a set of 10 pixels in the search box and compare
the average current intensity to the intensity of the previous frame.
#. If this difference is larger than 2, consider the LED “ON” and
immediately turn the LED “OFF”.
#. If the LED has been turned “OFF”in the previous frame, turn the LED
“ON”again.
The code used for this can be found on the Gitlab repository of PiVR
`Gitlab repository of PiVR `__ in
branch ‘LED_flash_test’ in the file ‘fast_tracking.py’ with
`relevant code going from line 1457 to 1584
`__.
Using the methodology described above, we found that the detection of a
‘LED ON’ event was either detected during the earliest possible frame or
one frame later. This difference in latency was dependent on the region
of the image (region of interest, ROI) used to compare the pixel
intensity. The detection latency was systematically longer when the
ROI was in the top (green box) as compared to the bottom of the image
(magenta box).
.. figure:: Figures/benchmarking/2_latency_70fps_640x480.jpg
:width: 100 %
:alt: 2_latency_70fps_640x480.jpg
As illustrated in the figure below, this can be explained by the fact
that turning the LED “ON” while the camera is grabbing the frame through
the rolling shutter cannot lead to a successful detection of the
change in light intensity. During frame #50 the LED is still “OFF” in
the top part of the image whereas it is “ON” in the lower part of
the image.
.. figure:: Figures/benchmarking/3_rolling_shutter_effect.png
:width: 100 %
:alt: 3_rolling_shutter_effect.png
As shown above the number of frames between two consecutive events
corresponding to the LED being turned “ON” was 3 frames if the ROI was
located in the top part of the image (green box). The schematic
diagram below outlines our interpretation of this 3-frame
delay: The LED is being turned “ON” during frame (j) while the frame is
being recorded (vertical arrow in frame j + 1). If the PiVR algorithm
is set to monitor a ROI in the upper part of the image, this ROI is
read before the LED intensity has switched to the “ON” state. Therefore,
the LED “ON”event is not observed during frame j. Instead, it is
detected during processing of frame j + 1. This delay happens again
when the second LED “ON” event is detected in frame j + 4.
.. figure:: Figures/benchmarking/4_top_diagram.jpg
:width: 100 %
:alt: 4_top_diagram.jpg
By contrast, if PiVR is set to monitor a ROI in the lower part of the
image, the LED turn “ON” event can be detected while processing frame j
+ 1
(see below).
.. figure:: Figures/benchmarking/5_bottom_diagram.jpg
:width: 100 %
:alt: 5_bottom_diagram.jpg
Consequently, the time that elapses between the two LED “ON” events is
either 5 frames (or 71ms at 70 Hz) for a ROI in the top part of the
image or 2 frames for a ROI in the bottom part of the image.
Based on these observations, we conclude that the LED “ON” event must
be happening **while** the image is being captured, which corresponds
to a duration of **1.34ms**. The longest possible latency between the
action of an animal (in this example during frame j) and the actuation
of the update of the LED is therefore 2 frames + 1.34ms
(time window associated with frame j + 2), which is equivalent to less
than 30 ms (frame duration at 70 Hz is **14.29 ms**.
.. _PiVR_loop_time_high_res:
PiVR loop time (High Res)
==========================
PiVR v1.5.0 was released on 27th of March, 2021. It allows users to
perform :ref:`online tracking ` with resolutions other
than 640x480.
Higher resolutions impact the :ref:`closed loop times ` as
a larger image is being analyzed to define the animal in each frame.
We tested the performance using both a
`Raspberry Pi 3 Model B Plus Rev 1.3
`__
and the newer and more powerful
`Raspberry Pi 4 Model B Rev 1.2
`__
The **Raspberry Pi 3** was able to handle 30fps without dropping frames
at 1024x768. At 1296x972 it was only able to handle 15fps without
dropping frames.
.. figure:: Figures/benchmarking/6_RPi3_Image_processing_time.jpg
:width: 100 %
:alt: 6_RPi3_Image_processing_time.jpg
The `50% more powerful
`__
**Raspberry Pi 4** on the other hand was able to handle 40fps at
1024x768 and 30fps at 1296x972:
.. figure:: Figures/benchmarking/7_RPi4_Image_processing_time.jpg
:width: 100 %
:alt: 7_RPi4_Image_processing_time.jpg