map-matching icon indicating copy to clipboard operation
map-matching copied to clipboard

Association of all provided GPXEntry to the corresponding EdgeMatch

Open Vannav opened this issue 9 years ago • 11 comments

Discussion: https://discuss.graphhopper.com/t/map-matchresult-to-gpxentry/977

The plan was that all GPXEntries which we used for matching should be associated to EdgeMatch

This doesn't work since the rework of the matching algorithm in doWork(List<GPXEntry> gpxList) from the pull-request https://github.com/graphhopper/map-matching/pull/49

The main reason for this is the filtering of GPXEntries by a distance threshold distance(previousGPX, currentGPX) > 2 * measurementErrorSigma which are never considered again in the the following resolvation of MostLikelySequence to EdgeMatch

GPXEntries are disregarded to avoid too many (superfluous) calculations.

Vannav avatar Aug 31 '16 13:08 Vannav

The plan was that all GPXEntries which we used for matching should be associated to EdgeMatch

I believe this is (technically) happening - the points not used for matching are not included. @karussel is the intention that all GPXEntries (even those that are not used for matching) be associated with an edges?

@Vannav, the reason for the filtering you referred to is directly from the published algorithm - e.g. if the GPS accuracy is 10m, but you've recorded points only one meter apart in your GPX entries, then it's assumed OK to ignore most of them as they don't provide much additional information (but do slow down the process a lot), and (I think) can cause problems (e.g. if you're sitting stationary at the lights, it may looks like you're moving back and forward - due to GPS measurements fluctuating - etc.)

kodonnell avatar Sep 15 '16 20:09 kodonnell

@Vannav can you elaborate why you 'need the internalEdgeId for every GPXEntry I have inputed'?

@karussel is the intention that all GPXEntries (even those that are not used for matching) be associated with an edges?

We should make this somehow happening to make post processing easier, maybe doing the matching first with only a few candidates and then doing an 'association step' for all GPXEntries in the range.

karussell avatar Sep 15 '16 20:09 karussell

... maybe doing the matching first with only a few candidates and then doing an 'association step' for all GPXEntries in the range.

Agreed. Shouldn't be too hard ...

kodonnell avatar Sep 15 '16 20:09 kodonnell

Hi @karussell and @kodonnell

my main goal is to associate every gps point inputed with the matched way segments in OSM data for other tracking purposes.

With the internalEdgeId I can map them with this extension to osm ways.

My current approach is to convert the resulted polyline to a osm way segment by querying for osm nodes which are epsilon-near the nodes of the polyline.

Greetings

Vannav avatar Sep 30 '16 21:09 Vannav

This is kind of duplicate of #23

karussell avatar Oct 08 '16 19:10 karussell

OK... I had a similar issue that might be solved. Isn't just taking the edgeMatches and computing distances to every input point the correct solution?

Something like (untested code):

// ... creation of MapMatching class (variable mapMatching)
// ... the array gpxEntries contains the source points from the gps file (as GPXEntry objects)

final Map<Integer, EdgeMatch> mMatch = new HashMap<>();
final Map<Integer, PointList> mPoints = new HashMap<>();

final MatchResult mr = mapMatching.doWork(gpxEntries);
final List<EdgeMatch> matches = mr.getEdgeMatches();

for (final EdgeMatch match : matches) {
	final EdgeIteratorState s = match.getEdgeState();
	final int eId = s.getEdge();
	mMatch.put(eId, match);
	mPoints.put(eId, s.fetchWayGeometry(1));
}

final EdgeMatch[] result = new EdgeMatch[gpxEntries.length];
for (int i = 0; i < gpxEntries.length - 1; ++i) {
	final GPXEntry gpx = gpxEntries[i];

	double minDistance = Integer.MAX_VALUE;
	int minEdgeId = -1;
	final Set<Entry<Integer, PointList>> s = mPoints.entrySet();
	for (final Entry<Integer, PointList> e : s) {
		final PointList points = e.getValue();
		for (final GHPoint3D p : points) {
			final double d = Math.abs(distCalc.calcDist(gpx.getLat(), gpx.getLon(), p.getLat(), p.getLon()));
			if (d < minDistance) {
				minDistance = d;
				minEdgeId = e.getKey();
			}
		}
	}

	if(minEdgeId >= 0) {
		result[i] = mMatch.get(minEdgeId);
	}
}

// now the result array should contain a matching point on the map matching result (matching the array indices from the source gpx entries), isn't it?

I know that this solution is not very fast, but is it what would solve this issue (or is it incorrect, to inaccurate??)?

If it is what's needed I can also send a PR :-)

nikolauskrismer avatar Dec 28 '16 14:12 nikolauskrismer

There's a plan for this to happen in #87 - see here and below.

kodonnell avatar Dec 30 '16 18:12 kodonnell

Since the work on completing this task is delayed, is there a possibility to separate the GPX point filter threshold from the map matching logic? ie instead of measurementErrorSigma for both GPX point filtering as well as map matching algorithm, add a new parameter such as "gpsFilterDistance".

I need to snap the original GPX points but am unable to do this accurately and in a performant way. I've branched off master and made this change locally.

Thanks, Trang

INRIX-Trang-Nguyen avatar Jul 25 '18 16:07 INRIX-Trang-Nguyen

I've got another vote for Trang's suggestion - I've got some data with variable accuracy, so if I use a high "GPS accuracy" value, lots of good points get deleted (often too many to perform map-matching at all) and inaccurate points are kept. Then the map-matching attempts to route via the bad points, leading to a really bad fit

Cheers, Pete

jetsetjim avatar Aug 07 '18 09:08 jetsetjim

Please use our forum in the first place. Issues should be specific to bugs and features.

karussell avatar Aug 07 '18 09:08 karussell

I've updated comments here: https://discuss.graphhopper.com/t/map-matchresult-to-gpxentry/977/9. Pete you can add additional comments to that thread. Cheers, Trang

INRIX-Trang-Nguyen avatar Aug 07 '18 11:08 INRIX-Trang-Nguyen