Skip to content

Commit

Permalink
Add ForLoop action to repeat entities with an index
Browse files Browse the repository at this point in the history
Signed-off-by: Christophe Bedard <[email protected]>
  • Loading branch information
christophebedard committed Nov 2, 2024
1 parent cb7b362 commit b9cd085
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
2 changes: 2 additions & 0 deletions launch/launch/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .emit_event import EmitEvent
from .execute_local import ExecuteLocal
from .execute_process import ExecuteProcess
from .for_loop import ForLoop
from .group_action import GroupAction
from .include_launch_description import IncludeLaunchDescription
from .log_info import LogInfo
Expand All @@ -45,6 +46,7 @@
'EmitEvent',
'ExecuteLocal',
'ExecuteProcess',
'ForLoop',
'GroupAction',
'IncludeLaunchDescription',
'LogInfo',
Expand Down
113 changes: 113 additions & 0 deletions launch/launch/actions/for_loop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Copyright 2024 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Module for the ForLoop action."""

from typing import Callable
from typing import List
from typing import Optional
from typing import Text


from ..action import Action
from ..launch_context import LaunchContext
from ..launch_description_entity import LaunchDescriptionEntity
from ..logging import get_logger
from ..substitutions import LaunchConfiguration


class ForLoop(Action):
"""
Action that instantiates entities through a function N times based on a launch argument.
A DeclareLaunchArgument must be created before this action to define the number of iterations
in the for-loop, i.e., N iterations. For each loop iteration, the provided callback function is
called with the index value, going from 0 to N (exclusive).
Simple example:
.. code-block:: python
def for_i(i: int):
return [
LogInfo(msg=['i=', str(i)]),
]
LaunchDescription([
DeclareLaunchArgument('num', default_value='2'),
ForLoop('num', function=for_i),
])
This would ouput the following log messages by default:
.. code-block:: text
i=0
i=1
If the launch argument was set to 5 (num:=5), then it would output:
.. code-block:: text
i=0
i=1
i=2
i=3
i=4
"""

def __init__(
self,
launch_argument_name: str,
*,
function: Callable[[int], Optional[List[LaunchDescriptionEntity]]],
**kwargs,
) -> None:
"""
Create a ForLoop.
:param launch_argument_name: the name of the launch argument that defines the length of the
for-loop
:param function: a function that receives an index value and returns entities
"""
super().__init__(**kwargs)
self._launch_argument_name = launch_argument_name
self._function = function
self._logger = get_logger(__name__)

@property
def launch_argument_name(self) -> str:
return self._launch_argument_name

@property
def function(self) -> Callable[[int], Optional[List[LaunchDescriptionEntity]]]:
return self._function

def describe(self) -> Text:
return (
type(self).__name__ +
f"(launch_argument_name='{self._launch_argument_name}', function={self._function})"
)

def execute(self, context: LaunchContext) -> Optional[List[LaunchDescriptionEntity]]:
# Get the for-loop length and convert to int
num = int(LaunchConfiguration(self._launch_argument_name).perform(context))
self._logger.debug(f'for-loop length={num}')

entities = []
for i in range(num):
i_entities = self._function(i)
if i_entities:
entities.extend(i_entities)
return entities

0 comments on commit b9cd085

Please sign in to comment.