-
Notifications
You must be signed in to change notification settings - Fork 193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[launch] Refactoring ExecuteProcess into Execute and Executable #272
base: gh-pages
Are you sure you want to change the base?
Conversation
Distro A; OPSEC #2893 Signed-off-by: Roger Strain <rstrain@swri.org>
Distro A; OPSEC #2893 Signed-off-by: Roger Strain <rstrain@swri.org>
Distro A; OPSEC #2893 Signed-off-by: Roger Strain <rstrain@swri.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea seems good.
My feedback here is similar to the one I previously provided in ros2/launch#114 (comment).
I think that we need to address if an alternate launch context is needed or not before going ahead with an implementation.
After a comment in a team meeting, this may be too We can finish the reviewing process in this PR to avoid splitting the discussion, and split the document between |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few comments. I'm sure @wjwwood has thoughts too (and he may not necessarily agree with me 😃).
articles/execute_process_refactor.md
Outdated
|
||
|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.| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain nit: here and everywhere else, capitalize each description sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of these were copied and pasted from the current class docs, so I was just maintaining how they appeared there. Easy enough change, however; addressing in upcoming revision.
articles/execute_process_refactor.md
Outdated
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain I think we're mixing things up again here e.g. a process is yet another execution detail that may or may not apply to a node. The fact that some of its arguments may be dependent on the actual execution environment sets this one apart from the rest. launch.descriptions.Executable
or launch.descriptions.Program
maybe? We can later compose things to serve common use cases.
articles/execute_process_refactor.md
Outdated
|
||
No events would be handled or emitted. | ||
|
||
### launch.actions.ExecuteLocalProcess |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain again I think we're mixing things up. I'd imagine e.g. Execute
and SSHExecute
actions only that can take Executable
descriptions, delegating all description-specific details to the descriptions themselves.
|
||
No events would be handled nor emitted. | ||
|
||
### launch_ros.descriptions.Node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, there can be many Node
s in a single process and even be dynamically composable. I'd imagine a ROSAwareExecutable
that can bear Node
s.
@roger-strain friendly ping |
Don't worry, this was actually next on my list. Things have been a little unsettled lately. Hope to have some updates pushed this week. |
@ivanpauno @hidmic I believe the various bits of functionality can work in this proposed architecture, but it's definitely another step or two removed from the current implementation, so I'd definitely appreciate some more experienced eyes to make sure I haven't overlooked something showstopping. One thing I noticed as I was doing this is that as it stands, I can't put a |
I think we're getting closer @roger-strain. First of all, thank you for pushing. I spent some time thinking on what you wrote, in comments and in the document itself. We have different concepts here that need to be represented and that today are somewhat mixed up (often just for the sake of simplicity and convenience):
And then there's lifecycle nodes. You're right those are tricky and that lifecycle composable nodes are not currently supported. Personally, I think the difficulties stem from the fact we are thinking in terms of lifecycle nodes instead of nodes that have a lifecycle. IMO, having a lifecycle should be a node trait (at least in Of course, we can come up with a bunch of handy combinations to both avoid breaking the current API and keeping the typical use cases simple. WDYT? |
At first blush, I think I see where you're going, and like the general concepts. I personally would shy away from having both a One question I have on this is, do we expect there to be any I definitely like the idea of moving the concept of I'll have to ponder this a little more fully before I can start putting together an update. I like to make sure I've really got all the pieces sorted in my head first. But I like where this is going, and really appreciate your help in moving it forward. |
The thing is, an executable is not a node. An executable has nodes. This is a fundamental shift from ROS 1, where there was a 1-to-1 mapping between nodes and processes. Simple executables often have only one node, but they could contain dozens. That's why I think that both concepts have to be decoupled. For sure, that doesn't mean that we can't have a
I do see the potential source for confusion. I'm not great at naming things 😅
Thank you for pushing ! |
...and actually, this isn't entirely true. Any node could implement the dynamic composition API. It's a stretch, but this could be yet another trait of a node. |
Apologies, I've been redirected onto a different effort for the past several weeks, but I'm trying to spin back up on this. Now that I'm getting into the details of trying to break this down as we've discussed, there are a couple of sticky points I would love some insight on so I can properly address them now, rather than getting perplexed when trying to implement.
This is a straightforward concept, but there's at least one part of the current implementation that bugs me. In the current Once we start delving into the concept of having a single executable which is host to multiple nodes (not using the composable interface you mentioned) I wonder how those should now apply. Conceivably you could specify alternate names, namespaces, parameters, remaps, etc. for the various nodes which are part of an executable. I haven't dug down into the other side of this to know if there are ways around it, so I'm hoping if there's some technique for properly passing those through and getting them to the right internal place, you can point me in the right direction. If something like specifying alternate node names for multiple nodes in a process isn't supported, then how should we approach things? I could possibly see doing something like either keeping an For the Composable node design, you mention that theoretically any node might implement the composition API. Would it be better to have a subclass of For the Lifecycle side of things I've got a hopefully simple question; Python isn't my native dialect, so your mention of "traits" is intriguing to me. I've found a couple of things which I believe might be what you're referring to, but can you point me at a concrete example so I know for sure what concepts I should be exploiting here? |
That's a good point, and it is supported. Take a look at the
IMHO inheritance is fine for composable node descriptions, but not for the container. And I'd rather not inject that functionality into the basic node description.
It's not a specific Python feature, but a concept. We know that a lifecycle node has a specific behavior and interface. Same for a node that can compose other nodes. So instead of encoding all that in a Python type object, we do so in a separate "trait" object that descriptions can take. For instance, instead of: launch_ros.descriptions.ComposableNodesContainerWithLifecycle(
node_name='my_node',
nodes=[
launch_ros.descriptions.ComposableNode(
plugin_name='some::Node',
),
# ...
],
# ...
) which is to say that it IS a lifecycle, composable nodes' container node, we go for:
which is to say that it IS a node THAT has a lifecycle and composes other nodes. In a way, it's like a type system based on runtime data. This is, however, my personal take on how we could tackle this problem in a scalable way. I'm sure @wjwwood and @ivanpauno have ideas too. |
Distro A; OPSEC #2893 Signed-off-by: Roger Strain <rstrain@swri.org>
Distro A; OPSEC #2893 Signed-off-by: Roger Strain <rstrain@swri.org>
@hidmic Took a while for me to think this through and get somewhere I'm happy with, but I think this might be getting closer to what you're envisioning. I think there are several places where we'll want to maintain wrappers that simplify some of the structure for typical use, but I think this manages to get things split into reasonable places. There are quite a few changes in the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay @roger-strain. It's looking really good !
articles/execute_process_refactor.md
Outdated
# 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain nit:
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. | |
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. |
articles/execute_process_refactor.md
Outdated
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain nit:
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. | |
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. |
Containerization isn't mutually exclusive with execution in a remote host :)
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain hmm, this is a good point. To some extent, I'd expect Python standard library to abstract us away from that. I think we should try to keep OS idiosyncrasies an implementation detail, preferably in an upstream package :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with you here; mostly it's an explanation of why some things that might normally be assumed to be part of an executable might need to be restricted to a more specific context. Assuming we get to the point of implementing non-local execution (which is where we want to go next) some of this design may have be reconsidered/adjusted as we find out which things really are and are not common. But that's a discussion for the future, I think. If there's anything that immediately seems like it's in the wrong spot, please let me know. :)
articles/execute_process_refactor.md
Outdated
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain why do executing actions have to deal with anything but an Executable
(or derived classes)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, removing reference to Node
here.
articles/execute_process_refactor.md
Outdated
| 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain why can't the IsExecutable
trait be subsumed into this Executable
subclass, taking package name and executable name as arguments (besides node descriptions)? The current Node
equivalent would then be:
ExecuteLocal(
ROSExecutable(
package_name='my_package',
executable_name='my_node_executable',
nodes=[
Node(name='my_node')
]
)
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this. I've made that change (though the parameter names may need to be tweaked). See how it looks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can drop the note entirely. cmd
is not a valid argument for RosExecutable
's constructor. No need to ask for it to not be used. If it comes along, TypeError: invalid arguments
should be raised.
articles/execute_process_refactor.md
Outdated
|
||
| Argument | Description | | ||
| -------------- | ------------------------------------------------------------ | | ||
| package | name of the ROS package the node executable lives in | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain hmm, I'd rather say ROS executables and node plugins live in packages, not nodes. So I'm not sure if it makes sense for node descriptions to refer to a package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've adjusted this now as well. package
has moved to the RosExecutable
object, and been re-introduced for ComposableNode
. I also want the one on ComposableNode
to be optional, so it can be picked up from the executable context if possible. If that's not reasonable, we can remove that concept. Would be nice to not have to respecify the package for each composed node. As I'm writing that, it feels wrong, so I think it might have to come back out. Let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also want the one on ComposableNode to be optional, so it can be picked up from the executable context if possible. If that's not reasonable, we can remove that concept. Would be nice to not have to respecify the package for each composed node.
That's interesting sugar. I like it.
Distro A; OPSEC #2893 Signed-off-by: Roger Strain <rstrain@swri.org>
@hidmic New version pushed up to address feedback. Still one point I'm not sure about w.r.t. whether |
I agree. I think the ability to be composed is significant enough (in terms of usability and implementation) to warrant a new derived type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense to me. I'll proof read it next week. @ivanpauno @wjwwood you guys should take a look too if you can.
articles/execute_process_refactor.md
Outdated
|
||
|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. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain I like the feature, but when loading a composable node into an already running executable, you may not necessarily have access to package names. So we should probably mention that this deduction may fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm adding a note to that effect, but as I think about it I worry that we may not have that information more often than not. Might have to determine whether this is feasible at implementation time.
articles/execute_process_refactor.md
Outdated
| Argument | Description | | ||
| --------------- | ------------------------------------------------------------ | | ||
| package | name of the ROS package the node executable lives in | | ||
|node_executable|Name of the executable to find| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain nit:
|node_executable|Name of the executable to find| | |
| executable_name |Name of the executable to find| |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reasonable. Was just copying/pasting parameter names from existing things, I think.
articles/execute_process_refactor.md
Outdated
| 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can drop the note entirely. cmd
is not a valid argument for RosExecutable
's constructor. No need to ask for it to not be used. If it comes along, TypeError: invalid arguments
should be raised.
articles/execute_process_refactor.md
Outdated
|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`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain consider:
Additional parameters that may be passed, which are handled by `launch.actions.ExecuteProcess`: `cmd`, `name`, `cwd`, `env`, `additional_env`. | |
Additional parameters that may be passed, which are handled by `launch.actions.Executable`: `name`, `cwd`, `env`, `additional_env`. |
| Argument | Description | | ||
| ---------------------- | ------------------------------------------------------------ | | ||
| 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. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain hmm, one thought (nothing to be changed): if connection_description
were to become an interface to a given execution environment, a single launch.actions.Execute()
could later deal with all forms of execution generically. May be overkill though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hidmic Wanted to follow up on this, as I was having some thoughts on that topic and wanted to run an idea by you before I start writing it up in the formal document. What would you think about going ahead with launch.actions.Execute()
, which takes two things: the launch.descriptions.Executable
to actually run, and optionally a launch.descriptions.ExecutionEnvironment
or subclass thereof, which describes how it should be executed. If you pass nothing, local execution is assumed, and a default launch.descriptions.LocalExecutionEnvironment
object is created under the hood.
You could inspect the object to get a reference to that default object later, if necessary. If you wanted to set any of the parameters currently assigned to launch.actions.ExecuteLocal
, you would instead create your own launch.descriptions.LocalExecutionEnvironment
with the appropriate bits.
(All of the following is forward-thinking and not part of the scope of this refactor):
This then would allow you to also define things like launch.descriptions.SshExecutionEnvironment
, which would open an SSH session using the various parameters passed to it, or launch.descriptions.PsExecutionEnvironment
if you have something with a PowerShell flavor. Where this could really shine is if you wanted to do something fancy, like have a single SSH session which could run multiple processes. That could look like a SharedSshExecutionEnvironment
that you pass to all the relevant launch.actions.Execute
calls, and then at the end a SharedSshExecutionEnvironment.ExecuteAll()
method would let you launch one SSH session and run all the things that had been queued up inside it.
I think I'd need to mull a little more about where certain things end up, but it seemed like an interesting approach, and I wanted to capture my thoughts and start the discussion before I forgot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first sight, all of that makes sense to me. If I may, I'd also suggest a Group
-like action to easily put multiple actions in the same execution environment (akin to roslaunch
's <machine/>
tag).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hidmic After poking around at this for a bit, I'm not sure we're really gaining anything with that aspect of the refactor. Basically everything that is defined in the currently proposed launch.actions.ExecuteLocal
would have to be migrated into the new launch.descriptions.LocalExecutionEnvironment
, and several methods which are currently overrides of launch.actions.Action
would have to be redefined and reimplemented on a base launch.descriptions.ExecutionEnvironment
. The new launch.actions.Execute
class would basically be a nearly-empty shell that reroutes its own methods into calling the same-named methods on the launch.descriptions.ExecutionEnvironment
class. It kind of feels like just adding an extra layer with little to no real benefit.
If it turns out that there would be benefit later, such as when trying to add multi-machine support, we could address it at that point.
Curious as to your thoughts. Assuming we're okay just staying with the design as it stands, do we need any further feedback from other contributors, or is it time to start implementation?
@hidmic I've updated the PR based on the latest feedback. I'd been holding off to see if @ivanpauno or @wjwwood had anything else to add so I didn't clutter up the commit history too much. How close do you think we are to getting to a point of being able to start implementation? I've held off because I'd hate to start doing work that doesn't line up with the overall project goals, but we do have some other things (most notably adding support for multi-machine launch files) that this will impact, so I'd like to give our other guys some certainty that this is the path we're going to follow. I feel like it's pretty close myself, but will be happier with a few more head-nods. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to read this more thoroughly, the idea sounds good to me.
I've left a couple minimal comments.
Distro A; OPSEC #2893 Signed-off-by: Roger Strain <rstrain@swri.org>
Thanks for your patience and work.
I'll proof read this at some point this week, but I think it's pretty good as-is. Let's see what others say. |
This pull request has been mentioned on ROS Discourse. There might be relevant details there: https://discourse.ros.org/t/ros-2-tsc-meeting-minutes-2020-07-16/15468/1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure of why the apply_context
method is needed.
Besides that, I really like the proposal.
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still unsure if the concept of overriding apply_context
is needed.
I don't see much benefit on it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ivanpauno The intent of allowing overrides of apply_context
is so an executable in a more specific domain can perform domain-specific substitutions. Basically, at this level, we're in a context that has no knowledge of ROS or any ROS-specific concepts. We can do some level of substitution here, but can't take everything into consideration. To support those ROS-specific concepts, we have the launch_ros.descriptions.RosExecutable
class. It would override apply_context
so that it could pass substitution information down to the launch_ros.descriptions.Node
objects, and possibly perform other actions necessary for preparing the ROS executable to run.
My fear is that if we don't do things this way, then we either have to make the launch
namespace aware of ROS-specific concepts like nodes, or we alternately need to come up with some other more generic framework to ensure all aspects of the definition have an opportunity to do pre-launch setup (primarily substitutions). If there's another approach I'm missing that doesn't require the override, I'd be very happy to discuss it and look for a different take.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intent of allowing overrides of apply_context is so an executable in a more specific domain can perform domain-specific substitutions
Can you give an example of a domain specific substitution?
I'm trying to understand the use case, but I'm failing to see how this will help.
so that it could pass substitution information down to the launch_ros.descriptions.Node objects, and possibly perform other actions necessary for preparing the ROS executable to run.
Can you give an example of what "other actions" can be.
You can still go ahead with a proposed implementation with this comment unsolved, it's not a big deal.
But I want to understand how this detail is supposed to help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ivanpauno It might be best to show you the current functionality I'm trying to find a place for. In the current setup, launch_ros.actions.Node
is a subclass of launch.actions.ExecuteProcess
. ExecuteProcess
defines the execute
method, which is overridden by Node
. Part of what Node
does with the override is applying the various substitutions by calling _perform_substitutions(LaunchContext)
. Some of those substitutions are ROS-specific, some may not be. (Honestly, I'm going to have to be very careful in that area to make sure I split things out appropriately.) Those substitutions still need to be possible after the refactor.
The purpose of this call is to allow a subclass (in this case, launch_ros.descriptions.RosExecutable
) to inject any additional substitution logic. For instance, the proposed launch.descriptions.Executable
has absolutely no reason to know anything at all about a launch_ros.descriptions.Node
's Name property, but it still needs to have an opportunity to perform substitutions. I'll admit to not being 100% on all the functionality going on down there, but my feeling is that I need some path to make sure everything can be covered. This was my best effort at ensuring that path exists when it's needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see what you mean now.
You need a way to "normalize" all launch.descriptions.Executable
derived classes, in a way that launch.actions.ExecuteLocal
or other actions can actually execute them.
The proposal makes sense to me!!
@hidmic I think we've probably gotten about as far as we will with this, so I'd like to see what the next steps should be. This is a larger issue than I've tackled in a project like this, so I'm not sure what the normal approach is. I'm thinking that the changes within Also, if @wjwwood has a chance for any final feedback, it would be greatly appreciated. |
Building up support for this in I'd also recommend you clearly state what the PR series is going to look like for reviewers' context.
In general, you don't want to hold back any significant amount of work until it's "done" (whatever the definition of done is). Architectural changes require early review and discussion, and this design document has already built some consensus. Implementation wise, complying with contribution guidelines and getting early feedback from OSRF and/or the community will overall result in less re-work. So, if your PR is medium sized or you come across some oversight in this document, submitting a draft is perhaps a good idea. But if you keep PRs small, you may as well just open them. |
@ivanpauno I've been working up a plan for how the PRs might look for this, and would appreciate a once over. Also have a few questions towards the end about things I think need to be dealt with, but that we haven't discussed yet. (Apologies that this is long, just wanting to make sure I have things covered.) Conflicting classes:
Planned PR sequence:
Questions:
|
The overall plan sounds good to me, I have some minimal comments:
You could still accept the old argument name, with a deprecation warning.
Maybe, we can create a "feature" branch in For example:
In that way, we ensure we're only merging to
Instead of adding testing in a separate step, each PR should test the class/feature is being added.
Tests should launch process/nodes/etc to verify.
I'm not sure if I understand the question. I think I've just suggested to do the opposite.
Don't break the existing XML/YAML support 😂. For the moment, you won't need to extend it. |
I think we're actually pretty close to the same page here. In the list I put together, the top level items basically represented a conceptual PR. So the testing would be part of the same PR as the class(es) being implemented. I mostly wanted to make sure I was representing adding those tests during the process, not as one block at the end. The order you put together actually exposes one of my concerns regarding backward compatibility. I don't want to, for instance, introduce a backward compatible Node until we also have LifecycleNode ready to go, for instance. Since the current LifecycleNode inherits from the current Node, I get slightly nervous thinking about whether it will still behave properly once the internals of the class are replaced. It should be backward compatible from the user/API perspective, but might (likely won't) be from the perspective of an inheriting class. And I will gladly stay hands-off from the XML/YAML for now. :) |
It shouldn't be a problem. My suggestion is because I prefer introducing the "brand new" way, without introducing duplicated code. That make things easier to maintain. Either way, the suggested order can be modified through the process if we find a problem. |
Indeed. This is probably the best path forward. We can create the branch once you submit the first PR of each subset. |
|
||
| 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. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roger-strain please, could you remind me why we have apply_context
and prepare
(as opposed to just prepare
)? If it's for (semantic) consistency's sake, I can see several variations of prepare
already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hidmic I don't know if there's a specific reason for both. It might have evolved from building from both ends, if you will. If you'd rather simplify that down to just one or the other, I can definitely look at doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latter sounds good.
What is the current progress on this proposed refactoring. I would like to use lifecycle nodes in a component but as far as I can see that is still not possible right now (or did I miss something?) Thanks in advance for your answer! |
A lot of the work is done at this point, although not the lifecycle portion just yet. We're trying to sort out a project issue behind the scenes to get the relevant PRs freed up and finalized. So still in the works, but not there just yet. |
Awesome, thanks for your quick response and work so far. Let me know if you need help with reviewing or testing the PR(s)! |
Not sure if this is the right naming or format; if there are issues, please let me know. Already had a couple of bits of feedback from @ivanpauno that are not yet addressed, but wanted to hopefully give this higher visibility so we might be able to start implementation of the concept if things look reasonable.
Design to address ros2/launch#114