diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 93b9383c7..b5ece10cc 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -16,6 +16,9 @@ "vscode": { "extensions": [ "ms-vscode.cpptools-extension-pack", + "ms-python.pylint", + "ms-python.autopep8", + "ms-python.isort", "eamodio.gitlens" ] } diff --git a/.github/workflows/build-release.yaml b/.github/workflows/build-release.yaml index ad910835a..209faaec8 100644 --- a/.github/workflows/build-release.yaml +++ b/.github/workflows/build-release.yaml @@ -1,26 +1,70 @@ -name: Build and Push Multi-Arch Images +name: Build and release on: push: branches: - - develop - main - tags: - - "v*.*.*" jobs: - get-tag: - runs-on: ubuntu-latest - name: Get tag + check-version: + name: Check if the version has been updated outputs: - tag: ${{ steps.parse-tag.outputs.tag }} + has_changed: ${{ steps.check.outputs.has_changed }} + version: ${{ steps.versions.outputs.new_version }} + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: aica-technology/.github/.github/actions/docker-tag-from-git@v0.6.1 - id: parse-tag + with: + fetch-depth: 2 + - id: versions + run: | + PREV_VERSION=$(git show HEAD^:VERSION) + NEW_VERSION=$(git show HEAD:VERSION) + echo "prev_version=${PREV_VERSION}" >> $GITHUB_OUTPUT + echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT + shell: bash + - uses: aica-technology/.github/.github/actions/compare-versions@v0.11.0 + id: check + with: + previous_version: ${{ steps.versions.outputs.prev_version }} + new_version: ${{ steps.versions.outputs.new_version }} + + metadata: + name: Get metadata + needs: check-version + runs-on: ubuntu-latest + outputs: + image_name: ${{ steps.ensure-image.outputs.image_name }} + image_tags: ${{ steps.tags.outputs.image_tags }} + create_tag: ${{ steps.tags.outputs.create_tag }} + git_tag: ${{ steps.tags.outputs.git_tag }} + steps: + - uses: aica-technology/.github/.github/actions/ghcr-ensure-prefix@v0.6.0 + id: ensure-image + with: + image_name: aica-technology/modulo + + - run: | + CREATE_TAG=false + GIT_TAG="" + if [ ${{ needs.check-version.outputs.has_changed }} = 'true' ]; then + CREATE_TAG=true + GIT_TAG="v${{ needs.check-version.outputs.version }}" + IMAGE_TAGS=latest,"${GIT_TAG}",rolling + else + IMAGE_TAGS=rolling + fi + echo "Image tags: ${IMAGE_TAGS}" + echo "Create tag: ${CREATE_TAG}" + echo "Git tag: ${GIT_TAG}" + echo "image_tags=${IMAGE_TAGS}" >> $GITHUB_OUTPUT + echo "create_tag=${CREATE_TAG}" >> $GITHUB_OUTPUT + echo "git_tag=${GIT_TAG}" >> $GITHUB_OUTPUT + id: tags + shell: bash build: - needs: [get-tag] + needs: metadata strategy: matrix: arch: [amd64, arm64] @@ -38,24 +82,24 @@ jobs: - uses: aica-technology/.github/.github/actions/list-add-suffixes@v0.6.0 id: merge-tags with: - list: ${{ needs.get-tag.outputs.tag }} + list: ${{ needs.metadata.outputs.image_tags }} suffixes: ${{ matrix.arch }} glue_separator: "-" - uses: aica-technology/.github/.github/actions/ghcr-build@v0.6.1 with: - image_name: aica-technology/modulo + image_name: ${{ needs.metadata.outputs.image_name }} image_tags: ${{ steps.merge-tags.outputs.list }} token: ${{ secrets.GITHUB_TOKEN }} multi-arch: runs-on: ubuntu-latest name: Merge into a multi-arch image - needs: [get-tag, build] + needs: [ metadata, build ] steps: - uses: aica-technology/.github/.github/actions/ghcr-manifest-merge@v0.6.1 with: - image_name: aica-technology/modulo - image_tags: ${{ needs.get-tag.outputs.tag }} + image_name: ${{ needs.metadata.outputs.image_name }} + image_tags: ${{ needs.metadata.outputs.image_tags }} archs: amd64,arm64 token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml index 96cdb983f..67d8abdd3 100644 --- a/.github/workflows/generate-docs.yml +++ b/.github/workflows/generate-docs.yml @@ -3,7 +3,6 @@ on: push: branches: - main - - develop release: types: [published] workflow_dispatch: diff --git a/.github/workflows/build-test.yml b/.github/workflows/test.yml similarity index 51% rename from .github/workflows/build-test.yml rename to .github/workflows/test.yml index 73953132f..a6e5e3fda 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/test.yml @@ -1,27 +1,20 @@ -name: Build and Test +name: Check CHANGELOG update and run tests on: pull_request: - workflow_dispatch: jobs: - check: - name: Check if changelog and version have been updated + check-changelog: + name: Check if changelog has been updated runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Check changelog - run: | + - uses: actions/checkout@v3 + - run: | git fetch origin main ${{ github.event.pull_request.base.sha }} - VER_DIFF=$(git diff ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- ./VERSION) - if ! [ "${VER_DIFF}" ]; then - echo "::warning title=Version check failed::VERSION must be updated!" - exit 1 - fi - CL_DIFF=$(git diff ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- ./CHANGELOG.md) - if ! [ "${CL_DIFF}" ]; then - echo "::warning title=CHEANGELOG check failed::CHANGELOG.md must be updated!" + PACKAGE_DIFF=$(git diff ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- ./source) + CL_DIFF=$(git diff ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- CHANGELOG.md) + if [ "${PACKAGE_DIFF}" ] && ! [ "${CL_DIFF}" ]; then + echo "::error file="CHANGELOG.md",title=Check failed::CHANGELOG.md must be updated!" exit 1 fi shell: bash @@ -30,14 +23,13 @@ jobs: name: Check skippable changes runs-on: ubuntu-latest outputs: - skip: ${{ steps.check_if_skippable.outputs.should_skip }} + skip: ${{ steps.check.outputs.should_skip }} steps: - - id: check_if_skippable + - id: check uses: fkirc/skip-duplicate-actions@master with: cancel_others: 'true' - do_not_skip: '["workflow_dispatch"]' - paths_ignore: '["**.md"]' + paths_ignore: '["**.md", ".**/**", "**.gitignore", "**.sh"]' skip_after_successful_duplicate: 'true' test: diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index d490efeac..9dcd9dd13 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,7 +3,7 @@ { "name": "AMD", "includePath": [ - "/opt/ros/humble/include/**", + "/opt/ros/iron/include/**", "/home/ros2/ros2_ws/install/**", "/home/ros2/ws/install/**", "/home/ros2/ws/src/modulo_utils/include", diff --git a/.vscode/settings.json b/.vscode/settings.json index 00a610035..5605ecfb3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,11 @@ { "C_Cpp.clang_format_style": "file:/home/ros2/.clang-format", "cmake.sourceDirectory": "/home/ros2/ws/src/modulo_components", + "python.analysis.typeCheckingMode": "basic", + "python.languageServer": "Pylance", + "editor.rulers": [ + 120 + ], + "autopep8.args": ["--max-line-length", "120", "--experimental"], + "pylint.args": ["--generate-members", "--max-line-length", "120", "-d", "C0114", "-d", "C0115", "-d", "C0116"] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 97617e800..817781899 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,33 @@ Release Versions: -- [3.1.0](#300) +- [3.2.0](#320) +- [3.1.0](#310) - [3.0.0](#300) - [2.3.0](#230) - [2.2.0](#220) - [2.1.1](#211) - [2.1.0](#210) + +## 3.2.0 + +### October 23, 2023 + +Version 3.2.0 is a minor update to modulo with a new feature that allows the component period parameter to be set +through a new parameter called 'rate'. In the future, the period parameter will be deprecated. + +Additionally, this is the last release with the current release strategy of creating release branches from develop and +merging them to main. From now on, branches will be directly created from main and merged back to main. If there is a +version update in such a PR, the CI will automatically create a new tag and push a tagged image. + +### Features + +- feat: add rate parameter to component interface (#57) + +### Behind the scenes + +- build: prepare workflows for deletion of develop branch (#58) + ## 3.1.0 ### September 27, 2023 diff --git a/VERSION b/VERSION index fd2a01863..944880fa1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.0 +3.2.0 diff --git a/doxygen/doxygen.conf b/doxygen/doxygen.conf index 5585bb895..51b225591 100644 --- a/doxygen/doxygen.conf +++ b/doxygen/doxygen.conf @@ -38,7 +38,7 @@ PROJECT_NAME = "Modulo" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 3.1.0 +PROJECT_NUMBER = 3.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/source/modulo_component_interfaces/package.xml b/source/modulo_component_interfaces/package.xml index 7b9a231f1..88bd667bc 100644 --- a/source/modulo_component_interfaces/package.xml +++ b/source/modulo_component_interfaces/package.xml @@ -2,7 +2,7 @@ modulo_component_interfaces - 3.1.0 + 3.2.0 Interface package for communicating with modulo components through the ROS framework Enrico Eberhard GPLv3 diff --git a/source/modulo_components/component_descriptions/modulo_component.json b/source/modulo_components/component_descriptions/modulo_component.json index 78ec66971..9175e008b 100644 --- a/source/modulo_components/component_descriptions/modulo_component.json +++ b/source/modulo_components/component_descriptions/modulo_component.json @@ -8,12 +8,20 @@ "registration": "modulo_components::Component", "inherits": "", "parameters": [ + { + "display_name": "Rate", + "description": "The frequency in Hertz for all periodic callbacks", + "parameter_name": "rate", + "parameter_type": "int", + "default_value": "10" + }, { "display_name": "Period", - "description": "The time interval in seconds for all periodic callbacks", + "description": "The time interval in seconds for all periodic callbacks. This parameter is deprecated and will be removed in the next major release. The rate parameter takes precedence and overrides the component period.", "parameter_name": "period", "parameter_type": "double", - "default_value": "0.1" + "default_value": "0.1", + "internal": true } ], "predicates": [ diff --git a/source/modulo_components/component_descriptions/modulo_lifecycle_component.json b/source/modulo_components/component_descriptions/modulo_lifecycle_component.json index afff8a96f..a84a3693d 100644 --- a/source/modulo_components/component_descriptions/modulo_lifecycle_component.json +++ b/source/modulo_components/component_descriptions/modulo_lifecycle_component.json @@ -8,12 +8,20 @@ "registration": "modulo_components::LifecycleComponent", "inherits": "", "parameters": [ + { + "display_name": "Rate", + "description": "The frequency in Hertz for all periodic callbacks", + "parameter_name": "rate", + "parameter_type": "int", + "default_value": "10" + }, { "display_name": "Period", - "description": "The time interval in seconds for all periodic callbacks", + "description": "The time interval in seconds for all periodic callbacks. This parameter is deprecated and will be removed in the next major release. The rate parameter takes precedence and overrides the component period.", "parameter_name": "period", "parameter_type": "double", - "default_value": "0.1" + "default_value": "0.1", + "internal": true } ], "predicates": [ diff --git a/source/modulo_components/include/modulo_components/ComponentInterface.hpp b/source/modulo_components/include/modulo_components/ComponentInterface.hpp index b9d9eef2d..2991f6e27 100644 --- a/source/modulo_components/include/modulo_components/ComponentInterface.hpp +++ b/source/modulo_components/include/modulo_components/ComponentInterface.hpp @@ -592,14 +592,15 @@ class ComponentInterface : public NodeT { template ComponentInterface::ComponentInterface( const rclcpp::NodeOptions& options, modulo_core::communication::PublisherType publisher_type, - const std::string& fallback_name -) : - NodeT(utilities::parse_node_name(options, fallback_name), options), publisher_type_(publisher_type) { + const std::string& fallback_name) + : NodeT(utilities::parse_node_name(options, fallback_name), utilities::modify_parameter_overrides(options)), + publisher_type_(publisher_type) { // register the parameter change callback handler parameter_cb_handle_ = NodeT::add_on_set_parameters_callback( [this](const std::vector& parameters) -> rcl_interfaces::msg::SetParametersResult { return this->on_set_parameters_callback(parameters); }); + this->add_parameter("rate", 10, "The rate in Hertz for all periodic callbacks", true); this->add_parameter("period", 0.1, "The time interval in seconds for all periodic callbacks", true); this->predicate_publisher_ = @@ -712,6 +713,13 @@ template inline bool ComponentInterface::validate_parameter( const std::shared_ptr& parameter ) { + if (parameter->get_name() == "rate") { + auto value = parameter->get_parameter_value(); + if (value <= 0 || !std::isfinite(value)) { + RCLCPP_ERROR(this->get_logger(), "Value for parameter 'rate' has to be a positive finite number."); + return false; + } + } if (parameter->get_name() == "period") { auto value = parameter->get_parameter_value(); if (value <= 0.0 || !std::isfinite(value)) { diff --git a/source/modulo_components/include/modulo_components/utilities/utilities.hpp b/source/modulo_components/include/modulo_components/utilities/utilities.hpp index a28754dc0..81c84104f 100644 --- a/source/modulo_components/include/modulo_components/utilities/utilities.hpp +++ b/source/modulo_components/include/modulo_components/utilities/utilities.hpp @@ -61,4 +61,40 @@ parse_node_name(const rclcpp::NodeOptions& options, const std::string& fallback } return output; } + +/** + * @brief Modify parameter overrides to handle the rate and period parameters + * @details This function checks for existence of the rate and period parameter in the parameter overrides + * and modifies them to correspond to the same value. If both the rate and the period parameter exist, the period will + * be set from the rate. + * @param options The node options passed to the component constructor + * @return The same node options with modified parameter overrides +*/ +[[maybe_unused]] static rclcpp::NodeOptions modify_parameter_overrides(const rclcpp::NodeOptions& options) { + auto modified = options; + rclcpp::Parameter rate; + rclcpp::Parameter period; + std::vector parameters; + for (const auto& parameter : options.parameter_overrides()) { + if (parameter.get_name() == "rate") { + rate = parameter; + } else if (parameter.get_name() == "period") { + period = parameter; + } else { + parameters.push_back(parameter); + } + } + if (rate.get_type() != rclcpp::ParameterType::PARAMETER_NOT_SET) { + period = rclcpp::Parameter("period", 1.0 / rate.as_int()); + } else if (period.get_type() != rclcpp::ParameterType::PARAMETER_NOT_SET) { + rate = rclcpp::Parameter("rate", static_cast(1.0 / period.as_double())); + } else { + modified.parameter_overrides() = parameters; + return modified; + } + parameters.push_back(rate); + parameters.push_back(period); + modified.parameter_overrides() = parameters; + return modified; +} }// namespace modulo_components::utilities diff --git a/source/modulo_components/modulo_components/component_interface.py b/source/modulo_components/modulo_components/component_interface.py index b6c222e2c..eb192e01b 100644 --- a/source/modulo_components/modulo_components/component_interface.py +++ b/source/modulo_components/modulo_components/component_interface.py @@ -12,7 +12,7 @@ from modulo_component_interfaces.srv import EmptyTrigger, StringTrigger from modulo_components.exceptions import AddServiceError, AddSignalError, ComponentError, ComponentParameterError, \ LookupTransformError -from modulo_components.utilities import parse_topic_name +from modulo_components.utilities import parse_topic_name, modify_parameter_overrides from modulo_core import EncodedState from modulo_core.exceptions import MessageTranslationError, ParameterTranslationError from modulo_core.translators.parameter_translators import get_ros_parameter_type, read_parameter_const, write_parameter @@ -42,6 +42,8 @@ class ComponentInterface(Node): def __init__(self, node_name: str, *args, **kwargs): node_kwargs = {key: value for key, value in kwargs.items() if key in NODE_KWARGS} + if "parameter_overrides" in node_kwargs.keys(): + node_kwargs["parameter_overrides"] = modify_parameter_overrides(node_kwargs["parameter_overrides"]) super().__init__(node_name, *args, **node_kwargs) self._parameter_dict: Dict[str, Union[str, sr.Parameter]] = {} self._predicates: Dict[str, Union[bool, Callable[[], bool]]] = {} @@ -59,8 +61,10 @@ def __init__(self, node_name: str, *args, **kwargs): self._qos = QoSProfile(depth=10) self.add_on_set_parameters_callback(self.__on_set_parameters_callback) + self.add_parameter(sr.Parameter("rate", 10, sr.ParameterType.INT), + "The rate in Hertz for all periodic callbacks") self.add_parameter(sr.Parameter("period", 0.1, sr.ParameterType.DOUBLE), - "Period (in s) between step function calls.") + "The time interval in seconds for all periodic callbacks") self._predicate_publisher = self.create_publisher(Predicate, "/predicates", self._qos) self.add_predicate("in_error_state", False) @@ -200,6 +204,11 @@ def __validate_parameter(self, parameter: sr.Parameter) -> bool: :param parameter: The parameter to be validated :return: The validation result """ + if parameter.get_name() == "rate": + value = parameter.get_value() + if value <= 0 or value > sys.float_info.max: + self.get_logger().error("Value for parameter 'rate' has to be a positive finite number.") + return False if parameter.get_name() == "period": value = parameter.get_value() if value <= 0.0 or value > sys.float_info.max: diff --git a/source/modulo_components/modulo_components/utilities/__init__.py b/source/modulo_components/modulo_components/utilities/__init__.py index 4ad06acaa..54c4beb44 100644 --- a/source/modulo_components/modulo_components/utilities/__init__.py +++ b/source/modulo_components/modulo_components/utilities/__init__.py @@ -1 +1 @@ -from modulo_components.utilities.utilities import parse_topic_name +from modulo_components.utilities.utilities import parse_topic_name, modify_parameter_overrides diff --git a/source/modulo_components/modulo_components/utilities/utilities.py b/source/modulo_components/modulo_components/utilities/utilities.py index bcd28a5dd..b51d233eb 100644 --- a/source/modulo_components/modulo_components/utilities/utilities.py +++ b/source/modulo_components/modulo_components/utilities/utilities.py @@ -1,4 +1,7 @@ import re +from typing import List + +from rclpy import Parameter def parse_topic_name(topic_name: str) -> str: @@ -12,3 +15,35 @@ def parse_topic_name(topic_name: str) -> str: sanitized_string = re.sub("\W", "", topic_name, flags=re.ASCII).lower() sanitized_string = sanitized_string.lstrip("_") return sanitized_string + + +def modify_parameter_overrides(parameter_overrides: List[Parameter]) -> List[Parameter]: + """ + Modify parameter overrides to handle the rate and period parameters. + This function checks for existence of the rate and period parameter in the parameter overrides and modifies them to + correspond to the same value. If both the rate and the period parameter exist, the period will be set from the rate. + + :param parameter_overrides: The parameter overrides passed to the component constructor + :return: The modified parameter overrides + """ + rate = Parameter("rate", type_=Parameter.Type.NOT_SET) + period = Parameter("period", type_=Parameter.Type.NOT_SET) + parameters = [] + for parameter in parameter_overrides: + if parameter.name == "rate": + rate = parameter + elif parameter.name == "period": + period = parameter + else: + parameters.append(parameter) + + if rate.type_ != Parameter.Type.NOT_SET: + period = Parameter("period", value=1.0 / rate.get_parameter_value().integer_value) + elif period.type_ != Parameter.Type.NOT_SET: + rate = Parameter("rate", value=int(1.0 / period.get_parameter_value().double_value)) + else: + return parameters + + parameters.append(rate) + parameters.append(period) + return parameters diff --git a/source/modulo_components/package.xml b/source/modulo_components/package.xml index fc43ca178..a5377ca19 100644 --- a/source/modulo_components/package.xml +++ b/source/modulo_components/package.xml @@ -2,7 +2,7 @@ modulo_components - 3.1.0 + 3.2.0 Modulo base classes that wrap ROS2 Nodes as modular components for the AICA application framework Baptiste Busch Enrico Eberhard diff --git a/source/modulo_components/test/cpp/test_component_interface.cpp b/source/modulo_components/test/cpp/test_component_interface.cpp index 741a2ff6a..0fb9c7002 100644 --- a/source/modulo_components/test/cpp/test_component_interface.cpp +++ b/source/modulo_components/test/cpp/test_component_interface.cpp @@ -11,6 +11,17 @@ namespace modulo_components { using namespace std::chrono_literals; +template +std::shared_ptr> make_component_interface(const rclcpp::NodeOptions& options) { + if (std::is_same::value) { + return std::make_shared>( + options, modulo_core::communication::PublisherType::PUBLISHER); + } else if (std::is_same::value) { + return std::make_shared>( + options, modulo_core::communication::PublisherType::LIFECYCLE_PUBLISHER); + } +} + template class ComponentInterfaceTest : public ::testing::Test { protected: @@ -23,24 +34,41 @@ class ComponentInterfaceTest : public ::testing::Test { } void SetUp() override { - exec_ = std::make_shared(); - if (std::is_same::value) { - this->component_ = std::make_shared>( - rclcpp::NodeOptions(), modulo_core::communication::PublisherType::PUBLISHER); - } else if (std::is_same::value) { - this->component_ = std::make_shared>( - rclcpp::NodeOptions(), modulo_core::communication::PublisherType::LIFECYCLE_PUBLISHER); - } + this->exec_ = std::make_shared(); + this->component_ = make_component_interface(rclcpp::NodeOptions()); } std::shared_ptr exec_; std::shared_ptr> component_; - std::shared_ptr node_; }; using NodeTypes = ::testing::Types; TYPED_TEST_SUITE(ComponentInterfaceTest, NodeTypes); +TYPED_TEST(ComponentInterfaceTest, RatePeriodParameters) { + std::shared_ptr> component; + auto node_options = rclcpp::NodeOptions(); + component = make_component_interface(node_options); + EXPECT_EQ(component->template get_parameter_value("rate"), 10); + EXPECT_EQ(component->template get_parameter_value("period"), 0.1); + + node_options = rclcpp::NodeOptions().parameter_overrides({rclcpp::Parameter("rate", 200)}); + component = make_component_interface(node_options); + EXPECT_EQ(component->template get_parameter_value("rate"), 200); + EXPECT_EQ(component->template get_parameter_value("period"), 0.005); + + node_options = rclcpp::NodeOptions().parameter_overrides({rclcpp::Parameter("period", 0.01)}); + component = make_component_interface(node_options); + EXPECT_EQ(component->template get_parameter_value("rate"), 100); + EXPECT_EQ(component->template get_parameter_value("period"), 0.01); + + node_options = + rclcpp::NodeOptions().parameter_overrides({rclcpp::Parameter("rate", 200), rclcpp::Parameter("period", 0.01)}); + component = make_component_interface(node_options); + EXPECT_EQ(component->template get_parameter_value("rate"), 200); + EXPECT_EQ(component->template get_parameter_value("period"), 0.005); +} + TYPED_TEST(ComponentInterfaceTest, AddBoolPredicate) { this->component_->add_predicate("foo", true); auto predicate_iterator = this->component_->predicates_.find("foo"); @@ -229,9 +257,9 @@ TYPED_TEST(ComponentInterfaceTest, CreateOutput) { EXPECT_TRUE(this->component_->periodic_outputs_.at("test")); auto pub_interface = this->component_->outputs_.at("test"); - if (typeid(this->node_) == typeid(rclcpp::Node)) { + if (std::is_same::value) { EXPECT_EQ(pub_interface->get_type(), modulo_core::communication::PublisherType::PUBLISHER); - } else if (typeid(this->node_) == typeid(rclcpp_lifecycle::LifecycleNode)) { + } else if (std::is_same::value) { EXPECT_EQ(pub_interface->get_type(), modulo_core::communication::PublisherType::LIFECYCLE_PUBLISHER); } EXPECT_EQ(pub_interface->get_message_pair()->get_type(), modulo_core::communication::MessageType::BOOL); diff --git a/source/modulo_components/test/python/test_component_interface.py b/source/modulo_components/test/python/test_component_interface.py index 12cf467f2..6b446c2f9 100644 --- a/source/modulo_components/test/python/test_component_interface.py +++ b/source/modulo_components/test/python/test_component_interface.py @@ -21,6 +21,27 @@ def component_interface(ros_context): yield ComponentInterface('component_interface') +def test_rate_period_parameters(ros_context): + component_interface = ComponentInterface('component_interface') + assert component_interface.get_parameter_value("rate") == 10 + assert component_interface.get_parameter_value("period") == 0.1 + + parameter_overrides=[rclpy.Parameter("rate", value=200)] + component_interface = ComponentInterface('component_interface', parameter_overrides=parameter_overrides) + assert component_interface.get_parameter_value("rate") == 200 + assert component_interface.get_parameter_value("period") == 0.005 + + parameter_overrides=[rclpy.Parameter("period", value=0.01)] + component_interface = ComponentInterface('component_interface', parameter_overrides=parameter_overrides) + assert component_interface.get_parameter_value("rate") == 100 + assert component_interface.get_parameter_value("period") == 0.01 + + parameter_overrides=[rclpy.Parameter("rate", value=200), rclpy.Parameter("period", value=0.01)] + component_interface = ComponentInterface('component_interface', parameter_overrides=parameter_overrides) + assert component_interface.get_parameter_value("rate") == 200 + assert component_interface.get_parameter_value("period") == 0.005 + + def test_add_bool_predicate(component_interface): component_interface.add_predicate('foo', True) assert 'foo' in component_interface._predicates.keys() diff --git a/source/modulo_core/package.xml b/source/modulo_core/package.xml index 6ffba21eb..a865bd2e5 100644 --- a/source/modulo_core/package.xml +++ b/source/modulo_core/package.xml @@ -2,7 +2,7 @@ modulo_core - 3.1.0 + 3.2.0 Modulo Core communication and translation utilities for interoperability with AICA Control Libraries Baptiste Busch Enrico Eberhard diff --git a/source/modulo_utils/package.xml b/source/modulo_utils/package.xml index e449ae2e1..bf589884a 100644 --- a/source/modulo_utils/package.xml +++ b/source/modulo_utils/package.xml @@ -2,7 +2,7 @@ modulo_utils - 3.1.0 + 3.2.0 Modulo utils package for shared test fixtures Dominic Reber GPLv3