def test_dictionary_with_str():
    orig = [{'foo': 'bar', 'fiz': ['b', 'u', 'z']}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 'bar', 'fiz': ('b', 'u', 'z')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 'False', 'fiz': ['True', 'False', 'True']}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 'False', 'fiz': ('True', 'False', 'True')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': '1.2', 'fiz': ['2.3', '3.4', '4.5']}]
    norm = normalize_parameters(orig)
    expected = ({'foo': '1.2', 'fiz': ('2.3', '3.4', '4.5')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': '1', 'fiz': ['2', '3', '4']}]
    norm = normalize_parameters(orig)
    expected = ({'foo': '1', 'fiz': ('2', '3', '4')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'strs': ['True', '2.0', '3']}]
    norm = normalize_parameters(orig)
    expected = ({'strs': ('True', '2.0', '3')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #2
0
def test_dictionary_with_dissimilar_array():
    orig = [{'foo': 1, 'fiz': [True, 2.0, 3]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': ('True', '2.0', '3')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 1, 'fiz': [True, 1, TextSubstitution(text='foo')]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': ('True', '1', 'foo')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 1, 'fiz': [TextSubstitution(text='foo'), True, 1]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': ('foo', 'True', '1')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 1, 'fiz': [True, 1, [TextSubstitution(text='foo')]]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': ('True', '1', 'foo')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 1, 'fiz': [[TextSubstitution(text='foo')], True, 1]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': ('foo', 'True', '1')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
def test_dictionary_with_substitution():
    orig = [{TextSubstitution(text='bar'): TextSubstitution(text='baz')}]
    norm = normalize_parameters(orig)
    expected = ({'bar': 'baz'}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    # substitutions get yamlfied
    orig = [{TextSubstitution(text='false'): TextSubstitution(text='off')}]
    norm = normalize_parameters(orig)
    expected = ({'false': False}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #4
0
def test_dictionary_with_substitution_list_value():
    orig = [{
        'foo': [TextSubstitution(text='fiz'),
                TextSubstitution(text='buz')]
    }]
    norm = normalize_parameters(orig)
    expected = ({'foo': 'fizbuz'}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{
        'foo': [[TextSubstitution(text='fiz')], [TextSubstitution(text='buz')]]
    }]
    norm = normalize_parameters(orig)
    expected = ({'foo': ('fiz', 'buz')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #5
0
def test_mixed_path_dicts():
    orig = ['/foo/bar', {'fiz': {'buz': 3}}, pathlib.Path('/tmp/baz')]
    norm = normalize_parameters(orig)
    expected = (pathlib.Path('/foo/bar'), {
        'fiz.buz': 3
    }, pathlib.Path('/tmp/baz'))
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #6
0
def test_dictionary_with_int_and_float():
    orig = [{'foo': 1, 'fiz': [2, 3.1, 4]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': (2.0, 3.1, 4.0)}, )
    evaluated = evaluate_parameters(LaunchContext(), norm)
    assert evaluated == expected
    # pytest doesn't check int vs float type
    assert tuple(map(type, evaluated[0]['fiz'])) == (float, float, float)

    orig = [{'foo': 1, 'fiz': [2.0, 3, 4]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': (2.0, 3.0, 4.0)}, )
    evaluated = evaluate_parameters(LaunchContext(), norm)
    assert evaluated == expected
    # pytest doesn't check int vs float type
    assert tuple(map(type, evaluated[0]['fiz'])) == (float, float, float)
    def __init__(
        self,
        *,
        package: SomeSubstitutionsType,
        node_plugin: SomeSubstitutionsType,
        node_name: Optional[SomeSubstitutionsType] = None,
        node_namespace: Optional[SomeSubstitutionsType] = None,
        parameters: Optional[SomeParameters] = None,
        remappings: Optional[SomeRemapRules] = None,
        extra_arguments: Optional[SomeParameters] = None,
    ) -> None:
        """
        Initialize a ComposableNode description.

        :param package: name of the ROS package the node plugin lives in
        :param node_plugin: name of the plugin to be loaded
        :param node_name: name the node should have
        :param node_namespace: namespace the node should create topics/services/etc in
        :param parameters: list of either paths to yaml files or dictionaries of parameters
        :param remappings: list of from/to pairs for remapping names
        :param extra_arguments: container specific arguments to be passed to the loaded node
        """
        self.__package = normalize_to_list_of_substitutions(package)
        self.__node_plugin = normalize_to_list_of_substitutions(node_plugin)

        self.__node_name = None  # type: Optional[List[Substitution]]
        if node_name is not None:
            self.__node_name = normalize_to_list_of_substitutions(node_name)

        self.__node_namespace = None  # type: Optional[List[Substitution]]
        if node_namespace is not None:
            self.__node_namespace = normalize_to_list_of_substitutions(
                node_namespace)

        self.__parameters = None  # type: Optional[Parameters]
        if parameters is not None:
            self.__parameters = normalize_parameters(parameters)

        self.__remappings = None  # type: Optional[RemapRules]
        if remappings:
            self.__remappings = normalize_remap_rules(remappings)

        self.__extra_arguments = None  # type: Optional[Parameters]
        if extra_arguments:
            self.__extra_arguments = normalize_parameters(extra_arguments)
Exemple #8
0
def test_dictionary_with_mixed_substitutions_and_strings():
    orig = [{'foo': [TextSubstitution(text='fiz'), 'bar']}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 'fizbar'}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': [[TextSubstitution(text='fiz')], 'bar']}]
    norm = normalize_parameters(orig)
    expected = ({'foo': ('fiz', 'bar')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': ['bar', TextSubstitution(text='fiz')]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 'barfiz'}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': ['bar', [TextSubstitution(text='fiz')]]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': ('bar', 'fiz')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
def test_unallowed_yaml_types_in_substitutions():
    with pytest.raises(TypeError) as exc:
        orig = [{'foo': 1, 'fiz': TextSubstitution(text="{'asd': 3}")}]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Allowed value types' in str(exc.value)
    assert 'dict' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{'foo': 1, 'fiz': TextSubstitution(text='[1, 2.0, 3]')}]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty sequence' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{
            'foo': 1,
            'fiz': TextSubstitution(text='[[2, 3], [2, 3], [2, 3]]')
        }]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty sequence' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{'foo': 1, 'fiz': TextSubstitution(text='[]')}]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty sequence' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{
            'foo':
            1,
            'fiz': [[TextSubstitution(text="['asd', 'bsd']")],
                    [TextSubstitution(text="['asd', 'csd']")]]
        }]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty sequence' in str(exc.value)
    def __init__(
        self,
        *,
        package: SomeSubstitutionsType,
        node_executable: SomeSubstitutionsType,
        node_name: Optional[SomeSubstitutionsType] = None,
        node_namespace: SomeSubstitutionsType = '',
        parameters: Optional[SomeParameters] = None,
        remappings: Optional[SomeRemapRules] = None,
        arguments: Optional[Iterable[SomeSubstitutionsType]] = None,
    ) -> None:
        """
        Construct a SandboxedNode description.

        The actual node execution is delegated to the sandboxing environment
        defined by the policy.

        :param: package is the name of the node's package and is required for
        resolving the node.
        :param: node_executable is the name of the node's executable and is
        required for resolving the node.
        :param: node_name is an optional name attached to the node when it is
        launched. Defaults to NONE.
        :param: node_namespace is an optional namespace attached to the node
        when it is launched. Defaults to empty string.
        :param: parameters are the optional runtime configurations for the
        node, read from a YAML file. Defaults to NONE.
        :param: remappings are the ordered list of 'to' and 'from' string
        pairs to be passed to a node as ROS remapping rules.
        """
        self.__package = \
            normalize_to_list_of_substitutions(package)
        self.__node_executable = \
            normalize_to_list_of_substitutions(node_executable)

        self.__node_name = None
        if node_name is not None:
            self.__node_name = normalize_to_list_of_substitutions(node_name)

        self.__node_namespace = None
        if node_namespace is not None:
            self.__node_namespace = \
                normalize_to_list_of_substitutions(node_namespace)

        self.__parameters = None
        if parameters is not None:
            self.__parameters = normalize_parameters(parameters)

        self.__remappings = None
        if remappings is not None:
            self.__remappings = normalize_remap_rules(remappings)
Exemple #11
0
def test_unallowed_yaml_types_as_strings():
    # All the tests from test_unallowed_yaml_types_in_substitutions
    # but coerced to the proper type with ParameterValue
    orig = [{'foo': 1, 'fiz': ParameterValue(TextSubstitution(text="{'asd': 3}"), value_type=str)}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': "{'asd': 3}"},)
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 1, 'fiz': ParameterValue(TextSubstitution(text='[1, 2.0, 3]'),
                                             value_type=str)}]
    norm = normalize_parameters(orig)
    evaluate_parameters(LaunchContext(), norm)
    expected = ({'foo': 1, 'fiz': '[1, 2.0, 3]'},)
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 1, 'fiz': ParameterValue(TextSubstitution(text='[[2, 3], [2, 3], [2, 3]]'),
                                             value_type=str)}]
    norm = normalize_parameters(orig)
    evaluate_parameters(LaunchContext(), norm)
    expected = ({'foo': 1, 'fiz': '[[2, 3], [2, 3], [2, 3]]'},)
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 1, 'fiz': ParameterValue(TextSubstitution(text='[]'), value_type=str)}]
    norm = normalize_parameters(orig)
    evaluate_parameters(LaunchContext(), norm)
    expected = ({'foo': 1, 'fiz': '[]'},)
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{
        'foo': 1,
        'fiz': ParameterValue([
            [TextSubstitution(text="['asd', 'bsd']")],
            [TextSubstitution(text="['asd', 'csd']")]
        ], value_type=List[str])
    }]
    norm = normalize_parameters(orig)
    evaluate_parameters(LaunchContext(), norm)
    expected = ({'foo': 1, 'fiz': ["['asd', 'bsd']", "['asd', 'csd']"]},)
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'foo': 1,
             'fiz': ParameterValue(TextSubstitution(text='Text That : Cannot Be Parsed As : Yaml'),
                                   value_type=str)}]
    norm = normalize_parameters(orig)
    evaluate_parameters(LaunchContext(), norm)
    expected = ({'foo': 1, 'fiz': 'Text That : Cannot Be Parsed As : Yaml'},)
    assert evaluate_parameters(LaunchContext(), norm) == expected
def test_dictionary_with_dissimilar_array():
    with pytest.raises(TypeError) as exc:
        orig = [{'foo': 1, 'fiz': [True, 2.0, 3]}]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{'foo': 1, 'fiz': [True, 1, TextSubstitution(text='foo')]}]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{'foo': 1, 'fiz': [TextSubstitution(text='foo'), True, 1]}]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{'foo': 1, 'fiz': [True, 1, [TextSubstitution(text='foo')]]}]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{'foo': 1, 'fiz': [[TextSubstitution(text='foo')], True, 1]}]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty' in str(exc.value)

    with pytest.raises(TypeError) as exc:
        orig = [{
            'foo': [
                [TextSubstitution(text='True')],
                [TextSubstitution(text='2.0')],
                [TextSubstitution(text='3')],
            ]
        }]
        norm = normalize_parameters(orig)
        evaluate_parameters(LaunchContext(), norm)
    assert 'Expected a non-empty' in str(exc.value)
def test_dictionary_with_substitution_list_value():
    orig = [{
        'foo': [[TextSubstitution(text='fiz'),
                 TextSubstitution(text='buz')],
                TextSubstitution(text='fiz')]
    }]
    norm = normalize_parameters(orig)
    expected = ({'foo': ('fizbuz', 'fiz')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{
        'foo': [TextSubstitution(text='fiz'),
                TextSubstitution(text='buz')]
    }]
    norm = normalize_parameters(orig)
    expected = ({'foo': 'fizbuz'}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{
        'foo': [[TextSubstitution(text='fiz')], [TextSubstitution(text='buz')]]
    }]
    norm = normalize_parameters(orig)
    expected = ({'foo': ('fiz', 'buz')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{
        'bools': [[TextSubstitution(text='True')],
                  [TextSubstitution(text='False')]]
    }]
    norm = normalize_parameters(orig)
    expected = ({'bools': (True, False)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{
        'ints': [[TextSubstitution(text='1')], [TextSubstitution(text='2')]]
    }]
    norm = normalize_parameters(orig)
    expected = ({'ints': (1, 2)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{
        'floats': [[TextSubstitution(text='1.0')],
                   [TextSubstitution(text='2.0')]]
    }]
    norm = normalize_parameters(orig)
    expected = ({'floats': (1.0, 2.0)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'strings': ['True', '1', '1.0']}]
    norm = normalize_parameters(orig)
    expected = ({'strings': ('True', '1', '1.0')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'int_sequence': TextSubstitution(text='[2, 3, 4]')}]
    norm = normalize_parameters(orig)
    expected = ({'int_sequence': (2, 3, 4)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'float_sequence': TextSubstitution(text='[2.0, 3.0, 4.0]')}]
    norm = normalize_parameters(orig)
    expected = ({'float_sequence': (2., 3., 4.)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{'bool_sequence': TextSubstitution(text='[True, False, True]')}]
    norm = normalize_parameters(orig)
    expected = ({'bool_sequence': (True, False, True)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected

    orig = [{
        'string_sequence':
        TextSubstitution(text="['True', '1', 'asd', '2.0']")
    }]
    norm = normalize_parameters(orig)
    expected = ({'string_sequence': ('True', '1', 'asd', '2.0')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #14
0
def test_dictionary_with_substitution_list_name():
    orig = [{(TextSubstitution(text='bar'), TextSubstitution(text='foo')): 1}]
    norm = normalize_parameters(orig)
    expected = ({'barfoo': 1}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #15
0
def test_multiple_dictionaries():
    orig = [{'foo': 1, 'bar': 2.0}, {'baz': 'asdf'}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'bar': 2.0}, {'baz': 'asdf'})
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #16
0
def test_single_dictionary():
    orig = [{'foo': 1, 'bar': 2.0}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'bar': 2.0}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #17
0
def test_path_with_substitutions():
    orig = [(TextSubstitution(text='/foo'), TextSubstitution(text='/bar'))]
    norm = normalize_parameters(orig)
    expected = (pathlib.Path('/foo/bar'), )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #18
0
def test_multiple_paths():
    norm = normalize_parameters([pathlib.Path('/foo/bar'), '/bar/baz'])
    expected = (pathlib.Path('/foo/bar'), pathlib.Path('/bar/baz'))
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #19
0
def test_dictionary_with_float():
    orig = [{'foo': 1.2, 'fiz': [2.3, 3.4, 4.5]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1.2, 'fiz': (2.3, 3.4, 4.5)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #20
0
def test_not_a_list():
    with pytest.raises(TypeError):
        normalize_parameters({'foo': 'bar'})
    with pytest.raises(TypeError):
        normalize_parameters('foobar')
Exemple #21
0
    def __init__(self,
                 *,
                 executable: Optional[SomeSubstitutionsType] = None,
                 node_executable: Optional[SomeSubstitutionsType] = None,
                 package: Optional[SomeSubstitutionsType] = None,
                 name: Optional[SomeSubstitutionsType] = None,
                 namespace: Optional[SomeSubstitutionsType] = None,
                 node_name: Optional[SomeSubstitutionsType] = None,
                 node_namespace: SomeSubstitutionsType = None,
                 exec_name: Optional[SomeSubstitutionsType] = None,
                 parameters: Optional[SomeParameters] = None,
                 remappings: Optional[SomeRemapRules] = None,
                 arguments: Optional[Iterable[SomeSubstitutionsType]] = None,
                 **kwargs) -> None:
        """
        Construct an Node action.

        Many arguments are passed eventually to
        :class:`launch.actions.ExecuteProcess`, so see the documentation of
        that class for additional details.
        However, the `cmd` is not meant to be used, instead use the
        `executable` and `arguments` keyword arguments to this function.

        This action, once executed, delegates most work to the
        :class:`launch.actions.ExecuteProcess`, but it also converts some ROS
        specific arguments into generic command line arguments.

        The launch_ros.substitutions.ExecutableInPackage substitution is used
        to find the executable at runtime, so this Action also raise the
        exceptions that substituion can raise when the package or executable
        are not found.

        If the name is not given (or is None) then no name is passed to
        the node on creation and instead the default name specified within the
        code of the node is used instead.

        The namespace can either be absolute (i.e. starts with /) or
        relative.
        If absolute, then nothing else is considered and this is passed
        directly to the node to set the namespace.
        If relative, the namespace in the 'ros_namespace' LaunchConfiguration
        will be prepended to the given relative node namespace.
        If no namespace is given, then the default namespace `/` is
        assumed.

        The parameters are passed as a list, with each element either a yaml
        file that contains parameter rules (string or pathlib.Path to the full
        path of the file), or a dictionary that specifies parameter rules.
        Keys of the dictionary can be strings or an iterable of Substitutions
        that will be expanded to a string.
        Values in the dictionary can be strings, integers, floats, or tuples
        of Substitutions that will be expanded to a string.
        Additionally, values in the dictionary can be lists of the
        aforementioned types, or another dictionary with the same properties.
        A yaml file with the resulting parameters from the dictionary will be
        written to a temporary file, the path to which will be passed to the
        node.
        Multiple dictionaries/files can be passed: each file path will be
        passed in in order to the node (where the last definition of a
        parameter takes effect).

        .. deprecated:: Foxy
           Parameters `node_executable`, `node_name`, and `node_namespace` are deprecated.
           Use `executable`, `name`, and `namespace` instead.

        :param: executable the name of the executable to find if a package
            is provided or otherwise a path to the executable to run.
        :param: node_executable (DEPRECATED) the name of the executable to find if a package
            is provided or otherwise a path to the executable to run.
        :param: package the package in which the node executable can be found
        :param: name the name of the node
        :param: namespace the ROS namespace for this Node
        :param: exec_name the label used to represent the process.
            Defaults to the basename of node executable.
        :param: node_name (DEPRECATED) the name of the node
        :param: node_namespace (DEPRECATED) the ros namespace for this Node
        :param: parameters list of names of yaml files with parameter rules,
            or dictionaries of parameters.
        :param: remappings ordered list of 'to' and 'from' string pairs to be
            passed to the node as ROS remapping rules
        :param: arguments list of extra arguments for the node
        """
        if node_executable is not None:
            warnings.warn(
                "The parameter 'node_executable' is deprecated, use 'executable' instead",
                stacklevel=2)
            if executable is not None:
                raise RuntimeError(
                    "Passing both 'node_executable' and 'executable' parameters. "
                    "Only use 'executable'")
            executable = node_executable

        if package is not None:
            cmd = [ExecutableInPackage(package=package, executable=executable)]
        else:
            cmd = [executable]
        cmd += [] if arguments is None else arguments
        # Reserve space for ros specific arguments.
        # The substitutions will get expanded when the action is executed.
        cmd += ['--ros-args'
                ]  # Prepend ros specific arguments with --ros-args flag
        if node_name is not None:
            warnings.warn(
                "The parameter 'node_name' is deprecated, use 'name' instead",
                stacklevel=2)
            if name is not None:
                raise RuntimeError(
                    "Passing both 'node_name' and 'name' parameters. Only use 'name'."
                )
            cmd += [
                '-r',
                LocalSubstitution("ros_specific_arguments['name']",
                                  description='node name')
            ]
            name = node_name
        if name is not None:
            cmd += [
                '-r',
                LocalSubstitution("ros_specific_arguments['name']",
                                  description='node name')
            ]
        if node_namespace:
            warnings.warn(
                "The parameter 'node_namespace' is deprecated, use 'namespace' instead"
            )
            if namespace:
                raise RuntimeError(
                    "Passing both 'node_namespace' and 'namespace' parameters. "
                    "Only use 'namespace'.")
            namespace = node_namespace
        if parameters is not None:
            ensure_argument_type(parameters, (list), 'parameters', 'Node')
            # All elements in the list are paths to files with parameters (or substitutions that
            # evaluate to paths), or dictionaries of parameters (fields can be substitutions).
            normalized_params = normalize_parameters(parameters)
        # Forward 'exec_name' as to ExecuteProcess constructor
        kwargs['name'] = exec_name
        super().__init__(cmd=cmd, **kwargs)
        self.__package = package
        self.__node_executable = executable
        self.__node_name = name
        self.__node_namespace = namespace
        self.__parameters = [] if parameters is None else normalized_params
        self.__remappings = [] if remappings is None else list(
            normalize_remap_rules(remappings))
        self.__arguments = arguments

        self.__expanded_node_name = self.UNSPECIFIED_NODE_NAME
        self.__expanded_node_namespace = self.UNSPECIFIED_NODE_NAMESPACE
        self.__expanded_parameter_arguments = None  # type: Optional[List[Tuple[Text, bool]]]
        self.__final_node_name = None  # type: Optional[Text]
        self.__expanded_remappings = None  # type: Optional[List[Tuple[Text, Text]]]

        self.__substitutions_performed = False

        self.__logger = launch.logging.get_logger(__name__)
Exemple #22
0
def test_nested_dictionaries():
    orig = [{'foo': {'bar': 'baz'}, 'fiz': {'buz': 3}}]
    norm = normalize_parameters(orig)
    expected = ({'foo.bar': 'baz', 'fiz.buz': 3}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #23
0
def test_dictionary_with_str():
    orig = [{'foo': 'bar', 'fiz': ['b', 'u', 'z']}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 'bar', 'fiz': ('b', 'u', 'z')}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #24
0
def test_dictionary_with_bytes():
    orig = [{'foo': 1, 'fiz': bytes([0xff, 0x5c, 0xaa])}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': bytes([0xff, 0x5c, 0xaa])}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
    def __init__(
        self, *,
        package: SomeSubstitutionsType,
        plugin: Optional[SomeSubstitutionsType] = None,
        name: Optional[SomeSubstitutionsType] = None,
        namespace: Optional[SomeSubstitutionsType] = None,
        node_plugin: Optional[SomeSubstitutionsType] = None,
        node_name: Optional[SomeSubstitutionsType] = None,
        node_namespace: Optional[SomeSubstitutionsType] = None,
        parameters: Optional[SomeParameters] = None,
        remappings: Optional[SomeRemapRules] = None,
        extra_arguments: Optional[SomeParameters] = None,
    ) -> None:
        """
        Initialize a ComposableNode description.

        .. deprecated:: Foxy
           Parameters `node_plugin`, `node_name`, and `node_namespace` are deprecated.
           Use `plugin`, `name`, and `namespace` instead.

        :param package: name of the ROS package the node plugin lives in
        :param plugin: name of the plugin to be loaded
        :param name: name to give to the ROS node
        :param namespace: namespace to give to the ROS node
        :param node_plugin: (DEPRECATED) name of the plugin to be loaded
        :param node_name: (DEPRECATED) name the node should have
        :param node_namespace: (DEPRECATED) namespace the node should create topics/services/etc in
        :param parameters: list of either paths to yaml files or dictionaries of parameters
        :param remappings: list of from/to pairs for remapping names
        :param extra_arguments: container specific arguments to be passed to the loaded node
        """
        if node_plugin is not None:
            warnings.warn("The parameter 'node_plugin' is deprecated, use 'plugin' instead")
            if plugin is not None:
                raise RuntimeError(
                    "Passing both 'node_plugin' and 'plugin' parameters. Only use 'plugin'."
                )
            plugin = node_plugin
        if plugin is None:
            raise RuntimeError("The 'plugin' parameter is required")
        if node_name is not None:
            warnings.warn("The parameter 'node_name' is deprecated, use 'name' instead")
            if name is not None:
                raise RuntimeError(
                    "Passing both 'node_name' and 'name' parameters. Only use 'name'."
                )
            name = node_name
        if node_namespace is not None:
            warnings.warn("The parameter 'node_namespace' is deprecated, use 'namespace' instead")
            if namespace is not None:
                raise RuntimeError(
                    "Passing both 'node_namespace' and 'namespace' parameters. "
                    "Only use 'namespace'."
                )
            namespace = node_namespace

        self.__package = normalize_to_list_of_substitutions(package)
        self.__node_plugin = normalize_to_list_of_substitutions(plugin)

        self.__node_name = None  # type: Optional[List[Substitution]]
        if name is not None:
            self.__node_name = normalize_to_list_of_substitutions(name)

        self.__node_namespace = None  # type: Optional[List[Substitution]]
        if namespace is not None:
            self.__node_namespace = normalize_to_list_of_substitutions(namespace)

        self.__parameters = None  # type: Optional[Parameters]
        if parameters is not None:
            self.__parameters = normalize_parameters(parameters)

        self.__remappings = None  # type: Optional[RemapRules]
        if remappings:
            self.__remappings = normalize_remap_rules(remappings)

        self.__extra_arguments = None  # type: Optional[Parameters]
        if extra_arguments:
            self.__extra_arguments = normalize_parameters(extra_arguments)
Exemple #26
0
def test_dictionary_with_int():
    orig = [{'foo': 1, 'fiz': [2, 3, 4]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': 1, 'fiz': (2, 3, 4)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #27
0
def test_single_pathlib_path():
    norm = normalize_parameters([pathlib.Path('/foo/bar')])
    expected = (pathlib.Path('/foo/bar'), )
    assert evaluate_parameters(LaunchContext(), norm) == expected
Exemple #28
0
    def __init__(self,
                 *,
                 package: SomeSubstitutionsType,
                 node_executable: SomeSubstitutionsType,
                 node_name: Optional[SomeSubstitutionsType] = None,
                 node_namespace: SomeSubstitutionsType = '',
                 parameters: Optional[SomeParameters] = None,
                 remappings: Optional[SomeRemapRules] = None,
                 arguments: Optional[Iterable[SomeSubstitutionsType]] = None,
                 **kwargs) -> None:
        """
        Construct an Node action.

        Many arguments are passed eventually to
        :class:`launch.actions.ExecuteProcess`, so see the documentation of
        that class for additional details.
        However, the `cmd` is not meant to be used, instead use the
        `node_executable` and `arguments` keyword arguments to this function.

        This action, once executed, delegates most work to the
        :class:`launch.actions.ExecuteProcess`, but it also converts some ROS
        specific arguments into generic command line arguments.

        The launch_ros.substitutions.ExecutableInPackage substitution is used
        to find the executable at runtime, so this Action also raise the
        exceptions that substituion can raise when the package or executable
        are not found.

        If the node_name is not given (or is None) then no name is passed to
        the node on creation and instead the default name specified within the
        code of the node is used instead.

        The node_namespace can either be absolute (i.e. starts with /) or
        relative.
        If absolute, then nothing else is considered and this is passed
        directly to the node to set the namespace.
        If relative, the namespace in the 'ros_namespace' LaunchConfiguration
        will be prepended to the given relative node namespace.
        If no node_namespace is given, then the default namespace `/` is
        assumed.

        The parameters are passed as a list, with each element either a yaml
        file that contains parameter rules (string or pathlib.Path to the full
        path of the file), or a dictionary that specifies parameter rules.
        Keys of the dictionary can be strings or an iterable of Substitutions
        that will be expanded to a string.
        Values in the dictionary can be strings, integers, floats, or tuples
        of Substitutions that will be expanded to a string.
        Additionally, values in the dictionary can be lists of the
        aforementioned types, or another dictionary with the same properties.
        A yaml file with the resulting parameters from the dictionary will be
        written to a temporary file, the path to which will be passed to the
        node.
        Multiple dictionaries/files can be passed: each file path will be
        passed in in order to the node (where the last definition of a
        parameter takes effect).

        :param: package the package in which the node executable can be found
        :param: node_executable the name of the executable to find
        :param: node_name the name of the node
        :param: node_namespace the ros namespace for this Node
        :param: parameters list of names of yaml files with parameter rules,
            or dictionaries of parameters.
        :param: remappings ordered list of 'to' and 'from' string pairs to be
            passed to the node as ROS remapping rules
        :param: arguments list of extra arguments for the node
        """
        cmd = [
            ExecutableInPackage(package=package, executable=node_executable)
        ]
        cmd += [] if arguments is None else arguments
        # Reserve space for ros specific arguments.
        # The substitutions will get expanded when the action is executed.
        cmd += ['--ros-args'
                ]  # Prepend ros specific arguments with --ros-args flag
        if node_name is not None:
            cmd += [
                '-r',
                LocalSubstitution("ros_specific_arguments['name']",
                                  description='node name')
            ]
        if parameters is not None:
            ensure_argument_type(parameters, (list), 'parameters', 'Node')
            # All elements in the list are paths to files with parameters (or substitutions that
            # evaluate to paths), or dictionaries of parameters (fields can be substitutions).
            i = 0
            for param in parameters:
                cmd += [
                    LocalSubstitution(
                        "ros_specific_arguments['params'][{}]".format(i),
                        description='parameter {}'.format(i))
                ]
                i += 1
            normalized_params = normalize_parameters(parameters)
        if remappings is not None:
            i = 0
            for remapping in normalize_remap_rules(remappings):
                k, v = remapping
                cmd += [
                    '-r',
                    LocalSubstitution(
                        "ros_specific_arguments['remaps'][{}]".format(i),
                        description='remapping {}'.format(i))
                ]
                i += 1
        super().__init__(cmd=cmd, **kwargs)
        self.__package = package
        self.__node_executable = node_executable
        self.__node_name = node_name
        self.__node_namespace = node_namespace
        self.__parameters = [] if parameters is None else normalized_params
        self.__remappings = [] if remappings is None else remappings
        self.__arguments = arguments

        self.__expanded_node_name = '<node_name_unspecified>'
        self.__expanded_node_namespace = ''
        self.__final_node_name = None  # type: Optional[Text]
        self.__expanded_parameter_files = None  # type: Optional[List[Text]]
        self.__expanded_remappings = None  # type: Optional[List[Tuple[Text, Text]]]

        self.__substitutions_performed = False

        self.__logger = launch.logging.get_logger(__name__)
Exemple #29
0
def test_dictionary_with_bool():
    orig = [{'foo': False, 'fiz': [True, False, True]}]
    norm = normalize_parameters(orig)
    expected = ({'foo': False, 'fiz': (True, False, True)}, )
    assert evaluate_parameters(LaunchContext(), norm) == expected