From e5d8bd9bf499b607cd5ab7a3cea018bafb953e18 Mon Sep 17 00:00:00 2001 From: Arndt Brenschede Date: Sat, 10 Mar 2018 10:41:11 +0100 Subject: [PATCH] initail commit suspect detection --- .../src/main/java/btools/router/OsmPath.java | 38 +++++- .../java/btools/router/RoutingContext.java | 16 ++- .../java/btools/router/RoutingEngine.java | 46 ++++++- .../main/java/btools/mapaccess/OsmNode.java | 4 + .../src/main/java/btools/server/BRouter.java | 2 +- .../java/btools/server/BadTRDetector.java | 93 ++++++++++++++ .../main/java/btools/server/IssueFilter.java | 40 ++++++ .../main/java/btools/server/IssueSorter.java | 121 ++++++++++++++++++ 8 files changed, 345 insertions(+), 15 deletions(-) create mode 100644 brouter-server/src/main/java/btools/server/BadTRDetector.java create mode 100644 brouter-server/src/main/java/btools/server/IssueFilter.java create mode 100644 brouter-server/src/main/java/btools/server/IssueSorter.java diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index 2ce003e..f16be77 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -184,7 +184,7 @@ abstract class OsmPath implements OsmLinkHolder } // check turn restrictions (n detail mode (=final pass) no TR to not mess up voice hints) - if ( nsection == 0 && rc.considerTurnRestrictions && !detailMode ) + if ( nsection == 0 ) { boolean hasAnyPositive = false; boolean hasPositive = false; @@ -223,8 +223,23 @@ abstract class OsmPath implements OsmLinkHolder } if ( !hasPositive && ( hasAnyPositive || hasNegative ) ) { - cost = -1; - return; + if ( rc.considerTurnRestrictions && !detailMode ) + { + cost = -1; + return; + } + if ( !rc.considerTurnRestrictions && detailMode ) // detect effective (=suspect) TRs + { + if ( rc.suspectTRs != null && priorityclassifier > 20 && cost > 2000 && cost < rc.maxcost - 2000 ) + { + Long id = Long.valueOf( sourceNode.getIdFromPos() ); + if ( rc.suspectTRs.get( id ) == null ) + { +System.out.println( "bad TR candidate: " + id ); + rc.suspectTRs.put( id, Integer.valueOf( priorityclassifier ) ); + } + } + } } } @@ -308,8 +323,12 @@ abstract class OsmPath implements OsmLinkHolder double elevation = ele2 == Short.MIN_VALUE ? 100. : ele2/4.; double sectionCost = processWaySection( rc, dist, delta_h, elevation, angle, cosangle, isStartpoint, nsection, lastpriorityclassifier ); - if ( ( sectionCost < 0. || costfactor > 9998. && !detailMode ) || sectionCost + cost >= 2000000000. ) + if ( ( sectionCost < 0. || costfactor > 9996. && !detailMode ) || sectionCost + cost >= 2000000000. ) { + if ( ( costfactor == 9998. && priorityclassifier == lastpriorityclassifier ) || costfactor == 9997. ) + { + rc.foundWayBlock = Math.max( rc.foundWayBlock, priorityclassifier ); + } cost = -1; return; } @@ -398,6 +417,17 @@ abstract class OsmPath implements OsmLinkHolder double targetCost = processTargetNode( rc ); if ( targetCost < 0. || targetCost + cost >= 2000000000. ) { + if ( rc.suspectNodes != null && priorityclassifier > 20 && !rc.inverseDirection ) + { + rc.foundNodeBlock = true; + Long id = Long.valueOf( targetNode.getIdFromPos() ); + Integer val = rc.suspectNodes.get( id ); + if ( val == null || priorityclassifier > val.intValue() ) + { + rc.suspectNodes.put( id, Integer.valueOf( priorityclassifier ) ); + } + } + cost = -1; return; } diff --git a/brouter-core/src/main/java/btools/router/RoutingContext.java b/brouter-core/src/main/java/btools/router/RoutingContext.java index 01ee5e2..c6d32a2 100644 --- a/brouter-core/src/main/java/btools/router/RoutingContext.java +++ b/brouter-core/src/main/java/btools/router/RoutingContext.java @@ -8,6 +8,7 @@ package btools.router; import java.io.DataOutput; import java.io.File; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -32,8 +33,15 @@ public final class RoutingContext public long profileTimestamp; public Map keyValues; - + public String rawTrackPath; + + public Map suspectNodes; + public Map suspectTRs; + public boolean foundNodeBlock; + public int foundWayBlock; + + public int maxcost; public String getProfileName() { @@ -57,7 +65,7 @@ public final class RoutingContext public int uphillcutoff; public boolean carMode; public boolean bikeMode; - public boolean considerTurnRestrictions; + public boolean considerTurnRestrictions = true; public boolean processUnusedTags; public boolean forceSecondaryData; public double pass1coefficient; @@ -100,7 +108,7 @@ public final class RoutingContext public void initModel() { pm.init( expctxWay, expctxNode, keyValues ); - } + } public long getKeyValueChecksum() { @@ -131,7 +139,7 @@ public final class RoutingContext bikeMode = 0.f != expctxGlobal.getVariableValue( "validForBikes", 0.f ); // turn-restrictions used per default for car profiles - considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue( "considerTurnRestrictions", carMode ? 1.f : 0.f ); + considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue( "considerTurnRestrictions", carMode && considerTurnRestrictions ? 1.f : 0.f ); // process tags not used in the profile (to have them in the data-tab) processUnusedTags = 0.f != expctxGlobal.getVariableValue( "processUnusedTags", 0.f ); diff --git a/brouter-core/src/main/java/btools/router/RoutingEngine.java b/brouter-core/src/main/java/btools/router/RoutingEngine.java index 56632fe..c71058d 100644 --- a/brouter-core/src/main/java/btools/router/RoutingEngine.java +++ b/brouter-core/src/main/java/btools/router/RoutingEngine.java @@ -9,6 +9,7 @@ import java.io.Writer; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import btools.mapaccess.NodesCache; import btools.mapaccess.OsmLink; @@ -951,6 +952,7 @@ public class RoutingEngine extends Thread } routingContext.firstPrePath = null; + routingContext.maxcost = maxTotalCost; for( OsmLink link = currentNode.firstlink; link != null; link = link.getNext( currentNode) ) { @@ -977,6 +979,10 @@ public class RoutingEngine extends Thread } } + int nPathPossible = 0; + routingContext.foundNodeBlock = false; + routingContext.foundWayBlock = 0; + for( OsmLink link = currentNode.firstlink; link != null; link = link.getNext( currentNode) ) { OsmNode nextNode = link.getTarget( currentNode ); @@ -985,14 +991,15 @@ public class RoutingEngine extends Thread { continue; // border node? } - if ( nextNode.firstlink == null ) - { - continue; // don't care about dead ends - } if ( nextNode == sourceNode ) { continue; // border node? } + if ( nextNode.firstlink == null ) + { + nPathPossible++; + continue; // don't care about dead ends + } if ( guideTrack != null ) { @@ -1008,11 +1015,14 @@ public class RoutingEngine extends Thread // not along the guide-track, discard, but register for voice-hint processing if ( routingContext.turnInstructionMode > 0 ) { + Map trSuspects = routingContext.suspectTRs; + routingContext.suspectTRs = null; OsmPath detour = routingContext.createPath( path, link, refTrack, true ); if ( detour.cost >= 0. && nextId != startNodeId1 && nextId != startNodeId2 ) { guideTrack.registerDetourForId( currentNode.getIdFromPos(), OsmPathElement.create( detour, false ) ); } + routingContext.suspectTRs = trSuspects; } continue; } @@ -1053,6 +1063,8 @@ public class RoutingEngine extends Thread } if ( bestPath != null ) { + nPathPossible++; + boolean trafficSim = endPos == null; bestPath.airdistance = trafficSim ? keepPathAirdistance : ( isFinalLink ? 0 : nextNode.calcDistance( endPos ) ); @@ -1078,7 +1090,6 @@ public class RoutingEngine extends Thread { bestPath.airdistance += boundary.getBoundaryDistance( nextNode ); } - bestPath.treedepth = path.treedepth + 1; link.addLinkHolder( bestPath, currentNode ); synchronized( openSet ) @@ -1090,6 +1101,29 @@ public class RoutingEngine extends Thread } } + // report oneway dead-ends as suspects + if ( routingContext.suspectNodes != null && path.priorityclassifier > 20 && currentNode.virgin && path.cost > 2000 && !routingContext.inverseDirection ) + { + int suspectPrio = 0; + if ( nPathPossible == 0 && (!routingContext.foundNodeBlock) ) + { + suspectPrio = path.priorityclassifier; + } + else if ( routingContext.foundWayBlock != 0 ) + { + suspectPrio = routingContext.foundWayBlock; + } + if ( suspectPrio > 20 ) + { + Long id = Long.valueOf( currentNode.getIdFromPos() ); + Integer val = routingContext.suspectNodes.get( id ); + if ( val == null || suspectPrio > val.intValue() ) + { + routingContext.suspectNodes.put( id, Integer.valueOf( suspectPrio ) ); + } + } + } + path.unregisterUpTree( routingContext ); } return null; @@ -1180,7 +1214,7 @@ public class RoutingEngine extends Thread track.buildMap(); // for final track.. - if ( guideTrack != null ) + if ( guideTrack != null && routingContext.turnInstructionMode > 0 ) { track.copyDetours( guideTrack ); track.processVoiceHints( routingContext ); diff --git a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java index 2e2ccd9..f65fd7b 100644 --- a/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java +++ b/brouter-mapaccess/src/main/java/btools/mapaccess/OsmNode.java @@ -39,6 +39,8 @@ public class OsmNode extends OsmLink implements OsmPos * The links to other nodes */ public OsmLink firstlink = null; + + public boolean virgin = true; public OsmNode() { @@ -232,6 +234,8 @@ public class OsmNode extends OsmLink implements OsmPos public final void unlinkLink( OsmLink link ) { + virgin = false; + OsmLink n = link.clear( this ); if ( link == firstlink ) diff --git a/brouter-server/src/main/java/btools/server/BRouter.java b/brouter-server/src/main/java/btools/server/BRouter.java index 0934f68..a49d4ec 100644 --- a/brouter-server/src/main/java/btools/server/BRouter.java +++ b/brouter-server/src/main/java/btools/server/BRouter.java @@ -135,7 +135,7 @@ public class BRouter } - private static OsmNodeNamed readPosition( String[] args, int idx, String name ) + public static OsmNodeNamed readPosition( String[] args, int idx, String name ) { OsmNodeNamed n = new OsmNodeNamed(); n.name = name; diff --git a/brouter-server/src/main/java/btools/server/BadTRDetector.java b/brouter-server/src/main/java/btools/server/BadTRDetector.java new file mode 100644 index 0000000..ea28021 --- /dev/null +++ b/brouter-server/src/main/java/btools/server/BadTRDetector.java @@ -0,0 +1,93 @@ +package btools.server; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import btools.router.OsmNodeNamed; +import btools.router.RoutingContext; +import btools.router.RoutingEngine; + +public class BadTRDetector +{ + public static void main(String[] args) throws Exception + { + System.out.println("BadTRDetector / 15102017 / abrensch"); + if ( args.length < 7 ) + { + System.out.println("Find bad TR candidates in OSM"); + System.out.println("usage: java BadTRDetector "); + return; + } + + int nshots = Integer.parseInt( args[6] ); + boolean findTrs = false; + if ( nshots < 0 ) + { + findTrs = true; + nshots = -nshots; + } + + OsmNodeNamed lowerLeft = BRouter.readPosition( args, 1, "lowerLeft" ); + OsmNodeNamed uppperRight = BRouter.readPosition( args, 3, "uppperRight" ); + + Random rand = new Random(); + Map suspectTRs = new HashMap(); + + + + for( int nshot = 0; nshot < nshots; nshot++ ) + { + OsmNodeNamed n = new OsmNodeNamed(); + n.name = "from"; + n.ilon = lowerLeft.ilon + (int)(rand.nextDouble() * ( uppperRight.ilon - lowerLeft.ilon ) ); + n.ilat = lowerLeft.ilat + (int)(rand.nextDouble() * ( uppperRight.ilat - lowerLeft.ilat ) ); + + // target ca 10km weg + + OsmNodeNamed t = new OsmNodeNamed(); + n.name = "to"; + double dir = rand.nextDouble() + 2. * Math.PI; + t.ilon = n.ilon + (int)( 300000. * Math.sin( dir ) ); + t.ilat = n.ilat + (int)( 200000. * Math.cos( dir ) ); + + List wplist = new ArrayList(); + wplist.add( n ); + wplist.add( t ); + + RoutingContext rc = new RoutingContext(); + rc.localFunction = args[5]; + rc.memoryclass = (int) ( Runtime.getRuntime().maxMemory() / 1024 / 1024 ); + if ( findTrs ) + { + rc.suspectTRs = suspectTRs; + rc.considerTurnRestrictions = false; + } + else + { + rc.suspectNodes = suspectTRs; + } + + RoutingEngine re = new RoutingEngine( "mytrack", "mylog", args[0], wplist, rc ); + re.doRun( 5000 ); + if ( re.getErrorMessage() != null ) + { + System.out.println( re.getErrorMessage() ); + } + } + // write tr-suspects to file + String suspectsFile = "deadend.suspects"; + BufferedWriter bw = new BufferedWriter( new FileWriter( new File( suspectsFile ) ) ); + for( Long suspect : suspectTRs.keySet() ) + { + bw.write( suspect + " " + suspectTRs.get( suspect ) + "\r\n" ); + } + bw.close(); + + } +} diff --git a/brouter-server/src/main/java/btools/server/IssueFilter.java b/brouter-server/src/main/java/btools/server/IssueFilter.java new file mode 100644 index 0000000..594c762 --- /dev/null +++ b/brouter-server/src/main/java/btools/server/IssueFilter.java @@ -0,0 +1,40 @@ +package btools.server; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + + +public class IssueFilter +{ + public static void main(String[] args) throws Exception + { + if ( args.length != 2 ) + { + System.out.println( "usage : IssueFilter " ); + System.exit(1); + } + + BufferedReader br = new BufferedReader( new FileReader( new File( args[0] ) ) ); + BufferedWriter bw = new BufferedWriter( new FileWriter( new File( args[1] ) ) ); + for(;;) + { + String line = br.readLine(); + if ( line == null ) break; + + if ( line.startsWith( "bad TR candidate: " ) ) + { + bw.write( line.substring( "bad TR candidate: ".length() ) ); + bw.write( "\r\n" ); + } + } + br.close(); + bw.close(); + } +} diff --git a/brouter-server/src/main/java/btools/server/IssueSorter.java b/brouter-server/src/main/java/btools/server/IssueSorter.java new file mode 100644 index 0000000..6c373db --- /dev/null +++ b/brouter-server/src/main/java/btools/server/IssueSorter.java @@ -0,0 +1,121 @@ +package btools.server; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.HashSet; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.TreeSet; + + +public class IssueSorter +{ + public static void main(String[] args) throws Exception + { + if ( args.length < 2 ) + { + System.out.println( "usage : IssueSorter []" ); + System.exit(1); + } + + File osmFilter = args.length > 2 ? new File( args[2] ) : null; + + Set filterSet = null; + + // if the osm-filter exists, read it + if ( osmFilter != null && osmFilter.exists() ) + { + filterSet = new HashSet(); + BufferedReader r = new BufferedReader( new FileReader( osmFilter ) ); + for(;;) + { + String line = r.readLine(); + if ( line == null ) break; + int idx0 = line.indexOf( "> keys = new TreeMap>(); + + BufferedReader br = new BufferedReader( new FileReader( new File( args[0] ) ) ); + for(;;) + { + String line = br.readLine(); + if ( line == null ) break; + StringTokenizer tk = new StringTokenizer( line ); + long id = Long.parseLong( tk.nextToken() ); + int prio = Integer.parseInt( tk.nextToken() ); + + if ( filterSet != null && !filterSet.contains( Long.valueOf( id ) ) ) + { + continue; + } + int ilon = (int) ( id >> 32 ); + int ilat = (int) ( id & 0xffffffff ); + + String key = getKey( ilon, ilat ); + TreeMap map = keys.get( key ); + if ( map == null ) + { + map = new TreeMap(); + keys.put( key, map ); + } + map.put( Long.valueOf( id ), Integer.valueOf( prio ) ); + } + br.close(); + + // write suspects to file + BufferedWriter bw = new BufferedWriter( new FileWriter( new File( args[1] ) ) ); + for( String key : keys.keySet() ) + { + TreeMap map = keys.get( key ); + for( Long suspect : map.keySet() ) + { + bw.write( suspect + " " + map.get( suspect ) + "\r\n" ); + } + } + bw.close(); + + // if the osm-filter does not exist, write it + if ( osmFilter != null && !osmFilter.exists() ) + { + bw = new BufferedWriter( new FileWriter( osmFilter ) ); + bw.write( "\n" ); + bw.write( "\n" ); + for( String key : keys.keySet() ) + { + TreeMap map = keys.get( key ); + for( Long suspect : map.keySet() ) + { + long id = suspect.longValue(); + int ilon = (int) ( id >> 32 ); + int ilat = (int) ( id & 0xffffffff ); + double dlon = (ilon-180000000)/1000000.; + double dlat = (ilat-90000000)/1000000.; + bw.write( "\n" ); + } + } + bw.write( "\n" ); + bw.close(); + } + + } + + + public static String getKey( int ilon, int ilat ) + { + int lon = (ilon / 1000000 ); + int lat = (ilat / 1000000 ); + return "" + (100000 + lon*360 + lat); + } +}