How I analyze drone's flight data gathered over UDP with Warp 10 and use a dashboard as code to display it.
A couple of years ago I've bought a small low-cost drone: Tello. You can pilot it with your smartphone through Wi-Fi connection and UDP protocol. I decided to hack it and to analyze the data that is emitted by the drone.
After the very serious post about chemtrails, it's time to open the second W. Files chapter!
So, I've developed a small NodeJS lib in order to programmatically pilot the drone, fetch its flights' telemetry, and stream its video on my laptop. After a couple of coffee and hours, I achieved it. You can find it here.
I have children and the main goal of this dev was to make them develop and have fun. In fact, they never gave a buck about that project, I am the only child who plays with it.
If you own a Tello, you can of course use this lib. But the main aim of this blog post is not really the drone but to manage its flight data.
This little drone communicates over UDP and regularly push its telemetry which contains :
Name | Unit | Description |
---|---|---|
h | cm | height |
baro | cm | barometer |
tof | cm | to floor distance |
templ | °C | min temperature |
temph | °C | max temperature |
pitch | ° | attitude pitch |
roll | ° | attitude roll |
yaw | ° | attitude yaw |
agx | 0.001g | acceleration x |
agy | 0.001g | acceleration y |
agz | 0.001g | acceleration z |
vgx | cm/s | speed x |
vgy | cm/s | speed y |
vgz | cm/s | speed z |
bat | % | battery |
Nice. Here, we will transmit the flight data through UDP to Warp 10.
Warp 10
The Warp 10 Platform has a lot of functionalities. In particular for our usage here, you can use the built-in UDPPlugin to start a UDP server.
Warp 10 is an open source platform designed to collect, store, and analyze sensor / IoT data. |
Assuming Warp 10 is installed in /opt/warp10
, activate it by editing the file /opt/warp10/etc/conf.d/80-udp-plugin.conf
:
// activate the UDP plugin
warp10.plugin.udp = io.warp10.plugins.udp.UDPWarp10Plugin
udp.dir = ${standalone.home}/udp
udp.period = 5000
You may also activate the Debug Extension:
warpscript.extension.debug = io.warp10.script.ext.debug.DebugWarpScriptExtension
Then, create a new directory /opt/warp10/udp
and create a new file called tello.mc2
in it:
And then restart Warp 10. Connect the drone to your Wi-Fi local card and launch this JavaScript which plays a small scenario:
import {Tello} from "@giwisoft/ryze-tello-sdk";
const tello = new Tello();
(async () => {
// Start the engine and play "Ride Of The Valkyries"
await tello.start(); await tello.takeoff();
// Go up
await tello.up(50);
// Perform a forward flip
await tello.flip("f");
// Go forward
await tello.forward(50);
await tello.right(20);
// Go backward
await tello.backward(100);
await tello.rotateCW(360);
// Finally land
await tello.land();
// And then shut down the engine
})().then(() => tello.stop());
If you tail /opt/warp10/logs/warp10.log
you will see the flight data:
[1616403713307] UDP: line from IP:192.168.10.1 port:8889 content=pitch:0;roll:0;yaw:-156;vgx:0;vgy:0;vgz:0;templ:79;temph:81;tof:10;h:0;bat:82;baro:-99.61;time:31;agx:1.00;agy:-10.00;agz:-998.00;
[1616403713409] UDP: line from IP:192.168.10.1 port:8889 content=pitch:0;roll:0;yaw:-156;vgx:0;vgy:0;vgz:0;templ:79;temph:81;tof:10;h:0;bat:82;baro:-99.83;time:31;agx:1.00;agy:-10.00;agz:-1002.00;
[1616403713511] UDP: line from IP:192.168.10.1 port:8889 content=pitch:0;roll:0;yaw:-156;vgx:0;vgy:0;vgz:0;templ:79;temph:81;tof:10;h:0;bat:82;baro:-99.87;time:31;agx:1.00;agy:-11.00;agz:-1003.00;
[1616403713613] UDP: line from IP:192.168.10.1 port:8889 content=pitch:0;roll:0;yaw:-156;vgx:0;vgy:0;vgz:0;templ:79;temph:81;tof:10;h:0;bat:82;baro:-99.86;time:31;agx:2.00;agy:-9.00;agz:-1001.00;
[1616403713714] UDP: line from IP:192.168.10.1 port:8889 content=pitch:0;roll:0;yaw:-156;vgx:0;vgy:0;vgz:0;templ:79;temph:81;tof:10;h:0;bat:82;baro:-99.80;time:31;agx:0.00;agy:-9.00;agz:-1002.00;
Huh, what an ugly CSV, yes it is. Ok, let's parse it with our previous WarpScript tello.mc2
:
Now, wait 5 seconds (Warp 10 put the mc2 in a cache, which TTL was set by udp.period = 5000
) and re-launch the previous JavaScript. In the log file you will see something like that:
[1616403713714] {"pitch":0,"roll":0,"yaw":-156,"vgx":0,"vgy":0,"vgz":0,"templ":79,"temph":82,"tof":10,"h":0,"bat":82,"baro":-99.66,"time":31,"agx":0,"agy":-9,"agz":-998}
It is time to persist data into the Warp 10 storage engine. You could either use a multivariate model or a GTS per metric model. To keep things simple I will use the second one (but the first one would be more optimized).
Modify tello.mc2
:
Then, wait 5 seconds and re-launch the previous JavaScript.
This drone produces 10 metrics per second for 15 metrics, so we insert 150 points per second. To optimize the ingestion you may use SHM extension to build a buffer and flush it periodically.
First analysis
Now open WarpStudio (https://studio.senx.io) and let's see the distance to floor:
If we look at the roll (tello.telemetry.roll
), the flip appears clearly:
Now, we can try to detect when comes the flip with GRUBBSTEST for example:
The dashboard
After that, we can use Discovery (a dashboarding solution to create highly dynamic Dashboards as Code) to build a dashboard:
Et voilà! As you can see in the code, I used LTTB to subsample while keeping the shape of the plot, it's a handy function when doing dataviz.
Going further
As you can see, it is really easy to fetch and store data coming from a UDP source.
Of course, we can extract a lot of KPIs from this dataset as we detect outliers. We could also develop an alerting system for low batteries or a dynamic dashboard with an auto-refresh feature in order to have a real-time dashboard. It's up to you to build your application.
If you want, we can share this dataset to you if you explain us your use-case. It's always interesting for us to knows what our users are building around Warp 10. Tell us on Twitter or Slack.
Read more
Automatic Time Series archiving
The Py4J plugin for Warp 10
Captain's Log, Stardate 4353.3
Senior Software Engineer