Improve routing! Fix issue 576. Fix issue with some skipped restrictions, fix turn calculation time, add specific test case

This commit is contained in:
Victor Shcherb 2011-08-14 18:41:25 +02:00
parent dd829d8a95
commit 81c1ad9a34
8 changed files with 125 additions and 49 deletions

View file

@ -26,9 +26,11 @@ import org.apache.commons.logging.Log;
public class BinaryRoutePlanner {
private final static boolean PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true;
private final int REVERSE_WAY_RESTRICTION_ONLY = 1024;
private final BinaryMapIndexReader[] map;
private static final Log log = LogUtil.getLog(BinaryRoutePlanner.class);
public BinaryRoutePlanner(BinaryMapIndexReader... map){
@ -393,7 +395,7 @@ public class BinaryRoutePlanner {
private RouteSegment processIntersectionsWithWays(RoutingContext ctx, PriorityQueue<RouteSegment> graphSegments,
TLongObjectHashMap<RouteSegment> visitedSegments, TLongObjectHashMap<RouteSegment> oppositeSegments,
double distOnRoadToPass, double distToFinalPoint,
RouteSegment segment, BinaryMapDataObject road, boolean firstOfSegment, int segmentEnd, RouteSegment next,
RouteSegment segment, BinaryMapDataObject road, boolean firstOfSegment, int segmentEnd, RouteSegment inputNext,
boolean reverseWay) {
// This variables can be in routing context
@ -406,7 +408,7 @@ public class BinaryRoutePlanner {
// 3.1 calculate time for obstacles (bumps, traffic_signals, level_crossing)
if (firstOfSegment) {
RouteSegment possibleObstacle = next;
RouteSegment possibleObstacle = inputNext;
while (possibleObstacle != null) {
obstaclesTime += ctx.getRouter().defineObstacle(possibleObstacle.road, possibleObstacle.segmentStart);
possibleObstacle = possibleObstacle.next;
@ -415,6 +417,7 @@ public class BinaryRoutePlanner {
// 3.2 calculate possible ways to put into priority queue
// for debug next.road.getId() >> 1 == 33911427 && road.getId() >> 1 == 33911442
RouteSegment next = inputNext;
while (next != null) {
long nts = (next.road.getId() << 8l) + next.segmentStart;
boolean oppositeConnectionFound = oppositeSegments.containsKey(nts) && oppositeSegments.get(nts) != null;
@ -428,7 +431,7 @@ public class BinaryRoutePlanner {
}
}
/* next.road.getId() >> 3 (1) != road.getId() >> 1 (3) - used that line for debug with osm map */
/* next.road.getId() >> 1 (3) != road.getId() >> 1 (3) - used that line for debug with osm map */
// road.id could be equal on roundabout, but we should accept them
if ((!visitedSegments.contains(nts) && processRoad) || oppositeConnectionFound) {
int type = -1;
@ -445,9 +448,24 @@ public class BinaryRoutePlanner {
type = next.road.getRestrictionType(i);
break;
}
// Check if there is restriction only to the current road
if (next.road.getRestrictionType(i) == MapRenderingTypes.RESTRICTION_ONLY_RIGHT_TURN
|| next.road.getRestrictionType(i) == MapRenderingTypes.RESTRICTION_ONLY_LEFT_TURN
|| next.road.getRestrictionType(i) == MapRenderingTypes.RESTRICTION_ONLY_STRAIGHT_ON) {
// check if that restriction applies to considered junk
RouteSegment foundNext = inputNext;
while(foundNext != null && foundNext.getRoad().getId() != next.road.getRestriction(i)){
foundNext = foundNext.next;
}
if(foundNext != null) {
type = REVERSE_WAY_RESTRICTION_ONLY; // special constant
}
}
}
}
if (type == -1 && exclusiveRestriction) {
if(type == REVERSE_WAY_RESTRICTION_ONLY){
// next = next.next; continue;
} else if (type == -1 && exclusiveRestriction) {
// next = next.next; continue;
} else if (type == MapRenderingTypes.RESTRICTION_NO_LEFT_TURN || type == MapRenderingTypes.RESTRICTION_NO_RIGHT_TURN
|| type == MapRenderingTypes.RESTRICTION_NO_STRAIGHT_ON || type == MapRenderingTypes.RESTRICTION_NO_U_TURN) {
@ -479,7 +497,8 @@ public class BinaryRoutePlanner {
// add obstacles time
distanceFromStart += obstaclesTime;
// segment.getRoad().getId() >> 1
if (next.parentRoute == null
|| ctx.roadPriorityComparator(next.distanceFromStart, next.distanceToEnd, distanceFromStart, distanceToEnd) > 0) {
next.distanceFromStart = distanceFromStart;
@ -496,9 +515,16 @@ public class BinaryRoutePlanner {
segmentsToVisitNotForbidden.add(next);
} else {
// case exclusive restriction (only_right, only_straight, ...)
exclusiveRestriction = true;
segmentsToVisitNotForbidden.clear();
segmentsToVisitPrescripted.add(next);
// 1. in case we are going backward we should not consider only_restriction
// as exclusive because we have main "in" roads and one "out"
// 2. in case we are going forward we have one "in" and many "out"
if (!reverseWay) {
exclusiveRestriction = true;
segmentsToVisitNotForbidden.clear();
segmentsToVisitPrescripted.add(next);
} else {
segmentsToVisitNotForbidden.add(next);
}
}
}

View file

@ -166,23 +166,46 @@ public class CarRouter extends VehicleRouter {
public double getMaxDefaultSpeed() {
return 30;
}
private double directionRoute(RouteSegment segment, int segmentEnd, boolean opp){
boolean plus = segmentEnd == 0;
int x = segment.road.getPoint31XTile(segmentEnd);
int y = segment.road.getPoint31YTile(segmentEnd);
int nx = segmentEnd;
int px = x;
int py = y;
do {
if(plus){
nx++;
if(nx >= segment.road.getPointsLength()){
break;
}
} else {
nx--;
if(nx < 0){
break;
}
}
px = segment.road.getPoint31XTile(nx);
py = segment.road.getPoint31YTile(nx);
} while(Math.abs(px - x) + Math.abs(py - y) < 100);
if(opp){
return Math.atan2(py - y, px - x);
} else {
return Math.atan2(y - py, x - px);
}
}
public double calculateTurnTime(RouteSegment segment, RouteSegment next, int segmentEnd) {
boolean end = (segmentEnd == segment.road.getPointsLength() - 1 || segmentEnd == 0);
boolean start = next.segmentStart == 0;
boolean start = next.segmentStart == 0 || next.segmentStart == next.getRoad().getPointsLength() - 1;
// that addition highly affects to trunk roads !(prefer trunk/motorway)
if (end && start) {
// next.road.getId() >> 1 != segment.road.getId() >> 1
if (next.road.getPointsLength() > 1) {
int x = segment.road.getPoint31XTile(segmentEnd);
int y = segment.road.getPoint31XTile(segmentEnd);
int prevSegmentEnd = segmentEnd - 1;
if(prevSegmentEnd < 0){
prevSegmentEnd = segmentEnd + 1;
}
int px = segment.road.getPoint31XTile(prevSegmentEnd);
int py = segment.road.getPoint31XTile(prevSegmentEnd);
double a1 = Math.atan2(y - py, x - px);
double a2 = Math.atan2(y - next.road.getPoint31YTile(1), x - next.road.getPoint31XTile(1));
double a1 = directionRoute(segment, segmentEnd, false);
double a2 = directionRoute(next, next.segmentStart, true);
double diff = Math.abs(a1 - a2);
if (diff > Math.PI / 2 && diff < 3 * Math.PI / 2) {
return 25;

View file

@ -25,6 +25,7 @@ public class RoutingContext {
private Boolean planRoadDirection = null;
private VehicleRouter router = new CarRouter();
private boolean useDynamicRoadPrioritising = true;
// not used right now
private boolean usingShortestWay = false;

View file

@ -38,6 +38,7 @@ public class RouterTestsSuite {
properties.load(RouterTestsSuite.class.getResourceAsStream("sources.properties"));
boolean allSuccess = true;
allSuccess &= test("belarus_test.xml", properties);
allSuccess &= test("germany_test.xml", properties);
if (allSuccess) {
System.out.println("All is successfull");
}
@ -81,6 +82,12 @@ public class RouterTestsSuite {
RoutingContext ctx = new RoutingContext();
String vehicle = testCase.getAttribute("vehicle");
String testDescription = testCase.getAttribute("description");
String skip = testCase.getAttribute("skip_comment");
if (skip != null && skip.length() > 0) {
System.err.println("\n\n!! Skipped test case '" + testDescription + "' because '" + skip + "'\n\n" );
return;
}
if("bicycle".equals(vehicle)){
ctx.setRouter(new BicycleRouter());
} else if("pedestrian".equals(vehicle)){

View file

@ -20,31 +20,33 @@
</test>
<test regions="belarus" description="MINSK (restriction + roundabout)" best_percent="80" vehicle="car" start_lat="53.91051937749127"
start_lon="27.57667064666748" target_lat="53.91098072030288" target_lon="27.579095363616943">
<segment id="99472425" start="2" end="4" name="null" />
<segment id="33542962" start="3" end="2" name="null" />
<segment id="33911466" start="1" end="4" name="просп. Машерова" />
<segment id="33911427" start="0" end="1" name="null" />
<segment id="25441562" start="0" end="7" name="ул. Козлова" />
<segment id="61594238" start="0" end="2" name="null" />
<segment id="25228310" start="0" end="6" name="null" />
<segment id="61594235" start="0" end="6" name="null" />
<segment id="61594239" start="0" end="1" name="null" />
<segment id="25228312" start="0" end="7" name="ул. Козлова" />
<segment id="33911443" start="0" end="1" name="просп. Независимости" />
<segment id="31691782" start="0" end="2" name="null" />
<segment id="40885457" start="0" end="1" name="null" />
<segment id="40885456" start="0" end="1" name="null" />
<segment id="40885459" start="2" end="3" name="null" />
<segment id="99472425" start="1" end="0" name="null"/>
<segment id="99472427" start="1" end="0" name="null"/>
<segment id="33542963" start="0" end="2" name="null"/>
<segment id="33971851" start="4" end="7" name="ул. Киселёва"/>
<segment id="25228576" start="0" end="5" name="null"/>
<segment id="65073371" start="0" end="4" name="просп. Независимости"/>
<segment id="38028210" start="0" end="8" name="Победы пл."/>
<segment id="25228575" start="0" end="4" name="просп. Независимости"/>
<segment id="65073390" start="0" end="4" name="просп. Независимости"/>
<segment id="65073385" start="0" end="1" name="просп. Независимости"/>
<segment id="25228294" start="0" end="8" name="просп. Независимости"/>
<segment id="33911442" start="0" end="1" name="просп. Независимости"/>
<segment id="33911443" start="0" end="1" name="просп. Независимости"/>
<segment id="31691782" start="0" end="2" name="null"/>
<segment id="40885457" start="0" end="1" name="null"/>
<segment id="40885456" start="0" end="1" name="null"/>
<segment id="40885459" start="2" end="3" name="null"/>
</test>
<test regions="belarus" description="Minsk (roundabout + restriction on it)" best_percent="75" vehicle="car" start_lat="53.90941971791074"
start_lon="27.494959831237793" target_lat="53.9104182605777" target_lon="27.495667934417725">
<segment id="30821138" start="0" end="4" name="null" />
<segment id="30821157" start="0" end="1" name="null" />
<segment id="30821161" start="0" end="4" name="null" />
<segment id="30821165" start="0" end="1" name="null" />
<segment id="30821143" start="0" end="4" name="null" />
<segment id="30821192" start="0" end="1" name="просп. Пушкина" />
<segment id="30821138" start="0" end="4" name="null"/>
<segment id="30821157" start="0" end="1" name="null"/>
<segment id="30821198" start="0" end="1" name="null"/>
<segment id="48470184" start="0" end="1" name="null"/>
<segment id="48470183" start="0" end="1" name="null"/>
<segment id="30821192" start="0" end="1" name="просп. Пушкина"/>
</test>
<test regions="belarus" description="Straight forward way" best_percent="95" vehicle="car" start_lat="53.9202" start_lon="27.5877"
target_lat="53.938582493008525" target_lon="27.605509757995605">
@ -63,9 +65,10 @@
<segment id="50727963" start="0" end="1" name="ул. Якуба Коласа" />
</test>
<test regions="belarus" description="Well known route" best_percent="60" vehicle="car"
start_lat="53.9113" start_lon="27.5795" target_lat="53.95386"
target_lon="27.68131">
target_lon="27.68131" skip_comment="Not work right now">
<segment id="40885456" start="1" end="5" name="null" />
<segment id="40885455" start="0" end="4" name="null" />
<segment id="37975292" start="2" end="4" name="Краснозвездная ул." />

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<router_tests>
<test regions="GERMANY_NIEDERSACHSEN" description="Straight on path" best_percent="100"
start_lat="53.32488825137637" start_lon="10.339593887329102" target_lat="53.34719536968702" target_lon="10.335710048675537">
<segment id="56018104" start="4" end="0" name=" B 404"/>
<segment id="56017053" start="1" end="0" name=" B 404"/>
<segment id="4310175" start="1" end="0" name=" B 404"/>
<segment id="25706717" start="1" end="0" name=" B 404"/>
<segment id="56017055" start="1" end="0" name=" B 404"/>
<segment id="56018105" start="1" end="0" name=" B 404"/>
<segment id="31322780" start="6" end="2" name=" B 404"/>
</test>
</router_tests>

View file

@ -1,5 +1,6 @@
BELARUS = /home/victor/projects/OsmAnd/data/osmand_index/Belarus.obf
NETHERLANDS = /home/victor/projects/OsmAnd/data/osmand_index/Netherlands_europe.obf
GERMANY_NIEDERSACHSEN = /home/victor/projects/OsmAnd/data/osmand_index/Germany_niedersachsen_europe_1.obf
# Not used for now
DENMARK =/home/victor/projects/OsmAnd/data/osmand_index/Denmark_europe.obf
GERMANY_BAYERN = /home/victor/projects/OsmAnd/data/osmand_index/Germany_bayern_europe_1.obf
GERMANY_BAYERN = /home/victor/projects/OsmAnd/data/osmand_index/Germany_bayern_europe_1.obf

View file

@ -48,16 +48,16 @@ import org.xml.sax.SAXException;
public class MapRouterLayer implements MapPanelLayer {
private /*final */ static boolean ANIMATE_CALCULATING_ROUTE = false;
private /*final */ static int SIZE_OF_ROUTES_TO_ANIMATE = 50;
private /*final */ static boolean ANIMATE_CALCULATING_ROUTE = true;
private /*final */ static int SIZE_OF_ROUTES_TO_ANIMATE = 1;
private MapPanel map;
private LatLon startRoute;
private LatLon endRoute;
// private LatLon startRoute;
// private LatLon endRoute;
// test route purpose
// private LatLon startRoute = new LatLon(53.910886,27.579095);
// private LatLon endRoute = new LatLon(53.95386,27.68131);
private LatLon startRoute = new LatLon(53.9113, 27.5795);
private LatLon endRoute = new LatLon(53.95386, 27.68131);
@Override
@ -349,6 +349,7 @@ public class MapRouterLayer implements MapPanelLayer {
BinaryRoutePlanner router = new BinaryRoutePlanner(rs);
RoutingContext ctx = new RoutingContext();
// ctx.setPlanRoadDirection(true);
// find closest way
RouteSegment st = router.findRouteSegment(start.getLatitude(), start.getLongitude(), ctx);
@ -411,7 +412,7 @@ public class MapRouterLayer implements MapPanelLayer {
List<RouteSegmentResult> searchRoute = router.searchRoute(ctx, st, e);
if (ANIMATE_CALCULATING_ROUTE) {
try {
Thread.sleep(4000);
Thread.sleep(2000);
} catch (InterruptedException e1) {
}
}