Skip to content
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

Support container in frontend #235

Merged
merged 16 commits into from
Jun 8, 2021
20 changes: 20 additions & 0 deletions launch_ros/launch_ros/actions/composable_node_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
from typing import Optional
kenji-miyake marked this conversation as resolved.
Show resolved Hide resolved

from launch.action import Action
from launch.frontend import Entity
from launch.frontend import expose_action
from launch.frontend import Parser
from launch.launch_context import LaunchContext
from launch.some_substitutions_type import SomeSubstitutionsType

Expand All @@ -26,6 +29,7 @@
from ..descriptions import ComposableNode


@expose_action('node_container')
class ComposableNodeContainer(Node):
"""Action that executes a container ROS node for composable ROS nodes."""

Expand All @@ -51,6 +55,22 @@ def __init__(
super().__init__(name=name, namespace=namespace, **kwargs)
self.__composable_node_descriptions = composable_node_descriptions

@classmethod
def parse(cls, entity: Entity, parser: Parser):
"""Parse node_container."""
_, kwargs = super().parse(entity, parser)

composable_nodes = entity.get_attr(
'composable_node', data_type=List[Entity], optional=True)
if composable_nodes is not None:
kwargs['composable_node_descriptions'] = []
for entity in composable_nodes:
_, composable_node_kwargs = ComposableNode.parse(parser, entity)
kwargs['composable_node_descriptions'].append(
ComposableNode(**composable_node_kwargs))
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved

return cls, kwargs

def execute(self, context: LaunchContext) -> Optional[List[Action]]:
"""
Execute the action.
Expand Down
21 changes: 21 additions & 0 deletions launch_ros/launch_ros/actions/load_composable_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import composition_interfaces.srv

from launch.action import Action
from launch.frontend import Entity
from launch.frontend import expose_action
from launch.frontend import Parser
from launch.launch_context import LaunchContext
import launch.logging
from launch.some_substitutions_type import SomeSubstitutionsType
Expand All @@ -46,6 +49,7 @@
from ..utilities.normalize_parameters import normalize_parameter_dict


@expose_action('load_composable_node')
class LoadComposableNodes(Action):
"""Action that loads composable ROS nodes into a running container."""

Expand Down Expand Up @@ -82,6 +86,23 @@ def __init__(
self.__final_target_container_name = None # type: Optional[Text]
self.__logger = launch.logging.get_logger(__name__)

@classmethod
def parse(cls, entity: Entity, parser: Parser):
"""Parse load_composable_node."""
_, kwargs = super().parse(entity, parser)

kwargs['target_container'] = parser.parse_substitution(
entity.get_attr('target', data_type=str))

composable_nodes = entity.get_attr('composable_node', data_type=List[Entity])
kwargs['composable_node_descriptions'] = []
for entity in composable_nodes:
_, composable_node_kwargs = ComposableNode.parse(parser, entity)
kwargs['composable_node_descriptions'].append(
ComposableNode(**composable_node_kwargs))
ivanpauno marked this conversation as resolved.
Show resolved Hide resolved

ivanpauno marked this conversation as resolved.
Show resolved Hide resolved
return cls, kwargs

def _load_node(
self,
request: composition_interfaces.srv.LoadNode.Request,
Expand Down
48 changes: 48 additions & 0 deletions launch_ros/launch_ros/descriptions/composable_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from typing import List
from typing import Optional

from launch.frontend import Entity
from launch.frontend import Parser
from launch.some_substitutions_type import SomeSubstitutionsType
from launch.substitution import Substitution
# from launch.utilities import ensure_argument_type
Expand Down Expand Up @@ -76,6 +78,52 @@ def __init__(
if extra_arguments:
self.__extra_arguments = normalize_parameters(extra_arguments)

@classmethod
def parse(cls, parser: Parser, entity: Entity):
"""Parse composable_node."""
from launch_ros.actions import Node
kwargs = {}

kwargs['package'] = parser.parse_substitution(entity.get_attr('pkg'))
kwargs['plugin'] = parser.parse_substitution(entity.get_attr('plugin'))
kwargs['name'] = parser.parse_substitution(entity.get_attr('name'))

namespace = entity.get_attr('namespace', optional=True)
if namespace is not None:
kwargs['namespace'] = parser.parse_substitution(namespace)

parameters = entity.get_attr('param', data_type=List[Entity], optional=True)
if parameters is not None:
kwargs['parameters'] = Node.parse_nested_parameters(parameters, parser)

remappings = entity.get_attr('remap', data_type=List[Entity], optional=True)
if remappings is not None:
kwargs['remappings'] = [
(
parser.parse_substitution(remap.get_attr('from')),
parser.parse_substitution(remap.get_attr('to'))
) for remap in remappings
]

for remap in remappings:
remap.assert_entity_completely_parsed()

extra_arguments = entity.get_attr('extra_arg', data_type=List[Entity], optional=True)
if extra_arguments is not None:
kwargs['extra_arguments'] = [
{
tuple(parser.parse_substitution(extra_arg.get_attr('name'))):
parser.parse_substitution(extra_arg.get_attr('value'))
} for extra_arg in extra_arguments
]

for extra_arg in extra_arguments:
extra_arg.assert_entity_completely_parsed()

entity.assert_entity_completely_parsed()

return cls, kwargs

@property
def package(self) -> List[Substitution]:
"""Get node package name as a sequence of substitutions to be performed."""
Expand Down