wannesm / LeuvenMapMatching

Leuven.MapMatching toolbox for aligning GPS measurements to locations on a map.
Other
228 stars 44 forks source link

How Can I get the matched nodes? #28

Open XanderPENG opened 2 years ago

XanderPENG commented 2 years ago

I have tested several times that if I set "use_latlon=True" then the matching will be perfect, however, "matcher.path_pred_onlynodes" will return an empty list, which means that I cannot extract the matched points and output.

What is interesting is that if I set "use_latlon=False", I can get the nodes list while the matching result is not so good.

I am wondering how this could happen and how to address it.

debjitbhowmick commented 2 years ago

Depends on the previous code on how you developed your map_con. Could you please share that?

angelyix commented 2 years ago

I had the same question, and it seems that the results of matcher.path_pred_onlynodes is not the matched points, instead of the starting nodes of the matched roads. I wonder how to get the matched points and are the points projected orthogonally onto the road network?

XanderPENG commented 2 years ago

Depends on the previous code on how you developed your map_con. Could you please share that?

Yes, there was something wrong with the map_con setting in my memory. Since it has been a quite long time, I cannot find the previous codes. However, I still remember that I used the "osmnx" package to derive map directly and built the subsequent map_con, which works very well.

XanderPENG commented 2 years ago

I had the same question, and it seems that the results of matcher.path_pred_onlynodes is not the matched points, instead of the starting nodes of the matched roads. I wonder how to get the matched points and are the points projected orthogonally onto the road network?

I had the same thoughts previously while I found that this requirement cannot be fulfilled by using this package only (Maybe could but I do not know how to achieve it). Thus, I firstly use this package to match the trajectory points into the road and get the instance of "matched road", then use the "Near" principle to match origin trajectory points with the matched road.

wannesm commented 2 years ago

Setting use_latlon should indeed have no direct influence on matcher.path_pred_onlynodes. It will return a different matching as you indicate but it should be the matching you see. What do you mean with a 'perfect matching'? Is it based on the visualization?

The matcher.path_pred_onlynodes method tries to simplify the matched path to only the nodes in the map that are passed through. The states return by states, last_idx = matcher.match(track) should also be informative.

You can also get access to the detailed mapping by looking at matcher.lattice_best (including where each matched point is on an edge etc). This is the datastructure that is also used for plotting. See this section in the docs: https://leuvenmapmatching.readthedocs.io/en/latest/usage/debug.html#inspect-the-best-matching .

angelyix commented 2 years ago

I had the same question, and it seems that the results of matcher.path_pred_onlynodes is not the matched points, instead of the starting nodes of the matched roads. I wonder how to get the matched points and are the points projected orthogonally onto the road network?

I had the same thoughts previously while I found that this requirement cannot be fulfilled by using this package only (Maybe could but I do not know how to achieve it). Thus, I firstly use this package to match the trajectory points into the road and get the instance of "matched road", then use the "Near" principle to match origin trajectory points with the matched road.

I'm glad that my solution idea is quite similar to yours, I first applied this package to get the road geometry information, such as 'osmid' and length of every road segment. Then, I used 'Arcpy' package in Pycharm for nearest neighbor search to orthogonally project the trajectory points to the matched road. So what tools did you use to process the "Near" principle? : )

wannesm commented 2 years ago

To clarify, you do not necessarily need an additional package to find the nearest matching point since the matching is doing this already (otherwise a package like ArcPy is a good choice).

For example for the first matched point (thus with index 0), you can do:

match = matcher.lattice_best[0]
location_on_gps_trace = match.edge_o.pi
location_on_map = match.edge_m.pi
debjitbhowmick commented 2 years ago

To clarify, you do not necessarily need an additional package to find the nearest matching point since the matching is doing this already (otherwise a package like ArcPy is a good choice).

For example for the first matched point (thus with index 0), you can do:

match = matcher.lattice_best[0]
location_on_gps_trace = match.edge_o.pi
location_on_map = match.edge_m.pi

Hi Wannes,

Thanks for your response. It really helped. I have a query regarding the plotting of the matched points.

It seems that the underlying code assumes that the matched OSM ways are straight lines, and therefore the matched GPS points seem to be not superimposed on the underlying road network when one single OSM way has some curvature. While this does not impact the map matching at all, but I would still like to get hold of the matched points on the road network. Before I dive into writing my own code for this, I was hoping if the it is possible to account for the curvature (inside the package itself)? I have attached some code and images for your reference.

image image

The relevant code block is as follows:

image image image image image image

debjitbhowmick commented 2 years ago

Update:

I employed the nearest_pointsfunction from shapely.ops to get the matched points on the road network. These were the corresponding results. I hope this helps others.

Code:

image

Results:

image image

wannesm commented 2 years ago

If you observe straight lines, this is probably caused by how you generate the graph that is given to the toolbox. Assuming you also use osmnx, you have to tell osmnx not to simplify curved lines into straight lines (see also issue #34):

graph = ox.graph_from_place('Leuven, Belgium', network_type='drive', simplify=False)
debjitbhowmick commented 2 years ago

Thanks. That was really helpful. Simplify=False had them plotted on the edges of the graph.

One more question. Does this affect the performance of map matching? I could not notice any change between the map matching performance while using the simplified vs un-simplified graphs? Only that the un-simplified graph map matching takes longer.