Track matching tries to find the best matching road segment in the map for a given position in respect to already matched positions. Thus the best matching road segment is not always the nearest to the position, but the one which fits best into the track. Track matching tries to fill the gap between subsequent matched segments by searching suitable paths between them. If there is no suitable path between two positions the resulting track is split up into separate paths which are not connected. The same applies if there are too many possible paths between two matched segments overburdening the calculation capacity. The calculation mode QUALITY takes further measures to fill gaps between matched segments than the mode PERFORMANCE.
Input
Use the createMatchedTrack endpoint to create a track and therefor start a track matching calculation. The input of this endpoint is a JSON in the body of the request (payload) with latitude and longitude (WGS84) of all the positions for which you want to find a matched track. A heading for each position could be provided, too. The heading is the direction in which the vehicle (resp. the device from which the position is delivered) is traveling. It is measured clockwise in degrees from north.
This endpoint also considers the calculation mode as query parameter.
The following POST request creates a track and starts the matching calculation with the calculation mode QUALITY:
https://api.myptv.com/mapmatch/v1/tracks?calculationMode=QUALITY&apiKey=YOUR_API_KEY
The JSON body of the request provides an array of input positions. If the timestamp has been specified, it must include the time zone. Either all positions must have a timestamp (in an ascending order) or none. For each position a heading information is given:
{
"positions": [
{
"heading": 120,
"latitude": 49.61976390541412,
"longitude": 6.115942522631116,
"timestamp": "2024-10-24T08:00:00+02:00"
},
{
"heading": 120,
"latitude": 49.61960571225083,
"longitude": 6.116124889380018,
"timestamp": "2024-10-24T08:01:00+02:00"
},
{
"heading": 120,
"latitude": 49.619543130198316,
"longitude": 6.11636625713592,
"timestamp": "2024-10-24T08:02:00+02:00"
},
{
"heading": 120,
"latitude": 49.61921457310396,
"longitude": 6.117017950076812,
"timestamp": "2024-10-24T08:03:00+02:00"
},
{
"heading": 120,
"latitude": 49.61888079854931,
"longitude": 6.117522140500224,
"timestamp": "2024-10-24T08:04:00+02:00"
}
]
}
If the request succeeds, the response contains an ID. Using this ID you can request the results of the match track calculation:
{
"id": "1e05ad60-35c1-48f9-be4d-1ead39b3d0c6"
}
The retention period of the matched track, which is represented by this ID, is seven days. After the first GET request with this ID the retention period is reduced to one hour.
Output
With a GET request to the getMatchedTrack endpoint you can fetch the results of the calculation. Therefor you have to provide the ID of the createMatchedTrack response as path parameter. The following request queries all the available results (GEOMETRY, PATHS, TRACK_POSITIONS, SEGMENT_ATTRIBUTES and ROUTE_ID):
https://api.myptv.com/mapmatch/v1/tracks/1e05ad60-35c1-48f9-be4d-1ead39b3d0c6?results=GEOMETRY,PATHS,TRACK_POSITIONS,ROUTE_ID
By using the results query parameter you can also specify which kind of result you want to get. The following values are supported:
- If the value GEOMETRY is set, the polygon line of the matched track is provided in the response.
- If the value PATHS is set, sub-paths in which the resulted track is split are returned.
- If the value TRACK_POSITIONS is set, all matched positions are returned.
- If the value SEGMENT_ATTRIBUTES is set, the positions are enriched by additional information for the matched segment. TRACK_POSITIONS will automatically be included.
- If the value ROUTE_ID is set, there is an ID for each subpath in the response that can be passed as input to the routing API. PATHS will automatically be included.
If the request was successful the response looks like this:
{
"status": "SUCCEEDED",
"matchedTrack": {
"id": "1e05ad60-35c1-48f9-be4d-1ead39b3d0c6",
"distance": 152,
"paths": [
{
"distance": 152,
"startTrackPositionIndex": 0,
"endTrackPositionIndex": 4,
"routeId": "6912c1b1-f31b-4e34-b006-4a3d41f8e24f"
}
],
"geometry": "{\"type\":\"GeometryCollection\",\"geometries\":[{\"type\":\"LineString\",\"coordinates\":[[6.1159430051,49.619764411],[6.115961665,49.619757158],[6.1162211846,49.619589026],[6.1169132367,49.61925276],[6.1170429965,49.619168693],[6.1172592628,49.619056604],[6.1175519311,49.618904916]]}]}",
"trackPositions": [
{
"matchType": "MATCH_SUCCESSFUL",
"timestamp": "2024-10-24T08:00:00.000+02:00",
"distanceFromPreviousMatch": 0,
"latitude": 49.619764411,
"longitude": 6.1159430051,
"segmentGeometry": "{\"type\":\"LineString\",\"coordinates\":[[6.1157453987,49.619841223],[6.115961665,49.619757158]]}",
"matchDistance": 0,
"angleDifference": 0.96,
"segmentAttributes":
{
"bridge": false,
"tunnel": false,
"ramp": false,
"frontage": false,
"paved": true,
"requiresFourWheelDrive": false,
"privatelyManaged": false,
"publicAccess": true,
"parkingLot": false,
"priorityRoad": false,
"builtUpArea": true,
"speedLimit": 50
}
},
{
"matchType": "MATCH_SUCCESSFUL",
"timestamp": "2024-10-24T08:01:00.000+02:00",
"distanceFromPreviousMatch": 28,
"latitude": 49.619589026,
"longitude": 6.1162211846,
"segmentGeometry": "{\"type\":\"LineString\",\"coordinates\":[[6.1162211846,49.619589026],[6.1169132367,49.61925276]]}",
"matchDistance": 7,
"angleDifference": 6.87,
"segmentAttributes":
{
"bridge": false,
"tunnel": false,
"ramp": false,
"frontage": false,
"paved": true,
"requiresFourWheelDrive": false,
"privatelyManaged": false,
"publicAccess": true,
"parkingLot": false,
"priorityRoad": false,
"builtUpArea": true,
"speedLimit": 50
}
},
{
"matchType": "NOT_CONSIDERED"
},
{
"matchType": "MATCH_SUCCESSFUL",
"timestamp": "2024-10-24T08:02:00.000+02:00",
"distanceFromPreviousMatch": 78,
"latitude": 49.619168693,
"longitude": 6.1170429965,
"segmentGeometry": "{\"type\":\"LineString\",\"coordinates\":[[6.1170429965,49.619168693],[6.1172592628,49.619056604]]}",
"matchDistance": 5,
"angleDifference": 8.66,
"segmentAttributes":
{
"bridge": false,
"tunnel": false,
"ramp": false,
"frontage": false,
"paved": true,
"requiresFourWheelDrive": false,
"privatelyManaged": false,
"publicAccess": true,
"parkingLot": false,
"priorityRoad": false,
"builtUpArea": true,
"speedLimit": 50
}
},
{
"matchType": "MATCH_SUCCESSFUL",
"timestamp": "2024-10-24T08:03:00.000+02:00",
"distanceFromPreviousMatch": 46,
"latitude": 49.618904916,
"longitude": 6.1175519311,
"segmentGeometry": "{\"type\":\"LineString\",\"coordinates\":[[6.1172592628,49.619056604],[6.118124328,49.618608245]]}",
"matchDistance": 3,
"angleDifference": 8.66,
"segmentAttributes":
{
"bridge": false,
"tunnel": false,
"ramp": false,
"frontage": false,
"paved": true,
"requiresFourWheelDrive": false,
"privatelyManaged": false,
"publicAccess": true,
"parkingLot": false,
"priorityRoad": false,
"builtUpArea": true,
"speedLimit": 50
}
}
]
}
}
The response contains the status of the matching calculation and - depending on the status - further information:
- If the status is RUNNING, the matching calculation is still running and no further information is provided.
- If the status is SUCCEEDED, the matching calculation has completed successfully and the matching result is present as matchedTrack.
- If the status is FAILED, the matching calculation has completed with a failure and the failure result is present as error.
A matched track will contain the distance of the whole track. This distance of the matched track is the sum of the distances of all paths.
If you have requested the PATHS an array of all paths is returned. Remember that a matched track can consist of more than one path if some parts of the matched track could not be linked.
For each path its distance is provided and if you have requested the ROUTE_ID then there is a route id provided. This route id can be used as a waypoint in a calculateRoute request at the Routing API to recalculate the matched track path and thus get additional information like toll costs or emissions.
If you have requested the TRACK_POSITIONS then there is the start and the end position of this path available. Start and end are given as 0-based index for the track positions array.
If you have requested the GEOMETRY a polygon line as GeoJSON is provided (or a set of them in the case of several paths).
If you have requested the TRACK_POSITIONS there is an entry in the array of track positions for each input position. The positions in the array correspond to them of the input positions.
For every track position the following details are provided in any case:
- The match type tells you if the position could be matched successfully to a road segment, or if it was not considered for the resulting track.
- The passed distance in meters from the previous match position.
- Latitude and longitude (WGS84) of the match position.
- The polygon line of the matched road segment as GeoJSON.
- The distance between the input position and the match position on the road network in meters.
- If a heading was given, the angle difference to the matched road segment in degrees.
- If timestamps were specified, they will also be reissued.
The following picture illustrates this response:
Quality of matching results
The quality of track matching depends highly on the quality of the input data. You get better matching results if your input data satisfies the following conditions:
- There are only slight deviations from the real position.
- A heading is provided as closely as possible.
- In areas with many intersections (urban areas) the input positions are dense.