Skip to content
Merged
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
1 change: 1 addition & 0 deletions ddsenabler/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ install(

# Add subdirectories for examples
add_subdirectory(utils)
add_subdirectory(discovery)
add_subdirectory(publish)
add_subdirectory(service)
add_subdirectory(action)
Expand Down
44 changes: 44 additions & 0 deletions ddsenabler/examples/discovery/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright 2026 Proyectos y Sistemas de Mantenimiento SL (eProsima).
#
# 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.20)
project(ddsenabler_example_discovery LANGUAGES CXX)

# When built standalone (not as a subdirectory of the DDS Enabler project), the
# 'ddsenabler' target does not exist yet, so locate the installed library. The
# imported 'ddsenabler' target links transitively against the packages below, so
# they must be found as well for the standalone build to configure and link.
if(NOT TARGET ddsenabler)
find_package(cpp_utils REQUIRED)
find_package(ddspipe_core REQUIRED)
find_package(ddspipe_participants REQUIRED)
find_package(ddspipe_yaml REQUIRED)
find_package(ddsenabler_participants REQUIRED)
find_package(ddsenabler_yaml REQUIRED)
find_package(ddsenabler REQUIRED)
endif()

add_executable(ddsenabler_example_discovery main.cpp)

target_link_libraries(ddsenabler_example_discovery PRIVATE ddsenabler)

# Install rule
install(TARGETS ddsenabler_example_discovery
RUNTIME DESTINATION examples/discovery
)
Comment thread
rsanchez15 marked this conversation as resolved.

# Install the example configuration file
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.yml
DESTINATION examples/discovery
)
54 changes: 54 additions & 0 deletions ddsenabler/examples/discovery/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Discovery Example README

This is the simplest DDS Enabler example and a good starting point.
It launches a DDS Enabler that listens to the DDS network and prints the **name** of every topic, service and action it discovers - nothing else (no types, no QoS, no data).

The application keeps running until it is stopped with `Ctrl+C`.

It registers only the three discovery notification callbacks of the `CallbackSet`:

- `dds.topic_notification` → prints discovered topic names.
- `service.service_notification` → prints discovered service names.
- `action.action_notification` → prints discovered action names.

## Compilation

The example is compiled together with the DDS Enabler when the project is built with the `-DCOMPILE_EXAMPLES=ON` CMake option.
It can also be compiled standalone against an already installed DDS Enabler.

First, source the environment where the DDS Enabler is installed.

```bash
source <ddsenabler-installation-path>/install/setup.bash
```

Then configure and build the example from its own directory.

```bash
mkdir build
cd build
cmake ..
cmake --build .
```

The `ddsenabler_example_discovery` executable is generated inside the `build` directory.

## Example Command

```bash
./ddsenabler_example_discovery config.yml
```

Run it and then start any DDS / ROS 2 application (for instance the ROS 2 `talker`, or another DDS Enabler example such as `publish`, `service` or `action`).
When a topic, service, or action is discovered, the application prints a line like:

```
[Discovery] Topic discovered: rt/chatter
[Discovery] Service discovered: /add_two_ints
[Discovery] Action discovered: /fibonacci
```

Press `Ctrl+C` to stop the application cleanly.

An optional YAML configuration file may be passed as the first argument to customize the DDS behavior (domain, allow/deny topic lists, etc.).
Without it, the Enabler uses its default configuration (DDS domain 0).
3 changes: 3 additions & 0 deletions ddsenabler/examples/discovery/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dds:
domain: 0

113 changes: 113 additions & 0 deletions ddsenabler/examples/discovery/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright 2026 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// 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.

/**
* @file main.cpp
*
* Minimal DDS Enabler example: print the name of every topic, service and action
* the Enabler discovers, and keep running until the user presses Ctrl+C.
*/

#include <condition_variable>
#include <csignal>
#include <iostream>
#include <mutex>
#include <string>

#include "ddsenabler/dds_enabler_runner.hpp"
#include "ddsenabler/DDSEnabler.hpp"

// Synchronization used to keep the application alive until a stop signal arrives.
std::mutex app_mutex;
std::condition_variable app_cv;
bool stop_app = false;

// Called by the Enabler every time a new DDS topic is discovered.
void on_topic_discovered(
const char* topic_name,
const eprosima::ddsenabler::participants::TopicInfo& /* topic_info */)
{
std::cout << "[Discovery] Topic discovered: " << topic_name << std::endl;
}

// Called by the Enabler every time a new ROS 2 / DDS service is discovered.
void on_service_discovered(
const char* service_name,
const eprosima::ddsenabler::participants::ServiceInfo& /* service_info */)
{
std::cout << "[Discovery] Service discovered: " << service_name << std::endl;
}

// Called by the Enabler every time a new ROS 2 / DDS action is discovered.
void on_action_discovered(
const char* action_name,
const eprosima::ddsenabler::participants::ActionInfo& /* action_info */)
{
std::cout << "[Discovery] Action discovered: " << action_name << std::endl;
}

// Stops the application cleanly when Ctrl+C (or another termination signal) is received.
void signal_handler(
int /* signum */)
{
{
std::lock_guard<std::mutex> lock(app_mutex);
stop_app = true;
}
app_cv.notify_all();
}

int main(
int argc,
char** argv)
{
using namespace eprosima::ddsenabler;

// Register only the discovery notification callbacks; everything else is left unset.
CallbackSet callbacks{};
callbacks.dds.topic_notification = on_topic_discovered;
callbacks.service.service_notification = on_service_discovered;
callbacks.action.action_notification = on_action_discovered;

// Create the Enabler. An optional YAML configuration file may be passed as the first argument.
std::shared_ptr<DDSEnabler> enabler;
bool enabler_created = (argc > 1)
? create_dds_enabler(argv[1], callbacks, enabler)
: create_dds_enabler(yaml::EnablerConfiguration(""), callbacks, enabler);

if (!enabler_created)
{
std::cerr << "Failed to create DDSEnabler instance." << std::endl;
return EXIT_FAILURE;
}

// Install signal handlers for a clean shutdown.
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);

std::cout << "DDS Enabler running. Listening for topics, services and actions. "
<< "Press Ctrl+C to stop." << std::endl;

// Block until a stop signal is received.
{
std::unique_lock<std::mutex> lock(app_mutex);
app_cv.wait(lock, []
{
return stop_app;
});
}

std::cout << "Stopping DDS Enabler..." << std::endl;
return EXIT_SUCCESS;
}
6 changes: 6 additions & 0 deletions ddsenabler_yaml/src/cpp/EnablerConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ void EnablerConfiguration::load_ddsenabler_configuration_(
enabler_configuration->id = "EnablerEnablerParticipant";
enabler_configuration->app_id = "DDS_ENABLER";

/////
// Set the DDS Enabler default log verbosity to ERROR, so that INFO and WARNING traces
// (from both the Enabler and the underlying DDS Pipe) are silenced unless the user
// explicitly raises the verbosity through the logging configuration.
ddspipe_configuration.log_configuration.verbosity.set_value(utils::VerbosityKind::Error);

/////
// Get optional Enabler configuration options
if (YamlReader::is_tag_present(yml, ENABLER_ENABLER_TAG))
Expand Down
Loading