From faede6e501ece11bb3f124cc8d6909095a03640e Mon Sep 17 00:00:00 2001 From: Dominic Reber <71256590+domire8@users.noreply.github.com> Date: Wed, 27 Sep 2023 16:33:20 +0200 Subject: [PATCH 1/4] release: version 3.1.0 (#56) --- .devcontainer/devcontainer.json | 2 +- CHANGELOG.md | 21 ++++++++++++++----- VERSION | 2 +- doxygen/doxygen.conf | 2 +- .../modulo_component_interfaces/package.xml | 2 +- source/modulo_components/package.xml | 2 +- source/modulo_core/package.xml | 2 +- source/modulo_utils/package.xml | 2 +- 8 files changed, 23 insertions(+), 12 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8df964ce2..93b9383c7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,7 @@ "dockerfile": "../Dockerfile", "context": "..", "target": "development", - "args": { "CL_VERSION": "v7.1.1" } + "args": { "CL_VERSION": "v7.2.0" } }, "workspaceMount": "source=${localWorkspaceFolder},target=/home/ros2/.devcontainer,type=bind,consistency=cached", "workspaceFolder": "/home/ros2/.devcontainer", diff --git a/CHANGELOG.md b/CHANGELOG.md index 76896207a..5c0d88a99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,19 +2,30 @@ Release Versions: +- [3.1.0](#300) - [3.0.0](#300) - [2.3.0](#230) - [2.2.0](#220) - [2.1.1](#211) - [2.1.0](#210) -## Upcoming changes (in development) +## 3.1.0 + +### September 27, 2023 + +Version 3.1.0 is a minor update to modulo with a new feature in the components and it marks the first official version +that uses `iron` as its ROS2 distribution. + +### Features + +- Add the on_step_callback for components (#51) + +### Behind the scenes - Revise test stage to fail on test errors (#48) -- build: unify dockerfiles and add vs code configuration (#50) -- feat: add on_step_callback for component (#51) -- build: use iron as ros2 distro (#53) -- ci: change test workflow to docker build (#55) +- Unify dockerfiles and add vs code configuration (#50) +- Use iron as ros2 distro (#53) +- Change test workflow to docker build (#55) ## 3.0.0 diff --git a/VERSION b/VERSION index eca690e73..fd2a01863 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.5 +3.1.0 diff --git a/doxygen/doxygen.conf b/doxygen/doxygen.conf index d01f9adb4..5585bb895 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.0.5 +PROJECT_NUMBER = 3.1.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 2d2299646..7b9a231f1 100644 --- a/source/modulo_component_interfaces/package.xml +++ b/source/modulo_component_interfaces/package.xml @@ -2,7 +2,7 @@ modulo_component_interfaces - 3.0.5 + 3.1.0 Interface package for communicating with modulo components through the ROS framework Enrico Eberhard GPLv3 diff --git a/source/modulo_components/package.xml b/source/modulo_components/package.xml index b902a3dcb..fc43ca178 100644 --- a/source/modulo_components/package.xml +++ b/source/modulo_components/package.xml @@ -2,7 +2,7 @@ modulo_components - 3.0.5 + 3.1.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_core/package.xml b/source/modulo_core/package.xml index a5bf8820a..6ffba21eb 100644 --- a/source/modulo_core/package.xml +++ b/source/modulo_core/package.xml @@ -2,7 +2,7 @@ modulo_core - 3.0.5 + 3.1.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 16f9fa523..e449ae2e1 100644 --- a/source/modulo_utils/package.xml +++ b/source/modulo_utils/package.xml @@ -2,7 +2,7 @@ modulo_utils - 3.0.5 + 3.1.0 Modulo utils package for shared test fixtures Dominic Reber GPLv3 From b8e61ce62d89dcf16fc2e9124fbb0c0870acab0e Mon Sep 17 00:00:00 2001 From: Dominic Reber <71256590+domire8@users.noreply.github.com> Date: Thu, 19 Oct 2023 18:53:11 +0200 Subject: [PATCH 2/4] feat: add rate parameter to component interface (#57) Add utility function to modify parameter overrides. Add rate parameter to component interfaces. Update tests and descriptions. --- .devcontainer/devcontainer.json | 3 ++ .vscode/c_cpp_properties.json | 2 +- .vscode/settings.json | 7 +++ CHANGELOG.md | 4 ++ VERSION | 2 +- doxygen/doxygen.conf | 2 +- .../modulo_component_interfaces/package.xml | 2 +- .../modulo_component.json | 12 ++++- .../modulo_lifecycle_component.json | 12 ++++- .../modulo_components/ComponentInterface.hpp | 14 ++++-- .../modulo_components/utilities/utilities.hpp | 36 +++++++++++++ .../modulo_components/component_interface.py | 13 ++++- .../modulo_components/utilities/__init__.py | 2 +- .../modulo_components/utilities/utilities.py | 35 +++++++++++++ source/modulo_components/package.xml | 2 +- .../test/cpp/test_component_interface.cpp | 50 +++++++++++++++---- .../test/python/test_component_interface.py | 21 ++++++++ source/modulo_core/package.xml | 2 +- source/modulo_utils/package.xml | 2 +- 19 files changed, 195 insertions(+), 28 deletions(-) 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/.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 5c0d88a99..bfc73a7d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ Release Versions: - [2.1.1](#211) - [2.1.0](#210) +## Upcoming changes (in development) + +- feat: add rate parameter to component interface (#57) + ## 3.1.0 ### September 27, 2023 diff --git a/VERSION b/VERSION index fd2a01863..94ff29cc4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.0 +3.1.1 diff --git a/doxygen/doxygen.conf b/doxygen/doxygen.conf index 5585bb895..790aca992 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.1.1 # 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..6bfad9021 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.1.1 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..43fa8d44e 100644 --- a/source/modulo_components/package.xml +++ b/source/modulo_components/package.xml @@ -2,7 +2,7 @@ modulo_components - 3.1.0 + 3.1.1 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..c0ce65ba8 100644 --- a/source/modulo_core/package.xml +++ b/source/modulo_core/package.xml @@ -2,7 +2,7 @@ modulo_core - 3.1.0 + 3.1.1 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..f89732af1 100644 --- a/source/modulo_utils/package.xml +++ b/source/modulo_utils/package.xml @@ -2,7 +2,7 @@ modulo_utils - 3.1.0 + 3.1.1 Modulo utils package for shared test fixtures Dominic Reber GPLv3 From 06b8bc87052447c3f5b9f03569abdf8091014605 Mon Sep 17 00:00:00 2001 From: Dominic Reber <71256590+domire8@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:39:02 +0200 Subject: [PATCH 3/4] build: prepare workflows for deletion of develop branch (#58) --- .github/workflows/build-release.yaml | 76 +++++++++++++++---- .github/workflows/generate-docs.yml | 1 - .../workflows/{build-test.yml => test.yml} | 32 +++----- CHANGELOG.md | 1 + VERSION | 2 +- doxygen/doxygen.conf | 2 +- .../modulo_component_interfaces/package.xml | 2 +- source/modulo_components/package.xml | 2 +- source/modulo_core/package.xml | 2 +- source/modulo_utils/package.xml | 2 +- 10 files changed, 79 insertions(+), 43 deletions(-) rename .github/workflows/{build-test.yml => test.yml} (51%) 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/CHANGELOG.md b/CHANGELOG.md index bfc73a7d5..56df1f33e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Release Versions: ## Upcoming changes (in development) - feat: add rate parameter to component interface (#57) +- build: prepare workflows for deletion of develop branch (#58) ## 3.1.0 diff --git a/VERSION b/VERSION index 94ff29cc4..ef538c281 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.1 +3.1.2 diff --git a/doxygen/doxygen.conf b/doxygen/doxygen.conf index 790aca992..8697abd93 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.1 +PROJECT_NUMBER = 3.1.2 # 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 6bfad9021..351f83ce9 100644 --- a/source/modulo_component_interfaces/package.xml +++ b/source/modulo_component_interfaces/package.xml @@ -2,7 +2,7 @@ modulo_component_interfaces - 3.1.1 + 3.1.2 Interface package for communicating with modulo components through the ROS framework Enrico Eberhard GPLv3 diff --git a/source/modulo_components/package.xml b/source/modulo_components/package.xml index 43fa8d44e..b59f46289 100644 --- a/source/modulo_components/package.xml +++ b/source/modulo_components/package.xml @@ -2,7 +2,7 @@ modulo_components - 3.1.1 + 3.1.2 Modulo base classes that wrap ROS2 Nodes as modular components for the AICA application framework Baptiste Busch Enrico Eberhard diff --git a/source/modulo_core/package.xml b/source/modulo_core/package.xml index c0ce65ba8..6749d991a 100644 --- a/source/modulo_core/package.xml +++ b/source/modulo_core/package.xml @@ -2,7 +2,7 @@ modulo_core - 3.1.1 + 3.1.2 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 f89732af1..168023e68 100644 --- a/source/modulo_utils/package.xml +++ b/source/modulo_utils/package.xml @@ -2,7 +2,7 @@ modulo_utils - 3.1.1 + 3.1.2 Modulo utils package for shared test fixtures Dominic Reber GPLv3 From 81fb18c726bc1978bd9b458a2c695b3514fd0306 Mon Sep 17 00:00:00 2001 From: Dominic Reber Date: Mon, 23 Oct 2023 11:49:08 +0200 Subject: [PATCH 4/4] release: version 3.2.0 --- CHANGELOG.md | 16 +++++++++++++++- VERSION | 2 +- doxygen/doxygen.conf | 2 +- source/modulo_component_interfaces/package.xml | 2 +- source/modulo_components/package.xml | 2 +- source/modulo_core/package.xml | 2 +- source/modulo_utils/package.xml | 2 +- 7 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56df1f33e..0705b7061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,23 @@ Release Versions: - [2.1.1](#211) - [2.1.0](#210) -## Upcoming changes (in development) +## 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 diff --git a/VERSION b/VERSION index ef538c281..944880fa1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.2 +3.2.0 diff --git a/doxygen/doxygen.conf b/doxygen/doxygen.conf index 8697abd93..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.2 +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 351f83ce9..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.2 + 3.2.0 Interface package for communicating with modulo components through the ROS framework Enrico Eberhard GPLv3 diff --git a/source/modulo_components/package.xml b/source/modulo_components/package.xml index b59f46289..a5377ca19 100644 --- a/source/modulo_components/package.xml +++ b/source/modulo_components/package.xml @@ -2,7 +2,7 @@ modulo_components - 3.1.2 + 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_core/package.xml b/source/modulo_core/package.xml index 6749d991a..a865bd2e5 100644 --- a/source/modulo_core/package.xml +++ b/source/modulo_core/package.xml @@ -2,7 +2,7 @@ modulo_core - 3.1.2 + 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 168023e68..bf589884a 100644 --- a/source/modulo_utils/package.xml +++ b/source/modulo_utils/package.xml @@ -2,7 +2,7 @@ modulo_utils - 3.1.2 + 3.2.0 Modulo utils package for shared test fixtures Dominic Reber GPLv3