Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add parameter substitution #297

Merged
merged 3 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions launch_ros/launch_ros/actions/set_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ def parse(cls, entity: Entity, parser: Parser):
@property
def name(self) -> ParameterName:
"""Getter for name."""
return self.__param_dict.keys()[0]
return list(self.__param_dict.keys())[0]

@property
def value(self) -> ParameterValue:
"""Getter for value."""
return self.__param_dict.values()[0]
return list(self.__param_dict.values())[0]

def execute(self, context: LaunchContext):
"""Execute the action."""
Expand Down
2 changes: 2 additions & 0 deletions launch_ros/launch_ros/substitutions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
from .find_package import FindPackage
from .find_package import FindPackagePrefix
from .find_package import FindPackageShare
from .parameter import Parameter


__all__ = [
'ExecutableInPackage',
'FindPackage',
'FindPackagePrefix',
'FindPackageShare',
'Parameter',
]
72 changes: 72 additions & 0 deletions launch_ros/launch_ros/substitutions/parameter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright 2022 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Module for the Parameter substitution."""

from typing import Iterable
from typing import List
from typing import Text

from launch.frontend import expose_substitution
from launch.launch_context import LaunchContext
from launch.some_substitutions_type import SomeSubstitutionsType
from launch.substitution import Substitution
from launch.substitutions.substitution_failure import SubstitutionFailure
from launch.utilities import normalize_to_list_of_substitutions
from launch.utilities import perform_substitutions


@expose_substitution('param')
class Parameter(Substitution):
"""
Substitution that tries to get a parameter that was set by SetParameter.

:raise: SubstitutionFailure when param is not found
"""

def __init__(
self,
name: SomeSubstitutionsType,
) -> None:
"""Create a Parameter substitution."""
super().__init__()
self.__name = normalize_to_list_of_substitutions(name)

@classmethod
def parse(cls, data: Iterable[SomeSubstitutionsType]):
"""Parse a Parameter substitution."""
if not data or len(data) != 1:
raise AttributeError('param substitutions expect 1 argument')
kwargs = {'name': data[0]}
return cls, kwargs

@property
def name(self) -> List[Substitution]:
"""Getter for name."""
return self.__name

def describe(self) -> Text:
"""Return a description of this substitution as a string."""
name_str = ' + '.join([sub.describe() for sub in self.name])
return '{}(name={})'.format(self.__class__.__name__, name_str)

def perform(self, context: LaunchContext) -> Text:
"""Perform the substitution."""
name = perform_substitutions(context, self.name)
params_container = context.launch_configurations.get('global_params', None)
for param in params_container:
if isinstance(param, tuple):
if param[0] == name:
return param[1]
raise SubstitutionFailure("parameter '{}' not found".format(name))
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright 2022 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import io
import textwrap

from launch import LaunchService
from launch.frontend import Parser
from launch.utilities import perform_substitutions


def test_parameter_substitution_yaml():
yaml_file = textwrap.dedent(
r"""
launch:
- set_parameter:
name: name
value: value

- let:
name: result
value: $(param name)
"""
)
with io.StringIO(yaml_file) as f:
check_parameter_substitution(f)


def test_parameter_substitution_xml():
xml_file = textwrap.dedent(
r"""
<launch>
<set_parameter name="name" value="value" />
<let name="result" value="$(param name)" />
</launch>
"""
)
with io.StringIO(xml_file) as f:
check_parameter_substitution(f)


def check_parameter_substitution(file):
root_entity, parser = Parser.load(file)
ld = parser.parse_description(root_entity)
ls = LaunchService()
ls.include_launch_description(ld)
assert 0 == ls.run()

def perform(substitution):
return perform_substitutions(ls.context, substitution)

set_parameter, let = ld.describe_sub_entities()
assert perform(set_parameter.name) == 'name'
assert perform(set_parameter.value) == 'value'
assert perform(let.name) == 'result'
assert perform(let.value) == 'value'
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2022 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Test for the Parameter substitutions."""

from launch import LaunchContext

from launch_ros.actions import SetParameter
from launch_ros.substitutions import Parameter


def test_parameter_substitution():
context = LaunchContext()
SetParameter('name', 'value').execute(context)
assert Parameter('name').perform(context) == 'value'
jacobperron marked this conversation as resolved.
Show resolved Hide resolved