Skip to content

Commit

Permalink
Add Modern C++ DL example (rticommunity#632)
Browse files Browse the repository at this point in the history
Updated cmake-utils to include the new Modern C++ DL imported target
  • Loading branch information
luisrg-rti authored Nov 20, 2023
1 parent 73b9199 commit fe09cf3
Show file tree
Hide file tree
Showing 7 changed files with 400 additions and 1 deletion.
1 change: 1 addition & 0 deletions examples/connext_dds/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ if(NOT DEFINED CONNEXTDDS_CONNEXT_DDS_EXAMPLES)
"custom_transport"
"deadline_contentfilter"
# "discovery_snapshot"
"distributed_logger"
"dynamic_data_using_publisher_subscriber"
"flat_data_api"
"flat_data_latency"
Expand Down
55 changes: 55 additions & 0 deletions examples/connext_dds/distributed_logger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Example Code: Distributed Logger

## Concept

RTI Distributed Logger is an API that allows publishing log messages to a DDS Topic.
This will allow your distributed application to send log messages that can be monitored
using tools such as RTI Spy or RTI Admin Console.

It is also possible to use the API directly, creating your own logging infrastructure.

## Example Description

Similar examples are available in other programming languages in the
`rti_workspace/<version>/examples/distributed_logger/<language>/`
folder created under your home directory when RTI Connext is installed.

This example shows a simple application running Distributed Logger to
log several messages using different configurations.

The log messages can then be visualized using RTI Tools such as RTI Spy
or RTI Admin Console.
For example, you may find RTI Spy in your RTI Connext DDS installation
and run it from a terminal as follows:

```sh
cd rti_connext_dds-7.2.0/bin
./rtiddsspy -printSample
```

Once the Distributed Logger example is running in a different terminal,
you should start seeing state information along with the logged messages
on RTI Spy:

```txt
RTI Connext DDS Spy built with DDS version: 7.2.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rtiddsspy is listening for data, press CTRL+C to stop it.
[...]
09:02:38 New data from 192.168.1.228 : topic="rti/distlog" type="com::rti::dl::LogMessage"
hostAndAppId:
rtps_host_id: 16867916
rtps_app_id: 1940525435
level: 400
category: ""
message: "This is a warning message"
messageId: 1
[...]
```

To learn more about the *Distributed Logger*, refer to the Connext DDS
API online documentation. (Eg.
[Modern C++ Distributed Logger](https://community.rti.com/static/documentation/connext-dds/7.2.0/doc/api/connext_dds/distributed_logger/api_cpp2/index.html)).
48 changes: 48 additions & 0 deletions examples/connext_dds/distributed_logger/c++11/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
# (c) 2023 Copyright, Real-Time Innovations, Inc. All rights reserved.
#
# RTI grants Licensee a license to use, modify, compile, and create derivative
# works of the Software. Licensee has the right to distribute object form
# only for use with RTI products. The Software is provided "as is", with no
# warranty of any type, including any warranty for fitness for any purpose.
# RTI is under no obligation to maintain or support the Software. RTI shall
# not be liable for any incidental or consequential damages arising out of the
# use or inability to use the software.
#
cmake_minimum_required(VERSION 3.11)
project (DistLoggerExample)

# Find RTI Connext dependencies
list(APPEND CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/../../../../resources/cmake/Modules"
)
include(ConnextDdsConfigureCmakeUtils)
connextdds_configure_cmake_utils()

find_package(
RTIConnextDDS "7.2.0"
REQUIRED
COMPONENTS
core
distributed_logger
)

# Main application
add_executable(${PROJECT_NAME}
"${CMAKE_CURRENT_SOURCE_DIR}/DistLoggerExample.cxx"
)

target_link_libraries(${PROJECT_NAME}
PRIVATE
RTIConnextDDS::cpp2_api
RTIConnextDDS::distributed_logger_cpp2
)

target_include_directories(${PROJECT_NAME}
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CONNEXTDDS_INCLUDE_DIRS}"
)

set_target_properties(${PROJECT_NAME}
PROPERTIES CXX_STANDARD 11)
105 changes: 105 additions & 0 deletions examples/connext_dds/distributed_logger/c++11/DistLoggerExample.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//
// (c) 2023 Copyright, Real-Time Innovations, Inc. All rights reserved.
//
// RTI grants Licensee a license to use, modify, compile, and create derivative
// works of the Software. Licensee has the right to distribute object form
// only for use with RTI products. The Software is provided "as is", with no
// warranty of any type, including any warranty for fitness for any purpose.
// RTI is under no obligation to maintain or support the Software. RTI shall
// not be liable for any incidental or consequential damages arising out of the
// use or inability to use the software.
//

#include <iostream>

#include <rti/util/util.hpp> // for rti::util::sleep()
#include <rti/distlogger/DistLogger.hpp>

using namespace std;
using namespace dds::domain;
using namespace rti::dist_logger;


void distlogger_example_main(
const string application_kind,
const int domain_id,
const int sleep,
const uint iterations)
{
// First, create the options to personalize Distributed Logger.
// If no options are provided, default ones will be created.
DistLoggerOptions options;
options.domain_id(domain_id);
options.application_kind(application_kind);

// Then, set the created options.
// You can only call set_options before getting the Distributed Logger
// instance. Once an instance has been created, attempting to call
// set_options will throw an exception.
DistLogger::set_options(options);

// Instantiate Distributed Logger
DistLogger dist_logger = DistLogger::get_instance();

// RTI Distributed Logger provides the ability to interact with its
// topics directly. However, for the sake of simplicity in this example,
// you may use RTI Tools such as RTI Spy or RTI Admin Console to visualize
// the logging.
for (uint i = 1; i <= iterations; ++i) {
cout << "\nIteration #" << i << endl;

// Log messages using the appropiate log levels for your messages.
dist_logger.debug("This is a debug message");
dist_logger.warning("This is a warning message");
dist_logger.error("This is an error message");

rti::util::sleep(dds::core::Duration(sleep));
}

// The DistLogger instance must be finalized for clean-up
// before the the participant factory is finalized.
DistLogger::finalize();
}


int main(int argc, char *argv[])
{
const string application = "Modern C++ Distributed Logger Example";

int domain_id = 0;
int sleep = 1;
uint iterations = 50;

for (int i = 1; i < argc;) {
const string &param = argv[i++];

if ((param == "-d" || param == "--domain_id") && i < argc) {
domain_id = atoi(argv[i++]);
} else if ((param == "-i" || param == "--iterations") && i < argc) {
iterations = atoi(argv[i++]);
} else if ((param == "-s" || param == "--sleep") && i < argc) {
sleep = atoi(argv[i++]);
} else {
cout << argv[0] << " [options]\n"
<< "\t-d, --domain_id <domain ID> (default: 0)\n"
<< "\t-s, --sleep <seconds between iterations> (default: 1)\n"
<< "\t-i, --iterations <number of iterations> (default: 50)\n"
<< "\t-h, --help Display this message.\n"
<< endl;
return -1;
}
}

try {
distlogger_example_main(application, domain_id, sleep, iterations);

// Finalize Domain Participant Factory
dds::domain::DomainParticipant::finalize_participant_factory();
} catch (const exception &ex) {
// This will catch DDS exceptions
cerr << "Exception in distlogger_example_main: " << ex.what() << endl;
return -1;
}

return 0;
}
172 changes: 172 additions & 0 deletions examples/connext_dds/distributed_logger/c++11/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Example Code: Modern C++ Distributed Logger Application

## Example Structure

The following files are part of the example:

- `DistLoggerExample.cxx`
- `distlogSupport.h`

> **Note**:
>
> The `distlogSupport.h` header is necessary to use Modern C++ Distributed
> Logger in RTI Connextdds 7.2.0.
>
> **Note**:
>
> The `CMakeLists.txt` file in this example uses the latest version
> of `FindRTIConnextDDS.cmake` from the
> [cmake-utils](https://github.com/rticommunity/rticonnextdds-cmake-utils)
> repository to find the Modern C++ Distributed Logger libraries.
> If you are using RTI Connext 7.2.0, you may want to use a newer version from
> that repository as well.
## Building the Example

In order to build this example, you need to define the variable `CONNEXTDDS_DIR`
You can do so by exporting it manually, by sourcing the `rtisetenv` script for
your architecture, or by passing it to the `cmake` command as arguments:

```sh
mkdir build
cd build
cmake -DCONNEXTDDS_DIR=<Connext DDS Directory> \ # If not exported
-DBUILD_SHARED_LIBS=ON|OFF \
-DCMAKE_BUILD_TYPE=Debug|Release ..
cmake --build .
```

> **Note**:
>
> You do not need to define `CONNEXTDDS_ARCH` if you only have one architecture
> target installed in your system.
>
> **Note**:
>
> When using a multi-configuration generator, make sure you specify
> the `--config` parameter in your call to `cmake --build .`. In general,
> it's a good practice to always provide it.
This will produce a binary directory (*build*) where the application
can be found.

> **Note:**
>
> When you need to cross-compile the example, the above
> command will not work, the assigned compiler won't be the cross-compiler and
> errors may happen when linking against the cross-compiled Connext binaries. To
> fix this, you have to create a file with the architecture name and call CMake
> with a specific flag called `-DCMAKE_TOOLCHAIN_FILE`. An example of the file to
> create with the toolchain settings (e.g. for an ARM architectures):
```cmake
set(CMAKE_SYSTEM_NAME Linux)
set(toolchain_path "<path to>/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian")
set(CMAKE_C_COMPILER "${toolchain_path}/bin/arm-linux-gnueabihf-gcc")
set(CMAKE_CXX_COMPILER "${toolchain_path}/bin/arm-linux-gnueabihf-g++")
```

Then you can call CMake like this:

```sh
cmake -DCONNEXTDDS_DIR=<connext dir> \
-DCMAKE_TOOLCHAIN_FILE=<toolchain file created above> \
-DCONNEXTDDS_ARCH=<connext architecture> ..
```

## Running the Example

### Example Application

Run the application in a terminal as follows:

On *Windows* systems run:

```sh
DistLoggerExample.exe [options]
```

On *UNIX* systems run:

```sh
./DistLoggerExample [options]
```

where the options are:

- `-d, --domain`: Domain ID.

**Default**: 0.

- `-s, --sleep`: Number of seconds to sleep between iterations.

**Default**: 1.

- `-i, --iterations`: Number of logging iterations.

**Default**: 50.

- `-h, --help`: Displays application usage and exits.

You should see the messages that are being logged on each iteration printed
on the terminal.

### Visualizing the log messages

Once the example application is running, open RTI Spy or
RTI Admin Console.
You should be able to visualize the logging messages being sent
by the application.

To learn more about RTI Tools, refer to their section in the
[Connext DDS documentation](https://community.rti.com/documentation).

## Customizing the Build

### Configuring Build Type and Generator

By default, CMake will generate build files using the most common generator for
your host platform (e.g., Makefiles on Unix-like systems and Visual Studio
Solutions on Windows). You can use the following CMake variables to modify the
default behavior:

- `-DCMAKE_BUILD_TYPE` - specifies the build mode. Valid values are `Release`
and `Debug`. See the [CMake documentation for more details
(Optional)](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html).

- `-DBUILD_SHARED_LIBS` - specifies the link mode. Valid values are `ON` for
dynamic linking and `OFF` for static linking. See [CMake documentation for
more details
(Optional)](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html).

- `-G` - CMake generator. The generator is the native build system used to
build the source code. All the valid values are described in the CMake
documentation for [CMake
Generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).

For example, to build an example in Debug/Dynamic mode run CMake as follows:

```sh
cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON .. -G "Visual Studio 15 2017" -A x64
```

### Configuring Connext Installation Path and Architecture

The CMake build infrastructure will try to guess the location of your Connext
installation and the Connext architecture based on the default settings
for your host platform. If you installed Connext in a custom location, you
can use the `CONNEXTDDS_DIR` variable to indicate the path to your RTI Connext
installation folder. For example:

```sh
cmake -DCONNEXTDDS_DIR=/home/rti/rti_connext_dds-x.y.z ..
```

Also, if you installed libraries for multiple target architectures on your system
(i.e., you installed more than one target `.rtipkg` file), you can use the
`CONNEXTDDS_ARCH` variable to indicate the architecture of the specific libraries
you want to link against. For example:

```sh
cmake -DCONNEXTDDS_ARCH=x64Linux3gcc5.4.0 ..
```
Loading

0 comments on commit fe09cf3

Please sign in to comment.