nrenner / brouter-web

Web client for BRouter, a routing engine based on OpenStreetMap
https://brouter.de/brouter-web/
MIT License
360 stars 68 forks source link

Permalinks with custom profiles #26

Open poutnikl opened 9 years ago

poutnikl commented 9 years ago

Would be possible to refer the cached profile in Permalink similarly as in CSV URL, and eventually fallback to Trekking one when cache expires ?

BTW, what is cache retention of custom profile ?

I have noticed the CSV download links contains URL reference to used cached custom profile

http://h2096617.stratoserver.net:443/brouter?lonlats=17.125454,48.843028|17.215233,48.842463&nogos=&profile=custom_1438472332376&alternativeidx=0&format=gpx

But Permalinks do not.

http://brouter.de/brouter-web/#zoom=13&lat=48.8389&lon=17.1572&layer=OpenStreetMap&lonlats=17.125454,48.843028|17.215233,48.842463&nogos=&alternativeidx=0&format=geojson

I suppose reason is obvious - The profile is cached just temporarily and will not be permanently available to Permalink. But the drawback for that is, that Permalink presented route does not follow the custom profile, but default Trekking profile, so author and recipient of Permalink will see 2 different routes.

I suppose this could be eventually addressed in later BR web versions with feature of saving / restoring / sharing of profiles

matkoniecz commented 9 years ago

duplicate of #9?

poutnikl commented 9 years ago

Partially. as it would address temporary status of the profiles. But when feature of saving / restoring / sharing of profiles is implemented both issues will be addressed.

nrenner commented 9 years ago

The custom profile is not included in the Permalink on purpose. The point is rather not to take responsibility for user content. And a permanent link on temporary content would give the wrong impression.

I don't know what the cache retention of custom profiles is, the server is managed by Arndt.

Sharing a Permalink with a custom profile active is indeed misleading and a drawback right now. I hope this will be either solved with #9, or there should at least be a warning - e.g. to first export the profile - so I leave this issue open.

poutnikl commented 9 years ago

The intention was to have Permalink right at least temporarily e.g. for online discussion with people not aware about such things like custom profiles. I just guess the profile is cached while I am working with it, and if during that that time I would provide some link........

:-) Perhaps, there should be available another link - "Tempolink" :-)

But I guess incoming promised profile features will address much of that by their own way. Perhaps saved and shared profiled will be able to be referenced in Permalinks in 0.6.0+ versions. I am looking forward to it.

HankyPanky19 commented 5 years ago

Hi, there is no profile with consider_elevation=false stick_to_cycleroutes=true Since I often use that setting I would prefer to have "any way" to change profile at the beginning of a session. I'm tired to change and upload the "trecking" profile again and again at session startup...

I'm using brouter web-client very frequently and by far (!!!) it provides the best routing engine to me! Many thanks for your continued support and efforts!

bagage commented 5 years ago

Until this issue is implemented, I can add it on https://brouter.damsy.net. Please provide me the profile's content and its name and I'll add it next to mtb/mtb2/trekking-no-path profiles.

HankyPanky19 commented 5 years ago

I always take the generic "trekking bike" profile and change both assignements: consider_elevation=false # elevation is less important if we want to follow cycleroutes stick_to_cycleroutes=true # follow cycleroutes If you like you can assign a name similar to the other names: Trekking bike (prefer cycleroutes)

Since I'm no expert of brouter engine and its profile parameter, I'm not sure whether there are additional parameters which might be changed to lead to better results for following cycleroutes.

# Trekking bike (prefer cycleroutes)
# *** The trekking profile is for slow travel
# *** and avoiding car traffic, but still with
# *** a focus on approaching your destination
# *** efficiently.

---context:global   # following code refers to global config

# Use the following switches to change behaviour
# (1=yes, 0=no):

assign   consider_elevation   = false  # set to false to ignore elevation in routing
assign   allow_steps          = true   # set to false to disallow steps
assign   allow_ferries        = true   # set to false to disallow ferries
assign   ignore_cycleroutes   = false  # set to true for better elevation results
assign   stick_to_cycleroutes = true   # set to true to just follow cycleroutes
assign   avoid_unsafe         = false  # set to true to avoid standard highways
assign   turnInstructionMode  = 1  # 0=none, 1=auto-choose, 2=locus-style, 3=osmand-style

assign   validForBikes        = true

# the elevation parameters

assign downhillcost    = if consider_elevation then 60 else 0
assign downhillcutoff  = 1.5
assign uphillcost      = 0
assign uphillcutoff    = 1.5

# classifier constants

assign classifier_none     = 1
assign classifier_ferry    = 2

---context:way   # following code refers to way-tags

#
# pre-calculate some logical expressions
#

assign any_cycleroute =
     if      route_bicycle_icn=yes then true
     else if route_bicycle_ncn=yes then true
     else if route_bicycle_rcn=yes then true
     else if route_bicycle_lcn=yes then true
     else false

assign nodeaccessgranted =
     if any_cycleroute then true
     else lcn=yes

assign is_ldcr =
     if ignore_cycleroutes then false
     else any_cycleroute

assign isbike = or bicycle=yes or or bicycle=permissive bicycle=designated lcn=yes
assign ispaved = surface=paved|asphalt|concrete|paving_stones
assign isunpaved = not or surface= or ispaved surface=fine_gravel|cobblestone
assign probablyGood = or ispaved and isbike not isunpaved

#
# this is the cost (in Meter) for a 90-degree turn
# The actual cost is calculated as turncost*cos(angle)
# (Suppressing turncost while following longdistance-cycleways
# makes them a little bit more magnetic)
#
assign turncost = if is_ldcr then 0
                  else if junction=roundabout then 0
                  else 90

#
# for any change in initialclassifier, initialcost is added once
#
assign initialclassifier =
     if route=ferry then classifier_ferry
     else classifier_none

#
# calculate the initial cost
# this is added to the total cost each time the costfactor
# changed
#
assign initialcost =
     if ( equal initialclassifier classifier_ferry ) then 10000
     else 0

#
# implicit access here just from the motorroad tag
# (implicit access rules from highway tag handled elsewhere)
#
assign defaultaccess =
       if access= then not motorroad=yes
       else if access=private|no then false
       else true

#
# calculate logical bike access
#
assign bikeaccess =
       if any_cycleroute then true
       else if bicycle= then
       (
         if vehicle= then defaultaccess
         else not vehicle=private|no
       )
       else not bicycle=private|no|dismount

#
# calculate logical foot access
#
assign footaccess =
       if bikeaccess then true
       else if bicycle=dismount then true
       else if foot= then defaultaccess
       else not foot=private|no

#
# if not bike-, but foot-acess, just a moderate penalty,
# otherwise access is forbidden
#
assign accesspenalty =
       if bikeaccess then 0
       else if footaccess then 4
       else 10000

#
# handle one-ways. On primary roads, wrong-oneways should
# be close to forbidden, while on other ways we just add
# 4 to the costfactor (making it at least 5 - you are allowed
# to push your bike)
#
assign badoneway =
       if reversedirection=yes then
         if oneway:bicycle=yes then true
         else if oneway= then junction=roundabout
         else oneway=yes|true|1
       else oneway=-1

assign onewaypenalty =
       if ( badoneway ) then
       (
         if ( cycleway=opposite|opposite_lane|opposite_track ) then 0
         else if ( oneway:bicycle=no                         ) then 0
         else if ( highway=primary|primary_link              ) then 50
         else if ( highway=secondary|secondary_link          ) then 30
         else if ( highway=tertiary|tertiary_link            ) then 20
         else 4.0
       )
       else 0.0

#
# calculate the cost-factor, which is the factor
# by which the distance of a way-segment is multiplied
# to calculate the cost of that segment. The costfactor
# must be >=1 and it's supposed to be close to 1 for
# the type of way the routing profile is searching for
#
assign costfactor

  #
  # exclude rivers, rails etc.
  #
  if ( and highway= not route=ferry ) then 10000

  #
  # exclude motorways and proposed roads
  #
  else if ( highway=motorway|motorway_link ) then   10000
  else if ( highway=proposed|abandoned     ) then   10000

  #
  # all other exclusions below (access, steps, ferries,..)
  # should not be deleted by the decoder, to be available
  # in voice-hint-processing
  #
  else min 9999

  #
  # apply oneway-and access-penalties
  #
  add max onewaypenalty accesspenalty

  #
  # steps and ferries are special. Note this is handled
  # before the cycleroute-switch, to be able
  # to really exlude them be setting cost to infinity 
  #
  if ( highway=steps ) then ( if allow_steps then 40 else 10000 )
  else if ( route=ferry   ) then ( if allow_ferries then 5.67 else 10000 )

  #
  # handle long-distance cycle-routes.
  #
  else if ( is_ldcr ) then 1                   # always treated as perfect (=1)
  else
  add ( if stick_to_cycleroutes then 0.5 else 0.05 )  # everything else somewhat up

  #
  # some other highway types
  #
  if      ( highway=pedestrian                ) then 3
  else if ( highway=bridleway                 ) then 5
  else if ( highway=cycleway                  ) then 1
  else if ( highway=residential|living_street ) then ( if isunpaved then 1.5 else 1.1 )
  else if ( highway=service                   ) then ( if isunpaved then 1.6 else 1.3 )

  #
  # tracks and track-like ways are rated mainly be tracktype/grade
  # But note that if no tracktype is given (mainly for road/path/footway)
  # it can be o.k. if there's any other hint for quality
  #
  else if ( highway=track|road|path|footway ) then
  (
    if      ( tracktype=grade1 ) then ( if probablyGood then 1.0 else 1.3 )
    else if ( tracktype=grade2 ) then ( if probablyGood then 1.1 else 2.0 )
    else if ( tracktype=grade3 ) then ( if probablyGood then 1.5 else 3.0 )
    else if ( tracktype=grade4 ) then ( if probablyGood then 2.0 else 5.0 )
    else if ( tracktype=grade5 ) then ( if probablyGood then 3.0 else 5.0 )
    else                              ( if probablyGood then 1.0 else 5.0 )
  )

  #
  # When avoiding unsafe ways, avoid highways without a bike hint
  #
  else add ( if ( and avoid_unsafe not isbike ) then 2 else 0 )

  #
  # actuals roads are o.k. if we have a bike hint
  #
       if ( highway=trunk|trunk_link         ) then ( if isbike then 1.5 else 10  )
  else if ( highway=primary|primary_link     ) then ( if isbike then 1.2 else  3  )
  else if ( highway=secondary|secondary_link ) then ( if isbike then 1.1 else 1.6 )
  else if ( highway=tertiary|tertiary_link   ) then ( if isbike then 1.0 else 1.4 )
  else if ( highway=unclassified             ) then ( if isbike then 1.0 else 1.3 )

  #
  # default for any other highway type not handled above
  #
  else 2.0

# way priorities used for voice hint generation

assign priorityclassifier =

  if      ( highway=motorway                  ) then  30
  else if ( highway=motorway_link             ) then  29
  else if ( highway=trunk                     ) then  28
  else if ( highway=trunk_link                ) then  27
  else if ( highway=primary                   ) then  26
  else if ( highway=primary_link              ) then  25
  else if ( highway=secondary                 ) then  24
  else if ( highway=secondary_link            ) then  23
  else if ( highway=tertiary                  ) then  22
  else if ( highway=tertiary_link             ) then  21
  else if ( highway=unclassified              ) then  20
  else if ( highway=residential|living_street ) then  6
  else if ( highway=service                   ) then  6
  else if ( highway=cycleway                  ) then  6
  else if ( bicycle=designated                ) then  6
  else if ( highway=track                     ) then if tracktype=grade1 then 6 else 4
  else if ( highway=bridleway|road|path|footway ) then  4
  else if ( highway=steps                     ) then  2
  else if ( highway=pedestrian                ) then  2
  else 0

# some more classifying bits used for voice hint generation...

assign isbadoneway = not equal onewaypenalty 0
assign isgoodoneway = if reversedirection=yes then oneway=-1
                      else if oneway= then junction=roundabout else oneway=yes|true|1
assign isroundabout = junction=roundabout
assign islinktype = highway=motorway_link|trunk_link|primary_link|secondary_link|tertiary_link
assign isgoodforcars = if greater priorityclassifier 6 then true
                  else if highway=residential|living_street|service then true
                  else if ( and highway=track tracktype=grade1 ) then true
                  else false

# ... encoded into a bitmask

assign classifiermask add          isbadoneway
                      add multiply isgoodoneway   2
                      add multiply isroundabout   4
                      add multiply islinktype     8
                          multiply isgoodforcars 16

---context:node  # following code refers to node tags

assign defaultaccess =
       if ( access= ) then true # add default barrier restrictions here!
       else if ( access=private|no ) then false
       else true

assign bikeaccess =
       if nodeaccessgranted=yes then true
       else if bicycle= then
       (
         if vehicle= then defaultaccess
         else not vehicle=private|no
       )
       else not bicycle=private|no|dismount

assign footaccess =
       if bicycle=dismount then true
       else if foot= then defaultaccess
       else not foot=private|no

assign initialcost =
       if bikeaccess then 0
       else ( if footaccess then 100 else 1000000 )
HankyPanky19 commented 5 years ago

Thank you for editing my first code block. My attempt to edit and include styling markdowns came a bit late!

bagage commented 5 years ago

No worries @HankyPanky19. I've added the profile, you can use https://brouter.damsy.net/latest/#map=14/43.7129/3.8120/OpenStreetMap&profile=trekking-cr favorite URL or similar. Don't be afraid if a "502 nginx error" popup appears - after a few seconds it should be gone.

poutnikl commented 5 years ago

Sticking to cycle routes with Ignoring elevation can bring very unexpected and not desired results.

It means it ignores elevation not only for cycleroutes, but for all roads.

It can easily lead you across the hill range along a non-cycloroute, if it is shorter enough than the cycle route going around.

If there is 4 km long short cut across the 200m high hills, it will take this shortcut and not 8 km long cycleroute around.

Sticking to cycle routes is not a cycleroute magnet. It just makes them more preferred.

To avoid most of situations above, I suggest to increase non cycleroute penalisation from 0.5 to 1.0-2.0.

The used value will be a tradeoff between using short but not acceptable non cycleroutes and taking too long detours by sticking to cycleroutes. Using a high value >> 1 would act like the cycleroute magnet, but with a drawback of possible long detours.

# handle long-distance cycle-routes.   #   else if ( is_ldcr ) then 1                   # always treated as perfect (=1)   else   add ( if stick_to_cycleroutes then 2.0 else 0.05 )  # everything else somewhat up

HankyPanky19 commented 5 years ago

I fully understand and agree to your point, that there are chances to get a path uphill. The question here is: when does "elevation" start to hurt? Sometimes people do not want to have any type of elevation, sometimes people can live with "moderate" elevation. Next question: what is moderate? If I have an elevation of more than 2000m/day - yes it will hurt. If it is only 800m/day - a hill of 200m will not "kill" me. The major question here is: if you want to bike from A to B and there is a famous cycleroute, I typically try to follow that route. And I have seen that brouter finds some paths, which are shorter or maybe they are more flat. Therefore the idea: stick to cycleroute!

I have tried your suggestion for 1 case. Unfortunately it still is not "ideal". Maybe what I'm looking for is a method to specify the name of long distance cycleroute to follow. Especially in regions where there are many different cycleroutes crossing each other, the routing engine will always lead to partially using the "wrong" paths. I have seen other engines, where you are able to click the named cycleroutes, which should be preferred by routing program.

Anyway: again I must say, that brouter by far is the offline routing tool of choice! Thanks a lot for your great support.

poutnikl commented 5 years ago

Well, my post was not about killing hills, but about cancelling elevation may distract you from following cycleroutes. As cycleroutes usually take easy way and no elevation rather discriminate cycleroutes.

Another case is choice between cycleroutes. BRouter with elevation more or less try to suggest the easiest route. You can be a long distance traveller with a heavy load, where every 100m counts.

In fact, elevation mgmt is one of the most important BRouter advantage over some naive bicycle online routers. It is not wise, IMHO, to get rid of it.

If you want to get uphill or take a particular route, you have still the option to express your wish. In fact, I have created 2 profiles that try to avoid easy routes. :-)

The idea behind the elevation management is: not wasting energy on elevation you are not so much aware of, to have energy for elevation challenge you want or have to take.

poutnikl commented 5 years ago

Specifying the route name is not currently possible. You may also try my FCR and LCR profiles. Especially the latter strongly distinguish between long distance ICN/NCN and local RCN/LCN.

poutnikl commented 5 years ago

Personally, route planning seems to me easier directly on the phone in the LocusMap than tranfering routes from the PC.

Note that if one uses the Elevate or Waymarks vector map style in LocusMap, the cycleroute classes are well distinguished and, especially in the former, the long distance ones appear in lower zooms.

theraser commented 3 years ago

The original problem with caching all custom profiles at brouter-web itself could be resolved for some users by allowing an external profile: there could be a field where you can provide an external URL with a profile file on another web server (direct link, could be on Github). Using this you could avoid using local caching in a lot of cases and you would allow sharing a track URL which simply includes a link to the external profile file and start/end points, too. If the external file isn't available you simply throw a warning and fall back to the internal default.

The parsing, validating etc. is already there so there shouldn't be any security concerns when downloading the profile from an external source instead of pasting it directly to the web interface.

If there would be a way to sponsor the development of permalinks in any kind, please let me know.

In my opinion this is one of the most required features since at the moment you can't share your tour with others when you aren't using one of the basic profiles provided - which is sad because the profiles are the thing which makes brouter so special und amazing! :star_struck: