Skip to content

Commit d759fc0

Browse files
committed
fix: resolve multiple validation bugs, add ontology auto-detection, fix documentation
- Fix ignore_tracks class with no attributes causing validation errors - Fix three bugs in _check_attribute_scopes (identity comparison, early return, tracking granularity) - Fix redundant sensor lookup, inconsistent horizon_tolerance default, bare ValueError/AssertionError - Remove dead _build_error_path function, fix placeholder docstring - Add detect_ontology() for automatic ontology detection based on unique class names - Integrate auto-detection into validate() when no ontology explicitly provided - Fix incorrect AutomatedTrain and OSDAR26 class listings in README, api.rst, and howtos - Remove ignore_tracks from OSDAR26 unique classes (exists in both automatedtrain and osdar26)
1 parent 8c935ef commit d759fc0

19 files changed

Lines changed: 343 additions & 44 deletions

File tree

README.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -181,25 +181,29 @@ Pre-built ontology parameter files are provided and accessible via the API:
181181
|----------|------|---------|-------------|
182182
| `osdar23` | OSDAR23 | OSDAR23 | Original railway environment annotation ontology. Includes standard occlusion ranges (0-25%, 25-50%, 50-75%, 75-99%, 100%) and core railway classes. |
183183
| `osdar26` | OSDAR26 | OSDAR26 | Extended railway environment ontology with 25 object classes. Features comprehensive signal aspects (Hp, Ks, Vr, Zs, Sh variants), updated occlusion ranges (0-24%, 25-49%, 50-74%, 75-99%, 100%), and additional classes. |
184-
| `automatedtrain` | AutomatedTrain | AutomatedTrain | Specialized ontology for automated train perception and safety-critical annotation. Includes obstacle detection, platform recognition, level crossings, speed signs. |
184+
| `automatedtrain` | AutomatedTrain | AutomatedTrain | Specialized ontology for automated train perception. Extended class set including train_front, reflective_test_object, trampoline, plane, and ignore_tracks. |
185185

186186
### OSDAR26 Classes (25 total)
187187
- **Persons**: `person`, `crowd`
188188
- **Personal Mobility**: `personal_item`, `pram`, `scooter`, `wheelchair`
189189
- **Vehicles**: `bicycle`, `group_of_bicycles`, `motorcycle`, `road_vehicle`
190190
- **Animals**: `animal`, `group_of_animals`
191191
- **Railway Vehicles**: `train`, `wagon`, `drag_shoe`
192-
- **Track Infrastructure**: `track`, `transition`, `switch`
192+
- **Track Infrastructure**: `track`, `switch`, `ignore_tracks`
193193
- **Signaling**: `signal`, `signal_pole`, `signal_bridge`, `catenary_pole`, `buffer_stop`
194194
- **Hazards**: `flame`, `smoke`
195195

196-
### AutomatedTrain Classes
196+
### AutomatedTrain Classes (29 total)
197197

198-
The AutomatedTrain ontology supports safety-critical classes for automated train operation:
199-
- **Core Classes**: `person`, `crowd`, `train`, `wagon`, `track`, `transition`, `switch`
198+
- **Persons**: `person`, `crowd`
199+
- **Personal Mobility**: `personal_item`, `pram`, `scooter`, `wheelchair`
200+
- **Vehicles**: `bicycle`, `group_of_bicycles`, `motorcycle`, `road_vehicle`
201+
- **Animals**: `animal`, `group_of_animals`
202+
- **Railway Vehicles**: `train`, `train_front`, `wagons`, `drag_shoe`
203+
- **Track Infrastructure**: `track`, `switch`, `ignore_tracks`
200204
- **Signaling**: `signal`, `signal_pole`, `signal_bridge`, `catenary_pole`, `buffer_stop`
201-
- **Vehicles**: `road_vehicle`, `bicycle`, `motorcycle`, `animal`
202-
- **Safety-Critical**: `obstacle`, `platform`, `level_crossing`, `speed_sign`
205+
- **Hazards**: `flame`, `smoke`
206+
- **Special**: `reflective_test_object`, `trampoline`, `plane`
203207

204208
## Supported Sensors
205209

config/ontologies/automatedtrain.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ track:
523523
attribute_type: boolean
524524
scope: frame
525525

526-
trackId:
526+
trackID:
527527
attribute_type: string
528528
scope: annotation
529529

@@ -812,10 +812,6 @@ smoke:
812812
scope: annotation
813813

814814
ignore_tracks:
815-
noError:
816-
attribute_type:
817-
type: single-select
818-
options: [noError]
819815

820816

821817
reflective_test_object:

config/schemas/ontology_schema_v2.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ definitions:
4747
class:
4848
additionalProperties:
4949
"$ref": "#/definitions/attribute"
50-
type: object
50+
type: [object, "null"]
5151

5252
integer_attribute:
5353
const: integer

docs/source/api.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ Available Ontologies
4040
and classes for personal_item, pram, scooter, flame, smoke.
4141

4242
**AutomatedTrain** (``automatedtrain``)
43-
Specialized ontology for automated train perception and safety-critical annotation.
44-
Includes obstacle detection, platform recognition, level crossings, and speed signs.
43+
Specialized ontology for automated train perception. Extended class set (29 classes)
44+
including train_front, reflective_test_object, trampoline, plane, and ignore_tracks.
4545

4646
**OSDAR23** (``osdar23``)
4747
Original railway environment annotation ontology for the OSDAR23 dataset.

docs/source/howtos/1 Validating Scenes.rst

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,15 @@ Pre-built ontology parameter files are provided in the ``config/ontologies/`` di
5959
- Updated occlusion ranges: 0-24%, 25-49%, 50-74%, 75-99%, 100%
6060
- Additional object classes: personal_item (suitcase, backpack, handbag, bag, etc.), pram (stroller, buggy, babySeat), scooter (eScooter, scooter, hoverboard)
6161
- Enhanced animal species coverage (dog, cat, racoon, badger, swan, sheep, cow, horse, pig, fox, wolf, wildBoar, deer, stork, rabbit, bird)
62-
- Complete railway infrastructure elements (track, switch, transition, catenary_pole, signal_pole, buffer_stop)
62+
- Complete railway infrastructure elements (track, switch, ignore_tracks, catenary_pole, signal_pole, buffer_stop)
6363
- Hazard detection (flame, smoke)
6464

6565
**AutomatedTrain** (``config/ontologies/automatedtrain.yaml``)
66-
Specialized ontology for automated train perception and safety-critical railway environment annotation:
66+
Specialized ontology for automated train perception with 29 object classes:
6767

68-
- **Safety-critical classes**: obstacle, platform, level_crossing, speed_sign
68+
- **Extended classes**: train_front, reflective_test_object, trampoline, plane, ignore_tracks
6969
- Switch state tracking (straight, diverging)
70-
- Emergency vehicle detection
71-
- Level crossing state monitoring (open, closing, closed, opening)
72-
- Boolean safety indicators for critical situations
70+
- Uses plural ``wagons`` (vs. singular ``wagon`` in OSDAR26)
7371

7472
Usage Examples
7573
##############

raillabel_providerkit/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .convert.convert import convert
1111
from .export.export_scenes import export_scenes
1212
from .ontologies import (
13+
detect_ontology,
1314
get_ontology_path,
1415
get_schema_path,
1516
list_available_ontologies,
@@ -29,6 +30,7 @@
2930
"convert",
3031
"export_scenes",
3132
"validate",
33+
"detect_ontology",
3234
"get_ontology_path",
3335
"get_schema_path",
3436
"list_available_ontologies",

raillabel_providerkit/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,8 +452,8 @@ def export_command(
452452
@click.option(
453453
"--horizon-tolerance",
454454
type=float,
455-
default=0.0,
456-
help="Tolerance buffer as percentage above horizon (e.g., 5.0 for 5%%). Default is 0.0.",
455+
default=10.0,
456+
help="Tolerance buffer as percentage above horizon (e.g., 10.0 for 10%%). Default is 10.0.",
457457
)
458458
@click.option("-q", "--quiet", is_flag=True, help="Disable progress bars")
459459
def run_raillabel_providerkit( # noqa: PLR0913

raillabel_providerkit/ontologies/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
"""Package for built-in ontology and schema definitions."""
55

66
from .manager import (
7+
detect_ontology,
78
get_ontology_path,
89
get_schema_path,
910
list_available_ontologies,
1011
list_available_schemas,
1112
)
1213

1314
__all__ = [
15+
"detect_ontology",
1416
"get_ontology_path",
1517
"get_schema_path",
1618
"list_available_ontologies",

raillabel_providerkit/ontologies/manager.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@
1414
All ontology files are stored centrally in the config/ontologies/ directory.
1515
"""
1616

17+
from __future__ import annotations
18+
1719
from pathlib import Path
1820

21+
import raillabel
22+
1923

2024
def _get_config_dir() -> Path:
2125
"""Get the path to the config directory.
@@ -156,7 +160,55 @@ def list_available_schemas() -> list[str]:
156160
return ["raillabel", "osdar23", "osdar26", "automatedtrain", "understand_ai_t4", "ontology"]
157161

158162

163+
_UNIQUE_CLASSES: dict[str, set[str]] = {
164+
"automatedtrain": {"train_front", "reflective_test_object", "trampoline", "plane"},
165+
"osdar23": {"transition"},
166+
}
167+
168+
_EXCLUSIVE_PAIRS: dict[str, set[str]] = {
169+
"automatedtrain": {"personal_item", "pram", "scooter"},
170+
"osdar26": {"wagon"},
171+
}
172+
173+
174+
def detect_ontology(scene: raillabel.Scene) -> str | None:
175+
"""Detect which ontology matches the object types in a scene.
176+
177+
Uses unique class names to determine which ontology should be applied. Returns
178+
None if no ontology can be reliably detected.
179+
180+
Parameters
181+
----------
182+
scene : raillabel.Scene
183+
The loaded scene to analyze.
184+
185+
Returns
186+
-------
187+
str | None
188+
Name of the detected ontology ('automatedtrain', 'osdar23', 'osdar26'),
189+
or None if detection is ambiguous or no objects are present.
190+
"""
191+
object_types = {obj.type for obj in scene.objects.values()}
192+
193+
if not object_types:
194+
return None
195+
196+
for ontology_name, unique_classes in _UNIQUE_CLASSES.items():
197+
if object_types & unique_classes:
198+
return ontology_name
199+
200+
if "wagon" in object_types:
201+
return "osdar26"
202+
if "wagons" in object_types:
203+
if object_types & _EXCLUSIVE_PAIRS["automatedtrain"]:
204+
return "automatedtrain"
205+
return "osdar23"
206+
207+
return None
208+
209+
159210
__all__ = [
211+
"detect_ontology",
160212
"get_ontology_path",
161213
"get_schema_path",
162214
"list_available_ontologies",

raillabel_providerkit/validation/validate.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from raillabel import Scene
1010
from raillabel.json_format import JSONScene
1111

12+
from raillabel_providerkit.ontologies import detect_ontology, get_ontology_path
1213
from raillabel_providerkit.validation import Issue
1314

1415
from . import (
@@ -95,6 +96,10 @@ def validate( # noqa: C901, PLR0912, PLR0913
9596

9697
if ontology_source is not None:
9798
errors.extend(validate_ontology(scene, ontology_source))
99+
else:
100+
detected = detect_ontology(scene)
101+
if detected is not None:
102+
errors.extend(validate_ontology(scene, get_ontology_path(detected)))
98103

99104
if validate_for_empty_frames:
100105
errors.extend(validate_empty_frames(scene))

0 commit comments

Comments
 (0)