feat(experement): add planner scene mode without reference runner
This commit is contained in:
@@ -17,7 +17,7 @@ import yaml
|
|||||||
|
|
||||||
|
|
||||||
EXPERIMENT_IDS = tuple(range(1, 21))
|
EXPERIMENT_IDS = tuple(range(1, 21))
|
||||||
MODES = ('view', 'execute')
|
MODES = ('view', 'execute', 'planner')
|
||||||
DEFAULT_START_DELAY_SEC = 3.0
|
DEFAULT_START_DELAY_SEC = 3.0
|
||||||
DEFAULT_TRACE_DIR = '~/.ros/iiwa_experement/runs'
|
DEFAULT_TRACE_DIR = '~/.ros/iiwa_experement/runs'
|
||||||
LOCAL_PROTOS = (
|
LOCAL_PROTOS = (
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ def supervisor_process(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def mode_read_only(mode: str) -> bool:
|
||||||
|
"""Only ``view`` is passive; execute and planner accept grab commands."""
|
||||||
|
return mode == 'view'
|
||||||
|
|
||||||
|
|
||||||
def runtime_actions(
|
def runtime_actions(
|
||||||
experiment_id: int,
|
experiment_id: int,
|
||||||
scene_config: str,
|
scene_config: str,
|
||||||
@@ -126,7 +131,10 @@ def runtime_actions(
|
|||||||
package_share = Path(get_package_share_directory('iiwa_experement'))
|
package_share = Path(get_package_share_directory('iiwa_experement'))
|
||||||
if geometry_path is None:
|
if geometry_path is None:
|
||||||
geometry_path = str(package_share / 'config' / 'geometry.yaml')
|
geometry_path = str(package_share / 'config' / 'geometry.yaml')
|
||||||
read_only = mode != 'execute'
|
# Only the passive view mode locks the supervisor. Both the reference
|
||||||
|
# executor and the external-graph planner need to accept grab/dock
|
||||||
|
# commands; the planner mode simply never starts the reference runner.
|
||||||
|
read_only = mode_read_only(mode)
|
||||||
actions = [
|
actions = [
|
||||||
IncludeLaunchDescription(
|
IncludeLaunchDescription(
|
||||||
PythonLaunchDescriptionSource(
|
PythonLaunchDescriptionSource(
|
||||||
@@ -264,7 +272,9 @@ def generate_launch_description():
|
|||||||
default_value='view',
|
default_value='view',
|
||||||
description=(
|
description=(
|
||||||
'view = open the prepared scene without motion; '
|
'view = open the prepared scene without motion; '
|
||||||
'execute = run the reference sequence after start_delay_sec.'
|
'execute = run the reference sequence after start_delay_sec; '
|
||||||
|
'planner = writable scene for an externally supplied graph, '
|
||||||
|
'no reference sequence.'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
|
|||||||
@@ -45,12 +45,17 @@ def test_invalid_experiment_ids_are_rejected(raw):
|
|||||||
validate_experiment_id(raw)
|
validate_experiment_id(raw)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('raw, expected', [('view', 'view'), ('execute', 'execute'), (' VIEW ', 'view')])
|
@pytest.mark.parametrize('raw, expected', [
|
||||||
|
('view', 'view'),
|
||||||
|
('execute', 'execute'),
|
||||||
|
('planner', 'planner'),
|
||||||
|
(' VIEW ', 'view'),
|
||||||
|
])
|
||||||
def test_valid_modes(raw, expected):
|
def test_valid_modes(raw, expected):
|
||||||
assert validate_mode(raw) == expected
|
assert validate_mode(raw) == expected
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('raw', ['', 'run', 'VIEW '[:-1] + 'x', '1'])
|
@pytest.mark.parametrize('raw', ['', 'run', 'VIEW '[:-1] + 'x', '1', 'plan'])
|
||||||
def test_invalid_modes_are_rejected(raw):
|
def test_invalid_modes_are_rejected(raw):
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
validate_mode(raw)
|
validate_mode(raw)
|
||||||
@@ -138,6 +143,46 @@ def test_execute_adds_the_reference_runner_after_the_supervisor():
|
|||||||
assert any(type(action) is ExecuteProcess for action in actions)
|
assert any(type(action) is ExecuteProcess for action in actions)
|
||||||
|
|
||||||
|
|
||||||
|
def _process_arguments(process):
|
||||||
|
return [item[0].text for item in process.cmd if item and item[0].text]
|
||||||
|
|
||||||
|
|
||||||
|
def test_planner_is_writable_and_has_no_reference_runner():
|
||||||
|
module = load_launch_module()
|
||||||
|
actions = module.runtime_actions(
|
||||||
|
experiment_id=20,
|
||||||
|
scene_config='/tmp/scenes.yaml',
|
||||||
|
setting_path='/tmp/setting.yaml',
|
||||||
|
mode='planner',
|
||||||
|
)
|
||||||
|
assert not any(
|
||||||
|
isinstance(action, Node) and action.node_executable == 'reference_runner'
|
||||||
|
for action in actions
|
||||||
|
)
|
||||||
|
processes = [action for action in actions if type(action) is ExecuteProcess]
|
||||||
|
assert len(processes) == 1
|
||||||
|
assert 'read_only:=false' in _process_arguments(processes[0])
|
||||||
|
assert module.mode_read_only('planner') is False
|
||||||
|
parameters = module.supervisor_parameters(
|
||||||
|
20, '/tmp/scenes.yaml', '/tmp/geometry.yaml', False,
|
||||||
|
)
|
||||||
|
assert parameters['read_only'] is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_view_remains_read_only_after_adding_the_planner_mode():
|
||||||
|
module = load_launch_module()
|
||||||
|
actions = module.runtime_actions(
|
||||||
|
experiment_id=1,
|
||||||
|
scene_config='/tmp/scenes.yaml',
|
||||||
|
setting_path='/tmp/setting.yaml',
|
||||||
|
mode='view',
|
||||||
|
)
|
||||||
|
processes = [action for action in actions if type(action) is ExecuteProcess]
|
||||||
|
assert 'read_only:=true' in _process_arguments(processes[0])
|
||||||
|
assert module.mode_read_only('view') is True
|
||||||
|
assert module.mode_read_only('execute') is False
|
||||||
|
|
||||||
|
|
||||||
def test_runtime_actions_can_register_cleanup(tmp_path):
|
def test_runtime_actions_can_register_cleanup(tmp_path):
|
||||||
module = load_launch_module()
|
module = load_launch_module()
|
||||||
actions = module.runtime_actions(
|
actions = module.runtime_actions(
|
||||||
|
|||||||
@@ -14,12 +14,17 @@ from iiwa_experement.runtime_config import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('raw, expected', [('view', 'view'), (' Execute ', 'execute')])
|
@pytest.mark.parametrize('raw, expected', [
|
||||||
|
('view', 'view'),
|
||||||
|
(' Execute ', 'execute'),
|
||||||
|
('planner', 'planner'),
|
||||||
|
(' PLANNER ', 'planner'),
|
||||||
|
])
|
||||||
def test_mode_validation(raw, expected):
|
def test_mode_validation(raw, expected):
|
||||||
assert validate_mode(raw) == expected
|
assert validate_mode(raw) == expected
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('raw', ['', 'motion', 'execute!'])
|
@pytest.mark.parametrize('raw', ['', 'motion', 'execute!', 'plan'])
|
||||||
def test_mode_validation_rejects_unknown_modes(raw):
|
def test_mode_validation_rejects_unknown_modes(raw):
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
validate_mode(raw)
|
validate_mode(raw)
|
||||||
|
|||||||
Reference in New Issue
Block a user