From 791bc6a7ba50eb0f39c35449a912af87e2d41e88 Mon Sep 17 00:00:00 2001 From: Chris Timperley Date: Tue, 2 Jun 2020 09:37:26 -0400 Subject: [PATCH] Add ROSLaunchController for controlling ROS launch processes (fixes #354) (#359) * added ROSLaunchController class * added terminate method * added filename to controller * added command attribute * added close method * added pid property * added ROSLaunchController to launch method * added __enter__ and __exit__ methods * added is_running method * added missing import * updated CHANGELOG * Added missing `not` Co-authored-by: afsafzal * mark running as property Co-authored-by: afsafzal --- CHANGELOG.md | 2 + src/roswire/proxy/roslaunch/controller.py | 54 +++++++++++++++++++++++ src/roswire/proxy/roslaunch/roslaunch.py | 13 +++++- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/roswire/proxy/roslaunch/controller.py diff --git a/CHANGELOG.md b/CHANGELOG.md index dfdc90cd..bd8b6fc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ systems * Allowed mypy to discover type hints via PEP 561 * Added missing type annotations +* Added ROSLaunchController for dynamically inspecting and controlling + roslaunch processes # 1.2.1 (2020-05-27) diff --git a/src/roswire/proxy/roslaunch/controller.py b/src/roswire/proxy/roslaunch/controller.py new file mode 100644 index 00000000..c4c74c45 --- /dev/null +++ b/src/roswire/proxy/roslaunch/controller.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +__all__ = ('ROSLaunchController',) + +from types import TracebackType +from typing import Iterator, Optional, Type + +import attr +import dockerblade + + +@attr.s(frozen=True, slots=True, auto_attribs=True) +class ROSLaunchController: + """Provides an interface to a roslaunch process. + + Attributes + ---------- + filename: str + The absolute path of the XML launch file used by this process. + command: str + The command string that was used by this process. + popen: dockerblade.popen.Popen + An interface to the underlying exec process for this roslaunch process. + pid: Optional[int] + The PID of the launch process inside the container, if known. + """ + filename: str + popen: dockerblade.popen.Popen = attr.ib(repr=False) + + def __enter__(self) -> 'ROSLaunchController': + return self + + def __exit__(self, + ex_type: Optional[Type[BaseException]], + ex_val: Optional[BaseException], + ex_tb: Optional[TracebackType] + ) -> None: + self.close() + + @property + def stream(self) -> Iterator[str]: + yield from self.popen.stream() # type: ignore + + @property + def running(self) -> bool: + """Checks whether or not this roslaunch process is still running.""" + return not self.popen.finished + + def terminate(self) -> None: + """Terminates this roslaunch process.""" + self.popen.terminate() + + def close(self) -> None: + """Terminates this roslaunch process.""" + self.terminate() diff --git a/src/roswire/proxy/roslaunch/roslaunch.py b/src/roswire/proxy/roslaunch/roslaunch.py index 9b3662e7..30d90b3e 100644 --- a/src/roswire/proxy/roslaunch/roslaunch.py +++ b/src/roswire/proxy/roslaunch/roslaunch.py @@ -11,6 +11,7 @@ import dockerblade from .config import LaunchConfig +from .controller import ROSLaunchController from .reader import LaunchFileReader from ... import exceptions as exc @@ -130,7 +131,7 @@ def launch(self, args: Optional[Mapping[str, Union[int, str]]] = None, prefix: Optional[str] = None, launch_prefixes: Optional[Mapping[str, str]] = None - ) -> None: + ) -> ROSLaunchController: """Provides an interface to the roslaunch command. Parameters @@ -148,6 +149,11 @@ def launch(self, An optional mapping from nodes, given by their names, to their individual launch prefix. + Returns + ------- + ROSLaunchController + An interface for inspecting and managing the launch process. + Raises ------ PackageNotFound @@ -172,6 +178,9 @@ def launch(self, if prefix: cmd = [prefix] + cmd cmd_str = ' '.join(cmd) - shell.popen(cmd_str, stdout=False, stderr=False) + popen = shell.popen(cmd_str, stdout=False, stderr=False) + + return ROSLaunchController(filename=filename, + popen=popen) __call__ = launch