Select to view content in your preferred language

Calculate speed from GPS points

157
3
2 weeks ago
GreerJarrett
New Contributor

I am working with GPS track points, and would like to calculate the speed of movement between points within the same attribute table. Google didn't come up with any obvious solutions, so I assume I need to calculate the distance between a point and the previous one, and then the time elapsed between each two points, and divide the former by the latter.

I therefore would like to know

  • how can I write an expression in Arcade that can work out the location of point 1, the location of point 2, and then the distance from point 2 to point 1?
  • how I can use Calculate Field to obtain the difference in time between points in the attribute table (all points have time stamps)?

Huge thanks to whoever can help with this. I am at the end of my thesis and I have spent too many hours trying to figure this out by myself. I'm sure it's simple, but I just cannot find a way to do it . Happy New Year!

0 Kudos
3 Replies
GKmieliauskas
Esri Regular Contributor

Hi, 

I think you can use logic from that thread. Instead of Distance you can check minimum difference in time between points. You can get both value (time and distance) on the same cycle.

Here is how to obtain the difference in time.

RPGIS
by MVP Regular Contributor
MVP Regular Contributor

Hi @GreerJarrett,

A few things to ask in order to figure out the direction.

  1. Is there a specific attribute that these points can be filtered by.
  2. Are these points timestamped.

If the answer is yes to both, then this can easily be accomplished.

 

var fs = $featureset
var QueryField = 'fieldname'
var QueryValue = $feature.fieldvalue
var Query = QueryField + ' = @QueryValue'

var DTField = 'DateTimeField'
var fs = Filter( fs , Query )
var Cntfs = Count( fs )
if( Cntfs  >= 2 ){
    var topfs = Top( OrderBy( fs , DTField + ' DESC' ) , 2 )
    var N = 0
    var A = Null
    var B = Null
    for( var i in topfs ){
        if( N < Cntfs ){ A = topfs[ i ] }
        else{ B = topfs[ i ] }
        N++
        }
    if( !IsEmpty( A ) && !IsEmpty( B ) ){
        var ATime = A[ DTField ]
        var BTime = B[ DTField ]
        var DTDiff = DateDiff( ATime , BTime , 'Seconds' )
        var Dist = Distance( Geometry( A ) , Geometry( B ) , 'Unit' )
        var Speed = Dist/DTDiff
        // If you need to round the speed, simply use Round( value , decimal places )
        if( Speed > 0 ){ return Speed }
        }
    }

 

 

You can simply use the expression to create an attribute rule and then run some anonymous field calculation to trigger the rule. You cannot do this in a field calculation, at least to the best of my knowledge.

Another option is to use Tracking Functions but only if you have GeoAnalytics.

DavidSolari
MVP Regular Contributor

Combining the previous answers should get you a working solution, but if you can field calculate using Python this will also work:

 

last_shp = None
last_dt = None
def run(shp, dt):
    global last_shp
    global last_dt
    retval = None
    if last_shp is not None and last_dt is not None:
        dist = last_shp.angleAndDistanceTo(shp, "GEODESIC")[1] / 1000  # Kilometres
        diff = (dt - last_dt).seconds / 3600  # Hours
        retval = dist / diff
    last_shp = arcpy.PointGeometry(shp.firstPoint, shp.spatialReference)
    last_dt = dt
    return retval

 

This assumes your data is pre-sorted but it should run faster than an Arcade equivalent due to the massive reduction in database hits. This assumes your data is stored in Web Mercator or another CRS that's meters based, you'll have to convert the CRS units to your desired ones as needed (e.g. multiply by 0.0001893936 if your data is in a US State Plane and you want MPH).

0 Kudos