Skip to content

Add Topic Keys tutorials #5573

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

Open
wants to merge 4 commits into
base: rolling
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions source/Tutorials/Advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Advanced
:maxdepth: 1

Advanced/Topic-Statistics-Tutorial/Topic-Statistics-Tutorial
Advanced/Topic-Keys/Topic-Keys-Tutorial
Advanced/Topic-Keys/Filtered-Topic-Keys-Tutorial
Advanced/Discovery-Server/Discovery-Server
Advanced/Allocator-Template-Tutorial
Advanced/Ament-Lint-For-Clean-Code
Expand Down
386 changes: 386 additions & 0 deletions source/Tutorials/Advanced/Topic-Keys/Filtered-Topic-Keys-Tutorial.rst

Large diffs are not rendered by default.

583 changes: 583 additions & 0 deletions source/Tutorials/Advanced/Topic-Keys/Topic-Keys-Tutorial.rst

Large diffs are not rendered by default.

986 changes: 986 additions & 0 deletions source/Tutorials/Advanced/Topic-Keys/figures/cft_tutorial_diagram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4,460 changes: 4,460 additions & 0 deletions source/Tutorials/Advanced/Topic-Keys/figures/tutorial_diagram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
125 changes: 125 additions & 0 deletions source/Tutorials/Advanced/Topic-Keys/resources/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
# Copyright 2025 Open Source Robotics Foundation, Inc.
#
# 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.

cmake_minimum_required(VERSION 3.12)

project(demo_keys_cpp)

# Default to C++17
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)
find_package(example_interfaces REQUIRED)
find_package(rcl REQUIRED)
find_package(rcl_interfaces REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(rcpputils REQUIRED)
find_package(rcutils REQUIRED)
find_package(rmw REQUIRED)
find_package(rosidl_default_generators REQUIRED)

# Generate message
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/SensorDataMsg.idl"
"msg/KeyedSensorDataMsg.idl"
)

ament_export_dependencies(rosidl_default_runtime)

# Prepare libraries
add_library(single_topic_sensor_component src/single_topic_sensor.cpp)
add_library(single_topic_controller_component src/single_topic_controller.cpp)
add_library(multiple_topic_sensor_component src/multiple_topic_sensor.cpp)
add_library(multiple_topic_controller_component src/multiple_topic_controller.cpp)
add_library(keyed_sensor_component src/keyed_sensor.cpp)
add_library(keyed_controller_component src/keyed_controller.cpp)

# Declare components
rclcpp_components_register_node(
single_topic_sensor_component
PLUGIN "demo_keys_cpp::SingleTopicSensorNode"
EXECUTABLE single_topic_sensor
)

rclcpp_components_register_node(
single_topic_controller_component
PLUGIN "demo_keys_cpp::SingleTopicControllerNode"
EXECUTABLE single_topic_controller
)

rclcpp_components_register_node(
multiple_topic_sensor_component
PLUGIN "demo_keys_cpp::MultipleTopicSensorNode"
EXECUTABLE multiple_topic_sensor
)

rclcpp_components_register_node(
multiple_topic_controller_component
PLUGIN "demo_keys_cpp::MultipleTopicControllerNode"
EXECUTABLE multiple_topic_controller
)

rclcpp_components_register_node(
keyed_sensor_component
PLUGIN "demo_keys_cpp::KeyedSensorNode"
EXECUTABLE keyed_sensor
)

rclcpp_components_register_node(
keyed_controller_component
PLUGIN "demo_keys_cpp::KeyedControllerNode"
EXECUTABLE keyed_controller
)

# Attach to cpp generation target
rosidl_get_typesupport_target(cpp_typesupport_target
${PROJECT_NAME} rosidl_typesupport_cpp)

# Link against the generated source files
target_link_libraries(single_topic_sensor_component "${cpp_typesupport_target}" rclcpp::rclcpp rclcpp_components::component)
target_link_libraries(single_topic_controller_component "${cpp_typesupport_target}" rclcpp::rclcpp rclcpp_components::component)
target_link_libraries(multiple_topic_sensor_component "${cpp_typesupport_target}" rclcpp::rclcpp rclcpp_components::component)
target_link_libraries(multiple_topic_controller_component "${cpp_typesupport_target}" rclcpp::rclcpp rclcpp_components::component)
target_link_libraries(keyed_sensor_component "${cpp_typesupport_target}" rclcpp::rclcpp rclcpp_components::component)
target_link_libraries(keyed_controller_component "${cpp_typesupport_target}" rclcpp::rclcpp rclcpp_components::component)

# Install
install(TARGETS
single_topic_sensor_component
single_topic_controller_component
multiple_topic_sensor_component
multiple_topic_controller_component
keyed_sensor_component
keyed_controller_component
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)


# Install launch files.
install(DIRECTORY
launch
DESTINATION share/${PROJECT_NAME}/
)

ament_package()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ROS 2 Topic Keys Demo

This project contains code for demonstrating the how-to-use topic keys feature in ROS 2 with Fast DDS or Connext RMWs.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
# Copyright 2025 Open Source Robotics Foundation, Inc.
#
# 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.

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():

sensor_nodes = []

for id in range(1, 11):

sensor_node = Node(
package="demo_keys_cpp",
executable="keyed_sensor",
parameters=[
{"id": id}
])

sensor_nodes.append(sensor_node)

return LaunchDescription(sensor_nodes)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
# Copyright 2025 Open Source Robotics Foundation, Inc.
#
# 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.

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():

sensor_nodes = []

for id in range(1, 11):

sensor_node = Node(
package="demo_keys_cpp",
executable="multiple_topic_sensor",
parameters=[
{"id": id}
])

sensor_nodes.append(sensor_node)

return LaunchDescription(sensor_nodes)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
# Copyright 2025 Open Source Robotics Foundation, Inc.
#
# 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.

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():

sensor_nodes = []

for id in range(1, 11):

sensor_node = Node(
package="demo_keys_cpp",
executable="single_topic_sensor",
parameters=[
{"id": id}
])

sensor_nodes.append(sensor_node)

return LaunchDescription(sensor_nodes)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
int16 sensor_id
string data
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
int16 sensor_id
string data
50 changes: 50 additions & 0 deletions source/Tutorials/Advanced/Topic-Keys/resources/Basic/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>demo_keys_cpp</name>
<version>0.0.0</version>
<description>
C++ demo package for showing the topic keys feature.
</description>

<maintainer email="[email protected]">Mario Dominguez</maintainer>
<license>Apache License 2.0</license>
<author email="[email protected]">Mario Dominguez</author>
<buildtool_depend>ament_cmake</buildtool_depend>

<build_depend>example_interfaces</build_depend>
<build_depend>rcl_interfaces</build_depend>
<build_depend>rcl</build_depend>
<build_depend>rclcpp_components</build_depend>
<build_depend>rclcpp</build_depend>
<build_depend>rcpputils</build_depend>
<build_depend>rcutils</build_depend>
<build_depend>rmw</build_depend>
<build_depend>rosidl_default_generators</build_depend>

<exec_depend>example_interfaces</exec_depend>
<exec_depend>launch_ros</exec_depend>
<exec_depend>launch_xml</exec_depend>
<exec_depend>rcl_interfaces</exec_depend>
<exec_depend>rcl</exec_depend>
<exec_depend>rclcpp_components</exec_depend>
<exec_depend>rclcpp</exec_depend>
<exec_depend>rcpputils</exec_depend>
<exec_depend>rcutils</exec_depend>
<exec_depend>rmw</exec_depend>
<exec_depend>rosidl_default_runtime</exec_depend>

<member_of_group>rosidl_interface_packages</member_of_group>

<test_depend>ament_cmake_pytest</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>launch</test_depend>
<test_depend>launch_testing</test_depend>
<test_depend>launch_testing_ament_cmake</test_depend>
<test_depend>launch_testing_ros</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
// Copyright 2025 Open Source Robotics Foundation, Inc.
//
// 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 <cstdio>

#include <demo_keys_cpp/msg/keyed_sensor_data_msg.hpp>
#include <rclcpp_components/register_node_macro.hpp>
#include <rclcpp/rclcpp.hpp>

namespace demo_keys_cpp
{

class KeyedControllerNode : public rclcpp::Node
{
public:

explicit KeyedControllerNode(const rclcpp::NodeOptions & options)
: Node("keyed_controller", options)
{
// Create a callback function for when messages are received.
setvbuf(stdout, NULL, _IONBF, BUFSIZ);
Copy link
Contributor

Choose a reason for hiding this comment

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

include <cstdio>

auto callback =
[this](demo_keys_cpp::msg::KeyedSensorDataMsg::ConstSharedPtr msg) -> void
{
RCLCPP_INFO(this->get_logger(), "Received data from sensor [%d]",(int)msg->sensor_id);
};

sub_ = create_subscription<demo_keys_cpp::msg::KeyedSensorDataMsg>("/robot/sensors",
rclcpp::QoS(rclcpp::KeepLast(1)).reliable().transient_local(),
callback);
}

private:
rclcpp::Subscription<demo_keys_cpp::msg::KeyedSensorDataMsg>::SharedPtr sub_;
};

} // namespace demo_keys_cpp

RCLCPP_COMPONENTS_REGISTER_NODE(demo_keys_cpp::KeyedControllerNode)
Loading