Introduce specialization technique for routing. Support avoid features and short way feature

This commit is contained in:
Victor Shcherb 2012-08-18 02:34:02 +02:00
parent e7c60a2a7b
commit 7a715eb931
9 changed files with 119 additions and 35 deletions

View file

@ -159,7 +159,7 @@ public class RouterTestsSuite {
System.err.println("\n\n!! Skipped test case '" + testDescription + "' because 'best_percent' attribute is not specified \n\n" );
return;
}
RoutingContext ctx = new RoutingContext(config.build(vehicle, true));
RoutingContext ctx = new RoutingContext(config.build(vehicle));
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" );

View file

@ -1,5 +1,6 @@
package net.osmand.router;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
@ -11,6 +12,9 @@ import net.osmand.router.BinaryRoutePlanner.RouteSegment;
public class GeneralRouter extends VehicleRouter {
public static final String USE_SHORTEST_WAY = "short_way";
public static final String AVOID_FERRIES = "avoid_ferries";
public static final String AVOID_TOLL = "avoid_toll";
public static final String AVOID_UNPAVED = "avoid_unpaved";
Map<String, Double> highwaySpeed ;
Map<String, Double> highwayPriorities ;
@ -266,12 +270,27 @@ public class GeneralRouter extends VehicleRouter {
}
return 0;
}
private void specialize(String specializationTag, Map<String, Double> m){
ArrayList<String> ks = new ArrayList<String>(m.keySet());
for(String s : ks){
if(s.startsWith(specializationTag +":")) {
m.put(s.substring((specializationTag +":").length()), m.get(s));
}
}
}
@Override
public GeneralRouter specialization(String specializationTag) {
GeneralRouter gr = new GeneralRouter(this);
gr.specialize(specializationTag, gr.highwayFuturePriorities);
gr.specialize(specializationTag, gr.highwayPriorities);
gr.specialize(specializationTag, gr.highwaySpeed);
gr.specialize(specializationTag, gr.avoid);
gr.specialize(specializationTag, gr.obstacles);
return gr;
}
}

View file

@ -53,10 +53,10 @@ public class RoutingConfiguration {
private Map<String, GeneralRouter> routers = new LinkedHashMap<String, GeneralRouter>();
private Map<String, String> attributes = new LinkedHashMap<String, String>();
public RoutingConfiguration build(String router, boolean useShortestWay) {
return build(router, useShortestWay, null);
public RoutingConfiguration build(String router, String... specialization) {
return build(router, null, specialization);
}
public RoutingConfiguration build(String router, boolean useShortestWay, Double direction) {
public RoutingConfiguration build(String router, Double direction, String... specialization) {
if (!routers.containsKey(router)) {
router = defaultRouter;
}
@ -79,8 +79,10 @@ public class RoutingConfiguration {
return i;
}
i.router = routers.get(router);
if(useShortestWay) {
i.router = i.router.specialization(GeneralRouter.USE_SHORTEST_WAY);
if(specialization != null) {
for(String s : specialization) {
i.router = i.router.specialization(s);
}
}
i.routerName = router;
return i;
@ -138,17 +140,20 @@ public class RoutingConfiguration {
DefaultHandler handler = new DefaultHandler() {
String currentSelectedRouter = null;
GeneralRouter currentRouter = null;
String previousKey = null;
String previousTag = null;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
String name = parser.isNamespaceAware() ? localName : qName;
if("osmand_routing_config".equals(name)) {
config.defaultRouter = attributes.getValue("defaultProfile");
} else if("attribute".equals(name)) {
String key = attributes.getValue("name");
if(currentSelectedRouter != null) {
key = currentSelectedRouter +"$"+key;
previousKey = attributes.getValue("name");
previousTag = name;
if (currentSelectedRouter != null) {
previousKey = currentSelectedRouter + "$" + previousKey;
}
config.attributes.put(key, attributes.getValue("value"));
config.attributes.put(previousKey, attributes.getValue("value"));
} else if("routingProfile".equals(name)) {
currentSelectedRouter = attributes.getValue("name");
Map<String, String> attrs = new LinkedHashMap<String, String>();
@ -157,26 +162,55 @@ public class RoutingConfiguration {
}
currentRouter = new GeneralRouter(GeneralRouterProfile.valueOf(attributes.getValue("baseProfile").toUpperCase()), attrs);
config.routers.put(currentSelectedRouter, currentRouter);
} else if ("specialization".equals(name)) {
String in = attributes.getValue("input");
if (previousKey != null) {
String k = in + ":" + previousKey;
if (attributes.getValue("penalty") != null) {
currentRouter.obstacles.put(k, parseSilentDouble(attributes.getValue("penalty"), 0));
}
if (attributes.getValue("priority") != null) {
currentRouter.highwayPriorities.put(k, parseSilentDouble(attributes.getValue("priority"), 0));
}
if (attributes.getValue("dynamicPriority") != null) {
currentRouter.highwayFuturePriorities.put(k, parseSilentDouble(attributes.getValue("dynamicPriority"), 0));
}
if (attributes.getValue("speed") != null) {
currentRouter.highwaySpeed.put(k, parseSilentDouble(attributes.getValue("speed"), 0));
}
if ("avoid".equals(previousTag)) {
double priority = parseSilentDouble(attributes.getValue("decreasedPriority"), 0);
if (priority == 0) {
currentRouter.avoid.put(k, priority);
} else {
currentRouter.highwayPriorities.put(k, priority);
}
}
}
} else if("road".equals(name)) {
String key = attributes.getValue("tag") +"$" + attributes.getValue("value");
currentRouter.highwayPriorities.put(key, parseSilentDouble(attributes.getValue("priority"),
previousTag = name;
previousKey = attributes.getValue("tag") +"$" + attributes.getValue("value");
currentRouter.highwayPriorities.put(previousKey, parseSilentDouble(attributes.getValue("priority"),
1));
currentRouter.highwayFuturePriorities.put(key, parseSilentDouble(attributes.getValue("dynamicPriority"),
currentRouter.highwayFuturePriorities.put(previousKey, parseSilentDouble(attributes.getValue("dynamicPriority"),
1));
currentRouter.highwaySpeed.put(key, parseSilentDouble(attributes.getValue("speed"),
currentRouter.highwaySpeed.put(previousKey, parseSilentDouble(attributes.getValue("speed"),
10));
} else if("obstacle".equals(name)) {
String key = attributes.getValue("tag") + "$" + attributes.getValue("value");
currentRouter.obstacles.put(key, parseSilentDouble(attributes.getValue("penalty"),
previousTag = name;
previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value");
currentRouter.obstacles.put(previousKey, parseSilentDouble(attributes.getValue("penalty"),
0));
} else if("avoid".equals(name)) {
String key = attributes.getValue("tag") + "$" + attributes.getValue("value");
previousTag = name;
previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value");
double priority = parseSilentDouble(attributes.getValue("decreasedPriority"),
0);
if(priority == 0) {
currentRouter.avoid.put(key, priority);
currentRouter.avoid.put(previousKey, priority);
} else {
currentRouter.highwayPriorities.put(key, priority);
currentRouter.highwayPriorities.put(previousKey, priority);
}
}
}

View file

@ -59,22 +59,35 @@
<road tag="highway" value="tertiary" speed="45" priority="1" dynamicPriority="0.9"/>
<road tag="highway" value="tertiary_link" speed="40" priority="1" dynamicPriority="0.9"/>
<!-- lowest form of grid network, usually 90% of urban roads -->
<road tag="highway" value="unclassified" speed="35" priority="0.7" dynamicPriority="0.7"/>
<road tag="highway" value="unclassified" speed="35" priority="0.7" dynamicPriority="0.7">
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
</road>
<!-- road = no type, no review and may be not accurate -->
<road tag="highway" value="road" speed="35" priority="0.7" dynamicPriority="0.7"/>
<road tag="highway" value="road" speed="35" priority="0.7" dynamicPriority="0.7">
<specialization input="short_way" priority="1" speed="45"/>
</road>
<!-- primarily for access to properties, small roads with 1/2 intersections -->
<road tag="highway" value="residential" speed="35" priority="0.7" dynamicPriority="0.7"/>
<road tag="highway" value="residential" speed="35" priority="0.7" dynamicPriority="0.7">
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
</road>
<!-- parking + private roads -->
<road tag="highway" value="service" speed="30" priority="0.5" dynamicPriority="0.5"/>
<road tag="highway" value="service" speed="30" priority="0.5" dynamicPriority="0.5">
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
</road>
<!-- very bad roads -->
<road tag="highway" value="track" speed="15" priority="0.3" dynamicPriority="0.5"/>
<road tag="highway" value="track" speed="15" priority="0.3" dynamicPriority="0.5">
<specialization input="short_way" priority="0.7" speed="45" dynamicPriority="0.7" />
<specialization input="avoid_unpaved" priority="0.1"/>
</road>
<!-- too small for cars usually -->
<road tag="highway" value="living_street" speed="25" priority="0.5" dynamicPriority="0.5"/>
<road tag="highway" value="living_street" speed="25" priority="0.5" dynamicPriority="0.5">
<specialization input="short_way" priority="1" dynamicPriority="1" speed="35"/>
</road>
<!-- car are able to enter in highway=pedestrian with restrictions -->
<!-- Time actually is uknown. Currently unsupported -->
<road tag="route" value="ferry" speed="15" priority="1.0" dynamicPriority="0.7">
<!-- <specialization input="avoid_ferries" speed="0"/> -->
<specialization input="avoid_ferries" speed="0"/>
</road>
<obstacle tag="highway" value="traffic_signals" penalty="30"/>
@ -89,7 +102,9 @@
<avoid tag="access" value="no"/>
<avoid tag="motorcycle" value="no"/>
<avoid tag="motorcar" value="no"/>
<!-- <avoid tag="toll" value="yes"/> -->
<avoid tag="toll" value="yes" decreasedPriority="1">
<specialization input="avoid_toll"/>
</avoid>
</routingProfile>

View file

@ -160,7 +160,7 @@ public class DataExtractionSettings {
public String getRouteMode(){
return preferences.get("routeMode", "car");
return preferences.get("routeMode", "car,short_way");
}
public void setRouteMode(String mode){

View file

@ -597,8 +597,9 @@ public class MapRouterLayer implements MapPanelLayer {
rs[it++] = new BinaryMapIndexReader(raf, false);
}
String m = DataExtractionSettings.getSettings().getRouteMode();
String[] props = m.split("\\,");
BinaryRoutePlanner router = new BinaryRoutePlanner(NativeSwingRendering.getDefaultFromSettings(), rs);
RoutingConfiguration config = builder.build(m, true);
RoutingConfiguration config = builder.build(props[0], props);
RoutingContext ctx = new RoutingContext(config);
ctx.previouslyCalculatedRoute = previousRoute;
log.info("Use " + config.routerName + "mode for routing");

View file

@ -140,7 +140,7 @@ public class OsmExtractionPreferencesDialog extends JDialog {
constr.gridy = gridY++;
l.setConstraints(nativeFilesDirectory, constr);
label = new JLabel("Routing mode (car/bicycle/pedestrian) : ");
label = new JLabel("Routing (car|bicycle|pedestrian,[short_way],[avoid_ferries]...) : ");
panel.add(label);
constr = new GridBagConstraints();
constr.ipadx = 5;

View file

@ -37,6 +37,7 @@ import net.osmand.plus.activities.ApplicationMode;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.router.BinaryRoutePlanner;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import net.osmand.router.GeneralRouter;
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
import net.osmand.router.Interruptable;
import net.osmand.router.RouteSegmentResult;
@ -167,7 +168,7 @@ public class RouteProvider {
if(previousToRecalculate != null) {
originalRoute = previousToRecalculate.getOriginalRoute();
}
res = findVectorMapsRoute(start, end, mode, fast, (OsmandApplication)ctx.getApplicationContext(), originalRoute, leftSide, interruptable);
res = findVectorMapsRoute(start, end, mode, (OsmandApplication)ctx.getApplicationContext(), originalRoute, leftSide, interruptable);
} else {
res = findCloudMadeRoute(start, end, mode, ctx, fast, leftSide);
}
@ -307,7 +308,7 @@ public class RouteProvider {
return new RouteCalculationResult(res, null, start, end, null, ctx, leftSide, true);
}
protected RouteCalculationResult findVectorMapsRoute(Location start, LatLon end, ApplicationMode mode, boolean fast, OsmandApplication app,
protected RouteCalculationResult findVectorMapsRoute(Location start, LatLon end, ApplicationMode mode, OsmandApplication app,
List<RouteSegmentResult> previousRoute,
boolean leftSide, Interruptable interruptable) throws IOException {
BinaryMapIndexReader[] files = app.getResourceManager().getRoutingMapFiles();
@ -332,7 +333,21 @@ public class RouteProvider {
} else {
p = GeneralRouterProfile.CAR;
}
RoutingContext ctx = new RoutingContext(config.build(p.name().toLowerCase(), !fast, start.hasBearing() ? start.getBearing() / 180d * Math.PI : null));
List<String> specs = new ArrayList<String>();
if (!app.getSettings().FAST_ROUTE_MODE.get()) {
specs.add(GeneralRouter.USE_SHORTEST_WAY);
}
if(app.getSettings().AVOID_FERRIES.get()){
specs.add(GeneralRouter.AVOID_FERRIES);
}
if(app.getSettings().AVOID_TOLL_ROADS.get()){
specs.add(GeneralRouter.AVOID_TOLL);
}
if(app.getSettings().AVOID_UNPAVED_ROADS.get()){
specs.add(GeneralRouter.AVOID_UNPAVED);
}
String[] specialization = specs.toArray(new String[specs.size()]);
RoutingContext ctx = new RoutingContext(config.build(p.name().toLowerCase(), start.hasBearing() ? start.getBearing() / 180d * Math.PI : null, specialization));
ctx.interruptable = interruptable;
ctx.previouslyCalculatedRoute = previousRoute;
RouteSegment st= router.findRouteSegment(start.getLatitude(), start.getLongitude(), ctx);

View file

@ -539,7 +539,6 @@ public class RoutingHelper {
private final GPXRouteParams gpxRoute;
private final RouteCalculationResult previousRoute;
private RouteService service;
private boolean fastRoute;
private boolean interrupted = false;
public RouteRecalculationThread(String name,
@ -550,7 +549,7 @@ public class RoutingHelper {
this.gpxRoute = gpxRoute;
this.previousRoute = previousRoute;
service = settings.ROUTER_SERVICE.get();
fastRoute = settings.FAST_ROUTE_MODE.get();
}
public void stopCalculation(){
@ -565,6 +564,7 @@ public class RoutingHelper {
@Override
public void run() {
boolean leftSide = settings.LEFT_SIDE_NAVIGATION.get();
boolean fastRoute = settings.FAST_ROUTE_MODE.get();
RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service, context, gpxRoute, previousRoute, fastRoute,
leftSide, this);
if (interrupted) {