Introducing the new Snap Tracks tool in GeoAnalytics Engine

557
1
02-14-2023 09:04 AM
arif-masrur
Esri Contributor
4 1 557

Map matching the problem of matching latitude/longitude points to roads is important for many applications including navigation systems, traffic probes, and route compression. Given a set of GPS points in time-sequential order, users may need to identify which roads in the network the vehicle traversed.  

The new Snap Tracks tool in GeoAnalytics Engine v1.1 supports mapping raw GPS point data to its traversed road segments on a road network - enabling Map Matching at speed and scale in a Spark environment.  You can use the tool to improve visualization of track data, as well as calculate more realistic and accurate route and movement behavior patterns. 

To run the Snap Tracks tool, you’ll need two input DataFrames (GPS point observations and lines), and there are three required parameters:  setConnectivityFields, setSearchDistance, and setTrackFields. Connectivity should be defined by the attributes in the input lines DataFrame that represent the from node and the to node of each line segment. The search distance method takes two parameters: 1) maximum search distance between a GPS point and any line and 2) the search distance unit (e.g., meters). Additionally, you need to set one or more fields from the GPS point observations DataFrame to identify the distinct tracks. For example, if the data represents a set of vehicles, then the distinct tracks could be identified by an attribute called vehicleID or similar.  

The code snippets below demonstrate an example use case of Snap Tracks using 1) a freely available  test GPS dataset from a drive on January 17, 2009, in the Seattle, WA area, and 2) the road network data of greater Seattle, WA. Figure 1 shows the output of the tool that snapped the raw GPS points to the traversed road network.  

 

# Imports  
import geoanalytics  
geoanalytics.auth(username="myusername", password="mypassword")  
from geoanalytics.tools import SnapTracks 

 

 

# Data import and processing  
gps_data = spark.read.csv("/FileStore/gps_data.csv", header=True)  
roads_data = spark.read.csv("/FileStore/Data/road_network.csv", header=True) 
gps_data_pnt = (gps_data.withColumn("point", ST.point("Longitude", "Latitude", 4326)) \
     .withColumn("Time", F.to_timestamp(F.col("Time (UTC)"), 'HH:mm:ss')) \
     .withColumn("tracid", F.lit("12345")) ) 
roads_data_line = (roads_data.withColumn("Linestring", ST.line_from_text("LINESTRING", sr=4326).alias("lines"))) 

 

 

# Snap Tracks tool  
result = SnapTracks() \ 
     .setTrackFields("tracid") \ 
     .setSearchDistance(search_distance=100, search_distance_unit="Meters") \ 
     .setDistanceMethod(distance_method="Geodesic") \ 
     .setConnectivityFields(from_node="To_Node_ID", to_node="From_Node_ID") \ 
     .setOutputMode(output_mode="AllPoints") \ 
     .run(gps_data_pnt, roads_data_line) 

 

 

# Visualization 
points_extent = gps_data_pnt.st.get_extent() 
adj = 0.0002 

# Add the streets, original observations points, and snapped points to the plot 
lines_ax = roads_data_line.st.plot(aspect="equal", color="grey", figsize=(16,10)) 
points_ax = gps_data_pnt.st.plot(ax=lines_ax, color="red", label='Input observations') 
points_ax.set(frame_on=True, xticks=[], yticks=[], xlim=((points_extent.min_x-adj), points_extent.max_x+adj), ylim=(points_extent.min_y-adj, points_extent.max_y+adj)) 
points_ax = result.st.plot(ax=points_ax, color="green",legend = True, label='Snapped results', basemap="light") 
leg = points_ax.legend(loc=2) 
points_ax.set_title("Observations and snapped results"); 

 

 

Snap Tracks Vis.jpg

Figure 1. a) GPS points snapped to the traversed road network across the Seattle area; b, c) zoomed-in views to highlight two road segments where green points and red points correspond to the snapped (on to the actual road) and raw GPS points, respectively.  

We hope this overview of Snap Tracks has been useful for you – let us know in the comments if you have questions or if there are other tools in GeoAnalytics Engine that you’d like to hear more about! 

 

1 Comment
SimonGIS
New Contributor III

Thanks for the post.  Worked a charm snapping some VPS data against our state road network.  Crunched 10M records, a single vehicle from this shown below.  1st outputs below, needs a bit of QA.

SimonGIS_0-1708756627094.png

SimonGIS_1-1708758247544.pngSimonGIS_2-1708758460356.png

 

If you're taking requests, would love to see how you would go about detecting speeding incidents from VPS data containing speed, and a road layer containing road speeds for each segment. 

Would assume a combination of snapping the data, then spatial join to get the road speed limit onto the points, and then detect incidents tool?