FastF1 and Raspberry PI: Formula 1 Professional Data with Python

0
(0)

For Formula 1 passionate like me, having a way to get the data that TV shows with drivers comparison would be fantastic in order to create my personal comparison between cars and driver’s performances. the Python FastF1 library with my Raspberry PI makes this possible with a very few intuitive command lines

In this tutorial, I’m going to show you how to install and use FastF1 with Rasberry PI computer boards.

Fast-F1 gives you access to F1 lap timing, car telemetry and position, tyre data, weather data, the event schedule and session results. It uses Pandas, Numpy and Matplotlib, making it easy to create customized, interactive charts and enabling accurate data analysis and visualization.

FastF1 gets its data from two main sources:

  • The official f1 data stream
  • Ergast web api

FastF1 provides its own event schedule for the 2018 season and all later seasons.

For this tutorial, I’ve made tests both with a Raspberry PI 3 Model A+ (with Raspberry PI OS Lite, for the shell-only examples) and a Raspberry PI 4 Model B (with Raspberry PI OS Desktop, for the charts tests).

Follow peppe8o posts on -> Twitter

What We Need

raspberry pi 3 model A+

As usual, I suggest adding from now to your favourite e-commerce shopping cart all the needed hardware, so that at the end you will be able to evaluate overall costs and decide if continue with the project or remove them from the shopping cart. So, hardware will be only:

Check hardware prices with the following links:

Amazon raspberry pi boards box
Amazon Raspberry PI 3 Model A+ box
Amazon Micro SD box
Amazon Raspberry PI Power Supply box

Step-by-Step Procedure

Prepare Operating System

Start preparing your OS. Please note that in order to use the interactive charts you will need the Raspberry PI OS Desktop, so requiring also a keyboard, mouse and monitor. If you need only the data results, you can work also with Raspberry PI OS Lite.

Make your OS up to date. From the terminal, please use the following command:

sudo apt update -y && sudo apt upgrade -y

Install FastF1 in Raspberry PI

In order to install FastF1, we need to use pip3. The commands will be the following:

sudo apt install python3-pip -y
pip3 install fastf1

You may get the following warning:

WARNING: The scripts f2py, f2py3 and f2py3.9 are installed in '/home/pi/.local/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.

This can change as your user may be different from the “pi”, but the solution is the same. This simply means that some packages have been installed into a local bin folder that is not in the path that your environment uses by default to identify executables. If you check the PATH variable from your system, you will get:

pi@raspberrypi:~ $ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games

Please open to edit your bashrc file:

nano ~/.bashrc

And append the following line at the end of this file:

export PATH="$HOME/.local/bin:$PATH"

You can reload the bashrc with the following terminal command without the need to logout or reboot:

source ~/.bashrc

Now your system PATH variable will include also the desired folder with the installed scripts:

pi@raspberrypi:~ $ echo $PATH
/home/pi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games

Finally, please create a cache folder that will be used later in examples to make queries faster:

mkdir ff1cache

Please note that this command creates the caching folder in your user home. In this tutorial I’m using the “pi” user, so having “/home/pi/ff1cache” string as the absolute path for caching. If you have a different user, you will need to set this path according to your user (changing the “pi” in the string).

That’s all. Fastf1 is now installed and ready to be used, as we’ll see in the following examples.

FastF1 Main Concepts

Before going to examples. let us see a few main FastF1 concepts.

Caching

Caching should almost always be enabled to speed up the runtime of your scripts and to prevent exceeding the rate limit of API servers. FastF1 will print an annoyingly obnoxious warning message if you do not enable caching.

The following class-level functions are used to setup, enable and (temporarily) disable caching:

  • fastf1.Cache.enable_cache(cache_folder) -> Enables the API cache.
  • fastf1.Cache.clear_cache(cache_folder[, deep]) -> Clear all cached data.
  • fastf1.Cache.disabled() -> Returns a context manager object that creates a context within which the cache is temporarily disabled.
  • fastf1.Cache.set_disabled() -> Disable the cache while keeping the configuration intact.
  • fastf1.Cache.set_enabled() -> Enable the cache after it has been disabled with set_disabled().

Fastf1 main objects

Fastf1 has 2 main objects:

  • Event -> you can think of an event as a complete GP (with all the practices, qualifying and race). Also each pre-season tests are managed as events
  • Session -> this is a single round inside an event (that are each of ‘Practice 1’, ‘Practice 2’, ‘Practice 3’, ‘Sprint Qualifying’, ‘Qualifying’ or ‘Race’)

You can call events and sessions with one of the following:

  • fastf1.get_session(year, gp[, identifier, …]) -> Create a Session object based on year, event name and session identifier.
  • fastf1.get_testing_session(year, …) -> Create a Session object for testing sessions based on year, test event number and session number.
  • fastf1.get_event(year, gp, *[, force_ergast]) -> Create an Event object for a specific season and gp.
  • fastf1.get_testing_session(year, …) -> Create a Session object for testing sessions based on year, test event number and session number.
  • fastf1.get_event_schedule(year, *[, …]) -> Create an EventSchedule object for a specific season.

With the last function, you will get the complete calendar for a specific season.

Session identifiers

In order to get a specific session data, we’ll have to call it with its identifier (besides the event year and GP name/number). FastF1 allows calling a session with one of the following alternatives:

  • session name abbreviation: ‘FP1’, ‘FP2’, ‘FP3’, ‘Q’, ‘SQ’, ‘R’
  • full session name: ‘Practice 1’, ‘Practice 2’, ‘Practice 3’, ‘Sprint Qualifying’, ‘Qualifying’, ‘Race’ (the name is case-insensitive)
  • number of the session: 1, 2, 3, 4, 5

Reducing Columns for Output

Fastf1 gives results with a lot of columns. As it uses Pandas, you can get better outputs with the loc function:

.loc[ rows_ref , columns_ref ]

which lets you choose what rows and columns to show. For each reference (both rows and columns), you can set it to show:

  • a range: that is identified by simply putting the first value to show, the colon symbol and the final value to show
  • a list: that is a sequence of columns labels or indexes to show
  • all the data: that is got by simply putting the colon symbol

The list of available columns can be get from the “.columns” property available for quite every fastf1 object.

Please let me give you an example. Once session data are loaded, the session result object (that we’ll see in the following examples) has the following columns:

>>> session.results.columns
Index(['DriverNumber', 'BroadcastName', 'Abbreviation', 'TeamName',
       'TeamColor', 'FirstName', 'LastName', 'FullName', 'Position',
       'GridPosition', 'Q1', 'Q2', 'Q3', 'Time', 'Status', 'Points'],
      dtype='object')

In this case, you can show all the rows with only part of its columns with the following line:

session.results.loc[:, ['Position', 'FullName', 'TeamName','Q1','Q2','Q3']]

FastF1 Examples

In this tutorial part, I’ll show you how to use fastf1 with your Raspberry PI. You can use it within a python script or in the interactive python3 shell. The main difference comes to print the data tables:

  • from the python3 interactive shell, you can directly issue the object name
  • from a python3 script, you will need to use the print() function

In both cases, you will need to start by importing the fastf1 library and enabling the cache (the latter will strongly improve the performance of your scripts once the data has been loaded the first time).

From the terminal, please open a python3 shell with the following command and press RETURN:

python3

Now import the fastf1 library and enable cache (please check the cache path according to your cache folder position):

import fastf1
fastf1.Cache.enable_cache("/home/pi/ff1cache")

Example 1: Getting the F1 season calendar

We can get the season calendar for a specified year with the following command (where 2022 is the year I selected):

schedule = fastf1.get_event_schedule(2022)

Now you can show the calendar for 2022:

raspberry pi fastf1 ex01 formula1 calendar

From the above output, you can see that there is a column with a “…” (3 points) symbol. This means that more columns are available and have been hidden in order to make the output printable in your display. Moreover, after the list we’ll see the rows and columns count that confirms this:

raspberry pi fastf1 ex01 formula1 calendar columns marked

Let’s see all the available columns for the schedule object with the “schedule.columns” command:

>>> schedule.columns
Index(['RoundNumber', 'Country', 'Location', 'OfficialEventName', 'EventDate',
       'EventName', 'EventFormat', 'Session1', 'Session1Date', 'Session2',
       'Session2Date', 'Session3', 'Session3Date', 'Session4', 'Session4Date',
       'Session5', 'Session5Date', 'F1ApiSupport'],
      dtype='object')

Please note that the session numbers match the order already explained in the related paragraph.

As said, we can fit the output to our needs by using the loc[] function. For example. we can get a simplified table by selecting all the rows but only part of the columns and showing only the race :

schedule.loc[:,['Country', 'Location', 'OfficialEventName', 'Session5Date']]
raspberry pi fastf1 ex01 formula1 calendar simpler

The resulting python3 script will be the following:

import fastf1
fastf1.Cache.enable_cache("/home/pi/ff1cache")

schedule = fastf1.get_event_schedule(2022)
print(schedule.loc[:,['Country', 'Location', 'OfficialEventName', 'Session5Date']])

While the single events give detailed info about the round organization, the session data are the most interesting part of fastf1. For this reason, in the following examples, we’ll be focused on sessions.

Example 2: getting Session Results

After importing the fastf1 library and enabling the cache, let’s set a session call and load its data:

session = fastf1.get_session(2022,3,'Q')
session.load()

Please note that during the loading of some sessions you could have some warnings about the missing data for some laps or telemetry, similar to the following:

api         WARNING     Driver 241: Position data is incomplete!

This is caused by some data missing from the official channels for several possible reasons (for example a lap not finished for an incident or for technical issues). Anyway, these cases do not affect the good results that the library provides.

As you can see, we have called the session by ID. Please note that official sessions have an ID that doesn’t include the pre-season sessions. A way to check it is by verifying the parent event:

session.event
raspberry pi fastf1 ex02 session event

or calling a specific record from these data:

>>> session.event['OfficialEventName']
'FORMULA 1 HEINEKEN AUSTRALIAN GRAND PRIX 2022'

Now, we can get the session results:

session.results
raspberry pi fastf1 ex02 session results

Again, let’s get a simplified view of available columns:

>>> session.results.columns
Index(['DriverNumber', 'BroadcastName', 'Abbreviation', 'TeamName',
       'TeamColor', 'FirstName', 'LastName', 'FullName', 'Position',
       'GridPosition', 'Q1', 'Q2', 'Q3', 'Time', 'Status', 'Points'],
      dtype='object')

With the following command:

session.results.loc[:,['Position', 'Abbreviation', 'TeamName', 'Q1', 'Q2', 'Q3']]
raspberry pi fastf1 ex02 session results simpler

The following will be the related python3 script:

import fastf1
fastf1.Cache.enable_cache("/home/pi/ff1cache")

session = fastf1.get_session(2022,3,'Q')
session.load()
print(session.results.loc[:,['Position', 'Abbreviation', 'TeamName', 'Q1', 'Q2', 'Q3']])

Example 3: Driver Performances

Let’s analyze the performance of a specific driver in the session. We’ll use the same session already set and loaded. Moreover, we’ll analyze data for LeClerc. We’ll get the Ferrari driver laps in the selected session with the following command:

lec = session.laps.pick_driver('LEC')

Showing these data:

raspberry pi fastf1 ex03 driver laps

As you can see, rows are tagged with an “IsAccurate” boolean column. According to the official documentation, “if True the lap has passed a basic accuracy check for timing data. This does not guarantee accuracy but laps marked as inaccurate need to be handled with caution. They might contain errors which can not be spotted easily.

A better visualization:

lec.loc[:,['Driver', 'Team', 'LapTime', 'LapNumber', 'Stint', 'Sector1Time', 'Sector2Time', 'Sector3Time', 'Compound', 'TyreLife']]
raspberry pi fastf1 ex03 driver laps simpler

From these laps, you can get the fastest one with the pick_fastest() attribute:

lec.pick_fastest()
raspberry pi fastf1 ex03 driver laps fastest

Finally, the related python3 script:

import fastf1
fastf1.Cache.enable_cache("/home/pi/ff1cache")

session = fastf1.get_session(2022,3,'Q')
session.load()
lec = session.laps.pick_driver('LEC')

print(lec.loc[:,['Driver', 'Team', 'LapTime', 'LapNumber', 'Stint', 'Sector1Time', 'Sector2Time', 'Sector3Time', 'Compound', 'TyreLife']])
print("Fastest:")
print(lec.pick_fastest())

Example 4: Compare Driver’s Performances by Overlaying Speed Traces of Two Laps

Fastf1 is capable to generate amazing interactive graphs to compare performances between drivers, like the ones you can see on TV. With Fastf1 installed on an OS having a Desktop environment (like Raspberry PI OS Desktop), you can get these graphs shown directly on your display and you can customize the info to show.

Data will be plotted by the matplotlib already installed with the fastf1 library. The python3 script to do the job is the following one.

import matplotlib.pyplot as plt
import fastf1.plotting

fastf1.Cache.enable_cache('/home/pi/ff1cache')  # replace with your cache directory

# set session
year=2022
gp=3
ses='Q'

# set drivers abbreviated name
drv_1='LEC'
drv_2='VER'

# enable some matplotlib patches for plotting timedelta values and load
# FastF1's default color scheme
fastf1.plotting.setup_mpl()

# load a session and its telemetry data
session = fastf1.get_session(year, gp, ses)
session.load()

drv_1_lap = session.laps.pick_driver(drv_1).pick_fastest()
drv_2_lap = session.laps.pick_driver(drv_2).pick_fastest()

drv_1_tel = drv_1_lap.get_car_data().add_distance()
drv_2_tel = drv_2_lap.get_car_data().add_distance()

fig, ax = plt.subplots()
ax.plot(drv_1_tel['Distance'], drv_1_tel['Speed'], color='red', label=drv_1)
ax.plot(drv_2_tel['Distance'], drv_2_tel['Speed'], color='blue', label=drv_2)

ax.set_xlabel('Distance in m')
ax.set_ylabel('Speed in km/h')

ax.legend()
plt.suptitle(f"Fastest Lap Comparison \n "
             f"{session.event['EventName']} {session.event.year} Qualifying")

plt.show()

A detailed explanation of this script can be found at Fast-F1 examples_gallery plot_speed_traces, where I’ve only changed some lines in order to make the script simpler to be managed with variables in the first part. The following is the interactive window that will pop out on your screen:

raspberry pi fastf1 ex04 drivers speed comparison output

The above picture can be seen at its full resolution from the following link: raspberry-pi-fastf1-ex04-drivers-speed-comparison-output.jpeg.

Example 5: Analyze Fastest Lap Gear Shifts

That’s another interactive window coming from FastF1 examples. This script shows the gear changes wi the fastest lap. The following is my customized script:

import fastf1

import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib import cm
import numpy as np

fastf1.Cache.enable_cache('/home/pi/ff1cache')  # replace with your cache directory

# set session
year=2022
gp=3
ses='Q'

session = fastf1.get_session(year, gp, ses)
session.load()

lap = session.laps.pick_fastest()
tel = lap.get_telemetry()

# Prepare the data for plotting by converting it to the appropriate numpy
# data types
x = np.array(tel['X'].values)
y = np.array(tel['Y'].values)

points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
gear = tel['nGear'].to_numpy().astype(float)

# Create a line collection. Set a segmented colormap and normalize the plot
# to full integer values of the colormap
cmap = cm.get_cmap('Paired')
lc_comp = LineCollection(segments, norm=plt.Normalize(1, cmap.N+1), cmap=cmap)
lc_comp.set_array(gear)
lc_comp.set_linewidth(4)
plt.gca().add_collection(lc_comp)
plt.axis('equal')
plt.tick_params(labelleft=False, left=False, labelbottom=False, bottom=False)

title = plt.suptitle(
    f"Fastest Lap Gear Shift Visualization\n"
    f"{lap['Driver']} - {session.event['EventName']} {session.event.year}"
)

# Add a colorbar to the plot. Shift the colorbar ticks by +0.5 so that they
# are centered for each color segment.
cbar = plt.colorbar(mappable=lc_comp, label="Gear", boundaries=np.arange(1, 10))
cbar.set_ticks(np.arange(1.5, 9.5))
cbar.set_ticklabels(np.arange(1, 9))

plt.show()

This example is explained by Fast-F1 examples_gallery plot_gear_shifts_on_track page.

The output is the following:

raspberry pi fastf1 ex04 fastest lap gear shifts

The full-size picture can be found at raspberry-pi-fastf1-ex04-fastest-lap-gear-shifts.jpeg.

What’s Next

If you want to discover many other projects for your Raspberry PI, you can take a look at peppe8o Raspberry PI tutorials.

Enjoy!

How useful was this post?

Click on a star to rate it anonymously!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?