Liftoff

Liftoff

Not enough ratings
Liftoff - Drone Telemetry
By JuniorDiscart and 2 collaborators
Liftoff: FPV Drone Racing allows you to stream drone telemetry data to external locations. That way, you can analyze flights, or diagnose issues with external programs that interface with Liftoff.
   
Award
Favorite
Favorited
Unfavorite
Introduction
Liftoff: FPV Drone Racing allows you to stream drone telemetry data to external locations. This way you can analyze flights or diagnose issues with external programs that interface with Liftoff.
Who is this for?
The Drone Telemetry feature is not something the average Liftoff: FPV player will find a use for. It is however, useful to players wanting some extremely detailed feedback or researchers interested in analyzing a drone's behavior, to plot out data in other software, or to train certain data models for A.I.
Setup
The Drone Telemetry feature can be enabled by placing a file in a specific directory. This location depends on the operating system running Liftoff:

  • Windows:
    C:\Users\%userprofile%\AppData\LocalLow\LuGus Studios\Liftoff\
  • macOS:
    ~/Library/Application Support/LuGus Studios/Liftoff/
  • Linux:
    ~/.config/unity3d/LuGus Studios/Liftoff/
  • Linux (when Steam is installed as a flatpak):

Within this directory, create a new file named TelemetryConfiguration.json to enable the drone telemetry.

Currently there is no way to enable or configure this feature from within Liftoff itself. This might be added in a future update.
Configuring the telemetry data
The Drone Telemetry data stream is configured using the TelemetryConfiguration.json file. We'll go over each of the parameters in this section. The example configurations section below provides a few practical examples.

Before diving into the different configuration possibilities, first let's define the types of data you can expect to receive on the data stream. Each component will state what type of value it will be. This will be important for when you parse the data on your end. So let's sum them up below:

  • float - a single precision floating point number, 4 bytes long.
  • int - an integral number, 4 bytes long.
  • byte - a single byte.

There are two main parameters that can be configured:
  • The data end point: all telemetry data are sent over a UDP packet stream. The EndPoint value allows you to configure where it is sent to. This value is formatted in IP end point notation, e.g. 127.0.0.1:9001, where you specify the intended IP address and port number.

  • The stream format: you can configure which telemetry data points you're interested in, as well as the sequence in which they are sent. The StreamFormat string array defines the sequence. The supported data points and their data layout are listed below. Note: Liftoff uses a left-handed, Y-Up coordinate system: the positive x-axis points to the right, the positive y-axis points up, and the positive z-axis points forward.

    • Timestamp (1 float) - current timestamp of the drone's flight. The unit scale is in seconds. This value is reset to zero when the drone is reset.

    • Position (3 floats) - the drone's world position as a 3D coordinate. The unit scale is in meters. Each position component can be addressed individually as PositionX, PositionY, or PositionZ.

    • Attitude (4 floats) - the drone's world attitude as a quaternion. Each quaternion component can be addressed individually as AttitudeX, AttitudeY, AttitudeZ and AttitudeW.

    • Velocity (3 floats) - the drone's linear velocity as a 3D vector in world-space. The unit scale is in meters/second. Each component can be addressed individually as SpeedX, SpeedY, or SpeedZ. Note: to get the velocity in local-space, transform it[math.stackexchange.com] using the values in the Attitude data stream.

    • Gyro (3 floats) - the drone's angular velocity rates, represented with three components in the order: pitch, roll and yaw. The unit scale is in degrees/second. Each component can also be addressed individually as GyroPitch, GyroRoll and GyroYaw.

    • Input (4 floats) - the drone's input at that time, represented with four components in the following order: throttle, yaw, pitch and roll. Each input can be addressed individually as InputThrottle, InputYaw, InputPitch and InputRoll.

    • Battery (2 floats) - the drone's current battery state, represented by the remaining voltage, and the charge percentage. Each of these two can be addressed individually with the BatteryPercentage and BatteryVoltage keys. Note - these values will only make sense when battery simulation is enabled in the game's options.

    • MotorRPM (1 byte + (1 float * number of motors)) - the rotations per minute for each motor. The byte at the front of this piece of data defines the amount of motors on the drone, and thus how many floats you can expect to find next. The sequence of motors for a quadcopter in Liftoff is as follows: left front, right front, left back, right back.

Note that this data stream is only available for drones that are actively being simulated by Liftoff. It won't work for drones being spectated in multiplayer or during a replay session.
Modifying the configuration while in-game
Each time the drone is reset, Liftoff will check whether the telemetry configuration file has been changed, and reload it if so. This allows you to tweak and change parameters without restarting Liftoff.

If the configuration file contains an error, Liftoff will display a popup message after the drone has been reset. Fix the error, reset the drone again, and the new telemetry configuration will be loaded.
Example configurations
Some example configurations of the TelemetryConfiguration.json file.

Everything

A configuration that will send over all telemetry data to a local end point.

{ "EndPoint": "127.0.0.1:9001", "StreamFormat": [ "Timestamp", "Position", "Attitude", "Velocity", "Gyro", "Input", "Battery", "MotorRPM" ] }

The total size of each data frame being sent would be 97 bytes.

Horizontal position over time

A configuration that will only send the position of the drone in the XZ-plane, along with the timestamp, to an end point in the local network.

{ "EndPoint": "192.168.1.6:6808", "StreamFormat": [ "Timestamp", "PositionX", "PositionZ" ] }

The total size of each data frame being sent would be 12 bytes.

From input to gyroscope

A configuration that correlates input axes to the drone's gyroscope, without a timestamp.

{ "EndPoint": "127.0.0.1:9001", "StreamFormat": [ "InputPitch", "GyroPitch", "InputRoll", "GyroRoll", "InputYaw", "GyroYaw" ] }

The total size of each data frame being sent would be 24 bytes.
32 Comments
Tobyo 12 hours ago 
I was able to receive the data, and they are indeed 4 bytes per float, but how to I translate them back to a float? What is the formula or the method to turn those 4 bytes from unity/liftoff into a float (using Pd, Max/MSP, or Javascript)
FahD 16 Feb @ 6:07pm 
@juniorDiscart well, thats kinda sad :(

@Poison Dart Frag i just think about this eresterday, the problem is that i need it to fly continously in a track. opening a GUI would hinder the performance by a lot. i wonder if i can bind the PID change to a button or some sort?
Poison Dart Frag 13 Feb @ 1:39am 
If there's no direct API to change values on-the-fly (pun not intended), perhaps you might need a more clunky solution like using something like https://pypi.org/project/PyAutoGUI-ng/ to input fake keyboard and mouse inputs to change things in the menu and reset the flight after saving each change to load them.

Dunno if there's a platform independent equivalent for emulating analog inputs via scripts; on Linux you could use something like https://pypi.org/project/evdev/ I think.

I have not tested either of those modules with Liftoff yet, no idea if there will be any obstacles. And to be honest, I have no idea if that would be the best approach in the first place. Really, I don't have much idea what I'm talking about; this is mostly just stuff I had bookmarked for some projects I never got around starting.
JuniorDiscart  [author] 13 Feb @ 12:39am 
@FahD This is an output-only stream. It's not possible to feed data to the drone.
FahD 12 Feb @ 6:06pm 
Hi, im currently developing an adaptive algorithm (AI) to tune the PIDs automatically. i already able to get the telemetry data through this. My question is, is there any way that my python/matlab code could change the in game PID value in realtime??
ponadto 1 Feb @ 9:17am 
My bad!
netcat uses TCP by default, I should have called:

netcat -ul 127.0.01 9001

Now it works like a charm!
ponadto 31 Jan @ 2:19pm 
This looks awesome!

Alas, I tried adding this TelemetryConfiguration.json file:

{
"EndPoint": "127.0.0.1:9001",
"StreamFormat": [
"Timestamp",
"Position",
"Attitude",
"Velocity",
"Gyro",
"Input",
"Battery",
"MotorRPM"
]
}

and saved it in my ~/.config/unity3d/LuGus Studios/Liftoff/ directory (I'm running Steam on Ubuntu 22.04), but after I launch Liftoff and listen on the port:

netcat -l 127.0.0.1 9001

I don't get any data :(

I was looking for any clues in my Player.log file, but no info about the TelemetryConfiguration.json file being loaded.

Any hints on how to get this working / How to debug it?
diko 24 Dec, 2024 @ 10:49am 
For anyone on LInux with steam installed as flatpak app. Your **TelemetryConfiguration.json** should have path **~/.var/app/com.valvesoftware.Steam/config/unity3d/LuGus/ Studios/Liftoff/TelemetryConfiguration.json**
o7ur 30 Nov, 2024 @ 8:59am 
Hey!

I'm on my Windows 11 computer, running the game in Windows through steam.

When I place the .json file in the correct location and named correctly, i'm not getting any telemetry out from the udp port... I have checked the Player.log file and Player-prev.log, and I can see that it's not finding the .json file.. I have double and triple checked the location of the file and the structure of the .json file itself, and its according to the instruction in this thread...

What i'm concerned about is that the path to the .json file in the .log file is using a "\"(backslash) to look for the .json file, instead of using "/"(forwardslash) in the path..

"Could not find a drone telemetry configuration file at C:/Users/magnu/AppData/LocalLow/LuGus Studios/Liftoff\TelemetryConfiguration.json"

Any thoughts on what might be the problem?
Kudo 21 Nov, 2024 @ 5:37pm 
@JuniorDiscart

Couldn't get it to work locally due to my isp but I set up a server and it works! Thanks for the help