Use markdown syntax

This commit is contained in:
Manuel Fuhr 2021-11-30 17:35:45 +01:00
parent d3482098f0
commit dfc4bff7fd

View file

@ -1,6 +1,5 @@
Profile developers guide - Technical reference Profile developers guide - Technical reference for BRouter profile scripts
for BRouter profile scripts ==========================================================================
==============================================
The tag-value lookup table The tag-value lookup table
-------------------------- --------------------------
@ -15,20 +14,20 @@ that are considered for encoding.
For each tag there are 2 special values: For each tag there are 2 special values:
- <empty> if the tag is not set or the value is empty - `<empty>` if the tag is not set or the value is empty
- "unknown" if the value is not contained in the table - `unknown` if the value is not contained in the table
Each value can have optional "aliases", these alias Each value can have optional *aliases*, these alias
values are encoded into the same binary value as the values are encoded into the same binary value as the
associated primary value. associated primary value.
A profile must use the primary value in expressions, as A profile must use the primary value in expressions, as
aliases trigger a parse error. E.g. if there is a line aliases trigger a parse error. E.g. if there is a line
in lookups.dat file: in `lookups.dat` file:
bicycle;0001245560 yes allowed `bicycle;0001245560 yes allowed`
then a profile must use "bicycle=yes", as "bicycle=allowed" then a profile must use `bicycle=yes`, as `bicycle=allowed`
gives an error. gives an error.
The numbers in the lookup table are statistical The numbers in the lookup table are statistical
@ -36,36 +35,34 @@ information on the frequency of the values in the
map of Germany - these are just informational and map of Germany - these are just informational and
are not processed by BRouter. are not processed by BRouter.
Context-Separation Context-Separation
------------------ ------------------
Way-tags and Node-Tags are treated independently, Way-tags and Node-Tags are treated independently,
so there are different sections in the lookup table so there are different sections in the lookup table
as well as in the profile scripts for each context. as well as in the profile scripts for each context.
The special tags: "---context:way" and "---context:node" The special tags: `---context:way` and `---context:node`
mark the beginning of each section. mark the beginning of each section.
An exception from context separation is the node-context, An exception from context separation is the node-context,
where variables from the way-context of the originating where variables from the way-context of the originating
way can be accessed using the "way:" prefix. For the way can be accessed using the `way:` prefix. For the
variable nodeaccessgranted there's an additional variable nodeaccessgranted there's an additional
legacy-hack to access it as a lookup value without prefix: legacy-hack to access it as a lookup value without prefix:
if nodeaccessgranted=yes then ... `if nodeaccessgranted=yes then ...`
while in the general case the prefixed expressions are variables: while in the general case the prefixed expressions are variables:
if greater way:costfactor 5 then ... `if greater way:costfactor 5 then ...`
In the profile scripts there is a third context "global" In the profile scripts there is a third context `global`
which contains global configuration which is shared for which contains global configuration which is shared for
all contexts and is accessible by the routing engine. all contexts and is accessible by the routing engine.
The variables from the "global" section in the profile The variables from the `global` section in the profile
scripts are read-only visible in the "way" and scripts are read-only visible in the `way` and
"node" sections of the scripts. `node` sections of the scripts.
Predefined variables in the profile scripts Predefined variables in the profile scripts
------------------------------------------- -------------------------------------------
@ -77,36 +74,37 @@ the routing engine:
- 7 elevation configuration parameters: - 7 elevation configuration parameters:
- downhillcost - `downhillcost`
- downhillcutoff - `downhillcutoff`
- uphillcost - `uphillcost`
- uphillcutoff - `uphillcutoff`
- elevationpenaltybuffer - `elevationpenaltybuffer`
- elevationmaxbuffer - `elevationmaxbuffer`
- elevationbufferreduce - `elevationbufferreduce`
- 3 boolean mode-hint flags - 3 boolean mode-hint flags
- validForBikes - `validForBikes`
- validForFoot - `validForFoot`
- validForCars - `validForCars`
- 2 variables to change the heuristic - 2 variables to change the heuristic
coefficients for the 2 routing passes coefficients for the 2 routing passes
( <0 disables a routing pass ) ( <0 disables a routing pass )
- pass1coefficient - `pass1coefficient`
- pass2coefficient - `pass2coefficient`
- 3 variables to influence the generation of turn-instructions - 3 variables to influence the generation of turn-instructions
- turnInstructionMode 0=none, 1=auto-choose, 2=locus-style, 3=osmand-style - `turnInstructionMode` 0=none, 1=auto-choose, 2=locus-style, 3=osmand-style
- turnInstructionCatchingRange default 40m - `turnInstructionCatchingRange` default=40m
- turnInstructionRoundabouts default=true=generate explicit roundabout hints - `turnInstructionRoundabouts` default=true generate explicit roundabout hints
- variables to modify BRouter behaviour - variables to modify BRouter behaviour
- processUnusedTags ( default is false ) - `processUnusedTags` default=false
If an OSM tag is unused within the profile, If an OSM tag is unused within the profile,
BRouter totally ignores the tag existence. BRouter totally ignores the tag existence.
Skipping unused tags improves BRouter speed. Skipping unused tags improves BRouter speed.
@ -117,30 +115,29 @@ the routing engine:
- for the way section these are - for the way section these are
- turncost - `turncost`
- initialcost - `initialcost`
- costfactor - `costfactor`
- uphillcostfactor - `uphillcostfactor`
- downhillcostfactor - `downhillcostfactor`
- nodeaccessgranted - `nodeaccessgranted`
- initialclassifier - `initialclassifier`
- priorityclassifier - `priorityclassifier`
- for the node section this is just - for the node section this is just
- initialcost - `initialcost`
Operators of the profile scripts
The operators of the profile scripts --------------------------------
------------------------------------
The profile scripts use polish notation (operator first). The profile scripts use polish notation (operator first).
The "assign" operator is special: it can be used The `assign` operator is special: it can be used
only on the top level of the expression hierarchy only on the top level of the expression hierarchy
and has 2 operands: and has 2 operands:
assign <variable-name> <expression> `assign <variable-name> <expression>`
It just assigns the expression value to this It just assigns the expression value to this
variable (which can be a predefined variable or variable (which can be a predefined variable or
@ -154,98 +151,97 @@ expression starting with an operator and so on.
All expressions have one of the following basic forms: All expressions have one of the following basic forms:
- <numeric value> - `<numeric value>`
- <numeric variable> - `<numeric variable>`
- <lookup-match> - `<lookup-match>`
- <1-op-operator> <operand> - `<1-op-operator> <operand>`
- <2-op-operator> <operand> <operand> - `<2-op-operator> <operand> <operand>`
- <3-op-operator> <operand> <operand> <operand> - `<3-op-operator> <operand> <operand> <operand>`
- A numeric value is just a number, floating point, with "." as - A numeric value is just a number, floating point, with `.` as
decimal separator. Boolean values are treated as numbers as well, decimal separator. Boolean values are treated as numbers as well,
with "0" = false and every nonzero value = true. with `0` = `false` and every nonzero value = `true`.
- A lookup match has the form <tag-name>=<value>, e.g. highway=primary - A lookup match has the form `<tag-name>=<value>`, e.g. `highway=primary`
Only the primary values can be used in lookup-matches, not aliases. Only the primary values can be used in lookup-matches, not aliases.
The <empty> value is referred to as an empty string, e.g. access= The `<empty>` value is referred to as an empty string, e.g. `access=`
- 1 Operand operators are: - 1 Operand operators are:
not <boolean expression> - `not <boolean expression>`
- 2 Operand operators are: - 2 Operand operators are:
or <boolean expression 1> <boolean expression 2> - `or <boolean expression 1> <boolean expression 2>`
and <boolean expression 1> <boolean expression 2> - `and <boolean expression 1> <boolean expression 2>`
xor <boolean expression 1> <boolean expression 2> - `xor <boolean expression 1> <boolean expression 2>`
multiply <numeric expression 1> <numeric expression 2> - `multiply <numeric expression 1> <numeric expression 2>`
add <numeric expression 1> <numeric expression 2> - `add <numeric expression 1> <numeric expression 2>`
sub <numeric expression 1> <numeric expression 2> - `sub <numeric expression 1> <numeric expression 2>`
max <numeric expression 1> <numeric expression 2> - `max <numeric expression 1> <numeric expression 2>`
min <numeric expression 1> <numeric expression 2> - `min <numeric expression 1> <numeric expression 2>`
equal <numeric expression 1> <numeric expression 2> - `equal <numeric expression 1> <numeric expression 2>`
greater <numeric expression 1> <numeric expression 2> - `greater <numeric expression 1> <numeric expression 2>`
lesser <numeric expression 1> <numeric expression 2> - `lesser <numeric expression 1> <numeric expression 2>`
- 3 Operand operators are: - 3 Operand operators are:
switch <boolean-expression> <true-expression> <false-expression> - `switch <boolean-expression> <true-expression> <false-expression>`
So the switch expression has a numeric value which is the So the switch expression has a numeric value which is the
true-expression if the boolean expression is true, the true-expression if the boolean expression is true, the
false-expression otherwise. false-expression otherwise.
Syntactic Sugar Syntactic Sugar
--------------- ---------------
To improve the readablity of the profile scripts, some syntactic variations To improve the readablity of the profile scripts, some syntactic variations
are possible: are possible:
- "if then else" : "if" can be used instead of the "switch" operator, if the - if then else: `if` can be used instead of the `switch` operator, if the
additional keywords "then" and "else" are placed between the operators: additional keywords `then` and `else` are placed between the operators:
if <boolean-expression> then <true-expression> else <false-expression> `if <boolean-expression> then <true-expression> else <false-expression>`
- Parentheses: each expression can be surrounded by parentheses: `(<expression>)`
- Parentheses: each expression can be surrounded by parentheses: ( <expression> )
Please note that the profile syntax, due to the polish notation, does not Please note that the profile syntax, due to the polish notation, does not
need parentheses, they are always optional. However, if there are parentheses, need parentheses, they are always optional. However, if there are parentheses,
the parser checks if they really match the expression boundaries. the parser checks if they really match the expression boundaries.
- or-ing lookup-matches: the pipe-symbol can be used as a short syntax for - or-ing lookup-matches: the pipe-symbol can be used as a short syntax for
lookup matches where more than one value is accepted for a key: lookup matches where more than one value is accepted for a key:
highway=primary|secondary|tertiary `highway=primary|secondary|tertiary`
- additional "=" symbol for "assign" operations: - additional `=` symbol for `assign` operations:
assign <variable-name> = <expression>
- boolean constants: "true" and "false" can be used instead of 1 and 0 `assign <variable-name> = <expression>`
- boolean constants: `true` and `false` can be used instead of 1 and 0
Please note that the tokenizer always expects blank space to separate Please note that the tokenizer always expects blank space to separate
symbols and expressions so it is not allowed to place parentheses or symbols and expressions so it is not allowed to place parentheses or
the "=" symbol without separating blank space! the `=` symbol without separating blank space!
The initial cost classifier The initial cost classifier
--------------------------- ---------------------------
To trigger the addition of the "initialcost", another variable is used: To trigger the addition of the `initialcost`, another variable is used:
"initialclassifier" - any change in the value of that variable leads `initialclassifier` - any change in the value of that variable leads
to adding the value of "initialcost". to adding the value of `initialcost`.
Initial cost is used typically for a ferry, where you want to apply Initial cost is used typically for a ferry, where you want to apply
a penalty independent of the length of the ferry line. a penalty independent of the length of the ferry line.
Another useful case may be an initial cost for bicycle mounting/dismounting, Another useful case may be an initial cost for bicycle mounting/dismounting,
having set an initialclassifier for ways without bicycle access, with high initialcost. having set an initialclassifier for ways without bicycle access, with high initialcost.
For backward compatibility, if "initialclassifier" = 0, it is replaced For backward compatibility, if `initialclassifier` = 0, it is replaced
by the costfactor. by the costfactor.
The priority classifier The priority classifier
----------------------- -----------------------
Priorityclassifier is a BRouter numerical parameter `priorityclassifier` is a BRouter numerical parameter
calculated for ways and used for generation of pictogram/voice navigation instructions. calculated for ways and used for generation of pictogram/voice navigation instructions.
Higher values means the more significant (noticeable) way, Higher values means the more significant (noticeable) way,
@ -254,79 +250,91 @@ as far as it can be predicted from OSM data.
To avoid a navigation instruction flood, it was decided To avoid a navigation instruction flood, it was decided
that the instructions are provided only if: that the instructions are provided only if:
1/ You are supposed to turn at a crossroad/junction 1. You are supposed to turn at a crossroad/junction
and some other ways having the same or higher Priorityclassifier value. and some other ways having the same or higher `priorityclassifier` value.
OR
2/ You are supposed to go straight ahead
and some other ways having the higher Priorityclassifier value.
2. You are supposed to go straight ahead
and some other ways having the higher `priorityclassifier` value.
The elevation buffer ( From Poutnik's glossary ) The elevation buffer ( From Poutnik's glossary )
------------------------------------------------ ------------------------------------------------
With related 3 internal BRouter variables: With related 3 internal BRouter variables:
- elevationpenaltybuffer
- elevationmaxbuffer - `elevationpenaltybuffer`
- elevationbufferreduce - `elevationmaxbuffer`
- `elevationbufferreduce`
the Elevation Buffer is BRouter feature to filter elevation noise along the route. the Elevation Buffer is BRouter feature to filter elevation noise along the route.
It may be real, or caused by the artefacts of used SRTM elevation data. It may be real, or caused by the artefacts of used SRTM elevation data.
From every elevation change is at the first place cut out amount 10*up/downhillcutoff From every elevation change is at the first place cut out amount `10*up/downhillcutoff`
per every km of the way length. What remains, starts to accumulate in the buffer. per every km of the way length. What remains, starts to accumulate in the buffer.
IF cutoff demand of elevation per length is not saturated from incoming elevation, IF cutoff demand of elevation per length is not saturated from incoming elevation,
it is applied on elevation remaining in the buffer as well. it is applied on elevation remaining in the buffer as well.
E.g. if the way climbs 20 m along 500 m, and uphillcutoff=3.0, then 10*3.0*0.5 = 15 m E.g. if the way climbs 20 m along 500 m, and `uphillcutoff=3.0`, then `10*3.0*0.5 km = 15 m`
is taken away and only remaining 5 m accumulates. But if it climbed only 10 m is taken away and only remaining 5 m accumulates. But if it climbed only 10 m
on those 500m, all 10 m would be "swallowed" by cutoff, on those 500 m, all 10 m would be *swallowed* by cutoff,
together with up to 5 m from the buffer, if there were any. together with up to 5 m from the buffer, if there were any.
When elevation does not fit the buffer of size elevationmaxbuffer, When elevation does not fit the buffer of size `elevationmaxbuffer`,
it is converted by up/downhillcost ratio to Elevationcost portion of Equivalentlength. it is converted by up/downhillcost ratio to Elevationcost portion of Equivalentlength.
Up/downhillcostfactors are used, if defined, otherwise CostFactor is used. Up/downhillcostfactors are used, if defined, otherwise costfactor is used.
elevationpenaltybuffer is BRouter variable, with default value 5(m). - `elevationpenaltybuffer` - default 5(m).
The variable value is used for 2 purposes:
With the buffer content > elevationpenaltybuffer, it starts partially convert
the buffered elevation to ElevationCost by Up/downhillcost, with elevation taken
= MIN (Buffer - elevationpenaltybuffer, WayLength[km] * elevationbufferreduce*10
The Up/downhillcost factor takes place instead of costfactor at the percentage of
how much is WayLength[km] * elevationbufferreduce*10 is saturated
by the buffer content above elevationpenaltybuffer.
elevationmaxbuffer - default 10(m) - is the size of the buffer, above which The variable value is used for 2 purposes
all elevation is converted to Elevationcost by Up/Downhillcost ratio,
and - if defined - Up/downhillcostfactor fully replaces Costfactor
in way cost calculation.
elevationbufferreduce - default 0(slope%)- is rate of conversion of the buffer content - with `buffer content > elevationpenaltybuffer`, it starts partially convert
above elevationpenaltybuffer to ElevationCost. For a way of length L, the buffered elevation to ElevationCost by Up/downhillcost
the amount of converted elevation is L[km] * elevationbufferreduce[%] * 10.
The elevation to Elevationcost conversion ratio is given by Up/downhillcost.
Example: - with `elevation taken = MIN (buffer content - elevationpenaltybuffer, WayLength[km] * elevationbufferreduce*10`
Let's examine steady slopes with elevationmaxbuffer=10, elevationpenaltybuffer=5, Up/downhillcost factor takes place instead of costfactor at the percentage
elevationbufferreduce=0.5, cutoffs=1.5, Up/downhillcosts=60. of how much is `WayLength[km] * elevationbufferreduce*10` is saturated by
the buffer content above elevationpenaltybuffer.
All slopes within 0 .. 1.5% are swallowed by the cutoff. - `elevationmaxbuffer` - default 10(m)
For slope 1.75%, there will remain 0.25%. is the size of the buffer, above which all elevation is converted to
That saturates the elevationbufferreduce 0.5% by 50%. That gives Way cost Elevationcost by Up/Downhillcost ratio, and - if defined -
to be calculated 50% from costfactor and 50% from Up/downhillcostfactor. Up/downhillcostfactor fully replaces costfactor in way cost calculation.
Additionally, 0.25% gives 2.5m per 1km, converted to 2.5*60 = 150m of Elevationcost.
For slope 2.0%, there will remain 0.5%. - `elevationbufferreduce` - default 0(slope%)
That saturates the elevationbufferreduce 0.5% by 100%. That gives Way cost
to be calculated fully from Up/downhillcostfactor. Additionally,
0.5% gives 5m per 1km, converted to 5*60 = 300m of Elevationcost.
Up to slope 2.0% the buffer value stays at 5m = elevationpenaltybuffer.
For slope 2.5%, there will remain 1.0% after cutoff subtract, is rate of conversion of the buffer content above elevationpenaltybuffer to
and 0.5% after the buffer reduce subtract. The remaining 0.5% accumulates in the buffer ElevationCost. For a way of length L, the amount of converted elevation is
by rate 5 m/km. When the buffer is full (elevationmaxbuffer), L[km] * elevationbufferreduce[%] * 10. The elevation to Elevationcost
the elevation transforms to elevationcost by full rate of 1.0%, i.e. 10 m/km, conversion ratio is given by Up/downhillcost.
giving elevationcost 10*60=600 m/km.
Example: Let's examine steady slopes with `elevationmaxbuffer=10`,
`elevationpenaltybuffer=5`, `elevationbufferreduce=0.5`, `cutoffs=1.5`,
`up/downhillcosts=60`.
All slopes within 0 .. 1.5% are swallowed by the cutoff.
- For slope 1.75%, there will remain 0.25%.
That saturates the elevationbufferreduce 0.5% by 50%. That gives Way
cost to be calculated 50% from costfactor and 50% from
Up/downhillcostfactor. Additionally, 0.25% gives 2.5m per 1km,
converted to 2.5*60 = 150m of Elevationcost.
- For slope 2.0%, there will remain 0.5%.
That saturates the elevationbufferreduce 0.5% by 100%. That gives Way
cost to be calculated fully from `up/downhillcostfactor`.
Additionally, 0.5% gives 5m per 1km, converted to 5*60 = 300m of
Elevationcost. Up to slope 2.0% the buffer value stays at 5m =
`elevationpenaltybuffer`.
- For slope 2.5%, there will remain 1.0% after cutoff subtract, and 0.5%
after the buffer reduce subtract.
The remaining 0.5% accumulates in the buffer by rate 5 m/km. When the
buffer is full (elevationmaxbuffer), the elevation transforms to
elevationcost by full rate of 1.0%, i.e. 10 m/km, giving elevationcost
10*60=600 m/km.
Technical constraints Technical constraints
@ -341,33 +349,32 @@ Technical constraints
search area and thus to long processing times. search area and thus to long processing times.
- Forbidden ways or nodes must be treated as very high cost, because - Forbidden ways or nodes must be treated as very high cost, because
there is no "forbidden" value. Technically, values >= 10000 for a there is no *forbidden* value. Technically, values >= 10000 for a
(way-)costfactor, and >= 1000000 for a nodes "initalcost" are treated (way-)costfactor, and >= 1000000 for a nodes `initalcost` are treated
as infinity, so please use these as the "forbidden" values. as infinity, so please use these as the *forbidden* values.
- Ways with costfactor >= 10000 are considered as if they did not exist at all. - Ways with costfactor >= 10000 are considered as if they did not exist at all.
- Ways with costfactor = 9999 are considered as - Ways with costfactor = 9999 are considered as if they did not exist during
if they did not exist during route calculation, route calculation, but the navigation hint generator takes them into account.
but the navigation hint generator takes them into account.
Developing and debugging scripts Developing and debugging scripts
-------------------------------- --------------------------------
For developing scripts, the "brouter-web" web-application is your For developing scripts, the *brouter-web* web-application is your
friend. You can use that either online at https://brouter.de/brouter-web friend. You can use that either online at https://brouter.de/brouter-web
or set up a local installation. or set up a local installation.
BRouter-Web has a window at the lower left corner with a "Profile" *brouter-web* has a window at the lower left corner with a *Profile*
and a "Data" tab. Here, you can upload profile scripts and see and a *Data* tab. Here, you can upload profile scripts and see
the individual cost calculations per way-section in the "Data"-tab. the individual cost calculations per way-section in the *Data*-tab.
For profile debugging activate "assign processUnusedTags = true" For profile debugging activate `assign processUnusedTags = true`
to see all present OSM tags on the Data tab, not just those used in the tested profile. to see all present OSM tags on the Data tab, not just those used in the tested profile.
Lookup-Table evolution and the the "major" and "minor" versions Lookup-Table evolution and the the *major* and *minor* versions
--------------------------------------------------------------- ---------------------------------------------------------------
The lookup-table is allowed to grow over time, to include more tags The lookup-table is allowed to grow over time, to include more tags
@ -386,7 +393,7 @@ compatible in both directions, using the following rules:
tables, it is ignored tables, it is ignored
- if the data contains a value that is not contained in the lookup - if the data contains a value that is not contained in the lookup
tables (but its key is known) that value is treated as "unknown" tables (but its key is known) that value is treated as `unknown`
- if a profile uses a key that is not present in the data, - if a profile uses a key that is not present in the data,
it sees empty (=unset) values for that key it sees empty (=unset) values for that key
@ -402,10 +409,8 @@ This is because the routing data files address tags and values
by their sequence numbers, so changing sequences would produce by their sequence numbers, so changing sequences would produce
garbage data. garbage data.
Other resources Other resources
--------------- ---------------
See https://github.com/poutnikl/Brouter-profiles/wiki/Glossary See [Poutnik's glossary](https://github.com/poutnikl/Brouter-profiles/wiki/Glossary)
as a complementary source about various profile internals. as a complementary source about various profile internals.