statistical encoding

This commit is contained in:
Arndt 2015-10-11 19:27:33 +02:00
parent f8dee5b7d1
commit ccf6641bad
41 changed files with 4543 additions and 1965 deletions

View file

@ -17,6 +17,11 @@
<artifactId>brouter-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.btools</groupId>
<artifactId>brouter-codec</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.btools</groupId>
<artifactId>brouter-mapaccess</artifactId>

View file

@ -18,7 +18,7 @@ final class MatchedWaypoint
public OsmNodeNamed crosspoint;
public OsmNodeNamed waypoint;
public double radius;
public int cost;
public boolean hasUpdate;
public void writeToStream( DataOutput dos ) throws IOException
{

View file

@ -129,7 +129,7 @@ final class OsmPath implements OsmLinkHolder
MessageData msgData = new MessageData();
OsmTransferNode transferNode = link.decodeFirsttransfer();
OsmTransferNode transferNode = link.decodeFirsttransfer( p1 );
OsmNode targetNode = link.targetNode;
for(;;)
{

View file

@ -140,6 +140,27 @@ public final class RoutingContext implements DistanceChecker
}
}
public void cleanNogolist( List<OsmNodeNamed> waypoints )
{
if ( nogopoints == null ) return;
List<OsmNodeNamed> nogos = new ArrayList<OsmNodeNamed>();
for( OsmNodeNamed nogo : nogopoints )
{
int radiusInMeter = (int)(nogo.radius * 111894.);
boolean goodGuy = true;
for( OsmNodeNamed wp : waypoints )
{
if ( wp.calcDistance( nogo ) < radiusInMeter )
{
goodGuy = false;
break;
}
}
if ( goodGuy ) nogos.add( nogo );
}
nogopoints = nogos;
}
public long[] getNogoChecksums()
{
long[] cs = new long[3];
@ -215,8 +236,7 @@ public final class RoutingContext implements DistanceChecker
// calculate remaining distance
if ( s2 < 0. )
{
double distance = d > 0. ? -s2 / d : 0.;
wayfraction = d > 0. ? distance / d : 0.;
wayfraction = -s2 / (d*d);
double xm = x2 - wayfraction*dx;
double ym = y2 - wayfraction*dy;
ilonshortest = (int)(xm / coslat6 + nogo.ilon);

View file

@ -3,12 +3,13 @@ package btools.router;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import btools.expressions.BExpressionContext;
import btools.expressions.BExpressionContextGlobal;
import btools.expressions.BExpressionContextNode;
import btools.expressions.BExpressionContextWay;
@ -28,6 +29,7 @@ public class RoutingEngine extends Thread
private boolean finished = false;
protected List<OsmNodeNamed> waypoints = null;
protected List<MatchedWaypoint> matchedWaypoints;
private int linksProcessed = 0;
protected OsmTrack foundTrack = new OsmTrack();
@ -85,8 +87,8 @@ public class RoutingEngine extends Thread
BExpressionMetaData meta = new BExpressionMetaData();
BExpressionContextGlobal expctxGlobal = new BExpressionContextGlobal( meta );
rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 262144 : 4096, meta );
rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 1024, meta );
rc.expctxWay = new BExpressionContextWay( rc.serversizing ? 262144 : 8192, meta );
rc.expctxNode = new BExpressionContextNode( rc.serversizing ? 16384 : 2048, meta );
meta.readMetaData( new File( profileDir, "lookups.dat" ) );
@ -111,6 +113,7 @@ public class RoutingEngine extends Thread
{
infoLogWriter.write( s );
infoLogWriter.write( '\n' );
infoLogWriter.flush();
}
catch( IOException io )
{
@ -119,6 +122,14 @@ public class RoutingEngine extends Thread
}
}
private void logThrowable( Throwable t )
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
logInfo( sw.toString() );
}
public void run()
{
doRun( 0 );
@ -135,6 +146,9 @@ public class RoutingEngine extends Thread
logInfo( "start request at " + new Date() );
}
// delete nogos with waypoints in them
routingContext.cleanNogolist( waypoints );
startTime = System.currentTimeMillis();
this.maxRunningTime = maxRunningTime;
int nsections = waypoints.size() - 1;
@ -205,14 +219,14 @@ public class RoutingEngine extends Thread
{
errorMessage = e instanceof IllegalArgumentException ? e.getMessage() : e.toString();
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
e.printStackTrace();
logThrowable( e );
}
catch( Error e)
{
String hint = cleanOnOOM();
errorMessage = e.toString() + hint;
logInfo( "Error (linksProcessed=" + linksProcessed + ": " + errorMessage );
e.printStackTrace();
logThrowable( e );
}
finally
{
@ -250,14 +264,14 @@ public class RoutingEngine extends Thread
{
errorMessage = e instanceof IllegalArgumentException ? e.getMessage() : e.toString();
logInfo( "Exception (linksProcessed=" + linksProcessed + ": " + errorMessage );
e.printStackTrace();
logThrowable( e );
}
catch( Error e)
{
String hint = cleanOnOOM();
errorMessage = e.toString() + hint;
logInfo( "Error (linksProcessed=" + linksProcessed + ": " + errorMessage );
e.printStackTrace();
logThrowable( e );
}
finally
{
@ -290,7 +304,7 @@ public class RoutingEngine extends Thread
private OsmTrack findTrack( OsmTrack[] refTracks, OsmTrack[] lastTracks )
{
OsmTrack totaltrack = new OsmTrack();
MatchedWaypoint[] wayointIds = new MatchedWaypoint[waypoints.size()];
int nUnmatched = waypoints.size();
// check for a track for that target
OsmTrack nearbyTrack = null;
@ -299,20 +313,27 @@ public class RoutingEngine extends Thread
nearbyTrack = OsmTrack.readBinary( routingContext.rawTrackPath, waypoints.get( waypoints.size()-1), routingContext.getNogoChecksums() );
if ( nearbyTrack != null )
{
wayointIds[waypoints.size()-1] = nearbyTrack.endPoint;
}
}
// match waypoints to nodes
for( int i=0; i<waypoints.size(); i++ )
{
if ( wayointIds[i] == null )
{
wayointIds[i] = matchNodeForPosition( waypoints.get(i) );
nUnmatched--;
}
}
for( int i=0; i<waypoints.size() -1; i++ )
if ( matchedWaypoints == null ) // could exist from the previous alternative level
{
matchedWaypoints = new ArrayList<MatchedWaypoint>();
for( int i=0; i<nUnmatched; i++ )
{
MatchedWaypoint mwp = new MatchedWaypoint();
mwp.waypoint = waypoints.get(i);
matchedWaypoints.add( mwp );
}
matchWaypointsToNodes( matchedWaypoints );
if ( nearbyTrack != null )
{
matchedWaypoints.add( nearbyTrack.endPoint );
}
}
for( int i=0; i<matchedWaypoints.size() -1; i++ )
{
if ( lastTracks[i] != null )
{
@ -320,7 +341,7 @@ public class RoutingEngine extends Thread
refTracks[i].addNodes( lastTracks[i] );
}
OsmTrack seg = searchTrack( wayointIds[i], wayointIds[i+1], i == waypoints.size()-2 ? nearbyTrack : null, refTracks[i] );
OsmTrack seg = searchTrack( matchedWaypoints.get(i), matchedWaypoints.get(i+1), i == matchedWaypoints.size()-2 ? nearbyTrack : null, refTracks[i] );
if ( seg == null ) return null;
totaltrack.appendTrack( seg );
lastTracks[i] = seg;
@ -328,6 +349,50 @@ public class RoutingEngine extends Thread
return totaltrack;
}
// geometric position matching finding the nearest routable way-section
private void matchWaypointsToNodes( List<MatchedWaypoint> unmatchedWaypoints )
{
resetCache();
nodesCache.waypointMatcher = new WaypointMatcherImpl( unmatchedWaypoints, 250. );
for( MatchedWaypoint mwp : unmatchedWaypoints )
{
preloadPosition( mwp.waypoint );
}
// preliminary-hack: use old stuff if not yet matched
for( int i=0; i<unmatchedWaypoints.size(); i++)
{
MatchedWaypoint mwp = unmatchedWaypoints.get(i);
if ( mwp.crosspoint == null )
{
System.out.println( "name=" + mwp.waypoint.name + " NOT matched r=" + mwp.radius * 111894. );
unmatchedWaypoints.set(i, matchNodeForPosition( mwp.waypoint ) );
}
else
{
System.out.println( "name=" + mwp.waypoint.name + " matched r=" + mwp.radius * 111894. );
}
}
}
private void preloadPosition( OsmNode n )
{
int d = 12500;
nodesCache.first_file_access_failed = false;
nodesCache.first_file_access_name = null;
nodesCache.loadSegmentFor( n.ilon, n.ilat );
if ( nodesCache.first_file_access_failed )
{
throw new IllegalArgumentException( "datafile " + nodesCache.first_file_access_name + " not found" );
}
for( int idxLat=-1; idxLat<=1; idxLat++ )
for( int idxLon=-1; idxLon<=1; idxLon++ )
{
nodesCache.loadSegmentFor( n.ilon + d*idxLon , n.ilat +d*idxLat );
}
}
// geometric position matching finding the nearest routable way-section
private MatchedWaypoint matchNodeForPosition( OsmNodeNamed wp )
{
@ -406,7 +471,6 @@ public class RoutingEngine extends Thread
mwp.node1 = n;
mwp.node2 = nextNode;
mwp.radius = wp.radius;
mwp.cost = testPath.cost;
mwp.crosspoint = new OsmNodeNamed();
mwp.crosspoint.ilon = routingContext.ilonshortest;
mwp.crosspoint.ilat = routingContext.ilatshortest;
@ -510,8 +574,7 @@ public class RoutingEngine extends Thread
private void resetCache()
{
nodesMap = new OsmNodesMap();
BExpressionContext ctx = routingContext.expctxWay;
nodesCache = new NodesCache(segmentDir, nodesMap, ctx.meta.lookupVersion, ctx.meta.lookupMinorVersion, routingContext.carMode, routingContext.forceSecondaryData, nodesCache );
nodesCache = new NodesCache(segmentDir, nodesMap, routingContext.expctxWay, routingContext.carMode, routingContext.forceSecondaryData, nodesCache );
}
private OsmNode getStartNode( long startId )

View file

@ -0,0 +1,140 @@
package btools.router;
import java.util.List;
import btools.codec.WaypointMatcher;
import btools.mapaccess.OsmNode;
/**
* the WaypointMatcher is feeded by the decoder with geoemtries of ways that are
* already check for allowed access according to the current routing profile
*
* It matches these geometries against the list of waypoints to find the best
* match for each waypoint
*/
public final class WaypointMatcherImpl implements WaypointMatcher
{
private List<MatchedWaypoint> waypoints;
private int lonStart;
private int latStart;
private boolean anyUpdate;
private int lonLast;
private int latLast;
public WaypointMatcherImpl( List<MatchedWaypoint> waypoints, double maxDistance )
{
this.waypoints = waypoints;
for ( MatchedWaypoint mwp : waypoints )
{
mwp.radius = maxDistance / 111894.; // 6378000. / 57.;
}
}
private void checkSegment( int lon1, int lat1, int lon2, int lat2 )
{
// todo: bounding-box pre-filter
double l = ( lat2 - 90000000 ) * 0.00000001234134;
double l2 = l * l;
double l4 = l2 * l2;
double coslat = 1. - l2 + l4 / 6.;
double coslat6 = coslat * 0.000001;
double dx = ( lon2 - lon1 ) * coslat6;
double dy = ( lat2 - lat1 ) * 0.000001;
double d = Math.sqrt( dy * dy + dx * dx );
if ( d == 0. )
return;
for ( MatchedWaypoint mwp : waypoints )
{
OsmNodeNamed wp = mwp.waypoint;
double x1 = ( lon1 - wp.ilon ) * coslat6;
double y1 = ( lat1 - wp.ilat ) * 0.000001;
double x2 = ( lon2 - wp.ilon ) * coslat6;
double y2 = ( lat2 - wp.ilat ) * 0.000001;
double r12 = x1 * x1 + y1 * y1;
double r22 = x2 * x2 + y2 * y2;
double radius = Math.abs( r12 < r22 ? y1 * dx - x1 * dy : y2 * dx - x2 * dy ) / d;
if ( radius < mwp.radius )
{
double s1 = x1 * dx + y1 * dy;
double s2 = x2 * dx + y2 * dy;
if ( s1 < 0. )
{
s1 = -s1;
s2 = -s2;
}
if ( s2 > 0. )
{
radius = Math.sqrt( s1 < s2 ? r12 : r22 );
if ( radius > mwp.radius )
continue;
}
// new match for that waypoint
mwp.radius = radius; // shortest distance to way
mwp.hasUpdate = true;
anyUpdate = true;
// calculate crosspoint
if ( mwp.crosspoint == null )
mwp.crosspoint = new OsmNodeNamed();
if ( s2 < 0. )
{
double wayfraction = -s2 / ( d * d );
double xm = x2 - wayfraction * dx;
double ym = y2 - wayfraction * dy;
mwp.crosspoint.ilon = (int) ( xm / coslat6 + wp.ilon );
mwp.crosspoint.ilat = (int) ( ym / 0.000001 + wp.ilat );
}
else if ( s1 > s2 )
{
mwp.crosspoint.ilon = lon2;
mwp.crosspoint.ilat = lat2;
}
else
{
mwp.crosspoint.ilon = lon1;
mwp.crosspoint.ilat = lat1;
}
}
}
}
@Override
public void startNode( int ilon, int ilat )
{
lonLast = lonStart = ilon;
latLast = latStart = ilat;
anyUpdate = false;
}
@Override
public void transferNode( int ilon, int ilat )
{
checkSegment( lonLast, latLast, ilon, ilat );
lonLast = ilon;
latLast = ilat;
}
@Override
public void endNode( int ilon, int ilat )
{
checkSegment( lonLast, latLast, ilon, ilat );
if ( anyUpdate )
{
for ( MatchedWaypoint mwp : waypoints )
{
if ( mwp.hasUpdate )
{
mwp.hasUpdate = false;
mwp.node1 = new OsmNode( lonStart, latStart );
mwp.node2 = new OsmNode( ilon, ilat );
}
}
}
}
}