Files
behavior-tree/ros2/bt_executor/tools/check_static.py
T

47 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Checks fixed-tree expansion and generated IDL headers without claiming ROS build."""
from pathlib import Path
import re
import xml.etree.ElementTree as ET
PACKAGE = Path(__file__).resolve().parents[1]
REPOSITORY = PACKAGE.parents[1]
root = ET.parse(PACKAGE / 'trees/fixed_workflow.xml').getroot()
assert root.attrib['BTCPP_format'] == '4'
trees = {v.attrib['ID']: v for v in root.findall('BehaviorTree')}
assert {'NavigateSkill', 'GroundTargetSkill', 'PickSkill', 'CheckFreeSpaceSkill',
'PlaceSkill', 'AskUserSkill'} <= set(trees)
assert [v.tag for v in trees['TaskRoot'][0]] == ['ApprovedPlanGate', 'SubTree']
def expand(node, inputs=None):
inputs = inputs or {}
if node.tag == 'RunStage':
stage = node.attrib['stage']
return [inputs[stage[1:-1]] if stage.startswith('{') else stage]
if node.tag == 'SubTree':
return expand(trees[node.attrib['ID']], {**inputs, **node.attrib})
return [stage for child in node for stage in expand(child, inputs)]
expected = re.findall(r'case Stage::\w+:return "(\w+)"',
(REPOSITORY / 'core/src/workflow.cpp').read_text())
actual = expand(trees['TaskRoot'])
assert actual == expected, (actual, expected)
assert not any(v.tag in {'Script', 'ScriptCondition', 'RetryUntilSuccessful'} for v in root.iter())
assert trees['AskUserSkill'][0].tag == 'RequestClarification'
def header_name(name):
return re.sub(r'([a-z0-9])([A-Z])', r'\1_\2',
re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', name)).lower()
for source in list((PACKAGE / 'src').glob('*.cpp')) + list((PACKAGE / 'include/bt_executor').glob('*.hpp')):
for kind, name in re.findall(r'bt_skill_interfaces/(action|msg)/(\w+)\.hpp', source.read_text()):
candidates = list((PACKAGE.parent / 'bt_skill_interfaces' / kind).glob('*'))
assert any(header_name(v.stem) == name for v in candidates), (source, kind, name)
ET.parse(PACKAGE / 'package.xml')
print(f'Static checks passed: {len(actual)} ordered core stages, six skill templates, generated IDL include names, package XML.')
print('This does not compile C++ or validate ROS2 middleware behavior.')