Skip to content

Commit

Permalink
Add valid actor reference in private actions check (#21)
Browse files Browse the repository at this point in the history
Signed-off-by: romanodanilo <[email protected]>

Signed-off-by: romanodanilo <[email protected]>
  • Loading branch information
romanodanilo authored Jul 9, 2024
1 parent 6057062 commit d8a1cee
Show file tree
Hide file tree
Showing 7 changed files with 368 additions and 0 deletions.
3 changes: 3 additions & 0 deletions qc_openscenario/checks/reference_checker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
from . import (
resolvable_traffic_signal_controller_by_traffic_signal_controller_ref as resolvable_traffic_signal_controller_by_traffic_signal_controller_ref,
)
from . import (
valid_actor_reference_in_private_actions as valid_actor_reference_in_private_actions,
)
2 changes: 2 additions & 0 deletions qc_openscenario/checks/reference_checker/reference_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
uniquely_resolvable_entity_references,
resolvable_signal_id_in_traffic_signal_state_action,
resolvable_traffic_signal_controller_by_traffic_signal_controller_ref,
valid_actor_reference_in_private_actions,
)


Expand Down Expand Up @@ -56,6 +57,7 @@ def run_checks(checker_data: models.CheckerData) -> None:
uniquely_resolvable_entity_references.check_rule,
resolvable_signal_id_in_traffic_signal_state_action.check_rule,
resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.check_rule,
valid_actor_reference_in_private_actions.check_rule,
]

for rule in rule_list:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import os, logging

from dataclasses import dataclass
from typing import List

from lxml import etree

from qc_baselib import Configuration, Result, IssueSeverity

from qc_openscenario import constants
from qc_openscenario.schema import schema_files
from qc_openscenario.checks import utils, models

from qc_openscenario.checks.reference_checker import reference_constants
from collections import deque, defaultdict

MIN_RULE_VERSION = "1.2.0"
RULE_SEVERITY = IssueSeverity.ERROR


def check_rule(checker_data: models.CheckerData) -> None:
"""
Rule ID: asam.net:xosc:1.2.0:reference_control.valid_actor_reference_in_private_actions
Description: In a ManeuverGroup, if the defined action is a private action an actor must be defined.
Severity: ERROR
Version range: [1.2.0, )
Remark:
None
More info at
- https://github.com/asam-ev/qc-openscenarioxml/issues/17
"""
logging.info("Executing valid_actor_reference_in_private_actions check")

schema_version = checker_data.schema_version
if schema_version is None:
logging.info(f"- Version not found in the file. Skipping check")
return

if utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0:
logging.info(
f"- Version {schema_version} is less than minimum required version {MIN_RULE_VERSION}. Skipping check"
)
return

rule_uid = checker_data.result.register_rule(
checker_bundle_name=constants.BUNDLE_NAME,
checker_id=reference_constants.CHECKER_ID,
emanating_entity="asam.net",
standard="xosc",
definition_setting=MIN_RULE_VERSION,
rule_full_name="reference_control.valid_actor_reference_in_private_actions",
)

root = checker_data.input_file_xml_root

maneuver_groups = root.findall(".//ManeuverGroup")
if maneuver_groups is None:
logging.error(
"Cannot find ManeuverGroup node in provided XOSC file. Skipping check"
)
return

for maneuver_group in maneuver_groups:

private_actions = maneuver_group.findall(".//PrivateAction")
entity_refs = maneuver_group.findall(".//EntityRef")

if private_actions is None or entity_refs is None:
logging.error(
"Cannot find PrivateAction or EntityRef node in provided XOSC file. Skipping check"
)
return

has_private_action = len(private_actions) > 0
no_actor_provided = len(entity_refs) == 0

has_issue = has_private_action and no_actor_provided

if has_issue:
xpath = root.getpath(maneuver_group)
issue_id = checker_data.result.register_issue(
checker_bundle_name=constants.BUNDLE_NAME,
checker_id=reference_constants.CHECKER_ID,
description="Issue flagging when no Actor is specified but a PrivateAction is used",
level=RULE_SEVERITY,
rule_uid=rule_uid,
)
private_actions_xpaths = [root.getpath(x) for x in private_actions]
checker_data.result.add_xml_location(
checker_bundle_name=constants.BUNDLE_NAME,
checker_id=reference_constants.CHECKER_ID,
issue_id=issue_id,
xpath=xpath,
description=f"ManeuverGroup at {xpath} uses private actions {private_actions_xpaths} but it defines no actor",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?xml version='1.0' encoding='UTF-8'?>
<OpenSCENARIO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../qc_openscenario/schema/1.3.0/OpenSCENARIO.xsd">
<FileHeader author="ASAM e.V." date="2021-02-05T18:50:17" description="Simple Overtaker example"
revMajor="1" revMinor="3" />
<ParameterDeclarations />
<CatalogLocations />
<RoadNetwork />
<Entities>
<ScenarioObject name="Vehicle 1">
<Vehicle name="Vehicle 1" vehicleCategory="car">
<BoundingBox>
<Center x="1.3" y="0.0" z="0.75" />
<Dimensions width="1.8" length="4.5" height="1.5" />
</BoundingBox>
<Performance maxSpeed="200.0" maxDeceleration="30.0" maxAcceleration="200.0" />
<Axles>
<FrontAxle positionZ="0.4" trackWidth="1.68" positionX="2.98"
maxSteering="0.5235987756" wheelDiameter="0.8" />
<RearAxle positionZ="0.4" trackWidth="1.68" positionX="0.0"
maxSteering="0.5235987756" wheelDiameter="0.8" />
</Axles>
</Vehicle>
</ScenarioObject>
</Entities>
<Storyboard>
<Init>
<Actions>
<Private entityRef="Vehicle 1">
<PrivateAction>
<TeleportAction>
<Position>
<WorldPosition x="0.0" y="0.0" />
</Position>
</TeleportAction>
</PrivateAction>
</Private>
</Actions>
</Init>
<Story name="Sample Story">
<Act name="Sample Act">
<ManeuverGroup maximumExecutionCount="1" name="Sample Maneuver">
<Actors selectTriggeringEntities="true">
<!-- Inserted rule violation since no EntityRef is defined but a
PrivateAction is used below. -->
</Actors>
<Maneuver name="Sample Maneuver">
<Event name="Sample Event" priority="overwrite">
<Action name="Sample Action">
<PrivateAction>
<LongitudinalAction>
<SpeedAction>
<SpeedActionTarget>
<AbsoluteTargetSpeed value="0.0" />
</SpeedActionTarget>
<SpeedActionDynamics dynamicsDimension="rate"
dynamicsShape="step" value="1" />
</SpeedAction>
</LongitudinalAction>
</PrivateAction>
</Action>
</Event>
</Maneuver>
</ManeuverGroup>
</Act>
</Story>
</Storyboard>
</OpenSCENARIO>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version='1.0' encoding='UTF-8'?>
<OpenSCENARIO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../qc_openscenario/schema/1.3.0/OpenSCENARIO.xsd">
<FileHeader author="ASAM e.V." date="2021-02-05T18:50:17" description="Simple Overtaker example"
revMajor="1" revMinor="3" />
<ParameterDeclarations />
<CatalogLocations />
<RoadNetwork />
<Entities>
<ScenarioObject name="Vehicle 1">
<Vehicle name="Vehicle 1" vehicleCategory="car">
<BoundingBox>
<Center x="1.3" y="0.0" z="0.75" />
<Dimensions width="1.8" length="4.5" height="1.5" />
</BoundingBox>
<Performance maxSpeed="200.0" maxDeceleration="30.0" maxAcceleration="200.0" />
<Axles>
<FrontAxle positionZ="0.4" trackWidth="1.68" positionX="2.98"
maxSteering="0.5235987756" wheelDiameter="0.8" />
<RearAxle positionZ="0.4" trackWidth="1.68" positionX="0.0"
maxSteering="0.5235987756" wheelDiameter="0.8" />
</Axles>
</Vehicle>
</ScenarioObject>
</Entities>
<Storyboard>
<Init>
<Actions>
<Private entityRef="Vehicle 1">
<PrivateAction>
<TeleportAction>
<Position>
<WorldPosition x="0.0" y="0.0" />
</Position>
</TeleportAction>
</PrivateAction>
</Private>
</Actions>
</Init>
<Story name="Sample Story">
<Act name="Sample Act">
<ManeuverGroup maximumExecutionCount="1" name="Sample Maneuver">
<Actors selectTriggeringEntities="true">
<EntityRef entityRef="Vehicle1234" />
</Actors>
<Maneuver name="Sample Maneuver">
<Event name="Sample Event" priority="overwrite">
<Action name="Sample Action">
<PrivateAction>
<LongitudinalAction>
<SpeedAction>
<SpeedActionTarget>
<AbsoluteTargetSpeed value="0.0" />
</SpeedActionTarget>
<SpeedActionDynamics dynamicsDimension="rate"
dynamicsShape="step" value="1" />
</SpeedAction>
</LongitudinalAction>
</PrivateAction>
</Action>
</Event>
</Maneuver>
</ManeuverGroup>
</Act>
</Story>
</Storyboard>
</OpenSCENARIO>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version='1.0' encoding='UTF-8'?>
<OpenSCENARIO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../qc_openscenario/schema/1.3.0/OpenSCENARIO.xsd">
<FileHeader author="ASAM e.V." date="2021-02-05T18:50:17" description="Simple Overtaker example"
revMajor="1" revMinor="3" />
<ParameterDeclarations />
<CatalogLocations />
<RoadNetwork />
<Entities>
<ScenarioObject name="Vehicle 1">
<Vehicle name="Vehicle 1" vehicleCategory="car">
<BoundingBox>
<Center x="1.3" y="0.0" z="0.75" />
<Dimensions width="1.8" length="4.5" height="1.5" />
</BoundingBox>
<Performance maxSpeed="200.0" maxDeceleration="30.0" maxAcceleration="200.0" />
<Axles>
<FrontAxle positionZ="0.4" trackWidth="1.68" positionX="2.98"
maxSteering="0.5235987756" wheelDiameter="0.8" />
<RearAxle positionZ="0.4" trackWidth="1.68" positionX="0.0"
maxSteering="0.5235987756" wheelDiameter="0.8" />
</Axles>
</Vehicle>
</ScenarioObject>
</Entities>
<Storyboard>
<Init>
<Actions>
<Private entityRef="Vehicle 1">
<PrivateAction>
<TeleportAction>
<Position>
<WorldPosition x="0.0" y="0.0" />
</Position>
</TeleportAction>
</PrivateAction>
</Private>
</Actions>
</Init>
</Storyboard>
</OpenSCENARIO>
87 changes: 87 additions & 0 deletions tests/test_reference_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,90 @@ def test_traffic_signal_controller_multiple_negative(
assert "bar" in reference_issues[0].locations[0].description
assert "0000" in reference_issues[1].locations[0].description
test_utils.cleanup_files()


def test_valid_actor_reference_in_private_actions_positive(
monkeypatch,
) -> None:
base_path = "tests/data/valid_actor_reference_in_private_actions/"
target_file_name = (
f"reference_control.valid_actor_reference_in_private_actions.positive.xosc"
)
target_file_path = os.path.join(base_path, target_file_name)

test_utils.create_test_config(target_file_path)

test_utils.launch_main(monkeypatch)

result = Result()
result.load_from_file(test_utils.REPORT_FILE_PATH)

_ = result.get_checker_result(
checker_bundle_name=constants.BUNDLE_NAME,
checker_id=reference_constants.CHECKER_ID,
)
assert (
len(
result.get_issues_by_rule_uid(
"asam.net:xosc:1.2.0:reference_control.valid_actor_reference_in_private_actions"
)
)
== 0
)


def test_valid_actor_reference_in_private_actions_positive_with_entity(
monkeypatch,
) -> None:
base_path = "tests/data/valid_actor_reference_in_private_actions/"
target_file_name = f"reference_control.valid_actor_reference_in_private_actions.positive.with_entity.xosc"
target_file_path = os.path.join(base_path, target_file_name)

test_utils.create_test_config(target_file_path)

test_utils.launch_main(monkeypatch)

result = Result()
result.load_from_file(test_utils.REPORT_FILE_PATH)

_ = result.get_checker_result(
checker_bundle_name=constants.BUNDLE_NAME,
checker_id=reference_constants.CHECKER_ID,
)
assert (
len(
result.get_issues_by_rule_uid(
"asam.net:xosc:1.2.0:reference_control.valid_actor_reference_in_private_actions"
)
)
== 0
)


def test_valid_actor_reference_in_private_actions_negative(
monkeypatch,
) -> None:
base_path = "tests/data/valid_actor_reference_in_private_actions/"
target_file_name = (
f"reference_control.valid_actor_reference_in_private_actions.negative.xosc"
)
target_file_path = os.path.join(base_path, target_file_name)

test_utils.create_test_config(target_file_path)

test_utils.launch_main(monkeypatch)

result = Result()
result.load_from_file(test_utils.REPORT_FILE_PATH)

_ = result.get_checker_result(
checker_bundle_name=constants.BUNDLE_NAME,
checker_id=reference_constants.CHECKER_ID,
)

reference_issues = result.get_issues_by_rule_uid(
"asam.net:xosc:1.2.0:reference_control.valid_actor_reference_in_private_actions"
)
assert len(reference_issues) == 1
assert reference_issues[0].level == IssueSeverity.ERROR
test_utils.cleanup_files()

0 comments on commit d8a1cee

Please sign in to comment.