Skip to main content
Telemetry data reveals exactly where one driver gains or loses time. This tutorial compares two drivers’ fastest laps, analyzing speed, acceleration forces, and driving inputs. Telemetry comparison with acceleration analysis

Load session and get fastest laps

We’ll compare VER and LEC at Monaco Qualifying.
import tif1
from tif1.plotting import get_team_color, setup_mpl
import matplotlib.pyplot as plt
import numpy as np

# Setup plotting
setup_mpl(color_scheme="fastf1")

# Load session
session = tif1.get_session(2024, "Monaco", "Q")
laps = session.laps

# Get fastest laps
driver_1 = "VER"
driver_2 = "LEC"

laps_d1 = laps.pick_driver(driver_1).pick_fastest()
laps_d2 = laps.pick_driver(driver_2).pick_fastest()

# Get telemetry with distance
tel_d1 = laps_d1.get_telemetry().add_distance()
tel_d2 = laps_d2.get_telemetry().add_distance()

Compute accelerations

Calculate longitudinal and lateral g-forces from telemetry data.
def compute_accelerations(telemetry):
    """Calculate longitudinal and lateral accelerations in g."""
    # Convert speed to m/s
    v = np.array(telemetry["Speed"]) / 3.6

    # Longitudinal acceleration from speed change
    dt = np.diff(telemetry["Time"].dt.total_seconds())
    dv = np.diff(v)
    lon_acc = np.append(dv / dt, 0) / 9.81  # Convert to g

    # Lateral acceleration from position change
    dx = np.gradient(telemetry["X"], telemetry["Distance"])
    dy = np.gradient(telemetry["Y"], telemetry["Distance"])

    # Calculate curvature
    curvature = (dx * np.gradient(dy) - dy * np.gradient(dx)) / (dx**2 + dy**2)**1.5
    lat_acc = v * v * curvature / 9.81

    # Clip outliers
    lon_acc = np.clip(lon_acc, -7.5, 7.5)
    lat_acc = np.clip(lat_acc, -7.5, 7.5)

    return lon_acc, lat_acc

# Add accelerations to telemetry
tel_d1["LongAcc"], tel_d1["LatAcc"] = compute_accelerations(tel_d1)
tel_d2["LongAcc"], tel_d2["LatAcc"] = compute_accelerations(tel_d2)

Label driver actions

Categorize each telemetry point as braking, full throttle, or lifting.
# Driver 1 actions
tel_d1.loc[tel_d1["Brake"] > 0, "Action"] = "Brake"
tel_d1.loc[tel_d1["Throttle"] == 100, "Action"] = "Full Throttle"
tel_d1.loc[(tel_d1["Brake"] == 0) & (tel_d1["Throttle"] < 100), "Action"] = "Lift"

# Driver 2 actions
tel_d2.loc[tel_d2["Brake"] > 0, "Action"] = "Brake"
tel_d2.loc[tel_d2["Throttle"] == 100, "Action"] = "Full Throttle"
tel_d2.loc[(tel_d2["Brake"] == 0) & (tel_d2["Throttle"] < 100), "Action"] = "Lift"

# Create action segments for visualization
tel_d1["ActionID"] = (tel_d1["Action"] != tel_d1["Action"].shift(1)).cumsum()
tel_d2["ActionID"] = (tel_d2["Action"] != tel_d2["Action"].shift(1)).cumsum()

Create comparison plot

Visualize speed, accelerations, and driver inputs.
# Get team colors
team_d1 = laps_d1.reset_index().loc[0, "Team"]
team_d2 = laps_d2.reset_index().loc[0, "Team"]
color_d1 = get_team_color(team_d1)
color_d2 = get_team_color(team_d2)

# Create figure
fig, ax = plt.subplots(4, figsize=(16, 12), sharex=True)

# Speed comparison
ax[0].plot(tel_d1["Distance"], tel_d1["Speed"], label=driver_1, color=color_d1, linewidth=2)
ax[0].plot(tel_d2["Distance"], tel_d2["Speed"], label=driver_2, color=color_d2, linewidth=2)
ax[0].set_ylabel("Speed (km/h)")
ax[0].legend()
ax[0].grid(True, alpha=0.3)

# Longitudinal acceleration
ax[1].plot(tel_d1["Distance"], tel_d1["LongAcc"], label=driver_1, color=color_d1, linewidth=2)
ax[1].plot(tel_d2["Distance"], tel_d2["LongAcc"], label=driver_2, color=color_d2, linewidth=2)
ax[1].set_ylabel("Long. Acc (g)")
ax[1].axhline(0, color="white", linestyle="--", alpha=0.5)
ax[1].legend()
ax[1].grid(True, alpha=0.3)

# Lateral acceleration
ax[2].plot(tel_d1["Distance"], tel_d1["LatAcc"], label=driver_1, color=color_d1, linewidth=2)
ax[2].plot(tel_d2["Distance"], tel_d2["LatAcc"], label=driver_2, color=color_d2, linewidth=2)
ax[2].set_ylabel("Lat. Acc (g)")
ax[2].axhline(0, color="white", linestyle="--", alpha=0.5)
ax[2].legend()
ax[2].grid(True, alpha=0.3)

# Driver actions bar chart
action_colors = {"Full Throttle": "lime", "Lift": "grey", "Brake": "red"}

# Plot actions for both drivers
# (simplified - see full example for complete implementation)

ax[3].set_xlabel("Distance (m)")
ax[3].set_ylabel("Driver Actions")

plt.suptitle(f"{session.event.year} {session.event['EventName']} - {session.name}")
plt.tight_layout()
plt.show()

What to analyze

  • Speed traces: Who carries more speed through corners?
  • Longitudinal acceleration: Positive = accelerating, negative = braking. Who brakes harder or accelerates earlier?
  • Lateral acceleration: Shows cornering forces. Higher values = faster through corners.
  • Driver actions: Visual representation of throttle and brake application.

Key insights

Look for:
  • Braking points: Who brakes later?
  • Throttle application: Who gets on power earlier?
  • Cornering speed: Who maintains higher minimum speeds?
  • G-forces: Who pushes the car harder in braking and cornering?
Telemetry analysis with tif1 gives you professional-level insights into driver performance and car behavior.
Last modified on March 6, 2026