Rewrap
This commit is contained in:
parent
dfc4bff7fd
commit
87a5cd21e8
1 changed files with 142 additions and 160 deletions
|
@ -4,51 +4,43 @@ Profile developers guide - Technical reference for BRouter profile scripts
|
|||
The tag-value lookup table
|
||||
--------------------------
|
||||
|
||||
Within the routing data files (rd5), tag information
|
||||
is encoded in a binary bitstream for the way tags and
|
||||
the node tags each.
|
||||
Within the routing data files (rd5), tag information is encoded in a binary
|
||||
bitstream for the way tags and the node tags each.
|
||||
|
||||
To encode and decode to/from this bitstream, a lookup
|
||||
table is used that contains all the tags and values
|
||||
that are considered for encoding.
|
||||
To encode and decode to/from this bitstream, a lookup table is used that
|
||||
contains all the tags and values that are considered for encoding.
|
||||
|
||||
For each tag there are 2 special values:
|
||||
|
||||
- `<empty>` if the tag is not set or the value is empty
|
||||
- `unknown` if the value is not contained in the table
|
||||
|
||||
Each value can have optional *aliases*, these alias
|
||||
values are encoded into the same binary value as the
|
||||
associated primary value.
|
||||
Each value can have optional *aliases*, these alias values are encoded into the
|
||||
same binary value as the associated primary value.
|
||||
|
||||
A profile must use the primary value in expressions, as
|
||||
aliases trigger a parse error. E.g. if there is a line
|
||||
in `lookups.dat` file:
|
||||
A profile must use the primary value in expressions, as aliases trigger a parse
|
||||
error. E.g. if there is a line in `lookups.dat` file:
|
||||
|
||||
`bicycle;0001245560 yes allowed`
|
||||
|
||||
then a profile must use `bicycle=yes`, as `bicycle=allowed`
|
||||
gives an error.
|
||||
then a profile must use `bicycle=yes`, as `bicycle=allowed` gives an error.
|
||||
|
||||
The numbers in the lookup table are statistical
|
||||
information on the frequency of the values in the
|
||||
map of Germany - these are just informational and
|
||||
are not processed by BRouter.
|
||||
The numbers in the lookup table are statistical information on the frequency of
|
||||
the values in the map of Germany - these are just informational and are not
|
||||
processed by BRouter.
|
||||
|
||||
Context-Separation
|
||||
------------------
|
||||
|
||||
Way-tags and Node-Tags are treated independently,
|
||||
so there are different sections in the lookup table
|
||||
as well as in the profile scripts for each context.
|
||||
The special tags: `---context:way` and `---context:node`
|
||||
mark the beginning of each section.
|
||||
Way-tags and Node-Tags are treated independently, so there are different
|
||||
sections in the lookup table as well as in the profile scripts for each context.
|
||||
The special tags: `---context:way` and `---context:node` mark the beginning of
|
||||
each section.
|
||||
|
||||
An exception from context separation is the node-context,
|
||||
where variables from the way-context of the originating
|
||||
way can be accessed using the `way:` prefix. For the
|
||||
variable nodeaccessgranted there's an additional
|
||||
legacy-hack to access it as a lookup value without prefix:
|
||||
An exception from context separation is the node-context, where variables from
|
||||
the way-context of the originating way can be accessed using the `way:` prefix.
|
||||
For the variable nodeaccessgranted there's an additional legacy-hack to access
|
||||
it as a lookup value without prefix:
|
||||
|
||||
`if nodeaccessgranted=yes then ...`
|
||||
|
||||
|
@ -56,19 +48,17 @@ while in the general case the prefixed expressions are variables:
|
|||
|
||||
`if greater way:costfactor 5 then ...`
|
||||
|
||||
In the profile scripts there is a third context `global`
|
||||
which contains global configuration which is shared for
|
||||
all contexts and is accessible by the routing engine.
|
||||
In the profile scripts there is a third context `global` which contains global
|
||||
configuration which is shared for all contexts and is accessible by the routing
|
||||
engine.
|
||||
|
||||
The variables from the `global` section in the profile
|
||||
scripts are read-only visible in the `way` and
|
||||
`node` sections of the scripts.
|
||||
The variables from the `global` section in the profile scripts are read-only
|
||||
visible in the `way` and `node` sections of the scripts.
|
||||
|
||||
Predefined variables in the profile scripts
|
||||
-------------------------------------------
|
||||
|
||||
Some variable names are pre-defined and accessed by
|
||||
the routing engine:
|
||||
Some variable names are pre-defined and accessed by the routing engine:
|
||||
|
||||
- for the global section these are:
|
||||
|
||||
|
@ -88,30 +78,29 @@ the routing engine:
|
|||
- `validForFoot`
|
||||
- `validForCars`
|
||||
|
||||
- 2 variables to change the heuristic
|
||||
coefficients for the 2 routing passes
|
||||
( <0 disables a routing pass )
|
||||
- 2 variables to change the heuristic coefficients for the 2 routing passes (
|
||||
<0 disables a routing pass )
|
||||
|
||||
- `pass1coefficient`
|
||||
- `pass2coefficient`
|
||||
|
||||
- 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
|
||||
- `turnInstructionRoundabouts` default=true generate explicit roundabout hints
|
||||
- `turnInstructionRoundabouts` default=true generate explicit roundabout
|
||||
hints
|
||||
|
||||
- variables to modify BRouter behaviour
|
||||
|
||||
- `processUnusedTags` default=false
|
||||
|
||||
If an OSM tag is unused within the profile,
|
||||
BRouter totally ignores the tag existence.
|
||||
Skipping unused tags improves BRouter speed.
|
||||
As a side effect, the tag is not even listed
|
||||
in the route segment table nor the table exported as CSV.
|
||||
Setting it to true/1, Brouter-web Data page will list
|
||||
all tags present in the RD5 file.
|
||||
If an OSM tag is unused within the profile, BRouter totally ignores the
|
||||
tag existence. Skipping unused tags improves BRouter speed. As a side
|
||||
effect, the tag is not even listed in the route segment table nor the
|
||||
table exported as CSV. Setting it to true/1, Brouter-web Data page will
|
||||
list all tags present in the RD5 file.
|
||||
|
||||
- for the way section these are
|
||||
|
||||
|
@ -133,21 +122,18 @@ Operators of the profile scripts
|
|||
|
||||
The profile scripts use polish notation (operator first).
|
||||
|
||||
The `assign` operator is special: it can be used
|
||||
only on the top level of the expression hierarchy
|
||||
and has 2 operands:
|
||||
The `assign` operator is special: it can be used only on the top level of the
|
||||
expression hierarchy and has 2 operands:
|
||||
|
||||
`assign <variable-name> <expression>`
|
||||
|
||||
It just assigns the expression value to this
|
||||
variable (which can be a predefined variable or
|
||||
any other variable, which in this case is defined
|
||||
implicitly). The expression can be a complex expression
|
||||
using other operators.
|
||||
It just assigns the expression value to this variable (which can be a predefined
|
||||
variable or any other variable, which in this case is defined implicitly). The
|
||||
expression can be a complex expression using other operators.
|
||||
|
||||
All other operators can be used recursively to an unlimited
|
||||
complexity, which means that each operand can be a composed
|
||||
expression starting with an operator and so on.
|
||||
All other operators can be used recursively to an unlimited complexity, which
|
||||
means that each operand can be a composed expression starting with an operator
|
||||
and so on.
|
||||
|
||||
All expressions have one of the following basic forms:
|
||||
|
||||
|
@ -158,13 +144,13 @@ All expressions have one of the following basic forms:
|
|||
- `<2-op-operator> <operand> <operand>`
|
||||
- `<3-op-operator> <operand> <operand> <operand>`
|
||||
|
||||
- A numeric value is just a number, floating point, with `.` as
|
||||
decimal separator. Boolean values are treated as numbers as well,
|
||||
with `0` = `false` and every nonzero value = `true`.
|
||||
- A numeric value is just a number, floating point, with `.` as decimal
|
||||
separator. Boolean values are treated as numbers as well, with `0` = `false`
|
||||
and every nonzero value = `true`.
|
||||
|
||||
- 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.
|
||||
The `<empty>` value is referred to as an empty string, e.g. `access=`
|
||||
- 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. The `<empty>`
|
||||
value is referred to as an empty string, e.g. `access=`
|
||||
|
||||
- 1 Operand operators are:
|
||||
|
||||
|
@ -188,26 +174,26 @@ All expressions have one of the following basic forms:
|
|||
|
||||
- `switch <boolean-expression> <true-expression> <false-expression>`
|
||||
|
||||
So the switch expression has a numeric value which is the
|
||||
true-expression if the boolean expression is true, the
|
||||
false-expression otherwise.
|
||||
So the switch expression has a numeric value which is the true-expression if
|
||||
the boolean expression is true, the false-expression otherwise.
|
||||
|
||||
Syntactic Sugar
|
||||
---------------
|
||||
|
||||
To improve the readablity of the profile scripts, some syntactic variations
|
||||
are possible:
|
||||
To improve the readablity of the profile scripts, some syntactic variations are
|
||||
possible:
|
||||
|
||||
- if then else: `if` can be used instead of the `switch` operator, if the
|
||||
additional keywords `then` and `else` are placed between the operators:
|
||||
|
||||
`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
|
||||
need parentheses, they are always optional. However, if there are parentheses,
|
||||
the parser checks if they really match the expression boundaries.
|
||||
Please note that the profile syntax, due to the polish notation, does not need
|
||||
parentheses, they are always optional. However, if there are parentheses, 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
|
||||
lookup matches where more than one value is accepted for a key:
|
||||
|
@ -219,42 +205,42 @@ are possible:
|
|||
|
||||
- boolean constants: `true` and `false` can be used instead of 1 and 0
|
||||
|
||||
Please note that the tokenizer always expects blank space to separate
|
||||
symbols and expressions so it is not allowed to place parentheses or
|
||||
the `=` symbol without separating blank space!
|
||||
Please note that the tokenizer always expects blank space to separate symbols
|
||||
and expressions so it is not allowed to place parentheses or the `=` symbol
|
||||
without separating blank space!
|
||||
|
||||
The initial cost classifier
|
||||
---------------------------
|
||||
|
||||
To trigger the addition of the `initialcost`, another variable is used:
|
||||
`initialclassifier` - any change in the value of that variable leads
|
||||
to adding the value of `initialcost`.
|
||||
`initialclassifier` - any change in the value of that variable leads to adding
|
||||
the value of `initialcost`.
|
||||
|
||||
Initial cost is used typically for a ferry, where you want to apply
|
||||
a penalty independent of the length of the ferry line.
|
||||
Initial cost is used typically for a ferry, where you want to apply a penalty
|
||||
independent of the length of the ferry line.
|
||||
|
||||
Another useful case may be an initial cost for bicycle mounting/dismounting,
|
||||
having set an initialclassifier for ways without bicycle access, with high initialcost.
|
||||
For backward compatibility, if `initialclassifier` = 0, it is replaced
|
||||
by the costfactor.
|
||||
having set an initialclassifier for ways without bicycle access, with high
|
||||
initialcost. For backward compatibility, if `initialclassifier` = 0, it is
|
||||
replaced by the costfactor.
|
||||
|
||||
The priority classifier
|
||||
-----------------------
|
||||
|
||||
`priorityclassifier` is a BRouter numerical parameter
|
||||
calculated for ways and used for generation of pictogram/voice navigation instructions.
|
||||
`priorityclassifier` is a BRouter numerical parameter calculated for ways and
|
||||
used for generation of pictogram/voice navigation instructions.
|
||||
|
||||
Higher values means the more significant (noticeable) way,
|
||||
as far as it can be predicted from OSM data.
|
||||
Higher values means the more significant (noticeable) way, as far as it can be
|
||||
predicted from OSM data.
|
||||
|
||||
To avoid a navigation instruction flood, it was decided
|
||||
that the instructions are provided only if:
|
||||
To avoid a navigation instruction flood, it was decided that the instructions
|
||||
are provided only if:
|
||||
|
||||
1. You are supposed to turn at a crossroad/junction
|
||||
and some other ways having the same or higher `priorityclassifier` value.
|
||||
1. You are supposed to turn at a crossroad/junction and some other ways having
|
||||
the same or higher `priorityclassifier` value.
|
||||
|
||||
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 )
|
||||
------------------------------------------------
|
||||
|
@ -265,21 +251,22 @@ With related 3 internal BRouter variables:
|
|||
- `elevationmaxbuffer`
|
||||
- `elevationbufferreduce`
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
IF cutoff demand of elevation per length is not saturated from incoming elevation,
|
||||
it is applied on elevation remaining in the buffer as well.
|
||||
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. IF cutoff demand of elevation per length is not
|
||||
saturated from incoming elevation, 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 km = 15 m`
|
||||
is taken away and only remaining 5 m accumulates. But if it climbed only 10 m
|
||||
on those 500 m, all 10 m would be *swallowed* by cutoff,
|
||||
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 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.
|
||||
|
||||
When elevation does not fit the buffer of size `elevationmaxbuffer`,
|
||||
it is converted by up/downhillcost ratio to Elevationcost portion of Equivalentlength.
|
||||
When elevation does not fit the buffer of size `elevationmaxbuffer`, it is
|
||||
converted by up/downhillcost ratio to Elevationcost portion of Equivalentlength.
|
||||
Up/downhillcostfactors are used, if defined, otherwise costfactor is used.
|
||||
|
||||
- `elevationpenaltybuffer` - default 5(m).
|
||||
|
@ -315,43 +302,41 @@ 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.
|
||||
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`.
|
||||
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.
|
||||
- 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.
|
||||
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
|
||||
---------------------
|
||||
|
||||
- The costfactor is required to be >= 1, otherwise the cost-cutoff
|
||||
logic of the routing algorithm does not work and you get wrong results.
|
||||
- The costfactor is required to be >= 1, otherwise the cost-cutoff logic of the
|
||||
routing algorithm does not work and you get wrong results.
|
||||
|
||||
- The profile should be able to find a route with an average costfactor
|
||||
not very much larger than one, because otherwise the routing algorithm
|
||||
will not find a reasonable cost-cutoff, leading to a very large
|
||||
search area and thus to long processing times.
|
||||
- The profile should be able to find a route with an average costfactor not very
|
||||
much larger than one, because otherwise the routing algorithm will not find a
|
||||
reasonable cost-cutoff, leading to a very large search area and thus to long
|
||||
processing times.
|
||||
|
||||
- Forbidden ways or nodes must be treated as very high cost, because
|
||||
there is no *forbidden* value. Technically, values >= 10000 for a
|
||||
(way-)costfactor, and >= 1000000 for a nodes `initalcost` are treated
|
||||
as infinity, so please use these as the *forbidden* values.
|
||||
- Forbidden ways or nodes must be treated as very high cost, because there is no
|
||||
*forbidden* value. Technically, values >= 10000 for a (way-)costfactor, and >=
|
||||
1000000 for a nodes `initalcost` are treated as infinity, so please use these
|
||||
as the *forbidden* values.
|
||||
|
||||
- Ways with costfactor >= 10000 are considered as if they did not exist at all.
|
||||
|
||||
|
@ -362,52 +347,49 @@ Technical constraints
|
|||
Developing and debugging scripts
|
||||
--------------------------------
|
||||
|
||||
For developing scripts, the *brouter-web* web-application is your
|
||||
friend. You can use that either online at https://brouter.de/brouter-web
|
||||
or set up a local installation.
|
||||
For developing scripts, the *brouter-web* web-application is your friend. You
|
||||
can use that either online at https://brouter.de/brouter-web or set up a local
|
||||
installation.
|
||||
|
||||
*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
|
||||
the individual cost calculations per way-section in the *Data*-tab.
|
||||
*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 the individual cost
|
||||
calculations per way-section in the *Data*-tab.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
Lookup-Table evolution and the the *major* and *minor* versions
|
||||
---------------------------------------------------------------
|
||||
|
||||
The lookup-table is allowed to grow over time, to include more tags
|
||||
and values as needed. To support that evolution, it carries a major
|
||||
and a minor version number. These numbers are also encoded into
|
||||
the routing data files, taken from the lookups.dat that is used
|
||||
to pre-process the routing data files.
|
||||
The lookup-table is allowed to grow over time, to include more tags and values
|
||||
as needed. To support that evolution, it carries a major and a minor version
|
||||
number. These numbers are also encoded into the routing data files, taken from
|
||||
the lookups.dat that is used to pre-process the routing data files.
|
||||
|
||||
A major version change is considered to always break compatibility
|
||||
between the routing datafiles and the lookup table.
|
||||
A major version change is considered to always break compatibility between the
|
||||
routing datafiles and the lookup table.
|
||||
|
||||
A minor version change keeps the routing data files and the lookup-table
|
||||
compatible in both directions, using the following rules:
|
||||
|
||||
- if the data contains a key that is not contained in the lookup
|
||||
tables, it is ignored
|
||||
- if the data contains a key that is not contained in the lookup tables, it is
|
||||
ignored
|
||||
|
||||
- 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`
|
||||
- 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`
|
||||
|
||||
- if a profile uses a key that is not present in the data,
|
||||
it sees empty (=unset) values for that key
|
||||
- if a profile uses a key that is not present in the data, it sees empty
|
||||
(=unset) values for that key
|
||||
|
||||
- if a profile uses a value that is not present in the data,
|
||||
lookup matches for that value are always false.
|
||||
- if a profile uses a value that is not present in the data, lookup matches for
|
||||
that value are always false.
|
||||
|
||||
For a minor version change it is required that tags are only
|
||||
appended at the end of the table (or replace one of the dummy
|
||||
tags located between the way-tags and the relation pseudo-tags),
|
||||
and that values are only appended at the end of the value lists.
|
||||
This is because the routing data files address tags and values
|
||||
by their sequence numbers, so changing sequences would produce
|
||||
garbage data.
|
||||
For a minor version change it is required that tags are only appended at the end
|
||||
of the table (or replace one of the dummy tags located between the way-tags and
|
||||
the relation pseudo-tags), and that values are only appended at the end of the
|
||||
value lists. This is because the routing data files address tags and values by
|
||||
their sequence numbers, so changing sequences would produce garbage data.
|
||||
|
||||
Other resources
|
||||
---------------
|
||||
|
|
Loading…
Reference in a new issue