Improve routing! Fix issue 576. Fix issue with some skipped restrictions, fix turn calculation time, add specific test case
This commit is contained in:
parent
dd829d8a95
commit
81c1ad9a34
8 changed files with 125 additions and 49 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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)){
|
||||
|
|
|
@ -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="Краснозвездная ул." />
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue