Beispiel #1
0
def launch(shutdown_pipe, package_name, launch_file_name, launch_arguments,
           debug):
    """Launch a ROS system."""
    event_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(event_loop)
    # based on ros2launch/command/launch.py:main
    if package_name is None:
        single_file = True
    else:
        single_file = False
        get_package_prefix(package_name)

    path = None
    launch_arguments = []
    if single_file:
        if os.path.exists(package_name):
            path = package_name
        else:
            raise ValueError(package_name)
        if launch_file_name is not None:
            launch_arguments.append(launch_file_name)
    else:
        try:
            path = get_share_file_path_from_package(package_name=package_name,
                                                    file_name=launch_file_name)
        except PackageNotFoundError as exc:
            raise RuntimeError("Package '{}' not found: {}".format(
                package_name, exc))
        except (FileNotFoundError, MultipleLaunchFilesError) as exc:
            raise RuntimeError(str(exc))
    launch_arguments.extend(launch_arguments)
    launch_service = LaunchService(argv=launch_arguments, debug=debug)
    launch_description = LaunchDescription([
        IncludeLaunchDescription(
            AnyLaunchDescriptionSource(path),
            launch_arguments={},
        ),
    ])
    launch_service.include_launch_description(launch_description)
    finished = False

    def shutdown():
        while not finished and not shutdown_pipe.poll(1):
            pass
        launch_service.shutdown()

    t = threading.Thread(target=shutdown)
    t.start()
    launch_service.run(shutdown_when_idle=True)
    finished = True
    t.join()
    event_loop.close()
Beispiel #2
0
def main(argv=sys.argv[1:]):
    """Main."""
    ld = LaunchDescription([
        launch_ros.actions.Node(package='demo_nodes_cpp',
                                node_executable='talker',
                                output='screen',
                                remappings=[('chatter', 'my_chatter')]),
        launch_ros.actions.Node(package='demo_nodes_cpp',
                                node_executable='listener',
                                output='screen',
                                remappings=[('chatter', 'my_chatter')]),
    ])

    print('Starting introspection of launch description...')
    print('')

    print(LaunchIntrospector().format_launch_description(ld))

    print('')
    print('Starting launch of launch description...')
    print('')

    # ls = LaunchService(debug=True)
    ls = LaunchService()
    ls.include_launch_description(
        get_default_launch_description(prefix_output_with_name=False))
    ls.include_launch_description(ld)
    return ls.run()
def test_executable():
    """Parse executable yaml example."""
    yaml_file = \
        """\
        launch:
        -   executable:
                cmd: ls -l -a -s
                cwd: '/'
                name: my_ls
                shell: true
                output: log
                launch_prefix: $(env LAUNCH_PREFIX)
                env:
                    -   name: var
                        value: '1'
        """
    yaml_file = textwrap.dedent(yaml_file)
    root_entity, parser = Parser.load(io.StringIO(yaml_file))
    ld = parser.parse_description(root_entity)
    executable = ld.entities[0]
    cmd = [i[0].perform(None) for i in executable.cmd]
    assert(
        cmd == ['ls', '-l', '-a', '-s'])
    assert(executable.cwd[0].perform(None) == '/')
    assert(executable.name[0].perform(None) == 'my_ls')
    assert(executable.shell is True)
    assert(executable.output == 'log')
    key, value = executable.additional_env[0]
    key = key[0].perform(None)
    value = value[0].perform(None)
    assert(key == 'var')
    assert(value == '1')
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert(0 == ls.run())
Beispiel #4
0
def test_execute_process_with_respawn():
    """Test launching a process with a respawn and respawn_delay attribute."""
    def on_exit_callback(event, context):
        on_exit_callback.called_count = on_exit_callback.called_count + 1

    on_exit_callback.called_count = 0

    respawn_delay = 2.0
    shutdown_time = 3.0  # to shutdown the launch service, so that the process only respawn once
    expected_called_count = 2  # normal exit and respawn exit

    def generate_launch_description():
        return LaunchDescription([
            ExecuteProcess(cmd=[sys.executable, '-c', "print('action')"],
                           respawn=True,
                           respawn_delay=respawn_delay,
                           on_exit=on_exit_callback),
            TimerAction(period=shutdown_time,
                        actions=[Shutdown(reason='Timer expired')])
        ])

    ls = LaunchService()
    ls.include_launch_description(generate_launch_description())
    assert 0 == ls.run()
    assert expected_called_count == on_exit_callback.called_count
Beispiel #5
0
def test_execute_process_with_on_exit_behavior():
    """Test a process' on_exit callback and actions are processed."""
    def on_exit_callback(event, context):
        on_exit_callback.called = True

    on_exit_callback.called = False

    executable_with_on_exit_callback = ExecuteProcess(
        cmd=[sys.executable, '-c', "print('callback')"],
        output='screen',
        on_exit=on_exit_callback)
    assert len(executable_with_on_exit_callback.get_sub_entities()) == 0

    def on_exit_function(context):
        on_exit_function.called = True

    on_exit_function.called = False
    on_exit_action = OpaqueFunction(function=on_exit_function)
    executable_with_on_exit_action = ExecuteProcess(
        cmd=[sys.executable, '-c', "print('action')"],
        output='screen',
        on_exit=[on_exit_action])
    assert executable_with_on_exit_action.get_sub_entities() == [
        on_exit_action
    ]

    ld = LaunchDescription(
        [executable_with_on_exit_callback, executable_with_on_exit_action])
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert 0 == ls.run()
    assert on_exit_callback.called
    assert on_exit_function.called
Beispiel #6
0
 def _assert_launch_frontend_no_errors(self, file) -> Trace:
     root_entity, parser = Parser.load(file)
     ld = parser.parse_description(root_entity)
     ls = LaunchService()
     ls.include_launch_description(ld)
     assert 0 == ls.run()
     trace_action = ld.describe_sub_entities()[0]
     return trace_action
Beispiel #7
0
def check_launch_namespace(file):
    root_entity, parser = Parser.load(file)
    ld = parser.parse_description(root_entity)
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert 0 == ls.run()
    assert 'ros_namespace' in ls.context.launch_configurations
    assert '/asd' == ls.context.launch_configurations['ros_namespace']
def check_launch_node(file):
    root_entity, parser = Parser.load(file)
    ld = parser.parse_description(root_entity)
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert(0 == ls.run())
    evaluated_parameters = evaluate_parameters(
        ls.context,
        ld.describe_sub_entities()[3]._Node__parameters
    )
    assert len(evaluated_parameters) == 3
    assert isinstance(evaluated_parameters[0], dict)
    assert isinstance(evaluated_parameters[1], dict)
    assert isinstance(evaluated_parameters[2], pathlib.Path)

    assert 'param1' in evaluated_parameters[0]
    assert evaluated_parameters[0]['param1'] == 'ads'

    param_dict = evaluated_parameters[1]
    assert 'param_group1.param_group2.param2' in param_dict
    assert 'param_group1.param3' in param_dict
    assert 'param_group1.param4' in param_dict
    assert 'param_group1.param5' in param_dict
    assert 'param_group1.param6' in param_dict
    assert 'param_group1.param7' in param_dict
    assert 'param_group1.param8' in param_dict
    assert 'param_group1.param9' in param_dict
    assert 'param_group1.param10' in param_dict
    assert 'param_group1.param11' in param_dict
    assert 'param_group1.param12' in param_dict
    assert 'param_group1.param13' in param_dict
    assert 'param_group1.param14' in param_dict
    assert 'param_group1.param15' in param_dict
    assert param_dict['param_group1.param_group2.param2'] == 2
    assert param_dict['param_group1.param3'] == [2, 5, 8]
    assert param_dict['param_group1.param4'] == [2, 5, 8]
    assert param_dict['param_group1.param5'] == '[2, 5, 8]'
    assert param_dict['param_group1.param6'] == [2., 5., 8.]
    assert param_dict['param_group1.param7'] == ['2', '5', '8']
    assert param_dict['param_group1.param8'] == ["'2'", "'5'", "'8'"]
    assert param_dict['param_group1.param9'] == ["'2'", "'5'", "'8'"]
    assert param_dict['param_group1.param10'] == ["'asd'", "'bsd'", "'csd'"]
    assert param_dict['param_group1.param11'] == ['asd', 'bsd', 'csd']
    assert param_dict['param_group1.param12'] == ''
    assert param_dict['param_group1.param13'] == '100'
    assert param_dict['param_group1.param14'] == ["'2'", "'5'", "'8'"]
    assert param_dict['param_group1.param15'] == ['2', '5', '8']

    # Check remappings exist
    remappings = ld.describe_sub_entities()[3]._Node__remappings
    assert remappings is not None
    assert len(remappings) == 2

    listener_node_action = ld.describe_sub_entities()[4]
    listener_node_cmd = listener_node_action.process_details['cmd']
    assert [
        sys.executable, '-c', 'import sys; print(sys.argv[1:])'
    ] == listener_node_cmd[:3]
def test_node_frontend(file):
    """Parse node xml example."""
    root_entity, parser = Parser.load(io.StringIO(file))
    ld = parser.parse_description(root_entity)
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert 0 == ls.run()
    assert 'ros_namespace' in ls.context.launch_configurations
    assert '/asd' == ls.context.launch_configurations['ros_namespace']
Beispiel #10
0
def test_launch_service_emit_event():
    """
    Test the emitting of events in the LaunchService class.

    Also covers basic tests for include_launch_description(), run(), and
    shutdown().
    """
    ls = LaunchService(debug=True)

    assert ls._LaunchService__context._event_queue.qsize() == 0

    from launch.actions import OpaqueFunction
    from launch.actions import RegisterEventHandler
    from launch.event_handler import EventHandler

    handled_events = queue.Queue()
    ld = LaunchDescription([
        RegisterEventHandler(EventHandler(
            matcher=lambda event: True,
            entities=OpaqueFunction(
                function=lambda context: handled_events.put(context.locals.event),
            ),
        ))
    ])
    ls.include_launch_description(ld)
    assert ls._LaunchService__context._event_queue.qsize() == 1

    class MockEvent:
        name = 'Event'

    ls.emit_event(MockEvent())
    assert ls._LaunchService__context._event_queue.qsize() == 2
    assert handled_events.qsize() == 0

    t = threading.Thread(target=ls.run, kwargs={'shutdown_when_idle': False})
    t.start()

    # First event (after including description of event handler).
    handled_events.get(block=True, timeout=5.0)

    # Emit and then check for a second event.
    ls.emit_event(MockEvent())
    handled_events.get(block=True, timeout=5.0)

    # Shutdown (generates a third event) and join the thread.
    ls.shutdown()
    t.join()
    # Check that the shutdown event was handled.
    handled_events.get(block=False)

    assert handled_events.qsize() == 0
    ls.emit_event(MockEvent())
    assert handled_events.qsize() == 0

    assert ls.run(shutdown_when_idle=True) == 0
    handled_events.get(block=False)
Beispiel #11
0
    def test_wait_for_ready(self):
        data = []

        self.launch_description.add_entity(
            RegisterEventHandler(
                StdoutReadyListener(
                    node_name="terminating_node",
                    ready_txt="Ready",
                    actions=[
                        OpaqueFunction(
                            function=lambda context: data.append('ok'))
                    ])))

        launch_service = LaunchService()
        launch_service.include_launch_description(self.launch_description)
        launch_service.run()

        # If the StdoutReadyListener worked, we should see 'ok' in the data
        self.assertIn('ok', data)
Beispiel #12
0
    def test_wait_for_wrong_message(self):
        data = []

        self.launch_description.add_entity(
            RegisterEventHandler(
                StdoutReadyListener(
                    node_name="different_node",
                    ready_txt="not_ready",
                    actions=[
                        OpaqueFunction(
                            function=lambda context: data.append('ok'))
                    ])))

        launch_service = LaunchService()
        launch_service.include_launch_description(self.launch_description)
        launch_service.run()

        # We should not get confused by output that doesn't match the ready_txt
        self.assertNotIn('ok', data)
Beispiel #13
0
def launch_gtest(test_path):
    """Launch a gtest."""
    ld = LaunchDescription([
        GTest(path=str(test_path),
              timeout=5.0,
              on_exit=[EmitEvent(event=Shutdown())])
    ])
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert 0 == ls.run()
Beispiel #14
0
    def setUpClass(cls):
        # It's easier to actually capture some IO from the launch system than it is to fake it
        # but it takes a few seconds.  We'll do it once and run tests on the same captured
        # IO

        node_env = os.environ.copy()
        node_env["PYTHONUNBUFFERED"] = "1"

        cls.proc_output = ActiveIoHandler()

        cls.node_1 = Node(package='apex_rostest',
                          node_executable='terminating_node',
                          env=node_env)

        # This node should be distinguishable by its cmd line args
        cls.node_2 = Node(package='apex_rostest',
                          node_executable='terminating_node',
                          arguments=['--extra'],
                          env=node_env)

        # This node should be distinguishable by its diffetent node name
        cls.node_3 = Node(package='apex_rostest',
                          node_executable='terminating_node',
                          node_name='different_name',
                          env=node_env)

        launch_description = LaunchDescription([
            cls.node_1,
            cls.node_2,
            cls.node_3,
            # This plumbs all the output to our IoHandler just like the ApexRunner does
            RegisterEventHandler(
                OnProcessIO(
                    on_stdout=cls.proc_output.append,
                    on_stderr=cls.proc_output.append,
                ))
        ])

        launch_service = LaunchService()
        launch_service.include_launch_description(launch_description)
        launch_service.run()
def test_execute_process_with_env():
    """Test launching a process with an environment variable."""
    ld = LaunchDescription([
        ExecuteProcess(
            cmd=[sys.executable, 'TEST_PROCESS_WITH_ENV'],
            output='screen',
            env={'TEST_PROCESS_WITH_ENV': 'Hello World'},
        )
    ])
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert 0 == ls.run()
Beispiel #16
0
def run_and_trace(
    base_path: str,
    session_name_prefix: str,
    ros_events: List[str],
    kernel_events: List[str],
    package_name: str,
    node_names: List[str],
    additional_actions: Union[List[Action], Action] = [],
) -> Tuple[int, str]:
    """
    Run a node while tracing.

    :param base_path: the base path where to put the trace directory
    :param session_name_prefix: the session name prefix for the trace directory
    :param ros_events: the list of ROS UST events to enable
    :param kernel_events: the list of kernel events to enable
    :param package_name: the name of the package to use
    :param node_names: the names of the nodes to execute
    :param additional_actions: the list of additional actions to prepend
    :return: exit code, full generated path
    """
    session_name = append_timestamp(session_name_prefix)
    full_path = os.path.join(base_path, session_name)
    if not isinstance(additional_actions, list):
        additional_actions = [additional_actions]

    launch_actions = additional_actions
    # Add trace action
    launch_actions.append(
        Trace(
            session_name=session_name,
            append_timestamp=False,
            base_path=base_path,
            events_ust=ros_events,
            events_kernel=kernel_events,
        ))
    # Add nodes
    for node_name in node_names:
        n = Node(
            package=package_name,
            executable=node_name,
            output='screen',
        )
        launch_actions.append(n)
    ld = LaunchDescription(launch_actions)
    ls = LaunchService()
    ls.include_launch_description(ld)

    exit_code = ls.run()

    return exit_code, full_path
Beispiel #17
0
def test_execute_process_shutdown():
    """Test shutting down a process in (non)interactive settings."""
    def on_exit(event, ctx):
        on_exit.returncode = event.returncode

    def generate_launch_description():
        process_action = ExecuteProcess(
            cmd=[sys.executable, '-c', 'import signal; signal.pause()'],
            sigterm_timeout='1',  # shorten timeouts
            on_exit=on_exit)
        # Launch process and emit shutdown event as if
        # launch had received a SIGINT
        return LaunchDescription([
            process_action,
            RegisterEventHandler(event_handler=OnProcessStart(
                target_action=process_action,
                on_start=[
                    EmitEvent(
                        event=ShutdownEvent(reason='none', due_to_sigint=True))
                ]))
        ])

    ls = LaunchService(noninteractive=True)
    ls.include_launch_description(generate_launch_description())
    assert 0 == ls.run()
    if platform.system() != 'Windows':
        assert on_exit.returncode == -signal.SIGINT  # Got SIGINT
    else:
        assert on_exit.returncode != 0  # Process terminated

    ls = LaunchService()  # interactive
    ls.include_launch_description(generate_launch_description())
    assert 0 == ls.run()
    if platform.system() != 'Windows':
        # Assume interactive Ctrl+C (i.e. SIGINT to process group)
        assert on_exit.returncode == -signal.SIGTERM  # Got SIGTERM
    else:
        assert on_exit.returncode != 0  # Process terminated
Beispiel #18
0
def main(argv):
    ld = generate_launch_description()

    print('Starting introspection of launch description...')
    print('')

    print(LaunchIntrospector().format_launch_description(ld))

    print('')
    print('Starting launch of launch description...')
    print('')

    ls = LaunchService()
    ls.include_launch_description(ld)
    return ls.run()
def main(argv=sys.argv[1:]):
    """Main."""
    ld = generate_launch_description()

    print('Starting introspection of launch description...')
    print('')

    print(LaunchIntrospector().format_launch_description(ld))

    print('')
    print('Starting launch of launch description...')
    print('')

    ls = LaunchService()
    ls.include_launch_description(get_default_launch_description())
    ls.include_launch_description(ld)
    return ls.run()
def test_node_frontend(file):
    """Parse node xml example."""
    root_entity, parser = Parser.load(io.StringIO(file))
    ld = parser.parse_description(root_entity)
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert (0 == ls.run())
    evaluated_parameters = evaluate_parameters(
        ls.context,
        ld.describe_sub_entities()[2]._Node__parameters)
    assert isinstance(evaluated_parameters[0], dict)
    assert isinstance(evaluated_parameters[1], dict)
    assert isinstance(evaluated_parameters[2], pathlib.Path)

    assert 'param1' in evaluated_parameters[0]
    assert evaluated_parameters[0]['param1'] == 'ads'

    param_dict = evaluated_parameters[1]
    assert 'param_group1.param_group2.param2' in param_dict
    assert 'param_group1.param3' in param_dict
    assert 'param_group1.param4' in param_dict
    assert 'param_group1.param5' in param_dict
    assert 'param_group1.param6' in param_dict
    assert 'param_group1.param7' in param_dict
    assert 'param_group1.param8' in param_dict
    assert 'param_group1.param9' in param_dict
    assert 'param_group1.param10' in param_dict
    assert 'param_group1.param11' in param_dict
    assert param_dict['param_group1.param_group2.param2'] == 2
    assert param_dict['param_group1.param3'] == (2, 5, 8)
    assert param_dict['param_group1.param4'] == (2, 5, 8)
    assert param_dict['param_group1.param5'] == '[2, 5, 8]'
    assert param_dict['param_group1.param6'] == (2., 5., 8.)
    assert param_dict['param_group1.param7'] == ('2', '5', '8')
    assert param_dict['param_group1.param8'] == ("'2'", "'5'", "'8'")
    assert param_dict['param_group1.param9'] == ("'2'", "'5'", "'8'")
    assert param_dict['param_group1.param10'] == ("'asd'", "'bsd'", "'csd'")
    assert param_dict['param_group1.param11'] == ('asd', 'bsd', 'csd')
    assert param_dict['param_group1.param12'] == ''

    listener_node_action = ld.describe_sub_entities()[3]
    listener_node_cmd = listener_node_action.process_details['cmd']
    assert [sys.executable, '-c',
            'import sys; print(sys.argv[1:])'] == listener_node_cmd[:3]
def test_include():
    """Parse node xml example."""
    # Always use posix style paths in launch XML files.
    path = (Path(__file__).parent / 'executable.xml').as_posix()
    xml_file = \
        """\
        <launch>
            <include file="{}"/>
        </launch>
        """.format(path)  # noqa: E501
    xml_file = textwrap.dedent(xml_file)
    root_entity, parser = Parser.load(io.StringIO(xml_file))
    ld = parser.parse_description(root_entity)
    include = ld.entities[0]
    assert isinstance(include, IncludeLaunchDescription)
    assert isinstance(include.launch_description_source, AnyLaunchDescriptionSource)
    ls = LaunchService(debug=True)
    ls.include_launch_description(ld)
    assert 0 == ls.run()
class TestCPUMonitor(unittest.TestCase):
    @classmethod
    def test_test_ekf_localization_node_interfaces(self):
        print("test_ekf_localization_node_interfaces Testcases Execution Start...")
        os.system("ros2 launch robot_localization test_ekf_localization_node_interfaces.launch.py")

    @classmethod
    def test_test_ukf_localization_node_interfaces(self):
        print("test_ukf_localization_node_interfaces Testcases Execution Start...")
        os.system("ros2 launch robot_localization test_ukf_localization_node_interfaces.launch.py")

    @classmethod
    def test_filter_base(self):
        print("filter_base Testcases Execution Start...")
        os.system("ros2 run robot_localization filter_base-test")

    @classmethod
    def test_filter_base_diagnostics_timestamps(self):
        print("test_filter_base_diagnostics_timestamps Testcases Execution Start...")
        os.system("ros2 launch robot_localization test_filter_base_diagnostics_timestamps.launch.py")

    @classmethod
    def setUpClass(cls):
        rclpy.init()
        cls.node = rclpy.create_node(TEST_NODE, namespace=TEST_NAMESPACE)

    @classmethod
    def tearDownClass(cls):
        cls.node.destroy_node()
        rclpy.shutdown()

    def _assert_launch_errors(self, actions):
        ld = LaunchDescription(actions)
        self.ls = LaunchService()
        self.ls.include_launch_description(ld)
        assert 0 != self.ls.run()

    def _assert_launch_no_errors(self, actions):
        ld = LaunchDescription(actions)
        self.ls = LaunchService()
        self.ls.include_launch_description(ld)
        t = threading.Thread(target=self.ls.run, kwargs={'shutdown_when_idle': False})
        t.start()
Beispiel #23
0
def test_execute_process_with_env(test_input, expected):
    """Test launching a process with an environment variable."""
    os.environ['TEST_CHANGE_CURRENT_ENV'] = '1'
    additional_env = {'TEST_PROCESS_WITH_ENV': 'Hello World'}
    executable = ExecuteProcess(cmd=[sys.executable, 'TEST_PROCESS_WITH_ENV'],
                                output='screen',
                                env=test_input,
                                additional_env=additional_env)
    ld = LaunchDescription([executable])
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert 0 == ls.run()
    env = executable.process_details['env']
    assert env['TEST_PROCESS_WITH_ENV'] == 'Hello World'
    assert ('TEST_CHANGE_CURRENT_ENV' in env) is expected[0]
    if expected[0]:
        assert env['TEST_CHANGE_CURRENT_ENV'] == '1'
    assert ('TEST_NEW_ENV' in env) is expected[1]
    if expected[1]:
        assert env['TEST_NEW_ENV'] == '2'
def test_executable():
    """Parse node xml example."""
    xml_file = str(Path(__file__).parent / 'executable.xml')
    root_entity, parser = Parser.load(xml_file)
    ld = parser.parse_description(root_entity)
    executable = ld.entities[0]
    cmd = [i[0].perform(None) for i in executable.cmd]
    assert cmd == ['ls', '-l', '-a', '-s']
    assert executable.cwd[0].perform(None) == '/'
    assert executable.name[0].perform(None) == 'my_ls'
    assert executable.shell is True
    assert executable.output == 'log'
    key, value = executable.additional_env[0]
    key = key[0].perform(None)
    value = value[0].perform(None)
    assert key == 'var'
    assert value == '1'
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert 0 == ls.run()
Beispiel #25
0
def test_node_frontend(file):
    """Parse node xml example."""
    root_entity, parser = Parser.load(io.StringIO(file))
    ld = parser.parse_description(root_entity)
    ls = LaunchService()
    ls.include_launch_description(ld)
    assert(0 == ls.run())
    evaluated_parameters = evaluate_parameters(
        ls.context,
        ld.describe_sub_entities()[2]._Node__parameters
    )
    assert isinstance(evaluated_parameters[0], pathlib.Path)
    assert isinstance(evaluated_parameters[1], dict)
    param_dict = evaluated_parameters[1]
    assert 'param1' in param_dict
    assert param_dict['param1'] == 'ads'
    assert 'param_group1.param_group2.param2' in param_dict
    assert 'param_group1.param3' in param_dict
    assert 'param_group1.param4' in param_dict
    assert 'param_group1.param5' in param_dict
    assert 'param_group1.param6' in param_dict
    assert 'param_group1.param7' in param_dict
    assert 'param_group1.param8' in param_dict
    assert 'param_group1.param9' in param_dict
    assert 'param_group1.param10' in param_dict
    assert 'param_group1.param11' in param_dict
    assert param_dict['param_group1.param_group2.param2'] == 2
    assert param_dict['param_group1.param3'] == (2, 5, 8)
    assert param_dict['param_group1.param4'] == (2, 5, 8)
    assert param_dict['param_group1.param5'] == '[2, 5, 8]'
    assert param_dict['param_group1.param6'] == (2., 5., 8.)
    assert param_dict['param_group1.param7'] == ('2', '5', '8')
    assert param_dict['param_group1.param8'] == ("'2'", "'5'", "'8'")
    assert param_dict['param_group1.param9'] == ("'2'", "'5'", "'8'")
    assert param_dict['param_group1.param10'] == ("'asd'", "'bsd'", "'csd'")
    assert param_dict['param_group1.param11'] == ('asd', 'bsd', 'csd')
    assert param_dict['param_group1.param12'] == ''
Beispiel #26
0
 def _assert_launch_no_errors(self, actions):
     ld = LaunchDescription(actions)
     ls = LaunchService(debug=True)
     ls.include_launch_description(ld)
     assert 0 == ls.run()
Beispiel #27
0
def main(argv=sys.argv[1:]):
    """Main."""
    # Configure rotating logs.
    launch.logging.launch_config.log_handler_factory = \
        lambda path, encoding=None: launch.logging.handlers.RotatingFileHandler(
            path, maxBytes=1024, backupCount=3, encoding=encoding)

    # Any number of actions can optionally be given to the constructor of LaunchDescription.
    # Or actions/entities can be added after creating the LaunchDescription.
    user_env_var = 'USERNAME' if platform.system() == 'Windows' else 'USER'
    ld = LaunchDescription([
        launch.actions.LogInfo(msg='Hello World!'),
        launch.actions.LogInfo(msg=(
            'Is that you, ', launch.substitutions.EnvironmentVariable(name=user_env_var), '?'
        )),
    ])

    # Setup a custom event handler for all stdout/stderr from processes.
    # Later, this will be a configurable, but always present, extension to the LaunchService.
    def on_output(event: launch.Event) -> None:
        for line in event.text.decode().splitlines():
            print('[{}] {}'.format(
                cast(launch.events.process.ProcessIO, event).process_name, line))

    ld.add_action(launch.actions.RegisterEventHandler(launch.event_handlers.OnProcessIO(
        # this is the action     ^              and this, the event handler ^
        on_stdout=on_output,
        on_stderr=on_output,
    )))

    # Run whoami, and use its output to log the name of the user.
    # Prefix just the whoami process with `time`.
    ld.add_action(launch.actions.SetLaunchConfiguration('launch-prefix', 'time'))
    # Run whoami, but keep handle to action to make a targeted event handler.
    if platform.system() == 'Windows':
        whoami_cmd = ['echo', '%USERNAME%']
    else:
        whoami_cmd = [launch.substitutions.FindExecutable(name='whoami')]
    whoami_action = launch.actions.ExecuteProcess(
        cmd=whoami_cmd,
        shell=True
    )
    ld.add_action(whoami_action)
    # Make event handler that uses the output.
    ld.add_action(launch.actions.RegisterEventHandler(launch.event_handlers.OnProcessIO(
        target_action=whoami_action,
        # The output of `time` will be skipped since `time`'s output always goes to stderr.
        on_stdout=lambda event: launch.actions.LogInfo(
            msg="whoami says you are '{}'.".format(event.text.decode().strip())
        ),
    )))
    # Unset launch prefix to prevent other process from getting this setting.
    ld.add_action(launch.actions.SetLaunchConfiguration('launch-prefix', ''))

    # Run the counting program, with default options.
    counter_action = launch.actions.ExecuteProcess(cmd=[sys.executable, '-u', './counter.py'])
    ld.add_action(counter_action)

    # Setup an event handler for just this process which will exit when `Counter: 4` is seen.
    def counter_output_handler(event):
        target_str = 'Counter: 4'
        if target_str in event.text.decode():
            return launch.actions.EmitEvent(event=launch.events.Shutdown(
                reason="saw '{}' from '{}'".format(target_str, event.process_name)
            ))

    ld.add_action(launch.actions.RegisterEventHandler(launch.event_handlers.OnProcessIO(
        target_action=counter_action,
        on_stdout=counter_output_handler,
        on_stderr=counter_output_handler,
    )))

    # Run the counter a few more times, with various options.
    ld.add_action(launch.actions.ExecuteProcess(
        cmd=[sys.executable, '-u', './counter.py', '--ignore-sigint']
    ))
    ld.add_action(launch.actions.ExecuteProcess(
        cmd=[sys.executable, '-u', './counter.py', '--ignore-sigint', '--ignore-sigterm']
    ))

    # Add our own message for when shutdown is requested.
    ld.add_action(launch.actions.RegisterEventHandler(launch.event_handlers.OnShutdown(
        on_shutdown=[launch.actions.LogInfo(msg=[
            'Launch was asked to shutdown: ',
            launch.substitutions.LocalSubstitution('event.reason'),
        ])],
    )))

    print('Starting introspection of launch description...')
    print('')

    print(LaunchIntrospector().format_launch_description(ld))

    print('')
    print('Starting launch of launch description...')
    print('')

    # ls = LaunchService(argv=argv, debug=True)  # Use this instead to get more debug messages.
    ls = LaunchService(argv=argv)
    ls.include_launch_description(ld)
    return ls.run()
def test_include_launch_description_launch_arguments():
    """Test the interactions between declared launch arguments and IncludeLaunchDescription."""
    # test that arguments are set when given, even if they are not declared
    ld1 = LaunchDescription([])
    action1 = IncludeLaunchDescription(
        LaunchDescriptionSource(ld1),
        launch_arguments={'foo': 'FOO'}.items(),
    )
    assert len(action1.launch_arguments) == 1
    lc1 = LaunchContext()
    result1 = action1.visit(lc1)
    assert len(result1) == 2
    assert isinstance(result1[0], SetLaunchConfiguration)
    assert perform_substitutions(lc1, result1[0].name) == 'foo'
    assert perform_substitutions(lc1, result1[0].value) == 'FOO'
    assert result1[1] == ld1

    # test that a declared argument that is not provided raises an error
    ld2 = LaunchDescription([DeclareLaunchArgument('foo')])
    action2 = IncludeLaunchDescription(LaunchDescriptionSource(ld2))
    lc2 = LaunchContext()
    with pytest.raises(RuntimeError) as excinfo2:
        action2.visit(lc2)
    assert 'Included launch description missing required argument' in str(
        excinfo2.value)

    # test that a declared argument that is not provided raises an error, but with other args set
    ld2 = LaunchDescription([DeclareLaunchArgument('foo')])
    action2 = IncludeLaunchDescription(
        LaunchDescriptionSource(ld2),
        launch_arguments={'not_foo': 'NOT_FOO'}.items(),
    )
    lc2 = LaunchContext()
    with pytest.raises(RuntimeError) as excinfo2:
        action2.visit(lc2)
    assert 'Included launch description missing required argument' in str(
        excinfo2.value)
    assert 'not_foo' in str(excinfo2.value)

    # test that a declared argument with a default value that is not provided does not raise
    ld2 = LaunchDescription(
        [DeclareLaunchArgument('foo', default_value='FOO')])
    action2 = IncludeLaunchDescription(LaunchDescriptionSource(ld2))
    lc2 = LaunchContext()
    action2.visit(lc2)

    # Test that default arguments in nested IncludeLaunchDescription actions do not raise
    ld1 = LaunchDescription(
        [DeclareLaunchArgument('foo', default_value='FOO')])
    action1 = IncludeLaunchDescription(LaunchDescriptionSource(ld1), )
    ld2 = LaunchDescription([action1, DeclareLaunchArgument('foo2')])
    action2 = IncludeLaunchDescription(
        LaunchDescriptionSource(ld2),
        launch_arguments={'foo2': 'FOO2'}.items(),
    )
    lc2 = LaunchContext()
    action2.visit(lc2)

    # Test that provided launch arguments of nested IncludeLaunchDescription actions do not raise
    ld1 = LaunchDescription([DeclareLaunchArgument('foo')])
    action1 = IncludeLaunchDescription(
        LaunchDescriptionSource(ld1),
        launch_arguments={'foo': 'FOO'}.items(),
    )
    ld2 = LaunchDescription([action1, DeclareLaunchArgument('foo2')])
    action2 = IncludeLaunchDescription(
        LaunchDescriptionSource(ld2),
        launch_arguments={'foo2': 'FOO2'}.items(),
    )
    lc2 = LaunchContext()
    action2.visit(lc2)

    # Test that arguments can not be passed from the parent launch description
    ld1 = LaunchDescription([DeclareLaunchArgument('foo')])
    action1 = IncludeLaunchDescription(LaunchDescriptionSource(ld1))
    ld2 = LaunchDescription([action1, DeclareLaunchArgument('foo2')])
    action2 = IncludeLaunchDescription(
        LaunchDescriptionSource(ld2),
        launch_arguments={
            'foo': 'FOO',
            'foo2': 'FOO2'
        }.items(),
    )
    ld3 = LaunchDescription([action2])
    ls = LaunchService()
    ls.include_launch_description(ld3)
    assert 1 == ls.run()

    # Test that arguments can be redeclared in the parent launch description
    ld1 = LaunchDescription([DeclareLaunchArgument('foo')])
    action1 = IncludeLaunchDescription(LaunchDescriptionSource(ld1))
    ld2 = LaunchDescription(
        [action1,
         DeclareLaunchArgument('foo'),
         DeclareLaunchArgument('foo2')])
    action2 = IncludeLaunchDescription(
        LaunchDescriptionSource(ld2),
        launch_arguments={
            'foo': 'FOO',
            'foo2': 'FOO2'
        }.items(),
    )
    lc2 = LaunchContext()
    action2.visit(lc2)

    # Test that arguments after a ResetLaunchConfigurations action are not checked
    ld1 = LaunchDescription([DeclareLaunchArgument('foo')])
    action1 = IncludeLaunchDescription(LaunchDescriptionSource(ld1))
    ld2 = LaunchDescription([
        DeclareLaunchArgument('foo2'),
        ResetLaunchConfigurations(),
        SetLaunchConfiguration('foo', 'asd'), action1
    ])
    action2 = IncludeLaunchDescription(
        LaunchDescriptionSource(ld2),
        launch_arguments={'foo2': 'FOO2'}.items(),
    )
    lc2 = LaunchContext()
    action2.visit(lc2)
Beispiel #29
0
#!/usr/bin/env python3
import os
from ament_index_python.packages import get_package_share_directory
from launch.frontend import Parser
from launch import LaunchService

XML_FILE_NAME = 'crs.launch.xml'
"""
@summary: entry point for ros2 launch [pkg] [launch]
@requires: ros-eloquent-launch-xml, install by running apt install ros-eloquent-launch-xml
"""


def generate_launch_description():

    xml_file_path = str(
        os.path.join(get_package_share_directory('crs_application'), 'launch',
                     XML_FILE_NAME))
    print('Opening ROS2 launch file: %s' % (xml_file_path))
    root_entity, parser = Parser.load(xml_file_path)
    ld = parser.parse_description(root_entity)
    return ld


# main is not needed but it can be used to run as a standalone python program
if __name__ == '__main__':
    ld = generate_launch_description()
    ls = LaunchService()
    ls.include_launch_description(ld)
    ls.run()
Beispiel #30
0
class ApexRunner(object):
    def __init__(self,
                 gen_launch_description_fn,
                 test_module,
                 launch_file_arguments=[],
                 debug=False):
        """
        Create an ApexRunner object.

        :param callable gen_launch_description_fn: A function that returns a ros2 LaunchDesription
        for launching the processes under test.  This function should take a callable as a
        parameter which will be called when the processes under test are ready for the test to
        start
        """
        self._gen_launch_description_fn = gen_launch_description_fn
        self._test_module = test_module
        self._launch_service = LaunchService(debug=debug)
        self._processes_launched = threading.Event(
        )  # To signal when all processes started
        self._tests_completed = threading.Event(
        )  # To signal when all the tests have finished
        self._launch_file_arguments = launch_file_arguments

        # Can't run LaunchService.run on another thread :-(
        # See https://github.com/ros2/launch/issues/126
        # Instead, we'll let the tests run on another thread
        self._test_tr = threading.Thread(target=self._run_test,
                                         name="test_runner_thread",
                                         daemon=True)

    def get_launch_description(self):
        return _normalize_ld(self._gen_launch_description_fn)(lambda: None)[0]

    def run(self):
        """
        Launch the processes under test and run the tests.

        :return: A tuple of two unittest.Results - one for tests that ran while processes were
        active, and another set for tests that ran after processes were shutdown
        """
        test_ld, test_context = _normalize_ld(self._gen_launch_description_fn)(
            lambda: self._processes_launched.set())

        # Data to squirrel away for post-shutdown tests
        self.proc_info = ActiveProcInfoHandler()
        self.proc_output = ActiveIoHandler()
        self.test_context = test_context
        parsed_launch_arguments = parse_launch_arguments(
            self._launch_file_arguments)
        self.test_args = {}
        for k, v in parsed_launch_arguments:
            self.test_args[k] = v

        # Wrap the test_ld in another launch description so we can bind command line arguments to
        # the test and add our own event handlers for process IO and process exit:
        launch_description = LaunchDescription([
            launch.actions.IncludeLaunchDescription(
                launch.LaunchDescriptionSource(launch_description=test_ld),
                launch_arguments=parsed_launch_arguments),
            RegisterEventHandler(
                OnProcessExit(
                    on_exit=lambda info, unused: self.proc_info.append(info))),
            RegisterEventHandler(
                OnProcessIO(
                    on_stdout=self.proc_output.append,
                    on_stderr=self.proc_output.append,
                )),
        ])

        self._launch_service.include_launch_description(launch_description)

        self._test_tr.start()  # Run the tests on another thread
        self._launch_service.run(
        )  # This will block until the test thread stops it

        if not self._tests_completed.wait(timeout=0):
            # LaunchService.run returned before the tests completed.  This can be because the user
            # did ctrl+c, or because all of the launched nodes died before the tests completed
            print("Processes under test stopped before tests completed")
            self._print_process_output_summary(
            )  # <-- Helpful to debug why processes died early
            # We treat this as a test failure and return some test results indicating such
            return FailResult(), FailResult()

        # Now, run the post-shutdown tests
        inactive_suite = PostShutdownTestLoader(
            injected_attributes={
                "proc_info": self.proc_info,
                "proc_output": self.proc_output._io_handler,
                "test_args": self.test_args,
            },
            injected_args=dict(
                self.test_context,
                # Add a few more things to the args dictionary:
                **{
                    "proc_info": self.proc_info,
                    "proc_output": self.proc_output._io_handler,
                    "test_args": self.test_args
                })).loadTestsFromModule(self._test_module)
        inactive_results = unittest.TextTestRunner(
            verbosity=2, resultclass=TestResult).run(inactive_suite)

        return self._results, inactive_results

    def validate(self):
        """Inspect the test configuration for configuration errors."""
        # Make sure the function signature of the launch configuration
        # generator is correct
        inspect.getcallargs(self._gen_launch_description_fn, lambda: None)

    def _run_test(self):
        # Waits for the DUT processes to start (signaled by the _processes_launched
        # event) and then runs the tests

        if not self._processes_launched.wait(timeout=15):
            # Timed out waiting for the processes to start
            print("Timed out waiting for processes to start up")
            self._launch_service.shutdown()
            return

        try:
            # Load the tests
            active_suite = PreShutdownTestLoader(
                injected_attributes={
                    "proc_info": self.proc_info,
                    "proc_output": self.proc_output,
                    "test_args": self.test_args,
                },
                injected_args=dict(
                    self.test_context,
                    # Add a few more things to the args dictionary:
                    **{
                        "proc_info": self.proc_info,
                        "proc_output": self.proc_output,
                        "test_args": self.test_args
                    })).loadTestsFromModule(self._test_module)

            # Run the tests
            self._results = unittest.TextTestRunner(
                verbosity=2, resultclass=TestResult).run(active_suite)

        finally:
            self._tests_completed.set()
            self._launch_service.shutdown()

    def _print_process_output_summary(self):
        failed_procs = [
            proc for proc in self.proc_info if proc.returncode != 0
        ]

        for process in failed_procs:
            print("Process '{}' exited with {}".format(process.process_name,
                                                       process.returncode))
            print("##### '{}' output #####".format(process.process_name))
            try:
                for io in self.proc_output[process.action]:
                    print("{}".format(io.text.decode('ascii')))
            except KeyError:
                pass  # Process generated no output
            print("#" * (len(process.process_name) + 21))