Skip to content

Commit

Permalink
Merge pull request #118 from asam-ev/ivex/tung/support-final-version-…
Browse files Browse the repository at this point in the history
…range

Add the concept of applicable versions
  • Loading branch information
andreaskern74 authored Nov 19, 2024
2 parents 78bfd69 + d27f414 commit 3ca80b5
Show file tree
Hide file tree
Showing 12 changed files with 1,195 additions and 118 deletions.
53 changes: 46 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,15 @@ Contributions of valid and invalid OpenDrive sample files are also welcome. New
1. Create a new Python module for each checker.
2. Specify the following global variables for the Python module

| Variable | Meaning |
| --- | --- |
| `CHECKER_ID` | The ID of the checker |
| `CHECKER_DESCRIPTION` | The description of the checker |
| `CHECKER_PRECONDITIONS` | A set of other checkers in which if any of them raise an issue, the current checker will be skipped |
| `RULE_UID` | The rule UID of the rule that the checker will check |
| Variable | Presence | Meaning |
| --- | --- | --- |
| `CHECKER_ID` | Required | The ID of the checker |
| `CHECKER_DESCRIPTION` | Required | The description of the checker |
| `CHECKER_PRECONDITIONS` | Required | A set of other checkers in which if any of them raise an issue, the current checker will be skipped |
| `RULE_UID` | Required | The rule UID of the rule that the checker will check |
| `APPLICABLE_VERSIONS` | Optional | An optional variable to define extra constraints on the applicable version. See details below. |

3. Implement the checker logic in the following function:
1. Implement the checker logic in the following function:

```python
def check_rule(checker_data: models.CheckerData) -> None:
Expand All @@ -304,3 +305,41 @@ def run_checks(config: Configuration, result: Result) -> None:
```

All the checkers in this checker bundle are implemented in this way. Take a look at some of them before implementing your first checker.

**A note on `APPLICABLE_VERSIONS`**

The `APPLICABLE_VERSIONS` variable can be used to define additional constraints on the versions of the input files that a rule supports, in addition to the **definition setting** in the rule UID. It can be specified in the same way as the [Python Version Specifiers](https://packaging.python.org/en/latest/specifications/version-specifiers/#id5). For example:

```python
APPLICABLE_VERSIONS = "<1.8.0"
APPLICABLE_VERSIONS = ">=1.6.0"
APPLICABLE_VERSIONS = "<1.8.0,>=1.6.0"
```

The specification consists of a series of version clauses, separated by commas. The comma is equivalent to a logical "AND" operator: a candidate version must match all given version clauses in order to match the **applicable versions** as a whole.

The **applicable versions** only supports versions of in the full semantic form `major.minor.patch`. Elision of `minor` or `patch` elements are not supported. For example, `1.7.0rc1` and `1.7` are not supported, but `1.7.0` is supported.

The **applicable versions** only supports the following comparison operators.

* `<` smaller than **(upper bound)**
* `<=` smaller or equal than **(upper bound)**
* `>` greater than **(lower bound)**
* `>=` greater or equal than **(lower bound)**

The **definition setting** in rule UID and the **applicable versions** together define the versions of the input file in which a rule can be applied. For example, let's consider a rule UID for ASAM OpenDRIVE `asam.net:xodr:1.6.0:*`. The **definition setting** in this case is `1.6.0`.

1. If no **applicable versions** is specified, a rule will be applied starting from the **definition setting** version, up to the most recent one.
* For the example, if the `APPLICABLE_VERSIONS` variable does not exist, then the rule is applied to OpenDRIVE versions 1.6.0, 1.6.1, 1.7.0, 1.8.0: the internal representation of the version specifier is `>=1.6.0`.

2. If the **applicable versions** is specified, and defines only **upper bounds**, then the **definition setting** defines the lower bound
* For the example, if `APPLICABLE_VERSIONS = "<1.8.0"`, then the rule is applied to OpenDRIVE versions 1.6.0, 1.6.1, 1.7.0: the internal representation of the version specifier is `>=1.6.0,<1.8.0`.

3. If the **applicable versions** is specified, and defines at least one **lower bound**, then the **definition setting** is ignored. Only the **lower bounds** defined in the **applicable versions** are taken into account.
* For the example, if `APPLICABLE_VERSIONS = ">=1.5.0"`, then the rule is applied to OpenDRIVE versions 1.5.0, 1.6.0, 1.6.1, 1.7.0, 1.8.0: the internal representation of the version specifier is `>=1.5.0`.

| Case Number | Example Rule | `APPLICABLE_VERSIONS` | Internal Representation | File versions to be checked |
|-------------|-------------------------|----------------------|----------------------------------|-----------------------------------|
| 1 | `asam.net:xodr:1.6.0:*` | `""` | `">=1.6.0"` | 1.6.0, 1.6.1, 1.7.0, 1.8.0 |
| 2 | `asam.net:xodr:1.6.0:*` | `"<1.8.0"` | `">=1.6.0,<1.8.0"` | 1.6.0, 1.6.1, 1.7.0 |
| 3 | `asam.net:xodr:1.6.0:*` | `">=1.5.0"` | `">=1.5.0"` | 1.5.0, 1.6.0, 1.6.1, 1.7.0, 1.8.0 |
75 changes: 43 additions & 32 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ scipy = "^1.14.0"
pyclothoids = "^0.1.5"
transforms3d = "^0.4.2"
xmlschema = "^3.3.1"
semver = "^3.0.0"

[tool.poetry.group.dev.dependencies]
pytest = "^8.2.2"
Expand Down
1 change: 1 addition & 0 deletions qc_opendrive/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
from . import constants as constants
from . import checks as checks
from . import basic_preconditions as basic_preconditions
from . import version as version
32 changes: 0 additions & 32 deletions qc_opendrive/base/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1762,35 +1762,3 @@ def get_middle_point_xyz_at_height_zero_from_lane_by_s(

def get_s_offset_from_access(access: etree._ElementTree) -> Optional[float]:
return to_float(access.get("sOffset"))


def compare_versions(version1: str, version2: str) -> int:
"""Compare two version strings like "X.x.x"
This function is to avoid comparing version string basing on lexicographical order
that could cause problem. E.g.
1.10.0 > 1.2.0 but lexicographical comparison of string would return the opposite
Args:
version1 (str): First string to compare
version2 (str): Second string to compare
Returns:
int: 1 if version1 is bigger than version2. 0 if the version are the same. -1 otherwise
"""
v1_components = list(map(int, version1.split(".")))
v2_components = list(map(int, version2.split(".")))

# Compare each component until one is greater or they are equal
for v1, v2 in zip(v1_components, v2_components):
if v1 < v2:
return -1
elif v1 > v2:
return 1

# If all components are equal, compare based on length
if len(v1_components) < len(v2_components):
return -1
elif len(v1_components) > len(v2_components):
return 1
else:
return 0
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
CHECKER_DESCRIPTION = "Each connecting road shall be represented by exactly one element. A connecting road may contain as many lanes as required."
CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS
RULE_UID = "asam.net:xodr:1.7.0:junctions.connection.one_connection_element"
APPLICABLE_VERSION = "<=1.7.0"


def _check_junctions_connection_one_connection_element(
Expand Down
Loading

0 comments on commit 3ca80b5

Please sign in to comment.