diff --git a/common/autoware_node/CMakeLists.txt b/common/autoware_node/CMakeLists.txt new file mode 100644 index 0000000000..4ef5fbeae7 --- /dev/null +++ b/common/autoware_node/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.8) +project(autoware_node) + +find_package(autoware_cmake REQUIRED) +autoware_package() + +ament_auto_add_library(${PROJECT_NAME} src/node.cpp) + +if(BUILD_TESTING) + file(GLOB_RECURSE TEST_FILES test/*.cpp) + + foreach(TEST_FILE ${TEST_FILES}) + # Get the test name without directory and extension + get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) + + # Add each test separately + ament_add_ros_isolated_gtest(${TEST_NAME} ${TEST_FILE} TIMEOUT 10) + target_include_directories(${TEST_NAME} PRIVATE src/include) + target_link_libraries(${TEST_NAME} ${PROJECT_NAME}) + ament_target_dependencies(${TEST_NAME} + rclcpp + rclcpp_lifecycle) + endforeach() +endif() + +ament_auto_package(INSTALL_TO_SHARE) diff --git a/common/autoware_node/README.md b/common/autoware_node/README.md new file mode 100644 index 0000000000..28e39e54ea --- /dev/null +++ b/common/autoware_node/README.md @@ -0,0 +1,23 @@ +# Autoware Node + +## Abbreviations + +- **AN:** Autoware Node + +## Overview + +AN is an `autoware.core` package designed to provide a base class for all future nodes in the +system. +It also inherits all lifecycle control capabilities of the base +class [LifecycleNode](https://docs.ros2.org/latest/api/rclcpp_lifecycle/classrclcpp__lifecycle_1_1LifecycleNode.html) + +## Usage + +Check the [autoware_test_node](../../demos/autoware_test_node/README.md) package for an example of how to use `autoware::Node`. + +## Design + +### Lifecycle + +AN inherits from ROS 2 [rclcpp_lifecycle::LifecycleNode](https://design.ros2.org/articles/node_lifecycle.html) and has +all the basic functions of it. diff --git a/common/autoware_node/include/autoware/node/node.hpp b/common/autoware_node/include/autoware/node/node.hpp new file mode 100644 index 0000000000..4531bf48c7 --- /dev/null +++ b/common/autoware_node/include/autoware/node/node.hpp @@ -0,0 +1,41 @@ +// Copyright 2024 The Autoware Contributors +// +// 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. + +#ifndef AUTOWARE__NODE__NODE_HPP_ +#define AUTOWARE__NODE__NODE_HPP_ + +#include "autoware/node/visibility_control.hpp" + +#include + +#include + +namespace autoware::node +{ +using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; + +class Node : public rclcpp_lifecycle::LifecycleNode +{ +public: + AUTOWARE_NODE_PUBLIC + explicit Node( + const std::string & node_name, const std::string & ns = "", + const rclcpp::NodeOptions & options = rclcpp::NodeOptions()); + +protected: + CallbackReturn on_shutdown(const rclcpp_lifecycle::State & state) override; +}; +} // namespace autoware::node + +#endif // AUTOWARE__NODE__NODE_HPP_ diff --git a/common/autoware_node/include/autoware/node/visibility_control.hpp b/common/autoware_node/include/autoware/node/visibility_control.hpp new file mode 100644 index 0000000000..b7a6bbd07c --- /dev/null +++ b/common/autoware_node/include/autoware/node/visibility_control.hpp @@ -0,0 +1,26 @@ +// Copyright 2024 The Autoware Contributors +// +// 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. + +#ifndef AUTOWARE__NODE__VISIBILITY_CONTROL_HPP_ +#define AUTOWARE__NODE__VISIBILITY_CONTROL_HPP_ + +#include "rcutils/visibility_control_macros.h" +#ifdef AUTOWARE_NODE_BUILDING_DLL +#define AUTOWARE_NODE_PUBLIC RCUTILS_EXPORT +#else +#define AUTOWARE_NODE_PUBLIC RCUTILS_IMPORT +#endif // !AUTOWARE_NODE_BUILDING_DLL +#define AUTOWARE_NODE_LOCAL RCUTILS_LOCAL + +#endif // AUTOWARE__NODE__VISIBILITY_CONTROL_HPP_ diff --git a/common/autoware_node/package.xml b/common/autoware_node/package.xml new file mode 100644 index 0000000000..e52fa4e4f7 --- /dev/null +++ b/common/autoware_node/package.xml @@ -0,0 +1,21 @@ + + + + autoware_node + 0.0.0 + Autoware Node is an Autoware.Core package designed to provide a base class for all nodes in the system. + M. Fatih Cırıt + Apache-2.0 + + ament_cmake_auto + autoware_cmake + + rclcpp_lifecycle + + ament_cmake_ros + autoware_lint_common + + + ament_cmake + + diff --git a/common/autoware_node/src/node.cpp b/common/autoware_node/src/node.cpp new file mode 100644 index 0000000000..385d3731d0 --- /dev/null +++ b/common/autoware_node/src/node.cpp @@ -0,0 +1,38 @@ +// Copyright 2024 The Autoware Contributors +// +// 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. + +#include +#include + +#include + +namespace autoware::node +{ +Node::Node( + const std::string & node_name, const std::string & ns, const rclcpp::NodeOptions & options) +: LifecycleNode(node_name, ns, options) +{ + RCLCPP_DEBUG( + get_logger(), "Node %s constructor was called.", + get_node_base_interface()->get_fully_qualified_name()); +} + +CallbackReturn Node::on_shutdown(const rclcpp_lifecycle::State & state) +{ + RCLCPP_DEBUG( + get_logger(), "Node %s shutdown was called with state %s.", + get_node_base_interface()->get_fully_qualified_name(), state.label().c_str()); + return CallbackReturn::SUCCESS; +} +} // namespace autoware::node diff --git a/common/autoware_node/test/test_an_init_shutdown.cpp b/common/autoware_node/test/test_an_init_shutdown.cpp new file mode 100644 index 0000000000..1224c17c92 --- /dev/null +++ b/common/autoware_node/test/test_an_init_shutdown.cpp @@ -0,0 +1,60 @@ +// Copyright 2024 The Autoware Contributors +// +// 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. + +#include +#include + +#include + +#include + +#include + +class AutowareNodeInitShutdown : public ::testing::Test +{ +public: + void SetUp() override { rclcpp::init(0, nullptr); } + + void TearDown() override { rclcpp::shutdown(); } + + rclcpp::NodeOptions node_options_an_; +}; + +TEST_F(AutowareNodeInitShutdown, NodeInitShutdown) +{ + autoware::node::Node::SharedPtr autoware_node = + std::make_shared("test_node", "test_ns", node_options_an_); + + auto executor = std::make_shared(); + executor->add_node(autoware_node->get_node_base_interface()); + + std::thread thread_spin = std::thread([&executor]() { executor->spin(); }); + + ASSERT_EQ( + autoware_node->get_current_state().id(), + lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED); + + auto state = autoware_node->shutdown(); + + ASSERT_EQ(state.id(), lifecycle_msgs::msg::State::PRIMARY_STATE_FINALIZED); + + // wait until executor is spinning + while (!executor->is_spinning()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + executor->cancel(); // make sure cancel is called after spin + if (thread_spin.joinable()) { + thread_spin.join(); + } +} diff --git a/demos/autoware_test_node/CMakeLists.txt b/demos/autoware_test_node/CMakeLists.txt new file mode 100644 index 0000000000..64db7b3b9b --- /dev/null +++ b/demos/autoware_test_node/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.8) +project(autoware_test_node) + +find_package(autoware_cmake REQUIRED) +autoware_package() + +ament_auto_add_library(${PROJECT_NAME} SHARED + src/test_node.cpp) + +rclcpp_components_register_node(${PROJECT_NAME} + PLUGIN "autoware::test_node::TestNode" + EXECUTABLE ${PROJECT_NAME}_node) + +ament_auto_package(INSTALL_TO_SHARE + launch) diff --git a/demos/autoware_test_node/README.md b/demos/autoware_test_node/README.md new file mode 100644 index 0000000000..91a07cd710 --- /dev/null +++ b/demos/autoware_test_node/README.md @@ -0,0 +1,53 @@ +# autoware_test_node + +This package contains a simple example of how to use `autoware::Node`. + +## Usage + +```bash +ros2 launch autoware_test_node autoware_test_node.launch.xml +``` + +### Lifecycle control + +Information on Lifecycle nodes can be found [here](https://design.ros2.org/articles/node_lifecycle.html). + +Output a list of nodes with lifecycle: + +```console +$ ros2 lifecycle nodes +/test_ns1/test_node1 +``` + +Get the current state of a node: + +```console +$ ros2 lifecycle get /test_ns1/test_node1 +unconfigured [1] +``` + +List the available transitions for the node: + +```console +$ ros2 lifecycle list /test_ns1/test_node1 +- configure [1] + Start: unconfigured + Goal: configuring +- shutdown [5] + Start: unconfigured + Goal: shuttingdown +``` + +Shutdown the node: + +```console +$ ros2 lifecycle set /test_ns1/test_node1 shutdown +Transitioning successful +``` + +```console +$ ros2 lifecycle get /test_ns1/test_node1 +finalized [4] +``` + +The node will remain alive in the `finalized` state until it is killed by the user. diff --git a/demos/autoware_test_node/launch/autoware_test_node.launch.xml b/demos/autoware_test_node/launch/autoware_test_node.launch.xml new file mode 100644 index 0000000000..c034fa0813 --- /dev/null +++ b/demos/autoware_test_node/launch/autoware_test_node.launch.xml @@ -0,0 +1,3 @@ + + + diff --git a/demos/autoware_test_node/package.xml b/demos/autoware_test_node/package.xml new file mode 100644 index 0000000000..50d8aedacf --- /dev/null +++ b/demos/autoware_test_node/package.xml @@ -0,0 +1,21 @@ + + + + autoware_test_node + 0.0.0 + Test package for Autoware Node. + M. Fatih Cırıt + Apache-2.0 + + ament_cmake_auto + autoware_cmake + + autoware_node + rclcpp + rclcpp_components + rclcpp_lifecycle + + + ament_cmake + + diff --git a/demos/autoware_test_node/src/include/test_node.hpp b/demos/autoware_test_node/src/include/test_node.hpp new file mode 100644 index 0000000000..027171d2d8 --- /dev/null +++ b/demos/autoware_test_node/src/include/test_node.hpp @@ -0,0 +1,32 @@ +// Copyright 2024 The Autoware Contributors +// +// 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. + +#ifndef TEST_NODE_HPP_ +#define TEST_NODE_HPP_ + +#include +#include + +namespace autoware::test_node +{ + +class TestNode : public autoware::node::Node +{ +public: + explicit TestNode(const rclcpp::NodeOptions & options = rclcpp::NodeOptions()); +}; + +} // namespace autoware::test_node + +#endif // TEST_NODE_HPP_ diff --git a/demos/autoware_test_node/src/test_node.cpp b/demos/autoware_test_node/src/test_node.cpp new file mode 100644 index 0000000000..2e2b60b824 --- /dev/null +++ b/demos/autoware_test_node/src/test_node.cpp @@ -0,0 +1,31 @@ +// Copyright 2024 The Autoware Contributors +// +// 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. + +#include "include/test_node.hpp" + +#include + +namespace autoware::test_node +{ +TestNode::TestNode(const rclcpp::NodeOptions & options) +: autoware::node::Node("test_node", "", options) +{ + RCLCPP_DEBUG( + get_logger(), "TestNode %s constructor was called.", + get_node_base_interface()->get_fully_qualified_name()); +} +} // namespace autoware::test_node + +#include +RCLCPP_COMPONENTS_REGISTER_NODE(autoware::test_node::TestNode)