Use motion to automatically split GTS

The easiest way to detect motion and to split a Geo Time Series accordingly. Split with distance between two timestamps, detect stopped/moving state etc.

Explicit Warning: if you use Warp 10 for data center monitoring, this article is not for you!

If you monitor things moving on the earth (boats, vehicles, planes, drones), this new function is for you!

Imagine you collect temperatures on a connected refrigerator truck (external temperature, internal temperature in several areas inside the truck). You are perfectly aware of Warp 10 2.0 multivalue feature, so your data model is really simple:

classname: temperatureslabel: VIN label: brandlabel: modeldata: multivalue payload (list of temperatures)

You want to study the temperatures when the truck is driving. Temperature, when doors are opened, are outliers for your study. When the truck is docked in, doors fully opened, or when the truck is stopped to deliver food at each restaurant, doors opened.

Well-known WarpScript split functions

As a WarpScript expert, you already know TIMESPLIT. This useful function splits a GTS into several sub GTS. The trigger to split is a quiet period, a period without any data points. TIMESPLIT is perfect to split your temperature GTS in “missions”: a mission start datalogger turns on, and ends when the datalogger stops.

That”s fine… but the datalogger on your fleet has its own battery! So it never stops recording. TIMESPLIT won”t help you.

VALUESPLIT is helpful for alerts or states, not for temperature.

DWTSPLIT is related to wavelet transforms. It won”t help.

CHUNK is perfect to do regular chunks. Not for you.

CLIP is the surgery scalpel you use when you know exactly where to cut your time series.

So, you think about doing your own mapper to produce several GTS (that”s possible with MACROMAPPER), with a state machine inside to detect movement, stops… That could be a solution, but it”s not a trivial one!

WarpScript MOTIONSPLIT, since 2.3.0

I will explain MOTIONSPLIT with the following example:

Paris, Champs-Elysées

Paris, its famous avenues, its well-known traffic jam, all you need for a good example. If you want to play with the same GTS, copy this snippet:


The function is able to split by time, by distance, to detect stopped state in a radius, exit the stopped state on several conditions.

It is available since Warp 10 2.3.0 release.

As the latest advanced function in WarpScript, MOTIONSPLIT takes a MAP for maximum flexibility of input parameters.

No operation


This won”t break your WarpScript… It is just an inefficient CLONE!

Time split

$gts {  "timesplit" 10.95 s }MOTIONSPLIT

This performs a time split when there is more than 10.95 seconds between two data points.

Distance split

$gts {  "timesplit" 10.95 s  "distance.split" 100}MOTIONSPLIT

If there are more than 100 meters between two positions, then split. I combined time split and distance split. Distance split could be very useful to remove outliers, such as GPS lost at (0 0) coordinates.

Add extra labels to output

$gts {  "timesplit" 10.95 s   "distance.split" 100  "label.split.number" "split"  "label.split.type" "reason"}MOTIONSPLIT

That”s the easiest way to filter out the GTS list later on, with filter.bylabels.


Stop detection split, simplest (time in an area)

$gts 1573135239233178 1160575178 TIMECLIP // cut the final stop{  "stopped.min.time"  60 s  "stopped.max.radius" 80  "label.stopped.time" "stop_time"  "label.split.start" "split"  "label.split.type" "reason"}MOTIONSPLIT

If the truck stays more than 60 seconds in an 80 meters radius, split. Note the stop_time extra-label could also be used later to keep long stops… or not!

Discover how to detect a sequence of values in WarpScript

Stop detection split, with maximum speed to consider a stop

<% 3.6 / %> "km/h" STORE$gts {  "stopped.min.time"  60 s  "stopped.max.speed" 10 @km/h  "stopped.max.radius" 80  "label.stopped.time" "stop_time"  "label.split.type" "reason"}MOTIONSPLIT

Why? Because when driving again, there is this extra point in the proximity zone. The stopped.max.speed fix the problem:

Stop detection split, with a maximum mean speed in the proximity zone that prevents the split

$gts{  "stopped.min.time"  60 s  "stopped.max.speed" 10 @km/h  "stopped.max.radius" 80  "stopped.max.mean.speed" 1 @km/h    "label.stopped.time" "stop_time"  "label.split.number" "split"  "label.split.type" "reason"}MOTIONSPLIT

It will split only if there is a full stop during the given time and radius, and if the mean speed in the proximity zone is less than 1km/h

Combine everything!

$gts {  "timesplit" 10.95 s   "distance.split" 100  "stopped.min.time"  60 s  "stopped.max.speed" 10 @km/h  "stopped.max.radius" 80  "stopped.max.mean.speed" 5 @km/h  "label.stopped.time" "stop_time"  "label.split.number" "split"  "label.split.type" "reason"}MOTIONSPLIT

When combining different split reason, the split type priorities are always:

Stopped > distance split > time split > end of sequence


Isolate movements in a GTS could now be done in a few lines of WarpScript, with a maximum of flexibility. This function will evolve in future versions, with more parameters to address more use cases.

Contact us to expose us your use cases, through our contact form or on stack overflow.