diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7596f15..b924661 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,7 @@ jobs: run: | mkdir -p ws/src ln -s ../../rclcpp_async ws/src/rclcpp_async + ln -s ../../rclcpp_async_example ws/src/rclcpp_async_example - name: Build and test run: | ROS_DISTRO=${{ matrix.ros_distro }} ./run.sh bash -c \ diff --git a/README.md b/README.md index c3a8646..35ea094 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,5 @@ # rclcpp_async -[![CI](https://github.com/otamachan/rclcpp_async/actions/workflows/ci.yml/badge.svg)](https://github.com/otamachan/rclcpp_async/actions/workflows/ci.yml) -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -![C++20](https://img.shields.io/badge/C%2B%2B-20-blue.svg) -![ROS 2 Jazzy](https://img.shields.io/badge/ROS%202-Jazzy-blue.svg) -![ROS 2 Rolling](https://img.shields.io/badge/ROS%202-Rolling-blue.svg) - A header-only C++20 coroutine library that brings `async/await` to ROS 2, inspired by [icey](https://github.com/iv461/icey). Write asynchronous ROS 2 code that reads like sequential code -- no callback nesting, no deadlocks, no `std::mutex`, no state machines -- all on a single-threaded executor. @@ -555,7 +549,7 @@ Task run(CoContext & ctx) A key advantage of coroutine-based I/O: nested service calls work without deadlocks, even on a single-threaded executor. For example, a service handler can `co_await` another service call, which can itself call yet another service -- all on the same thread. -See [`example/nested_demo.cpp`](rclcpp_async/example/nested_demo.cpp) for a full demonstration. +See [`nested_demo.cpp`](rclcpp_async_example/src/nested_demo.cpp) for a full demonstration. ## API Reference diff --git a/rclcpp_async/CMakeLists.txt b/rclcpp_async/CMakeLists.txt index fb77690..02e8a80 100644 --- a/rclcpp_async/CMakeLists.txt +++ b/rclcpp_async/CMakeLists.txt @@ -60,32 +60,6 @@ if(BUILD_TESTING) find_package(std_srvs REQUIRED) find_package(example_interfaces REQUIRED) - # Examples - add_executable(demo_server example/demo_server.cpp) - target_link_libraries(demo_server ${PROJECT_NAME} - ${std_msgs_TARGETS} ${std_srvs_TARGETS} ${example_interfaces_TARGETS}) - - add_executable(subscriber example/subscriber.cpp) - target_link_libraries(subscriber ${PROJECT_NAME} ${std_msgs_TARGETS}) - - add_executable(service_client example/service_client.cpp) - target_link_libraries(service_client ${PROJECT_NAME} ${std_srvs_TARGETS}) - - add_executable(action_client example/action_client.cpp) - target_link_libraries(action_client ${PROJECT_NAME} ${example_interfaces_TARGETS}) - - add_executable(nested_demo example/nested_demo.cpp) - target_link_libraries(nested_demo ${PROJECT_NAME} - ${std_srvs_TARGETS} ${example_interfaces_TARGETS}) - - install(TARGETS demo_server subscriber service_client action_client nested_demo - DESTINATION lib/${PROJECT_NAME} - ) - - install(DIRECTORY launch/ - DESTINATION share/${PROJECT_NAME}/launch - ) - # Level 1: Pure unit tests (no ROS2 runtime) ament_add_gtest(test_result test/test_result.cpp) target_link_libraries(test_result ${PROJECT_NAME}) diff --git a/rclcpp_async/package.xml b/rclcpp_async/package.xml index d4b0b98..8595ca4 100644 --- a/rclcpp_async/package.xml +++ b/rclcpp_async/package.xml @@ -22,8 +22,6 @@ std_msgs std_srvs example_interfaces - ros2launch - ament_cmake diff --git a/rclcpp_async_example/CMakeLists.txt b/rclcpp_async_example/CMakeLists.txt new file mode 100644 index 0000000..3a57e36 --- /dev/null +++ b/rclcpp_async_example/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.14) +project(rclcpp_async_example) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 20) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic -Werror=deprecated-declarations -fcoroutines) +endif() + +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclcpp_action REQUIRED) +find_package(rclcpp_async REQUIRED) +find_package(std_msgs REQUIRED) +find_package(std_srvs REQUIRED) +find_package(example_interfaces REQUIRED) + +add_executable(demo_server src/demo_server.cpp) +target_link_libraries(demo_server rclcpp_async::rclcpp_async + ${std_msgs_TARGETS} ${std_srvs_TARGETS} ${example_interfaces_TARGETS}) + +add_executable(subscriber src/subscriber.cpp) +target_link_libraries(subscriber rclcpp_async::rclcpp_async ${std_msgs_TARGETS}) + +add_executable(service_client src/service_client.cpp) +target_link_libraries(service_client rclcpp_async::rclcpp_async ${std_srvs_TARGETS}) + +add_executable(action_client src/action_client.cpp) +target_link_libraries(action_client rclcpp_async::rclcpp_async ${example_interfaces_TARGETS}) + +add_executable(nested_demo src/nested_demo.cpp) +target_link_libraries(nested_demo rclcpp_async::rclcpp_async + ${std_srvs_TARGETS} ${example_interfaces_TARGETS}) + +install(TARGETS demo_server subscriber service_client action_client nested_demo + DESTINATION lib/${PROJECT_NAME} +) + +install(DIRECTORY launch/ + DESTINATION share/${PROJECT_NAME}/launch +) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + set(AMENT_LINT_AUTO_EXCLUDE ament_cmake_uncrustify ament_cmake_cppcheck) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() diff --git a/rclcpp_async_example/CPPLINT.cfg b/rclcpp_async_example/CPPLINT.cfg new file mode 100644 index 0000000..ce8679f --- /dev/null +++ b/rclcpp_async_example/CPPLINT.cfg @@ -0,0 +1 @@ +filter=-build/include_order diff --git a/rclcpp_async/launch/action_demo.launch.py b/rclcpp_async_example/launch/action_demo.launch.py similarity index 91% rename from rclcpp_async/launch/action_demo.launch.py rename to rclcpp_async_example/launch/action_demo.launch.py index 21d7ce8..122f7d9 100644 --- a/rclcpp_async/launch/action_demo.launch.py +++ b/rclcpp_async_example/launch/action_demo.launch.py @@ -19,13 +19,13 @@ def generate_launch_description(): return LaunchDescription([ Node( - package='rclcpp_async', + package='rclcpp_async_example', executable='demo_server', name='demo_server', output='screen', ), Node( - package='rclcpp_async', + package='rclcpp_async_example', executable='action_client', name='action_client', output='screen', diff --git a/rclcpp_async/launch/service_demo.launch.py b/rclcpp_async_example/launch/service_demo.launch.py similarity index 91% rename from rclcpp_async/launch/service_demo.launch.py rename to rclcpp_async_example/launch/service_demo.launch.py index 1286175..006c27f 100644 --- a/rclcpp_async/launch/service_demo.launch.py +++ b/rclcpp_async_example/launch/service_demo.launch.py @@ -19,13 +19,13 @@ def generate_launch_description(): return LaunchDescription([ Node( - package='rclcpp_async', + package='rclcpp_async_example', executable='demo_server', name='demo_server', output='screen', ), Node( - package='rclcpp_async', + package='rclcpp_async_example', executable='service_client', name='service_client', output='screen', diff --git a/rclcpp_async/launch/subscriber_demo.launch.py b/rclcpp_async_example/launch/subscriber_demo.launch.py similarity index 91% rename from rclcpp_async/launch/subscriber_demo.launch.py rename to rclcpp_async_example/launch/subscriber_demo.launch.py index 0147a4d..3baaee4 100644 --- a/rclcpp_async/launch/subscriber_demo.launch.py +++ b/rclcpp_async_example/launch/subscriber_demo.launch.py @@ -19,13 +19,13 @@ def generate_launch_description(): return LaunchDescription([ Node( - package='rclcpp_async', + package='rclcpp_async_example', executable='demo_server', name='demo_server', output='screen', ), Node( - package='rclcpp_async', + package='rclcpp_async_example', executable='subscriber', name='async_subscriber', output='screen', diff --git a/rclcpp_async_example/package.xml b/rclcpp_async_example/package.xml new file mode 100644 index 0000000..ca9b292 --- /dev/null +++ b/rclcpp_async_example/package.xml @@ -0,0 +1,29 @@ + + + + rclcpp_async_example + 0.1.0 + Example programs demonstrating rclcpp_async usage + nishino + Apache-2.0 + + ament_cmake + + rclcpp + rclcpp_action + rclcpp_async + std_msgs + std_srvs + example_interfaces + + ros2launch + + ament_lint_auto + ament_lint_common + ament_cmake_clang_tidy + ament_cmake_clang_format + + + ament_cmake + + diff --git a/rclcpp_async/example/action_client.cpp b/rclcpp_async_example/src/action_client.cpp similarity index 100% rename from rclcpp_async/example/action_client.cpp rename to rclcpp_async_example/src/action_client.cpp diff --git a/rclcpp_async/example/demo_server.cpp b/rclcpp_async_example/src/demo_server.cpp similarity index 100% rename from rclcpp_async/example/demo_server.cpp rename to rclcpp_async_example/src/demo_server.cpp diff --git a/rclcpp_async/example/nested_demo.cpp b/rclcpp_async_example/src/nested_demo.cpp similarity index 100% rename from rclcpp_async/example/nested_demo.cpp rename to rclcpp_async_example/src/nested_demo.cpp diff --git a/rclcpp_async/example/service_client.cpp b/rclcpp_async_example/src/service_client.cpp similarity index 100% rename from rclcpp_async/example/service_client.cpp rename to rclcpp_async_example/src/service_client.cpp diff --git a/rclcpp_async/example/subscriber.cpp b/rclcpp_async_example/src/subscriber.cpp similarity index 100% rename from rclcpp_async/example/subscriber.cpp rename to rclcpp_async_example/src/subscriber.cpp