GithubHelp home page GithubHelp logo

wannesm / leuvenmapmatching Goto Github PK

View Code? Open in Web Editor NEW
212.0 5.0 40.0 369 KB

Leuven.MapMatching toolbox for aligning GPS measurements to locations on a map.

License: Other

Makefile 0.31% Python 99.69%
map-matching hmm non-emitting-states silent-states

leuvenmapmatching's People

Contributors

eracle avatar larsupb avatar wannesm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

leuvenmapmatching's Issues

HTTPError: Forbidden

I run the code shows:
File "/Users/xiguan/anaconda/lib/python3.6/urllib/request.py", line 650, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)

HTTPError: Forbidden

But I run the code successfully before.Why is this happening recently?
Thank you!

Visualisation

hello,
I want to zoom in a specific part of a map to see the results. So I wrote this Code:

plot_map(map_con,
            matcher=matcher,
            use_osm=True,
            zoom_path=True,
            show_graph=True,
            show_matching=False,
            linewidth=1,
            bb=[-105.0224, 37.9344, -104.9961, 37.9637],
            filename=str(directory / "Foto.png"))

But it doesn't work. What am I doing wrong? Is this correct to write bb=[] like this or does it have another format?
I would be thankful for your help.

does timestamp could be used for matching?

image
i find that path accept tuple(lat, lng, time), but i got some err when i run the code with path which have timestamp. i can't find any code to handle 'time' in the source code.could some one help to explain ? thanks.

Map object has missing edges when importing from OSMNX

Hi,

Something is going wrong when I am converting an OSMNX graph to a map object. I noticed the matching was a bit off, and when I compare the original graph to the map object I can see it is very simplified - edges simply connect all nodes.

Original OSMNX graph:
3cab033e-2369-4115-8ec4-29e057033ed4

Map object after adding nodes and edges from original graph
b1bfe1c8-940c-4b38-8f17-dc2e6e13c69b

I noted that there are about 1000 less edges in the map object than the original graph. The number of nodes is identical. I am using "Approach 2" in the examples to add nodes and edges to an InMemMap. No errors are thrown when looping through the edges and using map_con.add_edge(), and the loop runs through all edges of the original graph. But when I count the edges with len(list(map_con.all_nodes())) immediately after the loop it is lower by around 1000. Is this something to do with OSMNX having linestring geometry between edges while the map object is a straight line from node to node? If so, is there a way to include the linestring geometry?

Am I missing something here? Any help would be greatly appreciated. The matching works fantastically for the incorrect network, so I am really hoping I can get it working on the original!

Here is the code block for adding the graph edges, nodes to the map object:

from leuvenmapmatching.map.inmem import InMemMap
from leuvenmapmatching.util.gpx import gpx_to_path

graph_proj = ox.project_graph(graph)  # graph of downloaded OSM roads

map_con = InMemMap("myosm", use_latlon=True, 
        use_rtree=False, index_edges=False)

nodes, edges = ox.graph_to_gdfs(graph_proj, nodes=True, edges=True)

nodes_proj = nodes.to_crs("EPSG:4326")
edges_proj = edges.to_crs("EPSG:4326")

for nid, row in nodes_proj.iterrows():
    map_con.add_node(nid, (row['lat'], row['lon']))

for nid1, nid2, _ in graph.edges:
    map_con.add_edge(nid1, nid2)

print(graph_proj.number_of_edges())  # gives 28440
print(len(list(map_con.all_edges())))  # gives 27309

no such module: rtree

Why does this prompt:no such module: rtree

The details are as follows:
File "D:\Anaconda3\lib\site-packages\leuvenmapmatching\map\sqlite.py", line 393, in all_edges
c.execute(q, (min_x, max_x, min_y, max_y))

OperationalError: no such module: rtree

I have two questions about matching details。

Hi, dear developer! The package is quite helpful for me, I appreciate it. But I have two questions:

  1. I find that some trajectory points are matched into more than one road segment, this is not reasonable, is there a solution to that?
    2022-09-29 143908
  2. Does the trajectory points have to be input in the order of the vehicle's driving direction?

node_path is an empty list with non-zero speed

image

image

I want to find the corresponding way id of my GPS points, by the way, my GPS data has non-zero speed.
But when I debug the "BaseMatcher", as shown in the first picture, I find "states" is an empty list. However, the matching picture is fine as shown in the second picture.
I don't know why the list is empty. Is there anyone kindful to help me?

How Can I get the matched nodes?

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.

match method returns more points than input coordinates

Hello,

Here's the example code

matcher = DistanceMatcher(graph, max_dist=12000, max_lattice_width=2)
coordinates = [[40.756470508651724,  -73.97319052003208]]

matcher.match(coordinates)
nodes = matcher.path_pred_onlynodes
print(len(nodes))

When I run this code I get 2 nodes while I only had one coordinate.
The nodes are ['7737876085', '6452768049']

Can you explain this please ?

Thanks a lot

Example 1 graph

In the graph structure of Example 1, in the list of nodes D is connected to, D should be replaced with F:

("D", (2, 4), ["B", "C", "D", "E", "K", "L"]) -> ("D", (2, 4), ["B", "C", "F", "E", "K", "L"])

raise Exception(f"Should not happen")

When I pip install and try to run an example, I get

File "/usr/local/lib/python2.7/dist-packages/leuvenmapmatching/util.py", line 152
raise Exception(f"Should not happen")
^
SyntaxError: invalid syntax

Improve performance when passing through tunnels

Dear developers,
I do appreciate your hard work to produce this nice and handy package.

However, I'm struggling when it comes to tuning the hyperparameters of the matcher. In particular, I am testing it with GPS locations recorded during a motorway trip, in which we crossed few tunnels. Tunnels seem to be difficult to handle and I wanted to ask your opinion on whether it is best to:

  • Increase the obs_noise (to get a larger sigma coefficient, which does not penalize too much my correct path in terms of emission probability)
  • Increase the max_lattice_width to keep track of a larger number of possible paths in the HMM (hopefully keeping the path through the tunnel)
  • Increase non_emitting_length_factor: my intuition is "in a tunnel there have to be many subsequent non emitting states, which I do not want to penalize".
    If you have any insights on any other method to improve your algorithm performance in the presence of a tunnel, I'm very interested in your opinion.

Also, I did not get exactly how the non_emitting_length_factor parameter is exploited in the code and how it should be tuned (eg. increasing it we obtain less or more penalty for a sequence of non-emitting states? And what is the neutral value to get no penalty neither reward for the sequence of non-emitting states against a normal sequence?)

pytest fails due to test data file missing

Most of these fails are because some test data files are missing, for e.g. LeuvenMapMatching/tests/rsrc/newson_krumm_2009/ground_truth_route.txt.

======================================================================================================= test session starts ========================================================================================================
platform linux -- Python 3.6.8, pytest-3.2.1, py-1.4.34, pluggy-0.4.0 -- /opt/anaconda3/bin/python
cachedir: .cache
rootdir: /....../LeuvenMapMatching, inifile: setup.cfg
plugins: anyio-3.3.0
collected 53 items                                                                                                                                                                                                                  

tests/test_bugs.py::test_bug1 PASSED
tests/test_bugs.py::test_bug2 FAILED
tests/test_conversion.py::test_path_to_gpx PASSED
tests/test_conversion.py::test_grs80 PASSED
tests/test_conversion.py::test_distance1 PASSED
tests/test_conversion.py::test_distance2 PASSED
tests/test_conversion.py::test_bearing1 PASSED
tests/test_conversion.py::test_destination1 FAILED
tests/test_conversion.py::test_distance_segment_to_segment1 PASSED
tests/test_conversion.py::test_distance_segment_to_segment2 PASSED
tests/test_conversion.py::test_distance_segment_to_segment3 PASSED
tests/test_conversion.py::test_distance_segment_to_segment4 PASSED
tests/test_conversion.py::test_distance_point_to_segment1 PASSED
tests/test_newsonkrumm2009.py::test_route_slice1 FAILED
tests/test_newsonkrumm2009.py::test_bug1 PASSED
tests/test_newsonkrumm2009.py::test_route SKIPPED
tests/test_newsonkrumm2009.py::test_bug2 SKIPPED
tests/test_nonemitting.py::test_path1 PASSED
tests/test_nonemitting.py::test_path1_inc PASSED
tests/test_nonemitting.py::test_path1_dist PASSED
tests/test_nonemitting.py::test_path2 PASSED
tests/test_nonemitting.py::test_path2_dist PASSED
tests/test_nonemitting.py::test_path2_incremental PASSED
tests/test_nonemitting.py::test_path_duplicate PASSED
tests/test_nonemitting.py::test_path3_many_obs PASSED
tests/test_nonemitting.py::test_path3_few_obs_en PASSED
tests/test_nonemitting.py::test_path3_few_obs_e PASSED
tests/test_nonemitting.py::test_path3_dist PASSED
tests/test_nonemitting_circle.py::test_path1 PASSED
tests/test_nonemitting_circle.py::test_path1_dist PASSED
tests/test_nonemitting_circle.py::test_path2 PASSED
tests/test_nonemitting_circle.py::test_path2_dist PASSED
tests/test_parallelroads.py::test_parallel PASSED
tests/test_parallelroads.py::test_bb1 PASSED
tests/test_parallelroads.py::test_merge1 PASSED
tests/test_parallelroads.py::test_path1 PASSED
tests/test_path.py::test_path1 PASSED
tests/test_path.py::test_path1_dist PASSED
tests/test_path.py::test_path2 PASSED
tests/test_path.py::test_path2_inc PASSED
tests/test_path.py::test_path2_dist PASSED
tests/test_path.py::test_path_outlier PASSED
tests/test_path.py::test_path_outlier2 PASSED
tests/test_path.py::test_path_outlier_dist PASSED
tests/test_path.py::test_path3 PASSED
tests/test_path.py::test_path3_dist PASSED
tests/test_path_latlon.py::test_path1 FAILED
tests/test_path_latlon.py::test_path1_full SKIPPED
tests/test_path_latlon.py::test_path2_proj FAILED
tests/test_path_latlon.py::test_path2 FAILED
tests/test_path_latlon.py::test_path3 FAILED
tests/test_path_onlyedges.py::test_path1 PASSED
tests/test_path_onlyedges.py::test_path3 PASSED

Different matching results with the same code and data source

I used pip command to install the package on my laptop and desktop respectively, and their versions are both 1.1.3. However, the following code can successfully match a route on my laptop, while the same code doesn't work on the desktop

import panda as pd
import geopandas as gpd
import osmnx as ox

G = ox.load_graphml('./graph/hangzhou.graphml')
G_p = ox.project_graph(G, to_crs=4549)
nodes, edges = ox.graph_to_gdfs(G_p, nodes=True, edges=True)
map_con = InMemMap(name='HZnetwork', use_latlon=False, use_rtree=True, index_edges=True)
for node_id, row in nodes.iterrows():
    map_con.add_node(node_id, (row['y'], row['x']))
for node_id_1, node_id_2, _ in G_p.edges:
    map_con.add_edge(node_id_1, node_id_2)

matcher = DistanceMatcher(map_con, max_dist=500, max_dist_init=500, 
                          min_prob_norm=0.1,  non_emitting_length_factor=0.95,
                          obs_noise=50, obs_noise_ne=50, dist_noise=50,
                          max_lattice_width=20, non_emitting_states=True)

gps_data = pd.read_csv('./test_data.csv')
geo_data = gpd.GeoDataFrame(data, geometry=gpd.points_from_xy(data.lng, data.lat), crs=4326)
geo_data = geo_data.to_crs(4549)
path = list(zip(geo_data.geometry.y, geo_data.geometry.x))

states, _ = matcher.match(path, unique=False)
mmviz.plot_map(map_con, matcher=matcher, show_lattice=True,
               show_labels=True, show_matching=True, show_graph=False, filename=None)

"""
laptop result
states = [(314934753, 314934751),  (314934751, 5338584732), .......

desktop result
states = []
"""

All the inputs, params and codes are sure to be the same. I have tried to reinstall the package but it had no effects.

Finding unmapped routes

Can it be used to find unmapped routes in the map ?
I want to add routes to the map using gps traces .

Missing map match results

When the vehicle is driving in a circle, the map matching sometimes misses this part of the result, what is the reason for this?
DR75_460K_雅宝

article

Hello dear developers! Is it possible to get an access to your publication : “HMM with Non-Emitting States for Map Matching” ?
I suppose not only me but all LeuvenMapMatching users will be glad if it will be possible
Thank you!

How to fix ValueError: not enough values to unpack (expected 2, got 0) in bb

This is my code and I want to visualize the gpx data for testing.

`from leuvenmapmatching.util.gpx import gpx_to_path
from leuvenmapmatching.matcher.distance import DistanceMatcher
from leuvenmapmatching.map.inmem import InMemMap
from leuvenmapmatching import visualization as mmviz

map_con = InMemMap("mymap", use_latlon=False)

track = gpx_to_path("route.gpx")
matcher = DistanceMatcher(map_con,
max_dist=100, max_dist_init=25, # meter
min_prob_norm=0.001,
non_emitting_length_factor=0.75,
obs_noise=50, obs_noise_ne=75, # meter
dist_noise=50, # meter
non_emitting_states=True,
max_lattice_width=5)
states, lastidx = matcher.match(track)

mmviz.plot_map(map_con, matcher=matcher,
use_osm=True, zoom_path=True,
show_labels=False, show_matching=True, show_graph=False,
filename="my_osm_plot.png")`

However, the following error appear.

Traceback (most recent call last):
File "C:\Users\Jason...\Data_prep\MapMatching.py", line 20, in
mmviz.plot_map(map_con, matcher=matcher,
File "C:\Users\Jason...\Data_prep\venv\Lib\site-packages\leuvenmapmatching\visualization.py", line 62, in plot_map
bb = map_con.bb()
^^^^^^^^^^^^
File "C:\Users\Jason...\Data_prep\venv\Lib\site-packages\leuvenmapmatching\map\inmem.py", line 187, in bb
glat, glon = zip(*[t[0] for t in self.graph.values()])
^^^^^^^^^^
ValueError: not enough values to unpack (expected 2, got 0)

Please, I wanna know how to fix it.

How can I get the matching points on the roadnet graph?

Hello! I've already gotten the matching section of the graph from returned values by DistanceMatcher.match(). But I couldn't get the accurate matching point by this method. What should I do? AND please give me a guide of the main classes if possible. THX!

always this problem:rtree

File "D:\Anaconda3\lib\site-packages\leuvenmapmatching\map\sqlite.py", line 151, in create_db
c.execute(q)
OperationalError: no such module: rtree

I've recompiled sqlite succefully.Then how could i use the python code with sqlite?I am a green hand,Beg for help.I've been working on it for a long time.Please

doesn't return states and nodes

Hello dear developers! I am trying to use LeuvenMapMatching in my Master thesis.
I am using the example with osmnx from documentation
https://leuvenmapmatching.readthedocs.io/en/latest/usage/openstreetmap.html#using-osmnx-and-geopandas

I have created map_con, graph osmnx from the example. Then, transformed GPS Points to CRS which Project graph use. Then ,implemented code from example :

matcher = DistanceMatcher(map_con, max_dist=2, obs_noise=1, min_prob_norm=0.5)
states, _ = matcher.match(path)
nodes = matcher.path_pred_onlynodes

print("States\n------")
print(states)
print("Nodes\n------")
print(nodes)
print("")
matcher.print_lattice_stats()

But it doesn't return any "states" or "nodes"

Can't import DistanceMatcher

Hi,
I am trying to run the example, but I got this error. Do you have any suggestion to this error?
the error is.

  File "test_match.py", line 2, in <module>
    from leuvenmapmatching.matcher.distance import DistanceMatcher
  File "/home/aa/aa/py37/lib/python3.7/site-packages/leuvenmapmatching/matcher/distance.py", line 13, in <module>
    from .base import BaseMatching, BaseMatcher
  File "<fstring>", line 1
    (prune_thr=)
              ^
SyntaxError: invalid syntax

And here is my example code.

from leuvenmapmatching import visualization as mmviz
from leuvenmapmatching.matcher.distance import DistanceMatcher
from leuvenmapmatching.map.inmemmap import InMemMap

map_con = InMemMap("mymap", graph={
    "A": ((1, 1), ["B", "C", "X"]),
    "B": ((1, 3), ["A", "C", "D", "K"]),
    "C": ((2, 2), ["A", "B", "D", "E", "X", "Y"]),
    "D": ((2, 4), ["B", "C", "D", "E", "K", "L"]),
    "E": ((3, 3), ["C", "D", "F", "Y"]),
    "F": ((3, 5), ["D", "E", "L"]),
    "X": ((2, 0), ["A", "C", "Y"]),
    "Y": ((3, 1), ["X", "C", "E"]),
    "K": ((1, 5), ["B", "D", "L"]),
    "L": ((2, 6), ["K", "D", "F"])
}, use_latlon=False)

path = [(0.8, 0.7), (0.9, 0.7), (1.1, 1.0), (1.2, 1.5), (1.2, 1.6), (1.1, 2.0),
        (1.1, 2.3), (1.3, 2.9), (1.2, 3.1), (1.5, 3.2), (1.8, 3.5), (2.0, 3.7),
        (2.3, 3.5), (2.4, 3.2), (2.6, 3.1), (2.9, 3.1), (3.0, 3.2),
        (3.1, 3.8), (3.0, 4.0), (3.1, 4.3), (3.1, 4.6), (3.0, 4.9)]

matcher = DistanceMatcher(map_con, max_dist=2, obs_noise=1, min_prob_norm=0.5)
states, _ = matcher.match_incremental(path[:5])
states, _ = matcher.match_incremental(path[5:], backtrace_len=-1)
nodes = matcher.path_pred_onlynodes

mmviz.plot_map(map_con, matcher=matcher,
               show_labels=True, show_matching=True, show_graph=True,
               filename="my_plot.png")

Thanks for your help.

osmnx, Geopandas, DistanceMatcher

Hi,
my question is, how can I combine osmnx, Geopandas and DistanceMatcher together? Can you show me this with an example please? for example with this Data:

Ponte_Haus.zip

I would be happy, if you could give me the answer.

No route satisfies mapmatch criteria

Mostly using examples in the docu, I do the following:

Download a map

from pathlib import Path
import requests
xml_file = Path(".") / "osm.xml"
url = 'http://overpass-api.de/api/map?bbox=4.694933,50.870047,4.709256000000001,50.879628'
r = requests.get(url, stream=True)
with xml_file.open('wb') as ofile:
for chunk in r.iter_content(chunk_size=1024):
if chunk:
ofile.write(chunk)

Create a map, removing the limitation 'highway in entity.tags'

from leuvenmapmatching.map.inmem import InMemMap
import osmread

map_con = InMemMap("myosm", use_latlon=True, use_rtree=True, index_edges=True)
for entity in osmread.parse_file(str(xml_file)):
#if isinstance(entity, osmread.Way) and 'highway' in entity.tags:
if isinstance(entity, osmread.Way):
for node_a, node_b in zip(entity.nodes, entity.nodes[1:]):
map_con.add_edge(node_a, node_b)
# Some roads are one-way. We'll add both directions.
map_con.add_edge(node_b, node_a)
if isinstance(entity, osmread.Node):
map_con.add_node(entity.id, (entity.lat, entity.lon))
map_con.purge()

Create my own track

track = [(50.87158705419287, 4.701149818142195),
(50.87162768899347, 4.701342872760166),
(50.87164800638049, 4.701557377891264),
(50.8716818686725, 4.70172898199615),
(50.87169541358241, 4.701932761870685),
(50.87173604828854, 4.702157992258305),
(50.87178345540092, 4.70228669533694),
(50.87179700028131, 4.7025012004680375),
(50.87168864112794, 4.702608453033586),
(50.87161414406387, 4.702554826750811),
(50.87155996430614, 4.702587002520461),
(50.871444832111806, 4.702694255086009),
(50.87131615461689, 4.702822958164683),
(50.87132292712548, 4.70291948547367),
(50.87132292712548, 4.703048188552304),
(50.87123488443708, 4.70314471586129),
(50.87111975143977, 4.703155441117853),
(50.87103170836759, 4.703198342144065),
(50.87093012000073, 4.703348495735825),
(50.870889484592006, 4.70347719881446),
(50.87080821366827, 4.703509374584148),
(50.87077435074152, 4.703595176636571),
(50.87075403297369, 4.703670253432471),
(50.87071339741144, 4.703713154458683),
(50.87064567139563, 4.703788231254543)]

Try to mapmatch it

from leuvenmapmatching.util.gpx import gpx_to_path

matcher = DistanceMatcher(map_con,
max_dist=100, max_dist_init=25, # meter
min_prob_norm=0.001,
non_emitting_length_factor=0.75,
obs_noise=50, obs_noise_ne=75, # meter
dist_noise=50, # meter
non_emitting_states=True,
max_lattice_width=5)
states, lastidx = matcher.match(track)

But the result is poor: no mapmatched way seems to satisfy the selection criteria.

assert not [l for l in matcher.lattice.values() if l.values_all()]

Could you please help me with that?

node id and match error

Hello dear developer, I appreciate that you have developed such a useful tool that has been very helpful to me. I have two questions : )
First question:
I use osmnx to get the road network. The following figure shows some node information in the road network. The nodes in the map match result are "osmid" sequence, is there any way to use "fid"?
1707147685099
Second question:
As shown in the figure below, I used the parameters in the examples you gave to match the map. Most match paths are complete, but some match paths are short ( not complete ) or are even empty. How can I modify these parameters or do something else to make the match more complete?
VESM)8_@5KSJN{GM()R%V

Error in Loading Serialized Map Data with InMemMap.deserialize

https://stackoverflow.com/questions/77878622/error-in-loading-serialized-map-data-with-inmemmap-deserialize

I am attempting to load map data from a pickle file using map_connn = InMemMap.deserialize(map_conn). After exporting the map data from memory with map_con.dump() as a dictionary, an error occurs:

TreeError: Error in "Index_CreateWithStream": Spatial Index Error: IllegalArgumentException: SpatialIndex::DiskStorageManager: Index/Data file cannot be created." 1.

map_con.dump()
import pickle
import os
map_data_file = 'E:\jupyternotebook\共享单车路径匹配\map_con\myosm.pkl'

if os.path.exists(map_data_file):
with open(map_data_file, 'rb') as f:
map_conn = pickle.load(f)
map_connn = InMemMap.deserialize(map_conn)


RTreeError Traceback (most recent call last)
Cell In[5], line 1
----> 1 map_connn = InMemMap.deserialize(map_conn)

File D:\miniconda3\envs\Map_Matching\lib\site-packages\leuvenmapmatching\map\inmem.py:144, in InMemMap.deserialize(cls, data)
141 @classmethod
142 def deserialize(cls, data):
143 """Create a new instance from a dictionary."""
--> 144 nmap = cls(data["name"], dir=data.get("dir", None),
145 use_latlon=data["use_latlon"], use_rtree=data["use_rtree"],
146 index_edges=data["index_edges"],
147 crs_lonlat=data.get("crs_lonlat", None), crs_xy=data.get("crs_xy", None),
148 graph=data.get("graph", None), linked_edges=data.get("linked_edges", None),
149 deserializing=True)
150 return nmap

File D:\miniconda3\envs\Map_Matching\lib\site-packages\leuvenmapmatching\map\inmem.py:81, in InMemMap.init(self, name, use_latlon, use_rtree, index_edges, crs_lonlat, crs_xy, graph, linked_edges, dir, deserializing)
79 self.use_rtree = use_rtree
80 if self.use_rtree:
---> 81 self.setup_index(deserializing=deserializing)
83 self.crs_lonlat = 'EPSG:4326' if crs_lonlat is None else crs_lonlat # GPS
84 self.crs_xy = 'EPSG:3395' if crs_xy is None else crs_xy # Mercator projection

File D:\miniconda3\envs\Map_Matching\lib\site-packages\leuvenmapmatching\map\inmem.py:384, in InMemMap.setup_index(self, force, deserializing)
382 else:
383 logger.debug(f"Creating new in-memory rtree index (args={args}) ...")
--> 384 self.rtree = rtree.index.Index(*args)
385 t_delta = time.time() - t_start
386 logger.debug(f"... done: rtree size = {self.rtree_size()}, time = {t_delta} sec")

File D:\miniconda3\envs\Map_Matching\lib\site-packages\rtree\index.py:273, in Index.init(self, *args, **kwargs)
271 if stream and self.properties.type == RT_RTree:
272 self._exception = None
--> 273 self.handle = self._create_idx_from_stream(stream)
274 if self._exception:
275 raise self._exception

File D:\miniconda3\envs\Map_Matching\lib\site-packages\rtree\index.py:1263, in Index._create_idx_from_stream(self, stream)
1260 return 0
1262 stream = core.NEXTFUNC(py_next_item)
-> 1263 return IndexStreamHandle(self.properties.handle, stream)

File D:\miniconda3\envs\Map_Matching\lib\site-packages\rtree\index.py:1396, in Handle.init(self, *args, **kwargs)
1395 def init(self, *args: Any, **kwargs: Any) -> None:
-> 1396 self._ptr = self._create(*args, **kwargs)

File D:\miniconda3\envs\Map_Matching\lib\site-packages\rtree\core.py:25, in check_void(result, func, cargs)
23 msg = f'Error in "{func.name}": {s}'
24 rt.Error_Reset()
---> 25 raise RTreeError(msg)
26 return result

RTreeError: Error in "Index_CreateWithStream": Spatial Index Error: IllegalArgumentException: SpatialIndex::DiskStorageManager: Index/Data file cannot be created.
Whenever I create a map in-memory object, it requires a significant amount of computation, including importing points, importing edges, and performing deduplication operations. This results in a long processing time each time I generate an in-memory map object. To overcome this, I attempted to export my pre-computed map in-memory object and load it directly from a file for future use.

Initially, I tried using Python's built-in pickle module. However, when I read the exported .pkl file, I found that it couldn't be used for path matching, as the matched paths were empty. I suspected that certain attributes, such as R-tree, might have been lost during the export of the map in-memory object.

To address this, I consulted the official documentation of LeuvenMap and discovered the dump() and deserialize() methods provided by the package. I attempted to use these recommended backup and loading methods. However, during the process, I encountered the aforementioned error.

I would greatly appreciate assistance in resolving this issue.

What does "non-emitting states" mean?

Hello! First of all, thank you for developing this model, it helps me a lot in my project.
Now I have difficulty understanding "non-emitting states". The Annotation in newsonkrumm.py says:
Newson and Krumm use shortest path to handle situations where the distances between observations are larger than distances between nodes in the graph. The LeuvenMapMatching toolbox uses non-emitting states to handle this. We thus do not implement the shortest path algorithm in this class.
So what is the main difference between the two algorithm?
I noticed that your model refers to the paper:
Meert Wannes, Mathias Verbeke, "HMM with Non-Emitting States for Map Matching", European Conference on Data Analysis (ECDA), Paderborn, Germany, 2018.
But I failed to find it on the internet. If you can help me on the question, or tell me where to find the paper, I'd be very grateful.
Thanks for reading!

Map matching does not work

Dear community,
Map matching doesn't work for me. "states" is an empty list and "lastidx" is zero. Do you have any idea what the problem is? I would be grateful for any help. Here is my code:

import numpy as np
import scipy
from datetime import datetime

#--------------------------------------------------------------
#Download a map

from pathlib import Path
import requests

start1 = datetime.now()
xml_file = Path(".") / "osm.xml"
url = 'http://overpass-api.de/api/map?bbox=4.694933,50.870047,4.709256000000001,50.879628'
r = requests.get(url, stream=True)
with xml_file.open('wb') as ofile:
    for chunk in r.iter_content(chunk_size=2230):
        if chunk:
            ofile.write(chunk)
print('Time to download: ' , datetime.now()-start1)
            
#--------------------------------------------------------------
#Creating graph (use osmread)

from leuvenmapmatching.map.inmem import InMemMap
import osmread

start2 = datetime.now()

map_con = InMemMap("myosm", use_latlon=True, use_rtree=True, index_edges=True)
for entity in osmread.parse_file(str(xml_file)):
    if isinstance(entity, osmread.Way) and 'highway' in entity.tags:
        for node_a, node_b in zip(entity.nodes, entity.nodes[1:]):
            map_con.add_edge(node_a, node_b)
            # Some roads are one-way. We'll add both directions.
            map_con.add_edge(node_b, node_a)
    if isinstance(entity, osmread.Node):
        map_con.add_node(entity.id, (entity.lat, entity.lon))
map_con.purge()
print('Time to Create graph: ' , datetime.now()-start2)

#--------------------------------------------------------------
#Perform map matching on an OpenStreetMap

from leuvenmapmatching.util.gpx import gpx_to_path
from leuvenmapmatching.matcher.distance import DistanceMatcher

start3 = datetime.now()
track = gpx_to_path("Seattle.gpx")
matcher = DistanceMatcher(map_con,
                         max_dist=100, max_dist_init=25,  
                         min_prob_norm=0.001,
                         non_emitting_length_factor=0.75,
                         obs_noise=50, obs_noise_ne=75,  
                         dist_noise=50,  
                         non_emitting_states=True,
                         max_lattice_width=5)
states, lastidx = matcher.match(track)
print('Time to perform map matching: ' , datetime.now() - start3)

#---------------------------------------------------------------
#visualization

from leuvenmapmatching import visualization as mmviz

start4 = datetime.now()
mmviz.plot_map(map_con, matcher=matcher,
                use_osm=True, zoom_path=True,
                show_labels=False, show_matching=True, show_graph=False,
                filename="Seattle.png")
print('Time to make a visualization: ' , datetime.now() - start4)
print('---------------------------------------------------------')
#---------------------------------------------------------------

Seattle

and here is the GPS-Data:

20220614040820-21088-data.txt

'Index' object has no attribute 'upsert'

Hi,
I am trying to run the "Create graph using osmread" code, but I got this error. Do you have any suggestions for this error?
The error is:

AttributeError Traceback (most recent call last)
C:\Users\203345~1\AppData\Local\Temp/ipykernel_5252/840127675.py in
25 map_con.add_edge(node_b, node_a)
26 if isinstance(entity, osmread.Node):
---> 27 map_con.add_node(entity.id, (entity.lat, entity.lon))
28 map_con.purge()

~\anaconda\envs\sxpipei3\lib\site-packages\leuvenmapmatching\map\inmem.py in add_node(self, node, loc)
191 if type(node) is not int:
192 raise Exception(f"Rtree index only supports integer keys for vertices")
--> 193 self.rtree.upsert(node, (loc[0], loc[1], loc[0], loc[1]))
194
195 def del_node(self, node):

AttributeError: 'Index' object has no attribute 'upsert'

pyproj/crs FutureWarning: '+init=<authority>:<code>' syntax is deprecated.

When I run this:

from leuvenmapmatching.map.inmem import InMemMap

map_con = InMemMap("myosm", use_latlon=True, use_rtree=True, index_edges=True)

I get this warning:


/home/user/anaconda3/envs/ox/lib/python3.8/site-packages/pyproj/crs/crs.py:55: FutureWarning: '+init=<authority>:<code>' syntax is deprecated. '<authority>:<code>' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6
  return _prepare_from_string(" ".join(pjargs))

/home/user/anaconda3/envs/ox/lib/python3.8/site-packages/pyproj/crs/crs.py:55: FutureWarning: '+init=<authority>:<code>' syntax is deprecated. '<authority>:<code>' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6
  return _prepare_from_string(" ".join(pjargs))

pip freeze gives me:

attrs==19.3.0
backcall==0.1.0
branca==0.4.0
certifi==2019.11.28
cffi==1.13.2
chardet==3.0.4
Click==7.0
click-plugins==1.1.1
cligj==0.5.0
cryptography==2.8
cycler==0.10.0
decorator==4.4.2
descartes==1.1.0
entrypoints==0.3
Fiona==1.8.13
folium==0.10.1
GDAL==3.0.4
geographiclib==1.50
geopandas==0.7.0
geopy==1.21.0
idna==2.9
ipykernel==5.1.4
ipython==7.13.0
ipython-genutils==0.2.0
jedi==0.16.0
Jinja2==2.11.1
joblib==0.14.1
jupyter-client==6.0.0
jupyter-core==4.6.3
kiwisolver==1.1.0
leuvenmapmatching==0.5.3
MarkupSafe==1.1.1
matplotlib==3.1.3
munch==2.5.0
networkx==2.4
numpy==1.18.1
osmnx==0.11.4
pandas==1.0.1
parso==0.6.2
pexpect==4.8.0
pickleshare==0.7.5
Pillow==7.0.0
prompt-toolkit==3.0.3
ptyprocess==0.6.0
pycparser==2.19
Pygments==2.5.2
pyOpenSSL==19.1.0
pyparsing==2.4.6
pyproj==2.5.0
PySocks==1.7.1
python-dateutil==2.8.1
pytz==2019.3
pyzmq==19.0.0
requests==2.23.0
Rtree==0.9.4
scikit-learn==0.22.1
scipy==1.4.1
Shapely==1.7.0
six==1.14.0
smopy==0.0.7
tornado==6.0.3
traitlets==4.3.3
urllib3==1.25.7
vincent==0.4.4
wcwidth==0.1.8

Exception: Did not find a matching node for path point at index 3723

I am trying to use the NoisePlanet which uses the Leuven DistanceMatcher on its backend for map matching. I am getting the following error

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-82-5396cffaa114> in <module>
----> 1 track_coor, route_corr, edgeid, stats = matching.match(G, track, method='hmm')
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/noiseplanet/matcher/matching.py in match(graph, track, method)
     61         track_corr, route_corr, edgeid, stats = model.match_nearest_edge(graph, track)
     62     elif method == 'hmm':
---> 63         track_corr, route_corr, edgeid, stats = model.match_leuven(graph, track)
     64     return track_corr, route_corr, edgeid, stats
     65 
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/noiseplanet/matcher/model/leuven.py in match_leuven(graph, track)
    111                              dist_noise=50,  # meter
    112                              non_emitting_edgeid=False)
--> 113     edgeid, lastidx = matcher.match(path)
    114 
    115     proj_dist = np.zeros(len(track))
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/leuvenmapmatching/matcher/base.py in match(self, path, unique, tqdm)
    463         else:
    464             start_idx = len(self.path) - 1
--> 465         node_path = self._build_node_path(start_idx, unique)
    466         return node_path, start_idx
    467 
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/leuvenmapmatching/matcher/base.py in _build_node_path(self, start_idx, unique, max_depth, last_is_e)
   1031                     node_max = m
   1032         if node_max is None:
-> 1033             raise Exception("Did not find a matching node for path point at index {}".format(start_idx))
   1034         if __debug__ and logger.isEnabledFor(logging.DEBUG):
   1035             logger.debug(self.matching.repr_header(stop="             "))
Exception: Did not find a matching node for path point at index 3723

Is there a way in which we can skip the non matching nodes in the function? Or is there a way to bypass this error as it dosent matter for me if some nodes are not matched and it shouldnt stop my program.

Please do let me know if there is any more information required.

can we support n-best path?

now we input one gps, output the most probably road network path, can we output the most n-best path? this is very useful, for we can get more information. and i think, it can realization at "Backtrack to find best path"

How to match GPX data that pass through an area with no road network?

Hello,
is it possible to interrupt the matched path and start a new matched path as soon as the algorithm finds a match with the graph again?

So far, the whole matching stops whenever the state cannot find a match. In my case, it is not due to very strict parameters but rather a missing road network. It would be nice if the matching did not stop after the first fail.

Thank you!

image

SimpleMatcher math domain error

I meet the problem when I wanna use SimpleMatcher. I don't understand why cos(d) raises the error unless the input is none or something similiar.
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.