def test_multiple_launch_with_timers(): def generate_launch_description(): return launch.LaunchDescription([ RosTimer(period=1., actions=[]), ]) ls = launch.LaunchService() ls.include_launch_description(generate_launch_description()) assert 0 == ls.run() ls = launch.LaunchService() ls.include_launch_description(generate_launch_description()) assert 0 == ls.run()
def test_timer_action_sanity_check(): """Test that timer actions work (sanity check).""" # This test is structured like test_shutdown_preempts_timers # as a sanity check that the shutdown listener # and other launch related infrastructure works as expected shutdown_reasons = [] ld = launch.LaunchDescription([ launch.actions.OpaqueFunction(function=set_start_time), RosTimer(period=1., actions=[ launch.actions.OpaqueFunction(function=set_end_time), launch.actions.Shutdown(reason='One second timeout') ]), _shutdown_listener_factory(shutdown_reasons), ]) ls = launch.LaunchService() ls.include_launch_description(ld) assert 0 == ls.run() assert shutdown_reasons[0].reason == 'One second timeout' # Verify that 1 sec has passed between start of test and timeout tolerance = 0.1 assert (end_time - start_time) > 1 - tolerance assert (end_time - start_time) < 1 + tolerance
def test_timer_can_block_preemption(): shutdown_reasons = [] ld = launch.LaunchDescription([ launch.actions.ExecuteProcess( cmd=[sys.executable, '-c', 'while True: pass'], ), launch.actions.TimerAction( period=1., actions=[launch.actions.Shutdown(reason='fast shutdown')]), launch.actions.TimerAction( period=2., actions=[launch.actions.Shutdown(reason='slow shutdown')], cancel_on_shutdown= False # Preempted in test_shutdown_preempts_timers, but not here ), _shutdown_listener_factory(shutdown_reasons), ]) ls = launch.LaunchService() ls.include_launch_description(ld) assert 0 == ls.run() assert len( shutdown_reasons) == 2 # Should see 'shutdown' event twice because assert shutdown_reasons[0].reason == 'fast shutdown' assert shutdown_reasons[1].reason == 'slow shutdown'
def launch_a_launch_file(*, launch_file_path, launch_file_arguments, noninteractive=False, args=None, option_extensions={}, debug=False): """Launch a given launch file (by path) and pass it the given launch file arguments.""" for name in sorted(option_extensions.keys()): option_extensions[name].prestart(args) launch_service = launch.LaunchService(argv=launch_file_arguments, noninteractive=noninteractive, debug=debug) parsed_launch_arguments = parse_launch_arguments(launch_file_arguments) # Include the user provided launch file using IncludeLaunchDescription so that the # location of the current launch file is set. launch_description = launch.LaunchDescription([ launch.actions.IncludeLaunchDescription( launch.launch_description_sources.AnyLaunchDescriptionSource( launch_file_path), launch_arguments=parsed_launch_arguments, ), ]) for name in sorted(option_extensions.keys()): result = option_extensions[name].prelaunch(launch_description, args) launch_description = result[0] launch_service.include_launch_description(launch_description) ret = launch_service.run() for name in sorted(option_extensions.keys()): option_extensions[name].postlaunch(ret, args) return ret
def launch_a_python_launch_file(*, python_launch_file_path, launch_file_arguments, debug=False): """Launch a given Python launch file (by path) and pass it the given launch file arguments.""" launch_service = launch.LaunchService(argv=launch_file_arguments, debug=debug) context = rclpy.context.Context() rclpy.init(args=launch_file_arguments, context=context) launch_service.include_launch_description( launch_ros.get_default_launch_description( prefix_output_with_name=False, rclpy_context=context, )) parsed_launch_arguments = parse_launch_arguments(launch_file_arguments) # Include the user provided launch file using IncludeLaunchDescription so that the # location of the current launch file is set. launch_description = launch.LaunchDescription([ launch.actions.IncludeLaunchDescription( launch.launch_description_sources.PythonLaunchDescriptionSource( python_launch_file_path), launch_arguments=parsed_launch_arguments, ), ]) launch_service.include_launch_description(launch_description) ret = launch_service.run() context = rclpy.shutdown(context=context) return ret
def test_timer_with_launch_configuration(): def generate_launch_description(): return launch.LaunchDescription([ DeclareLaunchArgument('my_period', default_value='0.1'), RosTimer(period=LaunchConfiguration('my_period'), actions=[]), ]) ls = launch.LaunchService() ls.include_launch_description(generate_launch_description()) assert 0 == ls.run()
def test_multiple_launch_with_timers(): # Regression test for https://github.com/ros2/launch/issues/183 # Unfortunately, when things aren't working this test just hangs on the second call to # ls.run def generate_launch_description(): return launch.LaunchDescription([ launch.actions.ExecuteProcess( cmd=[sys.executable, '-c', 'while True: pass'], ), launch.actions.TimerAction( period=1., actions=[launch.actions.Shutdown(reason='Timer expired')]) ]) ls = launch.LaunchService() ls.include_launch_description(generate_launch_description()) assert 0 == ls.run() # Always works ls = launch.LaunchService() ls.include_launch_description(generate_launch_description()) # Next line hangs forever before https://github.com/ros2/launch/issues/183 was fixed. assert 0 == ls.run()
def test_shutdown_preempts_timers(): shutdown_reasons = [] ld = launch.LaunchDescription([ RosTimer(period=1., actions=[launch.actions.Shutdown(reason='fast shutdown')]), RosTimer(period=2., actions=[launch.actions.Shutdown(reason='slow shutdown')]), _shutdown_listener_factory(shutdown_reasons), ]) ls = launch.LaunchService() ls.include_launch_description(ld) assert 0 == ls.run() assert len(shutdown_reasons) == 1 assert shutdown_reasons[0].reason == 'fast shutdown'
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 proc_env = os.environ.copy() proc_env["PYTHONUNBUFFERED"] = "1" cls.proc_output = ActiveIoHandler() cls.proc_1 = launch.actions.ExecuteProcess( cmd=[TEST_PROC_PATH], env=proc_env ) # This process should be distinguishable by its cmd line args cls.proc_2 = launch.actions.ExecuteProcess( cmd=[TEST_PROC_PATH, '--extra'], env=proc_env ) # This process should be distinguishable by its different name cls.proc_3 = launch.actions.ExecuteProcess( cmd=[TEST_PROC_PATH, 'node:=different_name'], env=proc_env ) launch_description = launch.LaunchDescription([ cls.proc_1, cls.proc_2, cls.proc_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 = launch.LaunchService() launch_service.include_launch_description(launch_description) launch_service.run()
def launch_a_python_launch_file(*, python_launch_file_path, launch_file_arguments, debug=False): """Launch a given Python launch file (by path) and pass it the given launch file arguments.""" launch_service = launch.LaunchService(argv=launch_file_arguments, debug=debug) launch_service.include_launch_description( launch_ros.get_default_launch_description( prefix_output_with_name=False)) # Include the user provided launch file using IncludeLaunchDescription so that the # location of the current launch file is set. launch_description = launch.LaunchDescription([ launch.actions.IncludeLaunchDescription( launch.launch_description_sources.PythonLaunchDescriptionSource( python_launch_file_path)) ]) launch_service.include_launch_description(launch_description) return launch_service.run()
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 proc_env = os.environ.copy() proc_env['PYTHONUNBUFFERED'] = '1' cls.proc_output = ActiveIoHandler() cls.proc_1 = launch.actions.ExecuteProcess(cmd=TEST_CMD, name='terminating_proc', env=proc_env) # This process should be distinguishable by its cmd line args cls.proc_2 = launch.actions.ExecuteProcess(cmd=TEST_CMD + ['--extra'], name='terminating_proc', env=proc_env) # This process should be distinguishable by its different name cls.proc_3 = launch.actions.ExecuteProcess(cmd=TEST_CMD + ['node:=different_name'], name='terminating_proc', env=proc_env) launch_description = launch.LaunchDescription([ cls.proc_1, cls.proc_2, cls.proc_3, # This plumbs all the output to our IoHandler just like the LaunchTestRunner does RegisterEventHandler( OnProcessStart(on_start=lambda event, _: cls.proc_output.track( event.process_name))), RegisterEventHandler( OnProcessIO( on_stdout=cls.proc_output.append, on_stderr=cls.proc_output.append, )) ]) launch_service = launch.LaunchService() launch_service.include_launch_description(launch_description) launch_service.run()
def test_wait_for_wrong_message(self): data = [] self.launch_description.add_entity( launch.actions.RegisterEventHandler( StdoutReadyListener( target_action=self.terminating_proc, ready_txt='not_ready', actions=[ launch.actions.OpaqueFunction( function=lambda context: data.append('ok')) ]))) launch_service = launch.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)
def test_wait_for_ready(self): data = [] self.launch_description.add_entity( launch.actions.RegisterEventHandler( StdoutReadyListener( target_action=self.terminating_proc, ready_txt='Ready', actions=[ launch.actions.OpaqueFunction( function=lambda context: data.append('ok')) ]))) launch_service = launch.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)
def launch_a_launch_file(*, launch_file_path, launch_file_arguments, noninteractive=False, args=None, option_extensions={}, debug=False): """Launch a given launch file (by path) and pass it the given launch file arguments.""" for name in sorted(option_extensions.keys()): option_extensions[name].prestart(args) # If 'launch-prefix' launch file argument is also provided in the user input, # the 'launch-prefix' option is applied since the last duplicate argument is used if args and args.launch_prefix: launch_file_arguments.append(f'launch-prefix:={args.launch_prefix}') if args and args.launch_prefix_filter: launch_file_arguments.append( f'launch-prefix-filter:={args.launch_prefix_filter}') launch_service = launch.LaunchService(argv=launch_file_arguments, noninteractive=noninteractive, debug=debug) parsed_launch_arguments = parse_launch_arguments(launch_file_arguments) # Include the user provided launch file using IncludeLaunchDescription so that the # location of the current launch file is set. launch_description = launch.LaunchDescription([ launch.actions.IncludeLaunchDescription( launch.launch_description_sources.AnyLaunchDescriptionSource( launch_file_path), launch_arguments=parsed_launch_arguments, ), ]) for name in sorted(option_extensions.keys()): result = option_extensions[name].prelaunch(launch_description, args) launch_description = result[0] launch_service.include_launch_description(launch_description) ret = launch_service.run() for name in sorted(option_extensions.keys()): option_extensions[name].postlaunch(ret, args) return ret
def test_wait_for_wrong_process(self): data = [] self.launch_description.add_entity( launch.actions.RegisterEventHandler( StdoutReadyListener( target_action=KeepAliveProc( ), # We never launched this process ready_txt='Ready', actions=[ launch.actions.OpaqueFunction( function=lambda context: data.append('ok')) ]))) launch_service = launch.LaunchService() launch_service.include_launch_description(self.launch_description) launch_service.run() # We should not get confused by output from another proc self.assertNotIn('ok', data)
def test_shutdown_preempts_timers(): shutdown_reasons = [] ld = launch.LaunchDescription([ launch.actions.ExecuteProcess( cmd=[sys.executable, '-c', 'while True: pass'], ), launch.actions.TimerAction( period=1., actions=[launch.actions.Shutdown(reason='fast shutdown')]), launch.actions.TimerAction( period=2., actions=[launch.actions.Shutdown(reason='slow shutdown')]), _shutdown_listener_factory(shutdown_reasons), ]) ls = launch.LaunchService() ls.include_launch_description(ld) assert 0 == ls.run() assert len(shutdown_reasons) == 1 assert shutdown_reasons[0].reason == 'fast shutdown'
def test_timer_action_sanity_check(): """Test that timer actions work (sanity check).""" # This test is structured like test_shutdown_preempts_timers and # test_timer_can_block_preemption as a sanity check that the shutdown listener # and other launch related infrastructure works as expected shutdown_reasons = [] ld = launch.LaunchDescription([ launch.actions.ExecuteProcess( cmd=[sys.executable, '-c', 'while True: pass'], ), launch.actions.TimerAction( period=1., actions=[launch.actions.Shutdown(reason='One second timeout')]), _shutdown_listener_factory(shutdown_reasons), ]) ls = launch.LaunchService() ls.include_launch_description(ld) assert 0 == ls.run() assert shutdown_reasons[0].reason == 'One second timeout'
def launch_a_launch_file(*, launch_file_path, launch_file_arguments, debug=False): """Launch a given launch file (by path) and pass it the given launch file arguments.""" launch_service = launch.LaunchService(argv=launch_file_arguments, debug=debug) parsed_launch_arguments = parse_launch_arguments(launch_file_arguments) # Include the user provided launch file using IncludeLaunchDescription so that the # location of the current launch file is set. launch_description = launch.LaunchDescription([ launch.actions.IncludeLaunchDescription( launch.launch_description_sources.AnyLaunchDescriptionSource( launch_file_path), launch_arguments=parsed_launch_arguments, ), ]) launch_service.include_launch_description(launch_description) ret = launch_service.run() return ret
def test_timer_uses_sim_time(rclpy_node): """Test that timer uses time from /clock topic.""" # Create clock publisher node publisher = rclpy_node.create_publisher(ClockMsg, '/clock', 10) # Increment sim time by 100 every time callback is called def timer_callback(publisher, time_msg): time_msg.sec += 100 publisher.publish(ClockMsg(clock=time_msg)) # For every second of system time, publish new sim time value callback_clock = Clock(clock_type=ClockType.SYSTEM_TIME) time_msg = Time(sec=0, nanosec=0) rclpy_node.create_timer(1, partial(timer_callback, publisher, time_msg), clock=callback_clock) thread = threading.Thread(target=rclpy.spin, args=(rclpy_node, ), daemon=True) thread.start() ld = launch.LaunchDescription([ launch.actions.OpaqueFunction(function=set_start_time), RosTimer( period=200., actions=[launch.actions.OpaqueFunction(function=set_end_time)], ), SetUseSimTime( True) # Must be set to allow timer action to use sim time ]) ls = launch.LaunchService() ls.include_launch_description(ld) assert 0 == ls.run() # Timer is using sim time which is 100x faster than system time, # so 200 sec timer should finish in 2 sec tolerance = 0.1 assert (end_time - start_time) > 2 - tolerance assert (end_time - start_time) < 2 + tolerance
def test_emulate_tty(test_input, expected): on_exit = OnExit() ld = launch.LaunchDescription() kwargs = {} if isinstance(test_input, bool): kwargs['emulate_tty'] = test_input elif isinstance(test_input, str): ld.add_action( launch.actions.SetLaunchConfiguration('emulate_tty', test_input)) ld.add_action( launch.actions.RegisterEventHandler( launch.event_handlers.OnProcessExit(on_exit=on_exit.handle))) ld.add_action( launch.actions.ExecuteProcess(cmd=[ sys.executable, '-c', 'import sys; sys.exit(sys.stdout.isatty())', ], **kwargs)) ls = launch.LaunchService() ls.include_launch_description(ld) ls.run() assert on_exit.returncode == expected
def main(argv=sys.argv[1:]): """Run lifecycle nodes via launch.""" ld = generate_launch_description() ls = launch.LaunchService(argv=argv) ls.include_launch_description(ld) return ls.run()
def generate_launch_description(argv=sys.argv[1:]): """Run lifecycle nodes via launch.""" ld = launch.LaunchDescription() # Prepare the marvel node. marvel_node = launch_ros.actions.LifecycleNode( node_name='marvelmind_nav', package='marvelmind_nav', node_executable='marvelmind_nav', output='screen', arguments=['/dev/ttyACM1', '9600']) # When the marvel reaches the 'inactive' state, make it take the 'activate' transition. register_event_handler_for_marvel_reaches_inactive_state = launch.actions.RegisterEventHandler( launch_ros.event_handlers.OnStateTransition( target_lifecycle_node=marvel_node, goal_state='inactive', entities=[ launch.actions.LogInfo( msg= "node 'marvelmind_nav' reached the 'inactive' state, 'activating'." ), launch.actions.EmitEvent( event=launch_ros.events.lifecycle.ChangeState( lifecycle_node_matcher=launch.events.matches_action( marvel_node), transition_id=lifecycle_msgs.msg.Transition. TRANSITION_ACTIVATE, )), ], )) # When the marvel node reaches the 'active' state, log a message register_event_handler_for_marvel_reaches_active_state = launch.actions.RegisterEventHandler( launch_ros.event_handlers.OnStateTransition( target_lifecycle_node=marvel_node, goal_state='active', entities=[ launch.actions.LogInfo( msg="node 'marvelmind_nav' reached the 'active' state.") ], )) # Make the marvel node take the 'configure' transition. emit_event_to_request_that_marvel_does_configure_transition = launch.actions.EmitEvent( event=launch_ros.events.lifecycle.ChangeState( lifecycle_node_matcher=launch.events.matches_action(marvel_node), transition_id=lifecycle_msgs.msg.Transition.TRANSITION_CONFIGURE, )) # Add the actions to the launch description. # The order they are added reflects the order in which they will be executed. ld.add_action(register_event_handler_for_marvel_reaches_inactive_state) ld.add_action(register_event_handler_for_marvel_reaches_active_state) ld.add_action(marvel_node) ld.add_action(emit_event_to_request_that_marvel_does_configure_transition) # print('Starting introspection of launch description...') # print('') # print(launch.LaunchIntrospector().format_launch_description(ld)) print('') print('Starting launch of launch description...') print('') # ls = launch.LaunchService(argv=argv, debug=True) ls = launch.LaunchService(argv=argv) ls.include_launch_description(ld) return ld
def launch_service(event_loop): """Create an instance of the launch service for each test case.""" ls = launch.LaunchService() yield ls finalize_launch_service(ls, eprefix='When tearing down launch_service fixture')
# Wire up stdout from processes 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_ros.actions.Node( package='pirobot_base', node_executable='motor', output='screen', parameters=[{"enable": 25, "forward": 23, "reverse": 24}] )) ld.add_action(launch_ros.actions.Node( package='pirobot_base', node_executable='motor', output='screen', parameters=[{"enable": 17, "forward": 27, "reverse": 22}], arguments=["Motor1:=Motor2"] )) ld.add_action(launch_ros.actions.Node( package='pirobot_base', node_executable='twoWheelDriving', output='screen', parameters=[{"bias":0, "turn_rate":50, "max_speed":75}] )) return ld if __name__ == '__main__': ls = launch.LaunchService(argv=sys.argv[1:]) ls.include_launch_description(generate_launch_description()) sys.exit(ls.run())
ld.add_action( Node(package='tsim', executable='requester', name='requester', output='screen', additional_env={'PYTHONUNBUFFERED': '1'}, parameters=[parameter_path])) ld.add_action( Node(package='tsim', executable='autopilot', name='autopilot', output='screen', additional_env={'PYTHONUNBUFFERED': '1'}, prefix='xterm -e')) return ld if __name__ == '__main__': ld = generate_launch_description() print('Starting introspection of launch description...\n') print(launch.LaunchIntrospector().format_launch_description(ld)) print('\nStarting launch of launch description...\n') #ls = LaunchService(debug=True) ls = launch.LaunchService() ls.include_launch_description(ld) ls.run(shutdown_when_idle=False)
def main(argv=sys.argv[1:]): """Main.""" ld = launch.LaunchDescription() # Prepare the talker node. talker_node = launch_ros.actions.LifecycleNode( node_name='talker', package='lifecycle', node_executable='lifecycle_talker', output='screen') # When the talker reaches the 'inactive' state, make it take the 'activate' transition. register_event_handler_for_talker_reaches_inactive_state = launch.actions.RegisterEventHandler( launch_ros.event_handlers.OnStateTransition( target_lifecycle_node=talker_node, goal_state='inactive', entities=[ launch.actions.LogInfo( msg= "node 'talker' reached the 'inactive' state, 'activating'." ), launch.actions.EmitEvent( event=launch_ros.events.lifecycle.ChangeState( lifecycle_node_matcher=launch.events.matches_action( talker_node), transition_id=lifecycle_msgs.msg.Transition. TRANSITION_ACTIVATE, )), ], )) # When the talker node reaches the 'active' state, log a message and start the listener node. register_event_handler_for_talker_reaches_active_state = launch.actions.RegisterEventHandler( launch_ros.event_handlers.OnStateTransition( target_lifecycle_node=talker_node, goal_state='active', entities=[ launch.actions.LogInfo( msg= "node 'talker' reached the 'active' state, launching 'listener'." ), launch_ros.actions.LifecycleNode( node_name='listener', package='lifecycle', node_executable='lifecycle_listener', output='screen'), ], )) # Make the talker node take the 'configure' transition. emit_event_to_request_that_talker_does_configure_transition = launch.actions.EmitEvent( event=launch_ros.events.lifecycle.ChangeState( lifecycle_node_matcher=launch.events.matches_action(talker_node), transition_id=lifecycle_msgs.msg.Transition.TRANSITION_CONFIGURE, )) # Add the actions to the launch description. # The order they are added reflects the order in which they will be executed. ld.add_action(register_event_handler_for_talker_reaches_inactive_state) ld.add_action(register_event_handler_for_talker_reaches_active_state) ld.add_action(talker_node) ld.add_action(emit_event_to_request_that_talker_does_configure_transition) print('Starting introspection of launch description...') print('') print(launch.LaunchIntrospector().format_launch_description(ld)) print('') print('Starting launch of launch description...') print('') # ls = launch.LaunchService(argv=argv, debug=True) ls = launch.LaunchService(argv=argv) ls.include_launch_description(get_default_launch_description()) ls.include_launch_description(ld) return ls.run()
""" Create launch description for starting SandboxedNodeContainer. Two nodes are loaded into the sandboxed container: talker and listener. No operation is performed since no sandboxing policy was defined. """ ld = launch.LaunchDescription() ld.add_action( launch_ros_sandbox.actions.SandboxedNodeContainer( sandbox_name='my_sandbox', policy=UserPolicy(run_as=User.from_username('dashing'), ), node_descriptions=[ launch_ros_sandbox.descriptions.SandboxedNode( package='demo_nodes_cpp', node_executable='talker', ), launch_ros_sandbox.descriptions.SandboxedNode( package='demo_nodes_cpp', node_executable='listener') ])) return ld if __name__ == '__main__': """Starts the SandboxedNodeContainer example as a script.""" ls = launch.LaunchService(argv=sys.argv[1:], debug=True) ls.include_launch_description(generate_launch_description()) sys.exit(ls.run())