Tuesday 24 December 2019

openstreetmap - calculate costs based on way difficulty


I am using Osm2Po to find routes between two points.


I am trying to find routes based on the difficulty specified by the user.


Basically, I would like to calculate the cost based on some parameter in the way. For now this parameter could be the type of road e.g. if its a primary road the cost would increase. If it was a secondary road it the cost would decrease especially. Any road with a cyclelane would have the best cost.


I have been looking into overriding the DefaultRouter methods: traverse, findpath and calcEdgeCost.


I was thinking that I could get the clazz type from the edge being currently examined and set its cost using calcEdgeCost.


One problem is that for some reason calling getVertexClazzes returns nothing but zeroes. getEdgeFlags returns null.


Here is part of my osm2po.config which might be relevant


#wayTagResolver.class = com.to.another.package.YourWayTagResolver

#nodeTagResolver.class = com.to.another.package.YourNodeTagResolver
#relationTagResolver.class = com.to.another.package.YourRelationTagResolver


# Properties of the DefaultWayTagResolver use this prefix.
wayTagResolver.prefix = wtr

# Custom flags with ascending binary values 1, 2, 4, 8 ...
# You may define up to 32 Flags (Bits).
wtr.flagList = car, bike, foot, rail, ferry

# final decision; only allow ways with these flags

wtr.finalMask = bike

# very special hint for level_crossing modification
wtr.shuttleTrainMask = rail|car

# Main-Tag definitions. Params 1-4:
# 1) concurrent order
# 2) class (1-127)
# 3) default speed in kmh
# 4) allowed transportation type (optional) - since v4.5.30


wtr.tag.highway.motorway = 1, 11, 120, car
wtr.tag.highway.motorway_link = 1, 12, 30, car
wtr.tag.highway.trunk = 1, 13, 90, car
wtr.tag.highway.trunk_link = 1, 14, 30, car
wtr.tag.highway.primary = 1, 15, 15, car|bike
wtr.tag.highway.primary_link = 1, 16, 30, car
wtr.tag.highway.secondary = 1, 21, 15, car|bike
wtr.tag.highway.secondary_link = 1, 22, 15, car|bike
wtr.tag.highway.tertiary = 1, 31, 12, car|bike

wtr.tag.highway.residential = 1, 32, 12, car|bike
wtr.tag.highway.road = 1, 41, 14, car|bike
wtr.tag.highway.unclassified = 1, 42, 12, car|bike
wtr.tag.highway.service = 1, 51, 5, car|bike
wtr.tag.highway.living_street = 1, 63, 7, car|bike|foot
wtr.tag.highway.pedestrian = 1, 62, 5, bike|foot
wtr.tag.highway.track = 1, 71, 10, bike|foot
wtr.tag.highway.path = 1, 72, 10, bike|foot
wtr.tag.highway.cycleway = 1, 81, 15, bike
#wtr.tag.highway.footway = 1, 91, 5, foot

#wtr.tag.highway.steps = 1, 92, 5, foot
wtr.tag.route.ferry = 2, 01, 10, ferry
wtr.tag.route.shuttle_train = 2, 02, 50, rail|car
wtr.tag.railway.rail = 3, 03, 50, rail

Answer



There are two aproaches. So, firstly decide whether you need static or dynamic data. For the latter it is necessary to overwrite the Java-API. I think this is a static problem, meaning, the costs can be precalculated.


What you need is a different configuration. In your scenario the speed is never used. So why not regarding it as "your" costs. And if I see it correcly, you have already tried to follow this idea. Let's suppose you're going to prefer cycleways to tertiaries:


wtr.finalMask=bike

wtr.tag.highway.tertiary = 1, 1, 10, bike

wtr.tag.highway.cycleway = 1, 2, 20, bike

wtr.maxSpeedOverrides=false

if maxSpeedOverrides is not set to false osm2po overrides the configured speed values (10, 20) with OSM's maxSpeed-tag-value if given.


As for the technical questions:


The graph.getVertexClazzes() method returns an array of user defined special flags/ids for nodes. 0 means that there is nothing special. A good example of how to use this array can be found in the osm2po plugins' sources. Search for Traffic-Signals.


Nevertheless, you actually need graph.getEdgeFlags() in order to receive street type infos. It's another array which can be populated with user defined 32-bit-integers. You can intercept the generation of these values by overwriting/injecting/configuring your own GraphBuildInterceptor. The "DefaultGraphBuildInterceptor" just copies the kmh and street-type(clazz) into the graph file while running osm2po with cmd=g (GraphBuild-Phase).


A return value of null means, that it is not needed and hence not cached by the graph-constructor. But there is a second constructor which lets you fine tune which addition you want. There are several consts, each starting with SUPPORTS. In your case graph.isSupported(SUPPORT_EDGEFLAGS) will return false. And finally, here is the constructor which includes vertex-coordinates and street-types/flags:


new Graph(graphFile, new Log(), Graph.SUPPORT_LATLON | Graph.SUPPORT_EDGEFLAGS);


By the way: The supported-flags can also be found the config. e.g.:


graph.support.edgeflags = true

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...