From f5b72d8e2fb7ef8d52ed620e4c21d59b02646484 Mon Sep 17 00:00:00 2001 From: Roger Strain Date: Wed, 29 Jan 2020 09:30:34 -0600 Subject: [PATCH 1/7] Added initial discussion of refactor effort for ExecuteProcess Distro A; OPSEC #2893 Signed-off-by: Roger Strain --- articles/execute_process_refactor.md | 149 +++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 articles/execute_process_refactor.md diff --git a/articles/execute_process_refactor.md b/articles/execute_process_refactor.md new file mode 100644 index 000000000..1ddff291a --- /dev/null +++ b/articles/execute_process_refactor.md @@ -0,0 +1,149 @@ +# Refactoring ExecuteProcess in ROS2 +Initially proposed in [114](https://github.com/ros2/launch/issues/114), this document describes changes to `ExecuteProcess` and related classes. As initially implemented, some aspects of this are tightly coupled to both the implementation chosen and the assumption that processes will execute only in the local environment of the launch process itself. The following changes are designed to provide a more decoupled architecture that will ease support of launching processes locally, remotely, or potentially in containerized environments. Additionally, these changes will support the goal of decoupling the description of an executable from the actual action of executing it. These changes are designed so that existing systems may continue to use the interface before these changes without modification; newer systems may find benefits from adapting to the newer syntax, particularly when composing more complicated environments. +## Affected classes before any changes +The following classes currently exist and are relevant to the proposed changes. A brief summary of some relevant concepts is included with each. +### launch.actions.ExecuteProcess +Extends the `Action` class. Allows many items to be set via constructor, including information both on how to launch the process, and how to interact with it after launching. The available parameters and their documentation follow, split into categories considering whether they are more relevant to launching the process, or to dealing with its execution following launch. + +_Launch Details_ + +|Argument|Description| +|---|---| +|cmd|a list where the first item is the executable and the rest are arguments to the executable, each item may be a string or a list of strings and `Substitution`s to be resolved at runtime| +|name|the label used to represent the process, as a string or a `Substitution` to be resolved at runtime, defaults to the basename of the executable| +|cwd|the directory in which to run the executable| +|env|dictionary of environment variables to be used, starting from a clean environment. If `None`, the current environment is used.| +|additional\_env|dictionary of environment variables to be added. If `env` was `None`, they are added to the current environment. If not, `env` is updated with `additional_env`.| + +_Execution Details_ + +|Argument|Description| +|---|---| +|shell|if True, a shell is used to execute the cmd| +|sigterm\_timeout|time until shutdown should escalate to `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigterm_timeout`| +|sigkill\_timeout|time until escalating to `SIGKILL` after `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigkill_timeout`| +|emulate\_tty|emulate a tty (terminal), defaults to `False`, but can be overridden with the `LaunchConfiguration` called `emulate_tty`, the value of which is evaluated as true or false according to `evaluate_condition_expression`.| +|prefix|a set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix`| +|output|configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen.| +|output\_format|for logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance.| +|log\_cmd|if `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved.| +|on\_exit|list of actions to execute upon process exit.| + +### launch_ros.actions.Node + +Extends the `ExecuteProcess` class. Added constructor parameters for this class all focus on concepts similar to the Launch Details discussed above, but the class also overrides the `execute` method of `ExecuteProcess`. The purpose of this override is to provide more granular structure for the command used to launch a ROS node. All the provided constructor parameters eventually reduce into a collection of substitution elements to compose the `cmd` parameter of `ExecuteProcess`. + +|Argument|Description| +|---|---| +|node_executable|the name of the executable to find if a package is provided or otherwise a path to the executable to run.| +|package|the package in which the node executable can be found| +|node_name|the name of the node| +|node_namespace|the ros namespace for this Node| +|parameters|list of names of yaml files with parameter rules, or dictionaries of parameters.| +|remappings|ordered list of 'to' and 'from' string pairs to be passed to the node as ROS remapping rules| +|arguments|list of extra arguments for the node| + +### launch_ros.descriptions.ComposableNode + +Does not extend another class. Constructor parameters closely mirror those of `Node`, and represent a node which may be executed as part of a composite process hosting multiple nodes. + +|Argument|Description| +|---|---| +|package|name of the ROS package the node plugin lives in| +|node_plugin|name of the plugin to be loaded| +|node_name|name the node should have| +|node_namespace|namespace the node should create topics/services/etc in| +|parameters|list of either paths to yaml files or dictionaries of parameters| +|remappings|list of from/to pairs for remapping names| +|extra_arguments|container specific arguments to be passed to the loaded node| + +### launch_ros.actions.ComposableNodeContainer + +Extends the `Node` class. Added constructor parameters for this class allow specification of the node container class name and namespace, along with a list of `Node`s to include. This class overrides the `execute` method of `Node` to add additional post-execution actions, loading the composable nodes into the now-executing container process. + +|Argument|Description| +|---|---| +|node_name|the name of the node, mandatory for full container node name resolution| +|node_namespace|the ros namespace for this Node, mandatory for full container node name resolution| +|composable\_node\_descriptions|optional descriptions of composable nodes to be loaded| + +### launch_ros.actions.LifecycleNode + +Extends the `Node` class. This class overrides the `execute` method of `Node` to register lifecycle message handlers, and exposes events to allow reactions to said lifecycle state transitions. + +## Considerations for Refactored Classes + +The primary goal of the refactor is to attempt to split the definition aspect of processes/nodes apart from the logic which executes those elements. `ComposableNode` provides a basis for similar breakouts of other elements. + +In general, classes should have similar analogs even in the refactor to ensure that existing classes can be replaced with backwards-compatible replacements that use the new structure. These replacements can be implemented to warn the user that the older definitions are deprecated, and suggest moving to the newer refactored style. + +Further consideration will be required for alternate frontends, such as XML, to determine how to implement these changes with streamlined syntax where possible. + +One difficulty when looking forward to allowing functionality such as remote and containerized execution is that the target environment is likely different than the local environment. Different packages may be installed, different environment variables may be defined, and so forth. To support this, it may be helpful to allow an alternate `launch.LaunchContext` to be defined for specific executions. + +## Proposed New Classes +### launch.descriptions.Process + +This class would represent only the information required to define a process which might be run. It would not include execution-time details, nor provide monitoring of the process after launch. The constructor parameters would be pulled directly from the current `launch.actions.ExecuteProcess` class. + +|Argument|Description| +|---|---| +|cmd|a list where the first item is the executable and the rest are arguments to the executable, each item may be a string or a list of strings and `Substitution`s to be resolved at runtime| +|name|the label used to represent the process, as a string or a `Substitution` to be resolved at runtime, defaults to the basename of the executable| +|cwd|the directory in which to run the executable| +|env|dictionary of environment variables to be used, starting from a clean environment. If `None`, the current environment is used.| +|additional\_env|dictionary of environment variables to be added. If `env` was `None`, they are added to the current environment. If not, `env` is updated with `additional_env`.| +|shell|if True, a shell is used to execute the cmd| + +### launch_ros.descriptions.Node + +This class would represent only the information required to define a node which might be run. It would inherit from `launch.descriptions.Process`, and populate its fields in the same manner as the current `launch.actions.Node`. + +|Argument|Description| +|---|---| +|node_executable|the name of the executable to find if a package is provided or otherwise a path to the executable to run.| +|package|the package in which the node executable can be found| +|node_name|the name of the node| +|node_namespace|the ros namespace for this Node| +|parameters|list of names of yaml files with parameter rules, or dictionaries of parameters.| +|remappings|ordered list of 'to' and 'from' string pairs to be passed to the node as ROS remapping rules| +|arguments|list of extra arguments for the node| + +### launch_ros.descriptions.ComposableNode + +This class would be modified to inherit from `launch_ros.descriptions.Node`. Most parameters would be passed to the new superclass. + +|Argument|Description| +|---|---| +|node_plugin|name of the plugin to be loaded| + +### launch.actions.ExecuteLocalProcess + +This class would represent the execution-time aspects of launch.actions.ExecuteProcess. The new `process_description` constructor parameter could be either a `launch.descriptions.Process` or a `launch_ros.descriptions.Node`; node-specific functionality is limited to proper configuration of the command line to be executed, so no special execution wrapper is needed. This is not the case for lifecycle nodes or composable nodes, which do require custom execution wrappers, described below. + +(Details regarding remote/containerized execution would not be considered here, and should be implemented in alternate execute actions as appropriate. They could, however, reuse the same process/node description classes, while providing alternate `launch.LaunchContext` information.) + +|Argument|Description| +|---|---| +|process\_description|the `launch.descriptions.Process` to execute as a local process| +|shell|if True, a shell is used to execute the cmd| +|sigterm\_timeout|time until shutdown should escalate to `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigterm_timeout`| +|sigkill\_timeout|time until escalating to `SIGKILL` after `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigkill_timeout`| +|emulate\_tty|emulate a tty (terminal), defaults to `False`, but can be overridden with the `LaunchConfiguration` called `emulate_tty`, the value of which is evaluated as true or false according to `evaluate_condition_expression`.| +|prefix|a set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix`| +|output|configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen.| +|output\_format|for logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance.| +|log\_cmd|if `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved.| +|on\_exit|list of actions to execute upon process exit.| + +### launch_ros.actions.ExecuteLocalLifecycleNode + +This class would extend the `launch.actions.ExecuteLocalProcess` class, and provide the additional functionality required for managing lifecycle node events that are currently defined in `launch_ros.actions.LifecycleNode`. No additional constructor parameters are defined in this class. + +### launch_ros.actions.ExecuteLocalNodeContainer + +This class would extend the `launch.actions.ExecuteLocalProcess` class, and provide the additional functionality required for loading multiple nodes into a single container. The description of the composable node container itself should be provided as the `process_description` parameter to pass to `ExecuteLocalProcess`; child nodes would be provided as an additional constructor parameter. + +|Argument|Description| +|---|---| +|composable\_node\_descriptions|optional descriptions of composable nodes to be loaded| From 3c14e3ef37786a06b3efbfb2d26f3c0bad34c632 Mon Sep 17 00:00:00 2001 From: Roger Strain Date: Thu, 6 Feb 2020 14:22:03 -0600 Subject: [PATCH 2/7] Expanded discussion of current and new classes Distro A; OPSEC #2893 Signed-off-by: Roger Strain --- articles/execute_process_refactor.md | 318 +++++++++++++++++++++++++-- 1 file changed, 302 insertions(+), 16 deletions(-) diff --git a/articles/execute_process_refactor.md b/articles/execute_process_refactor.md index 1ddff291a..b41383d32 100644 --- a/articles/execute_process_refactor.md +++ b/articles/execute_process_refactor.md @@ -3,9 +3,14 @@ Initially proposed in [114](https://github.com/ros2/launch/issues/114), this doc ## Affected classes before any changes The following classes currently exist and are relevant to the proposed changes. A brief summary of some relevant concepts is included with each. ### launch.actions.ExecuteProcess -Extends the `Action` class. Allows many items to be set via constructor, including information both on how to launch the process, and how to interact with it after launching. The available parameters and their documentation follow, split into categories considering whether they are more relevant to launching the process, or to dealing with its execution following launch. -_Launch Details_ +Extends the `launch.actions.Action` class. This command initiates the execution of a command on the local system, and is not ROS-specific. + +#### Constructor + +Allows many items to be set via constructor, including information both on how to launch the process, and how to interact with it after launching. The available parameters and their documentation follow, split into categories considering whether they are more relevant to launching the process, or to dealing with its execution following launch. + +##### Launch Details |Argument|Description| |---|---| @@ -15,7 +20,7 @@ _Launch Details_ |env|dictionary of environment variables to be used, starting from a clean environment. If `None`, the current environment is used.| |additional\_env|dictionary of environment variables to be added. If `env` was `None`, they are added to the current environment. If not, `env` is updated with `additional_env`.| -_Execution Details_ +##### Execution Details |Argument|Description| |---|---| @@ -29,9 +34,49 @@ _Execution Details_ |log\_cmd|if `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved.| |on\_exit|list of actions to execute upon process exit.| +#### Properties + +| Name | Description | +| --------------- | ------------------------------------------------------------ | +| process_details | `None` if the process is not yet started; otherwise an object containing information such as the command, working directory, environment, and process ID | + +Additional properties provide access to constructor parameters for `name`, `cmd`, `cwd`, `env`, `additional_env`, `shell`, and `output`. + +#### Methods + +| Name | Description | +| ------------------ | ------------------------------------------------------------ | +| get_sub_entities | Override. If on_exit was provided in the constructor, returns that; otherwise returns an empty list. | +| execute | Override. Establishes event handlers for process execution, performs variable expansion, then uses `osrf_pycommon.process_utils.async_execute_process` to launch the defined process. | +| get_asyncio_future | Override. Return an asyncio Future, used to let the launch system know when we're done. | + +#### Events + +##### Handled Events + +| Event Type | Description | +| ------------------------------------- | ------------------------------------------------------------ | +| `launch.events.process.ShutdownProcess` | begins standard shutdown procedure for a running executable | +| `launch.events.process.SignalProcess` | passes the signal provided by the event to the running process | +| `launch.events.process.ProcessStdin` | passes the text provided by the event to the stdin of the process | +| `launch.events.Shutdown` | same as ShutdownProcess | + +##### Emitted Events + +| Event Type | Description | +| ------------------------------------ | ------------------------------------------------------------ | +| `launch.events.process.ProcessStarted` | emitted when the process starts | +| `launch.events.process.ProcessExited` | emitted when the process exits; event contains return code | +| `launch.events.process.ProcessStdout` | emitted when the process produces data the stdout pipe; event contains the data from the pipe | +| `launch.events.process.ProcessStderr` | emitted when the process produces data the stderr pipe; event contains the data from the pipe | + ### launch_ros.actions.Node -Extends the `ExecuteProcess` class. Added constructor parameters for this class all focus on concepts similar to the Launch Details discussed above, but the class also overrides the `execute` method of `ExecuteProcess`. The purpose of this override is to provide more granular structure for the command used to launch a ROS node. All the provided constructor parameters eventually reduce into a collection of substitution elements to compose the `cmd` parameter of `ExecuteProcess`. +Extends the `ExecuteProcess` class. This allows execution of a ROS-specific node, and extends the available information to include node related details. + +#### Constructor + +Added constructor parameters for this class all focus on concepts similar to the Launch Details discussed above, but the class also overrides the `execute` method of `ExecuteProcess`. The purpose of this override is to provide more granular structure for the command used to launch a ROS node. All the provided constructor parameters eventually reduce into a collection of substitution elements to compose the `cmd` parameter of `ExecuteProcess`. |Argument|Description| |---|---| @@ -43,9 +88,35 @@ Extends the `ExecuteProcess` class. Added constructor parameters for this class |remappings|ordered list of 'to' and 'from' string pairs to be passed to the node as ROS remapping rules| |arguments|list of extra arguments for the node| +Additional parameters which were provided to `ExecuteProcess` are also applicable here, such as `name`, `cwd`, `env`, `additional_env`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `prefix`, `output`, `output_format`, `log_cmd`, and `on_exit`. The `cmd` parameter is *not* supported, as it will be composed to execute the ROS node specified by the `Node`-specific parameters. + +#### Properties + +| Name | Description | +| --------- | ------------------------------------------------------------ | +| node_name | Returns the node's name after execution; this may be affected by substitutions. Throws an error if called prior to execution. | + +Properties available from `ExecuteProcess` are inherited: `process_details`, along with constructor parameters for `name`, `cmd`, `cwd`, `env`, `additional_env`, `shell`, and `output`. + +#### Methods + +| Name | Description | +| ------- | ------------------------------------------------------------ | +| execute | Override. Applies additional ROS-related substitutions to several parameters, then calls the superclass to execute the parsed command. | + +Methods available from `Node` are inherited: `get_sub_entities` and `get_asyncio_future`. + +#### Events + +Inherits events from `Node`, but does not define any additional events. + ### launch_ros.descriptions.ComposableNode -Does not extend another class. Constructor parameters closely mirror those of `Node`, and represent a node which may be executed as part of a composite process hosting multiple nodes. +Does not extend another class. Represents a node which may be executed as part of a composite process hosting multiple nodes. + +#### Constructor + +Constructor parameters closely mirror those of `Node`, despite not being related. |Argument|Description| |---|---| @@ -57,9 +128,25 @@ Does not extend another class. Constructor parameters closely mirror those of `N |remappings|list of from/to pairs for remapping names| |extra_arguments|container specific arguments to be passed to the loaded node| +#### Properties + +Properties are available to access constructor parameters: `package`, `node_plugin`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `extra_arguments`. + +#### Methods + +No custom methods are defined. + +#### Events + +No custom events are defined. + ### launch_ros.actions.ComposableNodeContainer -Extends the `Node` class. Added constructor parameters for this class allow specification of the node container class name and namespace, along with a list of `Node`s to include. This class overrides the `execute` method of `Node` to add additional post-execution actions, loading the composable nodes into the now-executing container process. +Extends the `Node` class. This class allows loading of composable nodes into a container process. + +#### Constructor + +Added constructor parameters for this class allow specification of the node container class name and namespace, along with a list of `Node`s to include. |Argument|Description| |---|---| @@ -67,24 +154,78 @@ Extends the `Node` class. Added constructor parameters for this class allow spec |node_namespace|the ros namespace for this Node, mandatory for full container node name resolution| |composable\_node\_descriptions|optional descriptions of composable nodes to be loaded| +Additional parameters which were provided to `Node` are also applicable here, such as `package`, `node_executable`, `parameters`, `remappings`, `arguments`, `name`, `cwd`, `env`, `additional_env`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `prefix`, `output`, `output_format`, `log_cmd`, and `on_exit`. + +#### Properties + +Properties available from `Node` are inherited: `node_name` and `process_details`, along with constructor parameters for `name`, `cmd`, `cwd`, `env`, `additional_env`, `shell`, and `output`. + +#### Methods + +| Name | Description | +| ------- | ------------------------------------------------------------ | +| execute | Override. Adds actions to load the contained nodes once the process is started, then calls the superclass to execute the parsed command. | + +Methods available from `Node` are inherited: `get_sub_entities` and `get_asyncio_future`. + +#### Events + +Inherits events from `Node`, but does not define any additional events. + ### launch_ros.actions.LifecycleNode -Extends the `Node` class. This class overrides the `execute` method of `Node` to register lifecycle message handlers, and exposes events to allow reactions to said lifecycle state transitions. +Extends the `Node` class. This class exposes additional events related to ROS lifecycle state transitions. + +#### Constructor + +Parameters which were provided to `Node` are applicable here, such as `package`, `node_name`, `node_namespace`, `node_executable`, `parameters`, `remappings`, `arguments`, `name`, `cwd`, `env`, `additional_env`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `prefix`, `output`, `output_format`, `log_cmd`, and `on_exit`. + +#### Properties + +Properties available from `Node` are inherited: `node_name` and `process_details`, along with constructor parameters for `name`, `cmd`, `cwd`, `env`, `additional_env`, `shell`, and `output`. + +#### Methods + +| Name | Description | +| ------- | ------------------------------------------------------------ | +| execute | Override. Adds subscription event handlers to listen for ROS node lifecycle state changes; this handler will trigger appropriate events from this class when transitions are detected. | + +#### Events + +##### Handled Events + +In addition to events handled by the `ExecuteProcess` superclass: + +| Event Type | Description | +| ------------------------------------- | ------------------------------------------------------------ | +| `launch.events.lifecycle.ChangeState` | this event can be targeted to a single lifecycle node, or more than one, or even all lifecycle nodes, and it requests the targeted nodes to change state, see its documentation for more details | + +##### Emitted Events + +In addition to events emitted by the `ExecuteProcess` superclass: + +| Event Type | Description | +| ----------------------------------------- | ------------------------------------------------------------ | +| `launch.events.lifecycle.StateTransition` | this event is emitted when a message is published to the "`//transition_event`" topic, indicating the lifecycle node represented by this action changed state | ## Considerations for Refactored Classes The primary goal of the refactor is to attempt to split the definition aspect of processes/nodes apart from the logic which executes those elements. `ComposableNode` provides a basis for similar breakouts of other elements. -In general, classes should have similar analogs even in the refactor to ensure that existing classes can be replaced with backwards-compatible replacements that use the new structure. These replacements can be implemented to warn the user that the older definitions are deprecated, and suggest moving to the newer refactored style. +In general, existing classes should have similar analogs in the refactor to ensure that existing classes can be replaced with backwards-compatible replacements that use the new structure. These replacements can be implemented to warn the user that the older definitions are deprecated, and suggest moving to the newer refactored style. Further consideration will be required for alternate frontends, such as XML, to determine how to implement these changes with streamlined syntax where possible. -One difficulty when looking forward to allowing functionality such as remote and containerized execution is that the target environment is likely different than the local environment. Different packages may be installed, different environment variables may be defined, and so forth. To support this, it may be helpful to allow an alternate `launch.LaunchContext` to be defined for specific executions. +One difficulty when looking forward to allowing functionality such as remote and containerized execution is that the target environment is likely different than the local environment. Different packages may be installed, different environment variables may be defined, and so forth. To support this, it may be helpful to allow an alternate `launch.LaunchContext` to be defined for specific executions. Additionally, the available support for concepts such as signals and PIDs may be different; to that end, it is likely that remote execution of processes will require sibling classes to those described below, rather than direct subclasses. ## Proposed New Classes ### launch.descriptions.Process -This class would represent only the information required to define a process which might be run. It would not include execution-time details, nor provide monitoring of the process after launch. The constructor parameters would be pulled directly from the current `launch.actions.ExecuteProcess` class. +This class would represent only the information required to define a process which might be run. It would not include execution-time details, nor provide monitoring of the process after launch. + +#### Constructor + +The constructor parameters would be pulled directly from the current `launch.actions.ExecuteProcess` class. |Argument|Description| |---|---| @@ -93,11 +234,30 @@ This class would represent only the information required to define a process whi |cwd|the directory in which to run the executable| |env|dictionary of environment variables to be used, starting from a clean environment. If `None`, the current environment is used.| |additional\_env|dictionary of environment variables to be added. If `env` was `None`, they are added to the current environment. If not, `env` is updated with `additional_env`.| -|shell|if True, a shell is used to execute the cmd| + +#### Properties + +Accessors would be provided for the various constructor parameters: `cmd`, `name`, `cwd`, `env`, and `additional_env`. + +#### Methods + +In the current classes, substitutions are handled through internal method calls. To support better isolation of class functionality, substitutions will be performed in this class, but exposed from a public method which can be overridden by subclasses to perform additional appropriate substitutions. + +| Name | Description | +| ------------- | ------------------------------------------------------------ | +| apply_context | Takes a given LaunchContext and performs actions necessary to prepare to execute the defined command in that context. This will primarily consist of expanding various substitutions. | + +#### Events + +No events would be handled nor emitted. ### launch_ros.descriptions.Node -This class would represent only the information required to define a node which might be run. It would inherit from `launch.descriptions.Process`, and populate its fields in the same manner as the current `launch.actions.Node`. +This class would represent only the information required to define a node which might be run. It would inherit from `launch.descriptions.Process`, and populate its fields in the same manner as the current `launch_ros.actions.Node`. + +#### Constructor + +These parameters are drawn from the current `launch_ros.actions.Node`. |Argument|Description| |---|---| @@ -109,20 +269,54 @@ This class would represent only the information required to define a node which |remappings|ordered list of 'to' and 'from' string pairs to be passed to the node as ROS remapping rules| |arguments|list of extra arguments for the node| +#### Properties + +Accessors would be provided for the various constructor parameters: `node_executable`, `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. Inherited accessors would also be available: `cmd`, `name`, `cwd`, `env`, and `additional_env`. + +#### Methods + +This class would override the `apply_context` method of `launch.descriptions.Process` to apply additional ROS-specific substitutions, then invoke the superclass method itself. This function would match that of the current `launch_ros.actions.Node` internal method `_perform_substitutions`. + +#### Events + +No events would be handled or emitted. + ### launch_ros.descriptions.ComposableNode -This class would be modified to inherit from `launch_ros.descriptions.Node`. Most parameters would be passed to the new superclass. +This class would be modified to inherit from `launch_ros.descriptions.Node`. + +#### Constructor + +Most parameters would be passed to the new superclass. |Argument|Description| |---|---| |node_plugin|name of the plugin to be loaded| +Additional parameters that may be passed, which are handled by `launch_ros.descriptions.Node`: `node_executable`, `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`. + +#### Properties + +Accessors would be provided for the additional constructor parameter: `node_plugin`. Inherited accessors would also be available: `cmd`, `name`, `cwd`, `env`, `additional_env`, `node_executable`, `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. + +#### Methods + +No custom methods would be defined or overridden. + +#### Events + +No events would be handled or emitted. + ### launch.actions.ExecuteLocalProcess -This class would represent the execution-time aspects of launch.actions.ExecuteProcess. The new `process_description` constructor parameter could be either a `launch.descriptions.Process` or a `launch_ros.descriptions.Node`; node-specific functionality is limited to proper configuration of the command line to be executed, so no special execution wrapper is needed. This is not the case for lifecycle nodes or composable nodes, which do require custom execution wrappers, described below. +This class would represent the execution-time aspects of `launch.actions.ExecuteProcess`. The new `process_description` constructor parameter could be either a `launch.descriptions.Process` or a `launch_ros.descriptions.Node`; node-specific functionality is limited to proper configuration of the command line to be executed, so no special execution wrapper is needed. This is not the case for lifecycle nodes or composable nodes, which do require custom execution wrappers, described below. + +This class is simplified from the current `launch.actions.ExecuteProcess` by removing the logic relating to process definition/configuration, and by removing the logic regarding substitutions thereof. (Details regarding remote/containerized execution would not be considered here, and should be implemented in alternate execute actions as appropriate. They could, however, reuse the same process/node description classes, while providing alternate `launch.LaunchContext` information.) +#### Constructor + |Argument|Description| |---|---| |process\_description|the `launch.descriptions.Process` to execute as a local process| @@ -136,14 +330,106 @@ This class would represent the execution-time aspects of launch.actions.ExecuteP |log\_cmd|if `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved.| |on\_exit|list of actions to execute upon process exit.| +#### Properties + +| Name | Description | +| --------------- | ------------------------------------------------------------ | +| process_details | `None` if the process is not yet started; otherwise an object containing information such as the command, working directory, environment, and process ID | + +Additional properties provide access to constructor parameters for `process_description`, `shell`, and `output`. + +#### Methods + +| Name | Description | +| ------------------ | ------------------------------------------------------------ | +| get_sub_entities | Override. If on_exit was provided in the constructor, returns that; otherwise returns an empty list. | +| execute | Override. Establishes event handlers for process execution, passes the execution context to the process definition for substitution expansion, then uses `osrf_pycommon.process_utils.async_execute_process` to launch the defined process. | +| get_asyncio_future | Override. Return an asyncio Future, used to let the launch system know when we're done. | + +#### Events + +##### Handled Events + +| Event Type | Description | +| --------------------------------------- | ------------------------------------------------------------ | +| `launch.events.process.ShutdownProcess` | begins standard shutdown procedure for a running executable | +| `launch.events.process.SignalProcess` | passes the signal provided by the event to the running process | +| `launch.events.process.ProcessStdin` | passes the text provided by the event to the stdin of the process | +| `launch.events.Shutdown` | same as ShutdownProcess | + +##### Emitted Events + +| Event Type | Description | +| -------------------------------------- | ------------------------------------------------------------ | +| `launch.events.process.ProcessStarted` | emitted when the process starts | +| `launch.events.process.ProcessExited` | emitted when the process exits; event contains return code | +| `launch.events.process.ProcessStdout` | emitted when the process produces data the stdout pipe; event contains the data from the pipe | +| `launch.events.process.ProcessStderr` | emitted when the process produces data the stderr pipe; event contains the data from the pipe | + ### launch_ros.actions.ExecuteLocalLifecycleNode -This class would extend the `launch.actions.ExecuteLocalProcess` class, and provide the additional functionality required for managing lifecycle node events that are currently defined in `launch_ros.actions.LifecycleNode`. No additional constructor parameters are defined in this class. +This class would extend the `launch.actions.ExecuteLocalProcess` class, and provide the additional functionality required for managing lifecycle node events that are currently defined in `launch_ros.actions.LifecycleNode`. + +#### Constructor + +No additional constructor parameters are defined in this class. All parameters which are handled by `launch.actions.ExecuteLocalProcess` may be passed to the constructor: `process_description`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `emulate_tty`, `prefix`, `output`, `output_format`, `log_cmd`, `on_exit`. + +#### Properties + +Properties available from `launch.actions.ExecuteLocalProcess` are inherited: `process_details`, along with constructor parameters for `process_description`, `shell`, and `output`. + +#### Methods + +| Name | Description | +| ------- | ------------------------------------------------------------ | +| execute | Override. Adds subscription event handlers to listen for ROS node lifecycle state changes; this handler will trigger appropriate events from this class when transitions are detected. | + +Methods available from `launch.actions.ExecuteLocalProcess` are inherited: `get_sub_entities` and `get_asyncio_future`. + +#### Events + +##### Handled Events + +In addition to events handled by the `launch.actions.ExecuteLocalProcess` superclass: + +| Event Type | Description | +| ------------------------------------- | ------------------------------------------------------------ | +| `launch.events.lifecycle.ChangeState` | this event can be targeted to a single lifecycle node, or more than one, or even all lifecycle nodes, and it requests the targeted nodes to change state, see its documentation for more details | + +##### Emitted Events + +In addition to events emitted by the `launch.actions.ExecuteLocalProcess` superclass: + +| Event Type | Description | +| ----------------------------------------- | ------------------------------------------------------------ | +| `launch.events.lifecycle.StateTransition` | this event is emitted when a message is published to the "`//transition_event`" topic, indicating the lifecycle node represented by this action changed state | ### launch_ros.actions.ExecuteLocalNodeContainer -This class would extend the `launch.actions.ExecuteLocalProcess` class, and provide the additional functionality required for loading multiple nodes into a single container. The description of the composable node container itself should be provided as the `process_description` parameter to pass to `ExecuteLocalProcess`; child nodes would be provided as an additional constructor parameter. +This class would extend the `launch.actions.ExecuteLocalProcess` class, and provide the additional functionality required for loading multiple nodes into a single container. + +#### Constructor + +The description of the composable node container itself should be provided as the `process_description` parameter to pass to `ExecuteLocalProcess`; child nodes would be provided as an additional constructor parameter. |Argument|Description| |---|---| |composable\_node\_descriptions|optional descriptions of composable nodes to be loaded| + +All parameters which are handled by `launch.actions.ExecuteLocalProcess` may be passed to the constructor: `process_description`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `emulate_tty`, `prefix`, `output`, `output_format`, `log_cmd`, `on_exit`. + +#### Properties + +Properties available from `launch.actions.ExecuteLocalProcess` are inherited: `process_details`, along with constructor parameters for `process_description`, `shell`, and `output`. + +#### Methods + +| Name | Description | +| ------- | ------------------------------------------------------------ | +| execute | Override. Adds actions to load the contained nodes once the process is started, then calls the superclass to execute the parsed command. | + +Methods available from `launch.actions.ExecuteLocalProcess` are inherited: `get_sub_entities` and `get_asyncio_future`. + +#### Events + +Inherits events from `launch.actions.ExecuteLocalProcess`, but does not define any additional events. \ No newline at end of file From 6ec03040b4841e94775daf39896e2b27fd46e9e7 Mon Sep 17 00:00:00 2001 From: Roger Strain Date: Mon, 10 Feb 2020 15:51:05 -0600 Subject: [PATCH 3/7] Minor text updates, added brief remote concept Distro A; OPSEC #2893 Signed-off-by: Roger Strain --- articles/execute_process_refactor.md | 92 +++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 9 deletions(-) diff --git a/articles/execute_process_refactor.md b/articles/execute_process_refactor.md index b41383d32..713ebb3e3 100644 --- a/articles/execute_process_refactor.md +++ b/articles/execute_process_refactor.md @@ -262,12 +262,12 @@ These parameters are drawn from the current `launch_ros.actions.Node`. |Argument|Description| |---|---| |node_executable|the name of the executable to find if a package is provided or otherwise a path to the executable to run.| -|package|the package in which the node executable can be found| -|node_name|the name of the node| -|node_namespace|the ros namespace for this Node| -|parameters|list of names of yaml files with parameter rules, or dictionaries of parameters.| -|remappings|ordered list of 'to' and 'from' string pairs to be passed to the node as ROS remapping rules| -|arguments|list of extra arguments for the node| +|package|name of the ROS package the node executable lives in| +|node_name| name the node should have | +|node_namespace|namespace the node should create topics/services/etc in| +|parameters| list of either paths to yaml files or dictionaries of parameters | +|remappings|list of from/to pairs for remapping names| +|arguments|container specific arguments to be passed to the node| #### Properties @@ -293,7 +293,7 @@ Most parameters would be passed to the new superclass. |---|---| |node_plugin|name of the plugin to be loaded| -Additional parameters that may be passed, which are handled by `launch_ros.descriptions.Node`: `node_executable`, `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`. +Additional parameters that may be passed, which are handled by `launch_ros.descriptions.Node`: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`. Note that the parameter `node_executable` would not be passed to the superclass, as it is not applicable to this object. #### Properties @@ -309,7 +309,7 @@ No events would be handled or emitted. ### launch.actions.ExecuteLocalProcess -This class would represent the execution-time aspects of `launch.actions.ExecuteProcess`. The new `process_description` constructor parameter could be either a `launch.descriptions.Process` or a `launch_ros.descriptions.Node`; node-specific functionality is limited to proper configuration of the command line to be executed, so no special execution wrapper is needed. This is not the case for lifecycle nodes or composable nodes, which do require custom execution wrappers, described below. +Extends the `launch.actions.Action` class. This class would represent the execution-time aspects of `launch.actions.ExecuteProcess`. The new `process_description` constructor parameter could be either a `launch.descriptions.Process` or a `launch_ros.descriptions.Node`; node-specific functionality is limited to proper configuration of the command line to be executed, so no special execution wrapper is needed. This is not the case for lifecycle nodes or composable nodes, which do require custom execution wrappers, described below. This class is simplified from the current `launch.actions.ExecuteProcess` by removing the logic relating to process definition/configuration, and by removing the logic regarding substitutions thereof. @@ -432,4 +432,78 @@ Methods available from `launch.actions.ExecuteLocalProcess` are inherited: `get_ #### Events -Inherits events from `launch.actions.ExecuteLocalProcess`, but does not define any additional events. \ No newline at end of file +Inherits events from `launch.actions.ExecuteLocalProcess`, but does not define any additional events. + +## Future Extension + +One topic of interest is the ability to launch nodes on remote machines as part of more complex systems. While the current refactoring will not attempt to implement this functionality, such functionality could be implemented using sibling classes to those described above. + +### launch.actions.ExecuteSshProcess + +Extends the `launch.actions.Action` class. This class would represent the execution-time aspects of an analog to `launch.actions.ExecuteProcess` which executes the given process via an SSH connection. This likely would be a remote machine in virtually all usages. This is *not* a subclass of the proposed `launch.actions.ExecuteLocalProcess` class; certain features provided by that class are not available from standard SSH connections. + +It is also conceivable that this class, or one like it, could be constructed to simultaneously execute multiple processes over a single SSH connection. If this is attempted, several features such as input/output pipes would likely no longer be feasible. + +Similar sibling classes could also be defined to combine SSH and Lifecycle or SSH and Composable Node containers. + +#### Constructor + +| Argument | Description | +| ---------------------- | ------------------------------------------------------------ | +| process\_description | the `launch.descriptions.Process` to execute as a local process | +| connection_description | an object defining the SSH connection information, such as host, port, user, etc. | +| prefix | a set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix` | +| output | configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen. | +| output\_format | for logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance. | +| log\_cmd | if `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved. | +| on\_exit | list of actions to execute upon process exit. | + +The following constructor parameters which were present in the proposed `launch.actions.ExecuteLocalProcess` are not provided as part of this class due to the SSH execution environment. + +| Argument | Rationale for Exclusion | +| --------------- | ------------------------------------------------------------ | +| shell | The process is being executed through SSH, which is by definition a shell | +| sigterm_timeout | Signal handling across SSH is not robust | +| sigkill_timeout | Signal handling across SSH is not robust | +| emulate_tty | The process is being executed through SSH, which may restrict flexibility of TTY choice | + +#### Properties + +| Name | Description | +| --------------- | ------------------------------------------------------------ | +| process_details | `None` if the process is not yet started; otherwise an object containing information such as the command, working directory, environment, and process ID | + +Additional properties provide access to constructor parameters for `process_description`, `connection_description`, and `output`. + +#### Methods + +| Name | Description | +| ------------------ | ------------------------------------------------------------ | +| get_sub_entities | Override. If on_exit was provided in the constructor, returns that; otherwise returns an empty list. | +| execute | Override. Establishes event handlers for process execution, passes the execution context to the process definition for substitution expansion, then uses `osrf_pycommon.process_utils.async_execute_process` to launch the defined process. | +| get_asyncio_future | Override. Return an asyncio Future, used to let the launch system know when we're done. | + +This assumes the SSH interface is provided by a library with get_asyncio_future support; if such a library is not found/used, an alternate method for providing the appropriate feedback will be required. + +#### Events + +##### Handled Events + +| Event Type | Description | +| --------------------------------------- | ------------------------------------------------------------ | +| `launch.events.process.ShutdownProcess` | begins standard shutdown procedure for a running executable | +| `launch.events.process.ProcessStdin` | passes the text provided by the event to the stdin of the process | +| `launch.events.Shutdown` | same as ShutdownProcess | + +The `launch.events.process.SignalProcess` event is not handled by this class, due to the difficulty in managing signals across SSH. The `ProcessStdin` event may need to be evaluated, depending on the SSH interface. + +##### Emitted Events + +| Event Type | Description | +| -------------------------------------- | ------------------------------------------------------------ | +| `launch.events.process.ProcessStarted` | emitted when the process starts | +| `launch.events.process.ProcessExited` | emitted when the process exits; event contains return code | +| `launch.events.process.ProcessStdout` | emitted when the process produces data the stdout pipe; event contains the data from the pipe | +| `launch.events.process.ProcessStderr` | emitted when the process produces data the stderr pipe; event contains the data from the pipe | + +The `ProcessStdout` and `ProcessStderr` events may need to be evaluated, depending on the SSH interface. \ No newline at end of file From 7b5f24448d4aab513b2e61e758038fd3ec60f3c3 Mon Sep 17 00:00:00 2001 From: Roger Strain Date: Fri, 27 Mar 2020 16:18:20 -0500 Subject: [PATCH 4/7] Further split node definition and execution detail Distro A; OPSEC #2893 Signed-off-by: Roger Strain --- articles/execute_process_refactor.md | 427 ++++++++++++++++----------- 1 file changed, 247 insertions(+), 180 deletions(-) diff --git a/articles/execute_process_refactor.md b/articles/execute_process_refactor.md index 713ebb3e3..0ad378843 100644 --- a/articles/execute_process_refactor.md +++ b/articles/execute_process_refactor.md @@ -1,38 +1,49 @@ # Refactoring ExecuteProcess in ROS2 -Initially proposed in [114](https://github.com/ros2/launch/issues/114), this document describes changes to `ExecuteProcess` and related classes. As initially implemented, some aspects of this are tightly coupled to both the implementation chosen and the assumption that processes will execute only in the local environment of the launch process itself. The following changes are designed to provide a more decoupled architecture that will ease support of launching processes locally, remotely, or potentially in containerized environments. Additionally, these changes will support the goal of decoupling the description of an executable from the actual action of executing it. These changes are designed so that existing systems may continue to use the interface before these changes without modification; newer systems may find benefits from adapting to the newer syntax, particularly when composing more complicated environments. + +Initially proposed in [114](https://github.com/ros2/launch/issues/114), this document describes changes to `ExecuteProcess` and related classes. +As initially implemented, some aspects of this are tightly coupled to both the implementation chosen and the assumption that processes will execute only in the local environment of the launch process itself. +The following changes are designed to provide a more decoupled architecture that will ease support of launching processes locally, remotely, or potentially in containerized environments. +Additionally, these changes will support the goal of decoupling the description of an executable from the actual action of executing it. +These changes are designed so that existing systems may continue to use the interface before these changes without modification; newer systems may find benefits from adapting to the newer syntax, particularly when composing more complicated environments. + ## Affected classes before any changes -The following classes currently exist and are relevant to the proposed changes. A brief summary of some relevant concepts is included with each. + +The following classes currently exist and are relevant to the proposed changes. +A brief summary of some relevant concepts is included with each. + ### launch.actions.ExecuteProcess -Extends the `launch.actions.Action` class. This command initiates the execution of a command on the local system, and is not ROS-specific. +Extends the `launch.actions.Action` class. +This command initiates the execution of a command on the local system, and is not ROS-specific. #### Constructor -Allows many items to be set via constructor, including information both on how to launch the process, and how to interact with it after launching. The available parameters and their documentation follow, split into categories considering whether they are more relevant to launching the process, or to dealing with its execution following launch. +Allows many items to be set via constructor, including information both on how to launch the process, and how to interact with it after launching. +The available parameters and their documentation follow, split into categories considering whether they are more relevant to launching the process, or to dealing with its execution following launch. ##### Launch Details |Argument|Description| |---|---| -|cmd|a list where the first item is the executable and the rest are arguments to the executable, each item may be a string or a list of strings and `Substitution`s to be resolved at runtime| -|name|the label used to represent the process, as a string or a `Substitution` to be resolved at runtime, defaults to the basename of the executable| -|cwd|the directory in which to run the executable| -|env|dictionary of environment variables to be used, starting from a clean environment. If `None`, the current environment is used.| -|additional\_env|dictionary of environment variables to be added. If `env` was `None`, they are added to the current environment. If not, `env` is updated with `additional_env`.| +|cmd|A list where the first item is the executable and the rest are arguments to the executable, each item may be a string or a list of strings and `Substitution`s to be resolved at runtime| +|name|The label used to represent the process, as a string or a `Substitution` to be resolved at runtime, defaults to the basename of the executable| +|cwd|The directory in which to run the executable| +|env|Dictionary of environment variables to be used, starting from a clean environment. If `None`, the current environment is used.| +|additional\_env|Dictionary of environment variables to be added. If `env` was `None`, they are added to the current environment. If not, `env` is updated with `additional_env`.| ##### Execution Details |Argument|Description| |---|---| -|shell|if True, a shell is used to execute the cmd| -|sigterm\_timeout|time until shutdown should escalate to `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigterm_timeout`| -|sigkill\_timeout|time until escalating to `SIGKILL` after `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigkill_timeout`| -|emulate\_tty|emulate a tty (terminal), defaults to `False`, but can be overridden with the `LaunchConfiguration` called `emulate_tty`, the value of which is evaluated as true or false according to `evaluate_condition_expression`.| -|prefix|a set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix`| -|output|configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen.| -|output\_format|for logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance.| -|log\_cmd|if `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved.| -|on\_exit|list of actions to execute upon process exit.| +|shell|If True, a shell is used to execute the cmd| +|sigterm\_timeout|Time until shutdown should escalate to `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigterm_timeout`| +|sigkill\_timeout|Time until escalating to `SIGKILL` after `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigkill_timeout`| +|emulate\_tty|Emulate a tty (terminal), defaults to `False`, but can be overridden with the `LaunchConfiguration` called `emulate_tty`, the value of which is evaluated as true or false according to `evaluate_condition_expression`.| +|prefix|A set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix`| +|output|Configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen.| +|output\_format|For logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance.| +|log\_cmd|If `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved.| +|on\_exit|List of actions to execute upon process exit.| #### Properties @@ -56,39 +67,43 @@ Additional properties provide access to constructor parameters for `name`, `cmd` | Event Type | Description | | ------------------------------------- | ------------------------------------------------------------ | -| `launch.events.process.ShutdownProcess` | begins standard shutdown procedure for a running executable | -| `launch.events.process.SignalProcess` | passes the signal provided by the event to the running process | -| `launch.events.process.ProcessStdin` | passes the text provided by the event to the stdin of the process | -| `launch.events.Shutdown` | same as ShutdownProcess | +| `launch.events.process.ShutdownProcess` | Begins standard shutdown procedure for a running executable | +| `launch.events.process.SignalProcess` | Passes the signal provided by the event to the running process | +| `launch.events.process.ProcessStdin` | Passes the text provided by the event to the stdin of the process | +| `launch.events.Shutdown` | Same as ShutdownProcess | ##### Emitted Events | Event Type | Description | | ------------------------------------ | ------------------------------------------------------------ | -| `launch.events.process.ProcessStarted` | emitted when the process starts | -| `launch.events.process.ProcessExited` | emitted when the process exits; event contains return code | -| `launch.events.process.ProcessStdout` | emitted when the process produces data the stdout pipe; event contains the data from the pipe | -| `launch.events.process.ProcessStderr` | emitted when the process produces data the stderr pipe; event contains the data from the pipe | +| `launch.events.process.ProcessStarted` | Emitted when the process starts | +| `launch.events.process.ProcessExited` | Emitted when the process exits; event contains return code | +| `launch.events.process.ProcessStdout` | Emitted when the process produces data the stdout pipe; event contains the data from the pipe | +| `launch.events.process.ProcessStderr` | Emitted when the process produces data the stderr pipe; event contains the data from the pipe | ### launch_ros.actions.Node -Extends the `ExecuteProcess` class. This allows execution of a ROS-specific node, and extends the available information to include node related details. +Extends the `ExecuteProcess` class. +This allows execution of a ROS-specific node, and extends the available information to include node related details. #### Constructor -Added constructor parameters for this class all focus on concepts similar to the Launch Details discussed above, but the class also overrides the `execute` method of `ExecuteProcess`. The purpose of this override is to provide more granular structure for the command used to launch a ROS node. All the provided constructor parameters eventually reduce into a collection of substitution elements to compose the `cmd` parameter of `ExecuteProcess`. +Added constructor parameters for this class all focus on concepts similar to the Launch Details discussed above, but the class also overrides the `execute` method of `ExecuteProcess`. +The purpose of this override is to provide more granular structure for the command used to launch a ROS node. +All the provided constructor parameters eventually reduce into a collection of substitution elements to compose the `cmd` parameter of `ExecuteProcess`. |Argument|Description| |---|---| -|node_executable|the name of the executable to find if a package is provided or otherwise a path to the executable to run.| -|package|the package in which the node executable can be found| -|node_name|the name of the node| -|node_namespace|the ros namespace for this Node| -|parameters|list of names of yaml files with parameter rules, or dictionaries of parameters.| -|remappings|ordered list of 'to' and 'from' string pairs to be passed to the node as ROS remapping rules| -|arguments|list of extra arguments for the node| +|node_executable|The name of the executable to find if a package is provided or otherwise a path to the executable to run.| +|package|The package in which the node executable can be found| +|node_name|The name of the node| +|node_namespace|The ros namespace for this Node| +|parameters|List of names of yaml files with parameter rules, or dictionaries of parameters.| +|remappings|Ordered list of 'to' and 'from' string pairs to be passed to the node as ROS remapping rules| +|arguments|List of extra arguments for the node| -Additional parameters which were provided to `ExecuteProcess` are also applicable here, such as `name`, `cwd`, `env`, `additional_env`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `prefix`, `output`, `output_format`, `log_cmd`, and `on_exit`. The `cmd` parameter is *not* supported, as it will be composed to execute the ROS node specified by the `Node`-specific parameters. +Additional parameters which were provided to `ExecuteProcess` are also applicable here, such as `name`, `cwd`, `env`, `additional_env`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `prefix`, `output`, `output_format`, `log_cmd`, and `on_exit`. +The `cmd` parameter is *not* supported, as it will be composed to execute the ROS node specified by the `Node`-specific parameters. #### Properties @@ -112,7 +127,8 @@ Inherits events from `Node`, but does not define any additional events. ### launch_ros.descriptions.ComposableNode -Does not extend another class. Represents a node which may be executed as part of a composite process hosting multiple nodes. +Does not extend another class. +Represents a node which may be executed as part of a composite process hosting multiple nodes. #### Constructor @@ -120,13 +136,13 @@ Constructor parameters closely mirror those of `Node`, despite not being related |Argument|Description| |---|---| -|package|name of the ROS package the node plugin lives in| -|node_plugin|name of the plugin to be loaded| -|node_name|name the node should have| -|node_namespace|namespace the node should create topics/services/etc in| -|parameters|list of either paths to yaml files or dictionaries of parameters| -|remappings|list of from/to pairs for remapping names| -|extra_arguments|container specific arguments to be passed to the loaded node| +|package|Name of the ROS package the node plugin lives in| +|node_plugin|Name of the plugin to be loaded| +|node_name|Name the node should have| +|node_namespace|Namespace the node should create topics/services/etc in| +|parameters|List of either paths to yaml files or dictionaries of parameters| +|remappings|List of from/to pairs for remapping names| +|extra_arguments|Container specific arguments to be passed to the loaded node| #### Properties @@ -142,7 +158,8 @@ No custom events are defined. ### launch_ros.actions.ComposableNodeContainer -Extends the `Node` class. This class allows loading of composable nodes into a container process. +Extends the `Node` class. +This class allows loading of composable nodes into a container process. #### Constructor @@ -150,9 +167,9 @@ Added constructor parameters for this class allow specification of the node cont |Argument|Description| |---|---| -|node_name|the name of the node, mandatory for full container node name resolution| -|node_namespace|the ros namespace for this Node, mandatory for full container node name resolution| -|composable\_node\_descriptions|optional descriptions of composable nodes to be loaded| +|node_name|The name of the node, mandatory for full container node name resolution| +|node_namespace|The ros namespace for this Node, mandatory for full container node name resolution| +|composable\_node\_descriptions|Optional descriptions of composable nodes to be loaded| Additional parameters which were provided to `Node` are also applicable here, such as `package`, `node_executable`, `parameters`, `remappings`, `arguments`, `name`, `cwd`, `env`, `additional_env`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `prefix`, `output`, `output_format`, `log_cmd`, and `on_exit`. @@ -174,7 +191,8 @@ Inherits events from `Node`, but does not define any additional events. ### launch_ros.actions.LifecycleNode -Extends the `Node` class. This class exposes additional events related to ROS lifecycle state transitions. +Extends the `Node` class. +This class exposes additional events related to ROS lifecycle state transitions. #### Constructor @@ -198,7 +216,7 @@ In addition to events handled by the `ExecuteProcess` superclass: | Event Type | Description | | ------------------------------------- | ------------------------------------------------------------ | -| `launch.events.lifecycle.ChangeState` | this event can be targeted to a single lifecycle node, or more than one, or even all lifecycle nodes, and it requests the targeted nodes to change state, see its documentation for more details | +| `launch.events.lifecycle.ChangeState` | This event can be targeted to a single lifecycle node, or more than one, or even all lifecycle nodes, and it requests the targeted nodes to change state, see its documentation for more details | ##### Emitted Events @@ -206,34 +224,41 @@ In addition to events emitted by the `ExecuteProcess` superclass: | Event Type | Description | | ----------------------------------------- | ------------------------------------------------------------ | -| `launch.events.lifecycle.StateTransition` | this event is emitted when a message is published to the "`//transition_event`" topic, indicating the lifecycle node represented by this action changed state | +| `launch.events.lifecycle.StateTransition` | This event is emitted when a message is published to the "`//transition_event`" topic, indicating the lifecycle node represented by this action changed state | ## Considerations for Refactored Classes -The primary goal of the refactor is to attempt to split the definition aspect of processes/nodes apart from the logic which executes those elements. `ComposableNode` provides a basis for similar breakouts of other elements. +The primary goal of the refactor is to attempt to split the definition aspect of processes/nodes apart from the logic which executes those elements. +`ComposableNode` provides a basis for similar breakouts of other elements. -In general, existing classes should have similar analogs in the refactor to ensure that existing classes can be replaced with backwards-compatible replacements that use the new structure. These replacements can be implemented to warn the user that the older definitions are deprecated, and suggest moving to the newer refactored style. +In general, existing classes should have similar analogs in the refactor to ensure that existing classes can be replaced with backwards-compatible replacements that use the new structure. +These replacements can be implemented to warn the user that the older definitions are deprecated, and suggest moving to the newer refactored style. Further consideration will be required for alternate frontends, such as XML, to determine how to implement these changes with streamlined syntax where possible. -One difficulty when looking forward to allowing functionality such as remote and containerized execution is that the target environment is likely different than the local environment. Different packages may be installed, different environment variables may be defined, and so forth. To support this, it may be helpful to allow an alternate `launch.LaunchContext` to be defined for specific executions. Additionally, the available support for concepts such as signals and PIDs may be different; to that end, it is likely that remote execution of processes will require sibling classes to those described below, rather than direct subclasses. +One difficulty when looking forward to allowing functionality such as remote and containerized execution is that the target environment is likely different than the local environment. +Different packages may be installed, different environment variables may be defined, and so forth. +An subclass implementation of the proposed `launch.descriptions.Executable` class may choose to override the base `apply_context` method to implement additional layer(s) of substitutions appropriate to its destination contexts, such as remote installation paths or environment variables. +Additionally, the available support for concepts such as signals and PIDs may be different; to that end, it is likely that remote execution of processes will require sibling classes to those described below, rather than direct subclasses. ## Proposed New Classes -### launch.descriptions.Process -This class would represent only the information required to define a process which might be run. It would not include execution-time details, nor provide monitoring of the process after launch. +### launch.descriptions.Executable + +This class would represent only the information required to define an entity which might be run. +It would not include execution-time details, nor provide monitoring of the process after launch. #### Constructor The constructor parameters would be pulled directly from the current `launch.actions.ExecuteProcess` class. -|Argument|Description| -|---|---| -|cmd|a list where the first item is the executable and the rest are arguments to the executable, each item may be a string or a list of strings and `Substitution`s to be resolved at runtime| -|name|the label used to represent the process, as a string or a `Substitution` to be resolved at runtime, defaults to the basename of the executable| -|cwd|the directory in which to run the executable| -|env|dictionary of environment variables to be used, starting from a clean environment. If `None`, the current environment is used.| -|additional\_env|dictionary of environment variables to be added. If `env` was `None`, they are added to the current environment. If not, `env` is updated with `additional_env`.| +| Argument | Description | +| --------------- | ------------------------------------------------------------ | +| cmd | A list where the first item is the executable and the rest are arguments to the executable, each item may be a string or a list of strings and `Substitution`s to be resolved at runtime | +| name | The label used to represent the process, as a string or a `Substitution` to be resolved at runtime, defaults to the basename of the executable | +| cwd | The directory in which to run the executable | +| env | Dictionary of environment variables to be used, starting from a clean environment. If `None`, the current environment is used. | +| additional\_env | Dictionary of environment variables to be added. If `env` was `None`, they are added to the current environment. If not, `env` is updated with `additional_env`. | #### Properties @@ -241,7 +266,9 @@ Accessors would be provided for the various constructor parameters: `cmd`, `name #### Methods -In the current classes, substitutions are handled through internal method calls. To support better isolation of class functionality, substitutions will be performed in this class, but exposed from a public method which can be overridden by subclasses to perform additional appropriate substitutions. +In the current classes, substitutions are handled through internal method calls. +To support better isolation of class functionality, substitutions will be performed in this class, but exposed from a public method which can be overridden by subclasses to perform additional appropriate substitutions. +Substituted versions of the various parameters will be stored in a local dictionary, similar to the current `__process_event_args`. | Name | Description | | ------------- | ------------------------------------------------------------ | @@ -251,184 +278,221 @@ In the current classes, substitutions are handled through internal method calls. No events would be handled nor emitted. -### launch_ros.descriptions.Node +### launch.actions.ExecuteLocal -This class would represent only the information required to define a node which might be run. It would inherit from `launch.descriptions.Process`, and populate its fields in the same manner as the current `launch_ros.actions.Node`. +Extends the `launch.actions.Action` class. +This class would represent the execution-time aspects of `launch.actions.ExecuteProcess`. +The new `process_description` constructor parameter could be a `launch.descriptions.Executable`, a `launch_ros.descriptions.Node`, or one of the other subclasses. -#### Constructor +This class is simplified from the current `launch.actions.ExecuteProcess` by removing the logic relating to process definition/configuration, and by removing the logic regarding substitutions thereof. -These parameters are drawn from the current `launch_ros.actions.Node`. +(Details regarding remote/containerized execution would not be considered here, and should be implemented in alternate execute actions as appropriate. +They could, however, reuse the same process/node description classes, while providing alternate `launch.LaunchContext` information.) -|Argument|Description| -|---|---| -|node_executable|the name of the executable to find if a package is provided or otherwise a path to the executable to run.| -|package|name of the ROS package the node executable lives in| -|node_name| name the node should have | -|node_namespace|namespace the node should create topics/services/etc in| -|parameters| list of either paths to yaml files or dictionaries of parameters | -|remappings|list of from/to pairs for remapping names| -|arguments|container specific arguments to be passed to the node| +#### Constructor + +| Argument | Description | +| -------------------- | ------------------------------------------------------------ | +| process\_description | The `launch.descriptions.Executable` to execute as a local process | +| shell | If True, a shell is used to execute the cmd | +| sigterm\_timeout | Time until shutdown should escalate to `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigterm_timeout` | +| sigkill\_timeout | Time until escalating to `SIGKILL` after `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigkill_timeout` | +| emulate\_tty | Emulate a tty (terminal), defaults to `False`, but can be overridden with the `LaunchConfiguration` called `emulate_tty`, the value of which is evaluated as true or false according to `evaluate_condition_expression`. | +| prefix | A set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix` | +| output | Configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen. | +| output\_format | For logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance. | +| log\_cmd | If `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved. | +| on\_exit | List of actions to execute upon process exit. | #### Properties -Accessors would be provided for the various constructor parameters: `node_executable`, `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. Inherited accessors would also be available: `cmd`, `name`, `cwd`, `env`, and `additional_env`. +| Name | Description | +| --------------- | ------------------------------------------------------------ | +| process_details | `None` if the process is not yet started; otherwise an object containing information such as the command, working directory, environment, and process ID | + +Additional properties provide access to constructor parameters for `process_description`, `shell`, and `output`. #### Methods -This class would override the `apply_context` method of `launch.descriptions.Process` to apply additional ROS-specific substitutions, then invoke the superclass method itself. This function would match that of the current `launch_ros.actions.Node` internal method `_perform_substitutions`. +| Name | Description | +| ------------------ | ------------------------------------------------------------ | +| get_sub_entities | Override. If on_exit was provided in the constructor, returns that; otherwise returns an empty list. | +| execute | Override. Establishes event handlers for process execution, passes the execution context to the process definition for substitution expansion, then uses `osrf_pycommon.process_utils.async_execute_process` to launch the defined process. | +| get_asyncio_future | Override. Return an asyncio Future, used to let the launch system know when we're done. | #### Events -No events would be handled or emitted. +##### Handled Events -### launch_ros.descriptions.ComposableNode +| Event Type | Description | +| --------------------------------------- | ------------------------------------------------------------ | +| `launch.events.process.ShutdownProcess` | Begins standard shutdown procedure for a running executable | +| `launch.events.process.SignalProcess` | Passes the signal provided by the event to the running process | +| `launch.events.process.ProcessStdin` | Passes the text provided by the event to the stdin of the process | +| `launch.events.Shutdown` | Same as ShutdownProcess | -This class would be modified to inherit from `launch_ros.descriptions.Node`. +##### Emitted Events -#### Constructor +| Event Type | Description | +| -------------------------------------- | ------------------------------------------------------------ | +| `launch.events.process.ProcessStarted` | Emitted when the process starts | +| `launch.events.process.ProcessExited` | Emitted when the process exits; event contains return code | +| `launch.events.process.ProcessStdout` | Emitted when the process produces data the stdout pipe; event contains the data from the pipe | +| `launch.events.process.ProcessStderr` | Emitted when the process produces data the stderr pipe; event contains the data from the pipe | -Most parameters would be passed to the new superclass. +### launch_ros.descriptions.Node -|Argument|Description| -|---|---| -|node_plugin|name of the plugin to be loaded| +This class would represent only the common information required to define a ROS2 node. +It would not inherit from any other class, and would have a subset of the fields of the current `launch_ros.actions.Node`. + +#### Constructor -Additional parameters that may be passed, which are handled by `launch_ros.descriptions.Node`: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`. Note that the parameter `node_executable` would not be passed to the superclass, as it is not applicable to this object. +These parameters are drawn from the shared parameters of the current `launch_ros.actions.Node` and `launch_ros.descriptions.ComposableNode`. + +| Argument | Description | +| -------------- | ------------------------------------------------------------ | +| package | name of the ROS package the node executable lives in | +| node_name | Name the node should have | +| node_namespace | Namespace the node should create topics/services/etc in | +| parameters | List of either paths to yaml files or dictionaries of parameters | +| remappings | List of from/to pairs for remapping names | +| arguments | Container specific arguments to be passed to the node | #### Properties -Accessors would be provided for the additional constructor parameter: `node_plugin`. Inherited accessors would also be available: `cmd`, `name`, `cwd`, `env`, `additional_env`, `node_executable`, `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. +Accessors would be provided for the various constructor parameters: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. #### Methods -No custom methods would be defined or overridden. +In the current classes, substitutions are handled through internal method calls. +To support better isolation of class functionality, substitutions will be performed in this class, but exposed from a public method which can be overridden by subclasses to perform additional appropriate substitutions. -#### Events +| Name | Description | +| ------- | ------------------------------------------------------------ | +| prepare | Takes a given LaunchContext and Action, and performs actions necessary to prepare the node for execution in that context. This will primarily consist of expanding various substitutions, but may additionally add event handlers related to the Action which will be invoked. | -No events would be handled or emitted. +This function would match that of the current `launch_ros.actions.Node` internal method `_perform_substitutions`. -### launch.actions.ExecuteLocalProcess +#### Events -Extends the `launch.actions.Action` class. This class would represent the execution-time aspects of `launch.actions.ExecuteProcess`. The new `process_description` constructor parameter could be either a `launch.descriptions.Process` or a `launch_ros.descriptions.Node`; node-specific functionality is limited to proper configuration of the command line to be executed, so no special execution wrapper is needed. This is not the case for lifecycle nodes or composable nodes, which do require custom execution wrappers, described below. +No events would be handled or emitted. -This class is simplified from the current `launch.actions.ExecuteProcess` by removing the logic relating to process definition/configuration, and by removing the logic regarding substitutions thereof. +### launch_ros.descriptions.LifecycleNode -(Details regarding remote/containerized execution would not be considered here, and should be implemented in alternate execute actions as appropriate. They could, however, reuse the same process/node description classes, while providing alternate `launch.LaunchContext` information.) +This class would extend the `launch_ros.descriptions.Node` class, and provide the additional functionality required for managing lifecycle node events that are currently defined in `launch_ros.actions.LifecycleNode`. #### Constructor -|Argument|Description| -|---|---| -|process\_description|the `launch.descriptions.Process` to execute as a local process| -|shell|if True, a shell is used to execute the cmd| -|sigterm\_timeout|time until shutdown should escalate to `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigterm_timeout`| -|sigkill\_timeout|time until escalating to `SIGKILL` after `SIGTERM`, as a string or a list of strings and `Substitution`s to be resolved at runtime, defaults to the `LaunchConfiguration` called `sigkill_timeout`| -|emulate\_tty|emulate a tty (terminal), defaults to `False`, but can be overridden with the `LaunchConfiguration` called `emulate_tty`, the value of which is evaluated as true or false according to `evaluate_condition_expression`.| -|prefix|a set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix`| -|output|configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen.| -|output\_format|for logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance.| -|log\_cmd|if `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved.| -|on\_exit|list of actions to execute upon process exit.| +No additional constructor parameters are defined in this class. +All parameters which are handled by `launch_ros.descriptions.Node` may be passed to the constructor: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. #### Properties -| Name | Description | -| --------------- | ------------------------------------------------------------ | -| process_details | `None` if the process is not yet started; otherwise an object containing information such as the command, working directory, environment, and process ID | - -Additional properties provide access to constructor parameters for `process_description`, `shell`, and `output`. +Constructor properties available from ``launch_ros.descriptions.Node`` are inherited: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. #### Methods -| Name | Description | -| ------------------ | ------------------------------------------------------------ | -| get_sub_entities | Override. If on_exit was provided in the constructor, returns that; otherwise returns an empty list. | -| execute | Override. Establishes event handlers for process execution, passes the execution context to the process definition for substitution expansion, then uses `osrf_pycommon.process_utils.async_execute_process` to launch the defined process. | -| get_asyncio_future | Override. Return an asyncio Future, used to let the launch system know when we're done. | +| Name | Description | +| ------- | ------------------------------------------------------------ | +| prepare | Overridden. Adds subscription event handlers to listen for ROS node lifecycle state changes; this handler will trigger appropriate events from this class when transitions are detected. | #### Events ##### Handled Events -| Event Type | Description | -| --------------------------------------- | ------------------------------------------------------------ | -| `launch.events.process.ShutdownProcess` | begins standard shutdown procedure for a running executable | -| `launch.events.process.SignalProcess` | passes the signal provided by the event to the running process | -| `launch.events.process.ProcessStdin` | passes the text provided by the event to the stdin of the process | -| `launch.events.Shutdown` | same as ShutdownProcess | +| Event Type | Description | +| ------------------------------------- | ------------------------------------------------------------ | +| `launch.events.lifecycle.ChangeState` | This event can be targeted to a single lifecycle node, or more than one, or even all lifecycle nodes, and it requests the targeted nodes to change state, see its documentation for more details | ##### Emitted Events -| Event Type | Description | -| -------------------------------------- | ------------------------------------------------------------ | -| `launch.events.process.ProcessStarted` | emitted when the process starts | -| `launch.events.process.ProcessExited` | emitted when the process exits; event contains return code | -| `launch.events.process.ProcessStdout` | emitted when the process produces data the stdout pipe; event contains the data from the pipe | -| `launch.events.process.ProcessStderr` | emitted when the process produces data the stderr pipe; event contains the data from the pipe | +| Event Type | Description | +| ----------------------------------------- | ------------------------------------------------------------ | +| `launch.events.lifecycle.StateTransition` | This event is emitted when a message is published to the "`//transition_event`" topic, indicating the lifecycle node represented by this action changed state | -### launch_ros.actions.ExecuteLocalLifecycleNode +### launch_ros.descriptions.ExecutableNode -This class would extend the `launch.actions.ExecuteLocalProcess` class, and provide the additional functionality required for managing lifecycle node events that are currently defined in `launch_ros.actions.LifecycleNode`. +This class would represent the information required to define a node which might be run as a single executable. +It would inherit from `launch.descriptions.Executable`, contain a `launch_ros.descriptions.Node`, and populate its fields in the same manner as the current `launch_ros.actions.Node`. #### Constructor -No additional constructor parameters are defined in this class. All parameters which are handled by `launch.actions.ExecuteLocalProcess` may be passed to the constructor: `process_description`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `emulate_tty`, `prefix`, `output`, `output_format`, `log_cmd`, `on_exit`. +These parameters are drawn from the current `launch_ros.actions.Node`. + +REQUEST FOR COMMENT: Currently, this calls out the node as a `launch_ros.descriptions.Node` object parameter; would this be better styled by accepting a flat list to make the inner Node less visible to users? + +| Argument | Description | +| --------------- | ------------------------------------------------------------ | +| node_executable | The name of the executable to find if a package is provided or otherwise a path to the executable to run. | +| node | The `launch_ros.descriptions.Node` (or subclass thereof) which is being run. | + +Most parameters which are handled by `launch.descriptions.Executable` may be passed to the constructor: `name`, `cwd`, `env`, and `additional_env`. +Note that the `cmd` parameter would *not* be passed through; the command would be constructed per ROS Node execution context. #### Properties -Properties available from `launch.actions.ExecuteLocalProcess` are inherited: `process_details`, along with constructor parameters for `process_description`, `shell`, and `output`. +Accessors would be provided for the various constructor parameters: `node_executable` and `node`. +Inherited accessors would also be available: `cmd`, `name`, `cwd`, `env`, and `additional_env`. #### Methods -| Name | Description | -| ------- | ------------------------------------------------------------ | -| execute | Override. Adds subscription event handlers to listen for ROS node lifecycle state changes; this handler will trigger appropriate events from this class when transitions are detected. | - -Methods available from `launch.actions.ExecuteLocalProcess` are inherited: `get_sub_entities` and `get_asyncio_future`. +This class would override the `apply_context` method of `launch.descriptions.Executable` to additionally invoke the `apply_context` method of the `launch_ros.descriptions.Node`, then invoke the superclass method itself. +This function would match that of the current `launch_ros.actions.Node` internal method `_perform_substitutions`. #### Events -##### Handled Events +No events would be handled or emitted. -In addition to events handled by the `launch.actions.ExecuteLocalProcess` superclass: +### launch_ros.descriptions.ComposableNode -| Event Type | Description | -| ------------------------------------- | ------------------------------------------------------------ | -| `launch.events.lifecycle.ChangeState` | this event can be targeted to a single lifecycle node, or more than one, or even all lifecycle nodes, and it requests the targeted nodes to change state, see its documentation for more details | +This class would be modified to inherit from `launch_ros.descriptions.Node`. -##### Emitted Events +#### Constructor + +Most parameters would be passed to the new superclass. -In addition to events emitted by the `launch.actions.ExecuteLocalProcess` superclass: +|Argument|Description| +|---|---| +|node_plugin|Name of the plugin to be loaded| -| Event Type | Description | -| ----------------------------------------- | ------------------------------------------------------------ | -| `launch.events.lifecycle.StateTransition` | this event is emitted when a message is published to the "`//transition_event`" topic, indicating the lifecycle node represented by this action changed state | +Additional parameters that may be passed, which are handled by `launch_ros.descriptions.Node`: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`. + +#### Properties -### launch_ros.actions.ExecuteLocalNodeContainer +Accessors would be provided for the additional constructor parameter: `node_plugin`. +Inherited accessors would also be available: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. -This class would extend the `launch.actions.ExecuteLocalProcess` class, and provide the additional functionality required for loading multiple nodes into a single container. +#### Methods + +No custom methods would be defined or overridden. + +#### Events + +No events would be handled or emitted. + +### launch_ros.descriptions.ExecutableNodeContainer + +This class would extend the `launch_ros.descriptions.ExecutableNode` class, and provide the additional functionality required for loading multiple nodes into a single container. #### Constructor -The description of the composable node container itself should be provided as the `process_description` parameter to pass to `ExecuteLocalProcess`; child nodes would be provided as an additional constructor parameter. +The description of the composable node container itself should be provided as the parameters passed to ``launch_ros.descriptions.ExecutableNode``; child nodes would be provided as an additional constructor parameter. -|Argument|Description| -|---|---| -|composable\_node\_descriptions|optional descriptions of composable nodes to be loaded| +| Argument | Description | +| ------------------------------ | ------------------------------------------------------ | +| composable\_node\_descriptions | Optional descriptions of composable nodes to be loaded | -All parameters which are handled by `launch.actions.ExecuteLocalProcess` may be passed to the constructor: `process_description`, `shell`, `sigterm_timeout`, `sigkill_timeout`, `emulate_tty`, `prefix`, `output`, `output_format`, `log_cmd`, `on_exit`. +All parameters which are handled by ``launch_ros.descriptions.ExecutableNode`` may be passed to the constructor: `node_executable`, `node`, `name`, `cwd`, `env`, and `additional_env`. #### Properties -Properties available from `launch.actions.ExecuteLocalProcess` are inherited: `process_details`, along with constructor parameters for `process_description`, `shell`, and `output`. +Properties available from ``launch_ros.descriptions.ExecutableNode`` are inherited: `process_details`, along with constructor parameters for `process_description`, `shell`, and `output`. #### Methods | Name | Description | | ------- | ------------------------------------------------------------ | -| execute | Override. Adds actions to load the contained nodes once the process is started, then calls the superclass to execute the parsed command. | - -Methods available from `launch.actions.ExecuteLocalProcess` are inherited: `get_sub_entities` and `get_asyncio_future`. +| prepare | Overridden. Calls the superclass to prepare node-related information, calls `prepare` on each composable node, and adds actions to the target Action to load the contained nodes once the process is started, then calls the superclass to execute the parsed command. | #### Events @@ -436,27 +500,29 @@ Inherits events from `launch.actions.ExecuteLocalProcess`, but does not define a ## Future Extension -One topic of interest is the ability to launch nodes on remote machines as part of more complex systems. While the current refactoring will not attempt to implement this functionality, such functionality could be implemented using sibling classes to those described above. +One topic of interest is the ability to launch nodes on remote machines as part of more complex systems. +While the current refactoring will not attempt to implement this functionality, such functionality could be implemented using sibling classes to those described above. ### launch.actions.ExecuteSshProcess -Extends the `launch.actions.Action` class. This class would represent the execution-time aspects of an analog to `launch.actions.ExecuteProcess` which executes the given process via an SSH connection. This likely would be a remote machine in virtually all usages. This is *not* a subclass of the proposed `launch.actions.ExecuteLocalProcess` class; certain features provided by that class are not available from standard SSH connections. - -It is also conceivable that this class, or one like it, could be constructed to simultaneously execute multiple processes over a single SSH connection. If this is attempted, several features such as input/output pipes would likely no longer be feasible. +Extends the `launch.actions.Action` class. +This class would represent the execution-time aspects of an analog to `launch.actions.ExecuteProcess` which executes the given process via an SSH connection. +This likely would be a remote machine in virtually all usages. This is *not* a subclass of the proposed `launch.actions.ExecuteLocal` class; certain features provided by that class are not available from standard SSH connections. -Similar sibling classes could also be defined to combine SSH and Lifecycle or SSH and Composable Node containers. +It is also conceivable that this class, or one like it, could be constructed to simultaneously execute multiple processes over a single SSH connection. +If this is attempted, several features such as input/output pipes would likely no longer be feasible. #### Constructor | Argument | Description | | ---------------------- | ------------------------------------------------------------ | -| process\_description | the `launch.descriptions.Process` to execute as a local process | -| connection_description | an object defining the SSH connection information, such as host, port, user, etc. | -| prefix | a set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix` | -| output | configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen. | -| output\_format | for logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance. | -| log\_cmd | if `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved. | -| on\_exit | list of actions to execute upon process exit. | +| process\_description | The `launch.descriptions.Executable` to execute as a local process | +| connection_description | An object defining the SSH connection information, such as host, port, user, etc. | +| prefix | A set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix` | +| output | Configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen. | +| output\_format | For logging each output line, supporting `str.format()` substitutions with the following keys in scope: `line` to reference the raw output line and `this` to reference this action instance. | +| log\_cmd | If `True`, prints the final cmd before executing the process, which is useful for debugging when substitutions are involved. | +| on\_exit | List of actions to execute upon process exit. | The following constructor parameters which were present in the proposed `launch.actions.ExecuteLocalProcess` are not provided as part of this class due to the SSH execution environment. @@ -491,19 +557,20 @@ This assumes the SSH interface is provided by a library with get_asyncio_future | Event Type | Description | | --------------------------------------- | ------------------------------------------------------------ | -| `launch.events.process.ShutdownProcess` | begins standard shutdown procedure for a running executable | -| `launch.events.process.ProcessStdin` | passes the text provided by the event to the stdin of the process | -| `launch.events.Shutdown` | same as ShutdownProcess | +| `launch.events.process.ShutdownProcess` | Begins standard shutdown procedure for a running executable | +| `launch.events.process.ProcessStdin` | Passes the text provided by the event to the stdin of the process | +| `launch.events.Shutdown` | Same as ShutdownProcess | -The `launch.events.process.SignalProcess` event is not handled by this class, due to the difficulty in managing signals across SSH. The `ProcessStdin` event may need to be evaluated, depending on the SSH interface. +The `launch.events.process.SignalProcess` event is not handled by this class, due to the difficulty in managing signals across SSH. +The `ProcessStdin` event may need to be evaluated, depending on the SSH interface. ##### Emitted Events | Event Type | Description | | -------------------------------------- | ------------------------------------------------------------ | -| `launch.events.process.ProcessStarted` | emitted when the process starts | -| `launch.events.process.ProcessExited` | emitted when the process exits; event contains return code | -| `launch.events.process.ProcessStdout` | emitted when the process produces data the stdout pipe; event contains the data from the pipe | -| `launch.events.process.ProcessStderr` | emitted when the process produces data the stderr pipe; event contains the data from the pipe | +| `launch.events.process.ProcessStarted` | Emitted when the process starts | +| `launch.events.process.ProcessExited` | Emitted when the process exits; event contains return code | +| `launch.events.process.ProcessStdout` | Emitted when the process produces data the stdout pipe; event contains the data from the pipe | +| `launch.events.process.ProcessStderr` | Emitted when the process produces data the stderr pipe; event contains the data from the pipe | The `ProcessStdout` and `ProcessStderr` events may need to be evaluated, depending on the SSH interface. \ No newline at end of file From ee6bd355456d0c1761af97ac2343c98b65707bfd Mon Sep 17 00:00:00 2001 From: Roger Strain Date: Tue, 16 Jun 2020 12:53:15 -0500 Subject: [PATCH 5/7] Split of functionality into traits Distro A; OPSEC #2893 Signed-off-by: Roger Strain --- articles/execute_process_refactor.md | 133 ++++++++++++++++++--------- 1 file changed, 88 insertions(+), 45 deletions(-) diff --git a/articles/execute_process_refactor.md b/articles/execute_process_refactor.md index 0ad378843..551652c75 100644 --- a/articles/execute_process_refactor.md +++ b/articles/execute_process_refactor.md @@ -347,7 +347,7 @@ It would not inherit from any other class, and would have a subset of the fields #### Constructor -These parameters are drawn from the shared parameters of the current `launch_ros.actions.Node` and `launch_ros.descriptions.ComposableNode`. +These parameters are drawn from the shared parameters of the current `launch_ros.actions.Node` and `launch_ros.descriptions.ComposableNode`, and introduces a new collection of `traits`, described in following classes. | Argument | Description | | -------------- | ------------------------------------------------------------ | @@ -357,10 +357,11 @@ These parameters are drawn from the shared parameters of the current `launch_ros | parameters | List of either paths to yaml files or dictionaries of parameters | | remappings | List of from/to pairs for remapping names | | arguments | Container specific arguments to be passed to the node | +| traits | Additional features of the node, specifically Lifecycle or Composable information| #### Properties -Accessors would be provided for the various constructor parameters: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. +Accessors would be provided for the various constructor parameters: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, and `traits`. #### Methods @@ -369,7 +370,7 @@ To support better isolation of class functionality, substitutions will be perfor | Name | Description | | ------- | ------------------------------------------------------------ | -| prepare | Takes a given LaunchContext and Action, and performs actions necessary to prepare the node for execution in that context. This will primarily consist of expanding various substitutions, but may additionally add event handlers related to the Action which will be invoked. | +| prepare | Takes a given LaunchContext and Action, and performs actions necessary to prepare the node for execution in that context. This will primarily consist of expanding various substitutions, but may additionally add event handlers related to the Action which will be invoked. Additionally, this will call the `prepare()` method of any defined traits. | This function would match that of the current `launch_ros.actions.Node` internal method `_perform_substitutions`. @@ -377,18 +378,67 @@ This function would match that of the current `launch_ros.actions.Node` internal No events would be handled or emitted. -### launch_ros.descriptions.LifecycleNode +### launch_ros.descriptions.ComposableNode -This class would extend the `launch_ros.descriptions.Node` class, and provide the additional functionality required for managing lifecycle node events that are currently defined in `launch_ros.actions.LifecycleNode`. +This class would extend the `launch_ros.descriptions.Node` class, and provide the additional information required for defining a node which can be launched in a composable context. #### Constructor -No additional constructor parameters are defined in this class. -All parameters which are handled by `launch_ros.descriptions.Node` may be passed to the constructor: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. +Most parameters would be passed to the superclass. + +|Argument|Description| +|---|---| +|node_plugin|Name of the plugin to be loaded| + +Additional parameters that may be passed, which are handled by `launch_ros.descriptions.NodeBase`: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, `traits`. #### Properties -Constructor properties available from ``launch_ros.descriptions.Node`` are inherited: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. +Accessors would be provided for the additional constructor parameter: `node_plugin`. +Inherited accessors would also be available: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, and `traits`. + +#### Methods + +No methods would be defined or overridden. + +#### Events + +No events would be handled or emitted. + +### launch_ros.traits.NodeTrait +This abstract class would not extend any others, and would provide a common interface to allow definition of traits which apply to `launch_ros.descriptions.Node` objects. + +#### Constructor + +This constructor would take no parameters, and should not be used directly. + +#### Properties + +This object would expose no properties. + +#### Methods + +To allow a trait to perform its actions, the `prepare()` method will be called prior to execution. + +| Name | Description | +| ------- | ------------------------------------------------------------ | +| prepare | Abstract method which takes a given Node, LaunchContext, and Action, and performs actions necessary to prepare the node for execution in that context.| + +#### Events + +No events would be handled or emitted. + +### launch_ros.traits.HasLifecycle + +This class would extend the `launch_ros.traits.NodeTrait` class, and provide the additional functionality required for managing lifecycle node events that are currently defined in `launch_ros.actions.LifecycleNode`. + +#### Constructor + +The constructor for this trait would take no parameters, as it serves only to assert that the ROS2 Lifecycle events are implemented by the `launch_ros.descriptions.Node`, and appropriate events should be managed. + +#### Properties + +This object would expose no properties. #### Methods @@ -410,42 +460,35 @@ Constructor properties available from ``launch_ros.descriptions.Node`` are inher | ----------------------------------------- | ------------------------------------------------------------ | | `launch.events.lifecycle.StateTransition` | This event is emitted when a message is published to the "`//transition_event`" topic, indicating the lifecycle node represented by this action changed state | -### launch_ros.descriptions.ExecutableNode +### launch_ros.traits.ComposesNodes -This class would represent the information required to define a node which might be run as a single executable. -It would inherit from `launch.descriptions.Executable`, contain a `launch_ros.descriptions.Node`, and populate its fields in the same manner as the current `launch_ros.actions.Node`. +This class would extend the `launch_ros.traits.NodeTrait` class, and provide the additional information required for launching composable nodes that are currently defined in `launch_ros.descriptions.ComposableNode`. #### Constructor -These parameters are drawn from the current `launch_ros.actions.Node`. - -REQUEST FOR COMMENT: Currently, this calls out the node as a `launch_ros.descriptions.Node` object parameter; would this be better styled by accepting a flat list to make the inner Node less visible to users? - -| Argument | Description | -| --------------- | ------------------------------------------------------------ | -| node_executable | The name of the executable to find if a package is provided or otherwise a path to the executable to run. | -| node | The `launch_ros.descriptions.Node` (or subclass thereof) which is being run. | +Most parameters would be passed to the new superclass. -Most parameters which are handled by `launch.descriptions.Executable` may be passed to the constructor: `name`, `cwd`, `env`, and `additional_env`. -Note that the `cmd` parameter would *not* be passed through; the command would be constructed per ROS Node execution context. +|Argument|Description| +|---|---| +|nodes|Collection of `launch_ros.descriptions.ComposableNode` objects that should be launched inside the `launch_ros.descriptions.Node` with this trait.| #### Properties -Accessors would be provided for the various constructor parameters: `node_executable` and `node`. -Inherited accessors would also be available: `cmd`, `name`, `cwd`, `env`, and `additional_env`. +Accessors would be provided for the constructor parameter: `nodes`. #### Methods -This class would override the `apply_context` method of `launch.descriptions.Executable` to additionally invoke the `apply_context` method of the `launch_ros.descriptions.Node`, then invoke the superclass method itself. -This function would match that of the current `launch_ros.actions.Node` internal method `_perform_substitutions`. +| Name | Description | +| ------- | ------------------------------------------------------------ | +| prepare | Overridden. Adds an event handler to launch the defined composable nodes in the container once the container is started. | #### Events No events would be handled or emitted. -### launch_ros.descriptions.ComposableNode +### launch_ros.traits.IsExecutable -This class would be modified to inherit from `launch_ros.descriptions.Node`. +This class would extend the `launch_ros.traits.NodeTrait` class, and provide the additional information required for launching executable nodes that are currently defined in `launch_ros.actions.Node`. #### Constructor @@ -453,14 +496,11 @@ Most parameters would be passed to the new superclass. |Argument|Description| |---|---| -|node_plugin|Name of the plugin to be loaded| - -Additional parameters that may be passed, which are handled by `launch_ros.descriptions.Node`: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`. +|node_executable|Name of the executable to find| #### Properties -Accessors would be provided for the additional constructor parameter: `node_plugin`. -Inherited accessors would also be available: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, and `arguments`. +Accessors would be provided for the constructor parameter: `node_exectuable`. #### Methods @@ -470,33 +510,36 @@ No custom methods would be defined or overridden. No events would be handled or emitted. -### launch_ros.descriptions.ExecutableNodeContainer +### launch_ros.descriptions.RosExecutable -This class would extend the `launch_ros.descriptions.ExecutableNode` class, and provide the additional functionality required for loading multiple nodes into a single container. +This class would represent the information required to run a ROS-aware process and inherit from `launch.descriptions.Executable`. +It would not include execution-time details, nor provide monitoring of the process after launch. #### Constructor -The description of the composable node container itself should be provided as the parameters passed to ``launch_ros.descriptions.ExecutableNode``; child nodes would be provided as an additional constructor parameter. - -| Argument | Description | -| ------------------------------ | ------------------------------------------------------ | -| composable\_node\_descriptions | Optional descriptions of composable nodes to be loaded | +| Argument | Description | +| --------------- | ------------------------------------------------------------ | +| nodes | A list of `launch_ros.descriptions.Node` objects which are part of the executable. | -All parameters which are handled by ``launch_ros.descriptions.ExecutableNode`` may be passed to the constructor: `node_executable`, `node`, `name`, `cwd`, `env`, and `additional_env`. +Additional parameters that may be passed, which are handled by `launch.actions.ExecuteProcess`: `cmd`, `name`, `cwd`, `env`, `additional_env`. +NOTE: To allow ROS to determine the appropriate executable based on the package and executable name, the `cmd` parameter should *NOT* be specified. When `cmd` is not specified, this class will determine the appropriate executable if and only if exactly one of the nodes it contains has the `launch_ros.traits.IsExecutable` trait. #### Properties -Properties available from ``launch_ros.descriptions.ExecutableNode`` are inherited: `process_details`, along with constructor parameters for `process_description`, `shell`, and `output`. +Accessors would be provided for the constructor parameter: `nodes`. +Inherited accessors would also be available: `cmd`, `name`, `cwd`, `env`, and `additional_env`. #### Methods -| Name | Description | -| ------- | ------------------------------------------------------------ | -| prepare | Overridden. Calls the superclass to prepare node-related information, calls `prepare` on each composable node, and adds actions to the target Action to load the contained nodes once the process is started, then calls the superclass to execute the parsed command. | +| Name | Description | +| ------------- | ------------------------------------------------------------ | +| apply\_context | Overridden. Calls `prepare()` on each `launch_ros.descriptions.Node`, and determines the appropriate executable if necessary. | + +In constructing the command line parameters for execution, if more than one node is defined, all appropriate parameters will be prefixed with the node name as necessary. #### Events -Inherits events from `launch.actions.ExecuteLocalProcess`, but does not define any additional events. +No events would be handled nor emitted. ## Future Extension From 476a6df314bc37a5f9601068c8e7bad51a91442b Mon Sep 17 00:00:00 2001 From: Roger Strain Date: Thu, 2 Jul 2020 11:04:13 -0500 Subject: [PATCH 6/7] Cleanup; removing IsExecutable trait Distro A; OPSEC #2893 Signed-off-by: Roger Strain --- articles/execute_process_refactor.md | 46 ++++++++-------------------- 1 file changed, 12 insertions(+), 34 deletions(-) diff --git a/articles/execute_process_refactor.md b/articles/execute_process_refactor.md index 551652c75..bf510346f 100644 --- a/articles/execute_process_refactor.md +++ b/articles/execute_process_refactor.md @@ -1,8 +1,8 @@ # Refactoring ExecuteProcess in ROS2 Initially proposed in [114](https://github.com/ros2/launch/issues/114), this document describes changes to `ExecuteProcess` and related classes. -As initially implemented, some aspects of this are tightly coupled to both the implementation chosen and the assumption that processes will execute only in the local environment of the launch process itself. -The following changes are designed to provide a more decoupled architecture that will ease support of launching processes locally, remotely, or potentially in containerized environments. +As initially implemented, some aspects of this class are tightly coupled to both the implementation chosen and the assumption that processes will execute only in the local environment of the launch process itself. +The following changes are designed to provide a more decoupled architecture that will ease support of launching processes locally, remotely, and potentially in containerized environments. Additionally, these changes will support the goal of decoupling the description of an executable from the actual action of executing it. These changes are designed so that existing systems may continue to use the interface before these changes without modification; newer systems may find benefits from adapting to the newer syntax, particularly when composing more complicated environments. @@ -282,7 +282,7 @@ No events would be handled nor emitted. Extends the `launch.actions.Action` class. This class would represent the execution-time aspects of `launch.actions.ExecuteProcess`. -The new `process_description` constructor parameter could be a `launch.descriptions.Executable`, a `launch_ros.descriptions.Node`, or one of the other subclasses. +The new `process_description` constructor parameter could be a `launch.descriptions.Executable` or a subclass. This class is simplified from the current `launch.actions.ExecuteProcess` by removing the logic relating to process definition/configuration, and by removing the logic regarding substitutions thereof. @@ -351,7 +351,6 @@ These parameters are drawn from the shared parameters of the current `launch_ros | Argument | Description | | -------------- | ------------------------------------------------------------ | -| package | name of the ROS package the node executable lives in | | node_name | Name the node should have | | node_namespace | Namespace the node should create topics/services/etc in | | parameters | List of either paths to yaml files or dictionaries of parameters | @@ -361,7 +360,7 @@ These parameters are drawn from the shared parameters of the current `launch_ros #### Properties -Accessors would be provided for the various constructor parameters: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, and `traits`. +Accessors would be provided for the various constructor parameters: `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, and `traits`. #### Methods @@ -388,14 +387,15 @@ Most parameters would be passed to the superclass. |Argument|Description| |---|---| +| package | Optional. Name of the ROS package the node plugin lives in. If not specified, the package of the containing executable will be assumed. | |node_plugin|Name of the plugin to be loaded| -Additional parameters that may be passed, which are handled by `launch_ros.descriptions.NodeBase`: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, `traits`. +Additional parameters that may be passed, which are handled by `launch_ros.descriptions.NodeBase`: `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, `traits`. #### Properties -Accessors would be provided for the additional constructor parameter: `node_plugin`. -Inherited accessors would also be available: `package`, `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, and `traits`. +Accessors would be provided for the additional constructor parameters: `package`, `node_plugin`. +Inherited accessors would also be available: `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, and `traits`. #### Methods @@ -486,30 +486,6 @@ Accessors would be provided for the constructor parameter: `nodes`. No events would be handled or emitted. -### launch_ros.traits.IsExecutable - -This class would extend the `launch_ros.traits.NodeTrait` class, and provide the additional information required for launching executable nodes that are currently defined in `launch_ros.actions.Node`. - -#### Constructor - -Most parameters would be passed to the new superclass. - -|Argument|Description| -|---|---| -|node_executable|Name of the executable to find| - -#### Properties - -Accessors would be provided for the constructor parameter: `node_exectuable`. - -#### Methods - -No custom methods would be defined or overridden. - -#### Events - -No events would be handled or emitted. - ### launch_ros.descriptions.RosExecutable This class would represent the information required to run a ROS-aware process and inherit from `launch.descriptions.Executable`. @@ -519,6 +495,8 @@ It would not include execution-time details, nor provide monitoring of the proce | Argument | Description | | --------------- | ------------------------------------------------------------ | +| package | name of the ROS package the node executable lives in | +|node_executable|Name of the executable to find| | nodes | A list of `launch_ros.descriptions.Node` objects which are part of the executable. | Additional parameters that may be passed, which are handled by `launch.actions.ExecuteProcess`: `cmd`, `name`, `cwd`, `env`, `additional_env`. @@ -526,7 +504,7 @@ NOTE: To allow ROS to determine the appropriate executable based on the package #### Properties -Accessors would be provided for the constructor parameter: `nodes`. +Accessors would be provided for the constructor parameters: `package`, `node_executable`, `nodes`. Inherited accessors would also be available: `cmd`, `name`, `cwd`, `env`, and `additional_env`. #### Methods @@ -559,7 +537,7 @@ If this is attempted, several features such as input/output pipes would likely n | Argument | Description | | ---------------------- | ------------------------------------------------------------ | -| process\_description | The `launch.descriptions.Executable` to execute as a local process | +| process\_description | The `launch.descriptions.Executable` to execute as a remote process | | connection_description | An object defining the SSH connection information, such as host, port, user, etc. | | prefix | A set of commands/arguments to preceed the `cmd`, used for things like `gdb`/`valgrind` and defaults to the `LaunchConfiguration` called `launch-prefix` | | output | Configuration for process output logging. Defaults to `log` i.e. log both `stdout` and `stderr` to launch main log file and stderr to the screen. | From 5bed7da07a5b9ac20ab6e931006994d9c7230050 Mon Sep 17 00:00:00 2001 From: Roger Strain Date: Wed, 15 Jul 2020 14:31:29 -0500 Subject: [PATCH 7/7] Minor updates per feedback. Distro A; OPSEC #2893 Signed-off-by: Roger Strain --- articles/execute_process_refactor.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/articles/execute_process_refactor.md b/articles/execute_process_refactor.md index bf510346f..649359ef3 100644 --- a/articles/execute_process_refactor.md +++ b/articles/execute_process_refactor.md @@ -387,10 +387,10 @@ Most parameters would be passed to the superclass. |Argument|Description| |---|---| -| package | Optional. Name of the ROS package the node plugin lives in. If not specified, the package of the containing executable will be assumed. | +| package | Optional. Name of the ROS package the node plugin lives in. If not specified, the package of the containing executable will be assumed. This may fail if context regarding the executable is not available. | |node_plugin|Name of the plugin to be loaded| -Additional parameters that may be passed, which are handled by `launch_ros.descriptions.NodeBase`: `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, `traits`. +Additional parameters that may be passed, which are handled by `launch_ros.descriptions.Node`: `node_name`, `node_namespace`, `parameters`, `remappings`, `arguments`, `traits`. #### Properties @@ -496,11 +496,10 @@ It would not include execution-time details, nor provide monitoring of the proce | Argument | Description | | --------------- | ------------------------------------------------------------ | | package | name of the ROS package the node executable lives in | -|node_executable|Name of the executable to find| +| executable_name |Name of the executable to find| | nodes | A list of `launch_ros.descriptions.Node` objects which are part of the executable. | -Additional parameters that may be passed, which are handled by `launch.actions.ExecuteProcess`: `cmd`, `name`, `cwd`, `env`, `additional_env`. -NOTE: To allow ROS to determine the appropriate executable based on the package and executable name, the `cmd` parameter should *NOT* be specified. When `cmd` is not specified, this class will determine the appropriate executable if and only if exactly one of the nodes it contains has the `launch_ros.traits.IsExecutable` trait. +Additional parameters that may be passed, which are handled by `launch.actions.Executable`: `name`, `cwd`, `env`, `additional_env`. #### Properties