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

Add boolean substitutions #598

Merged
merged 10 commits into from
Mar 29, 2022
Merged

Conversation

kenji-miyake
Copy link
Contributor

Considering the following use cases, I think it's useful to add boolean substitutions.

<launch>
  <arg name="condition_1" />
  <arg name="condition_2" />

  <!-- Without this PR (if I understand correctly) -->
  <let name="and" value="$(eval '\'$(var condition_1)\' and \'$(var condition_2)\'')" />
  <group if="$(var and)">
    <log message="do something" />
  </group>

  <!-- With this PR -->
  <group if="$(and $(var condition_1) $(var condition_2))">
    <log message="do something" />
  </group>
</launch>

Of course, in this case we can change the arg like this:

<launch>
  <arg name="condition_1_and_condition_2" />

  <group if="$(var condition_1_and_condition_2)">
    <log message="do something" />
  </group>
</launch>

However, I think it doesn't work with the following case:

// caller.launch.xml
<launch>
  <arg name="condition_1" />
  <arg name="condition_2" />

  <group if="$(var condition_1)">
    <log message="do something 1" />
  </group>

  <group if="$(var condition_2)">
    <log message="do something 2" />
  </group>

  <let name="and" value="$(eval '\'$(var condition_1)\' and \'$(var condition_2)\'')" />
  <include file="called.launch.xml">
    <arg name="do_something" value="$(var and)" />
  <include />
</launch>

// called.launch.xml
<launch>
  <arg name="do_something" />

  <group if="$(var do_something)">
    <log message="do something in called.launch.xml" />
  </group>
</launch>

@kenji-miyake
Copy link
Contributor Author

@adityapande-1995 @hidmic Hello, could you kindly review this, please? 🙏

@kenji-miyake
Copy link
Contributor Author

As an alternative approach, I guess we can consider handling !, &&, || in IfCondition.

@kenji-miyake
Copy link
Contributor Author

Mm... I'm not sure why the test failed. 🤔

$ colcon test --event-handlers console_cohesion+
=================================== FAILURES ===================================
_____________________ test_invalid_parser_implementations ______________________
test/launch/frontend/test_parser.py:64: in test_invalid_parser_implementations
    assert(caught_warnings)
E   assert []
$ colcon test-result --verbose
build/launch/pytest.xml: 306 tests, 0 errors, 1 failure, 0 skipped
- launch.test.launch.frontend.test_parser test_invalid_parser_implementations
  <<< failure message
    assert []
  >>>
build/launch_testing/pytest.xml: 90 tests, 0 errors, 3 failures, 0 skipped
- launch_testing.test.launch_testing.examples.parameters_launch_test parameters_launch_test
  <<< failure message
    parameters_launch_test.TestProcessOutput.test_process_outputs_expected_value[flag1] failed
  >>>
- launch_testing.test.launch_testing.examples.ready_action_test ready_action_test
  <<< failure message
    ready_action_test.TestGoodProcess.test_count_to_four failed
    ready_action_test.TestProcessOutput.test_exit_code failed
    ready_action_test.TestProcessOutput.test_full_output failed
    ready_action_test.TestProcessOutput.test_out_of_order failed
  >>>
- launch_testing.test.launch_testing.examples.terminating_proc_launch_test terminating_proc_launch_test
  <<< failure message
    terminating_proc_launch_test.TestTerminatingProc.test_no_args failed
    terminating_proc_launch_test.TestTerminatingProc.test_unhandled_exception failed
    terminating_proc_launch_test.TestTerminatingProc.test_with_args failed
  >>>
$ pytest -s launch/test/launch/frontend/test_parser.py
================================================================================ test session starts ================================================================================
platform linux -- Python 3.8.10, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /home/kenji/tmp/launch/launch, configfile: pytest.ini
plugins: launch-testing-ros-0.17.0, launch-pytest-0.21.0, launch-testing-0.21.0, ament-pep257-0.11.4, ament-lint-0.11.4, ament-xmllint-0.11.4, ament-copyright-0.11.4, ament-flake8-0.11.4, cov-2.12.1, asyncio-0.15.1, rerunfailures-10.1, repeat-0.9.1, lazy-fixture-0.6.3, datadir-1.3.1, dash-2.0.0, mock-1.10.4, colcon-core-0.7.1
collected 2 items                                                                                                                                                                   

launch/test/launch/frontend/test_parser.py ..

================================================================================= 2 passed in 0.01s =================================================================================

@kenji-miyake
Copy link
Contributor Author

kenji-miyake commented Feb 27, 2022

Actually, this was wrong and only works with limited cased.
For example, "true" and "false" works but "false" and "true" doens't.

So we have to write in a more complicated way or use True/False instead of true/false or 1/0.

@kenji-miyake
Copy link
Contributor Author

The cause of the error was root_entity, parser = Parser.load(file), which seems to affect globally.

@hidmic hidmic added the enhancement New feature or request label Mar 3, 2022
Copy link
Contributor

@hidmic hidmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an alternative to this, we could simplify eval usage. However, for such common functionality and in the interest of not polluting frontends with Python code, I'm onboard with this addition.

launch/launch/substitutions/boolean_substitution.py Outdated Show resolved Hide resolved
launch/launch/substitutions/boolean_substitution.py Outdated Show resolved Hide resolved
Kenji Miyake added 3 commits March 4, 2022 22:36
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Kenji Miyake added 3 commits March 4, 2022 23:22
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
@kenji-miyake
Copy link
Contributor Author

I've added the auto-expansion in 8bdf336. Is it allowed? 🤔

@kenji-miyake
Copy link
Contributor Author

kenji-miyake commented Mar 10, 2022

If #600 is accepted, this PR might be replaced by it.

def perform(self, context: LaunchContext) -> Text:
"""Perform the substitution."""
try:
value = LaunchConfiguration(self.value, default=self.value).perform(context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kenji-miyake hmm, so you're potentially expanding another LaunchConfiguration and hoping the result is not itself a valid launch configuration name for the default to kick in? Same as in #600 (review), IMO if you want these substitutions to have access to launch configurations as variables, you have to expand all substitutions first and then attempt a variable lookup.

CC @ivanpauno @wjwwood

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you're potentially expanding another LaunchConfiguration and hoping the result is not itself a valid launch configuration name for the default to kick in?

@hidmic It was a hacky way. I'm sorry for confusing you. 🙇

What I wanted to do are:

  • Convert value =(TextSubstitution('value')) to LaunchConfiguration('value').
  • Fall back $(var value) (= LaunchConfiguration('value')).

Same as in #600 (review), IMO if you want these substitutions to have access to launch configurations as variables, you have to expand all substitutions first and then attempt a variable lookup.

Since it was an optional feature for me, I've dropped it for now.
If you kindly show me some examples, I can work on the feature in a proper way.

This reverts commit 8bdf336.

Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Copy link
Contributor

@hidmic hidmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kenji-miyake overall LGTM, pending green CI.

  • Linux Build Status
  • Linux-aarch64 Build Status
  • Windows Build Status

As an alternative approach, I guess we can consider handling !, &&, || in IfCondition.

There're a few competing paths to address this. One could think of nested conditions, or even resorting to full Python expressions. All in all, I think the current approach is simple yet flexible enough to accommodate most use cases. It also doesn't require Python in XML or YAML launch files, which IMHO it's a plus.

@hidmic hidmic requested a review from jacobperron March 22, 2022 11:35
Kenji Miyake added 2 commits March 22, 2022 21:06
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Copy link
Member

@jacobperron jacobperron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I agree that this nice because it is simple and should cover the majority of use-cases.

Co-authored-by: Jacob Perron <jacob@openrobotics.org>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
@jacobperron
Copy link
Member

Re-triggering CI with latest changes (and including launch_yaml):

  • Linux Build Status
  • Linux-aarch64 Build Status
  • Windows Build Status

@kenji-miyake
Copy link
Contributor Author

@jacobperron Hello, can this be merged?

@hidmic
Copy link
Contributor

hidmic commented Mar 29, 2022

Alright, I think this is ready to go. Thank you for contribution and patience @kenji-miyake.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants