-
Notifications
You must be signed in to change notification settings - Fork 144
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ForLoop action to repeat entities with an index
Signed-off-by: Christophe Bedard <[email protected]>
- Loading branch information
1 parent
cb7b362
commit b9cd085
Showing
2 changed files
with
115 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |