.. _getting_started: Getting Started =============== The "Getting Started" section of this documentation serves as a comprehensive guide to assist in creating a basic publication/subscription application using Safe DDS. By following the step-by-step instructions provided, it is possible to quickly establish a functional example of Safe DDS and gain a better understanding of the library. .. _getting_started_requirements: It is important to note that in order to successfully install and run Safe DDS, certain minimum requirements must be met. These requirements are outlined in the :ref:`installation_minimum_requirements` section, which should be referred prior to installation. .. note:: This example is ready to be compatible with `Fast DDS Hello World example `__. .. note:: To obtain a copy of Safe DDS library please contact `support@eProsima.com `__. .. admonition:: Download Code Try this example by downloading the code from :download:`this CMake project <../code/zip/getting_started.zip>`. Build and install library ------------------------- To build and install Safe DDS, the standard CMake procedure is employed, as follows: .. literalinclude:: ../code/build_documentation_code.sh :language: bash :start-after: # INSTALLATION_CMAKE_COMMAND :end-before: #! INSTALLATION_CMAKE_COMMAND Once the installation process is completed, the ``libsafedds.a`` file and an ``include`` directory can be found in the designated installation directory. .. _getting_started_create_project: Create a CMake project ---------------------- To get started with Safe DDS, the first step is to create a CMake project with a folder structure as shown below: .. code-block:: bash safe_hello_world ├── CMakeLists.txt └── src └── main.cpp After the project structure folder has been created, a minimal version of the ``CMakeLists.txt`` file can be generated as follows: .. code-block:: bash mkdir safe_hello_world cd safe_hello_world touch CMakeLists.txt The ``CMakeLists.txt`` file is a crucial component, as it contains the build instructions for the project. The following example ``CMakeLists.txt`` file is provided to assist in properly configuring the project's build infrastructure: .. literalinclude:: ../code/getting_started/CMakeLists.txt :language: cmake :start-after: # GETTING_STARTED_CMAKE_EXAMPLE :end-before: #! GETTING_STARTED_CMAKE_EXAMPLE .. _getting_started_application: Safe DDS application -------------------- After the project folder and ``CMakeLists.txt`` file have been set up, the next step is to create a ``main.cpp`` file that will contain the application's source code: .. code-block:: bash mkdir src cd src touch main.cpp To further illustrate the usage of Safe DDS, a simple application that publishes a ``HelloWorld`` message on a ``HelloWorldTopic`` topic is presented. To achieve this, the application requires both the **DDS headers** and a **type support**. The specifics of typesupport are be covered in the upcoming :ref:`getting_started_typesupport` section. .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_INCLUDE_BLOCK :end-before: //! GETTING_STARTED_INCLUDE_BLOCK DomainParticipant ^^^^^^^^^^^^^^^^^ To create a DDS :ref:`dds_layers_domain_participant` for the application, a :ref:`dds_layers_domain_participant_factory` is used: .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_CREATE_DOMAINPARTICIPANT :end-before: //! GETTING_STARTED_CREATE_DOMAINPARTICIPANT :dedent: 4 .. _getting_started_typesupport: TypeSupport ^^^^^^^^^^^ Once the Domain Participant has been created, the next step is to register the Type Support. More information on how to handle Type Supports in Safe DDS can be found in :ref:`typesupport`. .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_REGISTER_TYPE :end-before: //! GETTING_STARTED_REGISTER_TYPE :dedent: 4 .. note:: For this particular application, the used Type Support class is the one provided as reference in :ref:`typesupport section ` Publication entities ^^^^^^^^^^^^^^^^^^^^ After the Type Support has been registered, the next step is to create a DDS :ref:`dds_layers_topic`, :ref:`dds_layers_publication_publisher`, and :ref:`dds_layers_publication_datawriter`, as demonstrated below: .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_CREATE_PUBLISHER :end-before: //! GETTING_STARTED_CREATE_PUBLISHER :dedent: 4 Creating the DDS :ref:`dds_layers_topic` involves specifying the name of the topic and the name of the type that it uses. Once the :ref:`dds_layers_topic` is created, a DDS :ref:`dds_layers_publication_publisher` is created, and finally, a DDS :ref:`dds_layers_publication_datawriter` is created, which is used to write messages to the topic. Subscription entities ^^^^^^^^^^^^^^^^^^^^^ Before a DDS :ref:`dds_layers_subscription_datareader` is created, an optional :ref:`dds_layers_subscription_datareaderlistener` class is implemented. This class will be notified when a new message is received. An example implementation ``HelloWorldListener`` is shown below: .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_DATAREADERLISTENER :end-before: //! GETTING_STARTED_DATAREADERLISTENER Once the Listener class has been implemented, a :ref:`dds_layers_subscription_subscriber` and a DDS :ref:`dds_layers_subscription_datareader` can be created using the previously created DDS :ref:`dds_layers_topic` as demonstrated below: .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_CREATE_SUBSCRIBER :end-before: //! GETTING_STARTED_CREATE_SUBSCRIBER :dedent: 4 Creating the DDS :ref:`dds_layers_subscription_datareader` involves specifying the required :ref:`dds_layers_topic`, as well as the previously created Listener. Once the :ref:`dds_layers_subscription_datareader` has been created, it can be used to read messages from the topic. Enabling entities ^^^^^^^^^^^^^^^^^ Once all entities have been created, they need :ref:`to be enabled ` in order to start processing messages. .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_ENABLING_ENTITIES :end-before: //! GETTING_STARTED_ENABLING_ENTITIES :dedent: 4 Publishing ^^^^^^^^^^ To enable periodic publication of messages, a Safe DDS Timer can be used to trigger a publication at regular intervals. The ``publish`` function is responsible for creating a message and writing it to the DDS DataWriter, as shown below: .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_PUBLISHING_TIMER :end-before: //! GETTING_STARTED_PUBLISHING_TIMER :dedent: 4 Note that the message is created using the Type Support class and filled with the desired data. Once the message is created, it is written into the a type aware DDS DataWriter named :ref:`TypedDataWriter `, which will publish it to the topic. Spinning entities ^^^^^^^^^^^^^^^^^ Once the DDS entities have been created and the timer has been set up, they need to be spun in order to start processing messages. Spinning refers to the process of dispatching DDS events, such as incoming messages, timeouts, and status changes, to the appropriate DDS entities. The easiest way to spin the DDS entities is using the default executor provided by the DDS DomainParticipantFactory, as shown below: .. literalinclude:: ../code/getting_started/src/main.cpp :language: c++ :start-after: // GETTING_STARTED_SPINNING_ENTITIES :end-before: //! GETTING_STARTED_SPINNING_ENTITIES :dedent: 4 This creates an executor that will internally dispatch events to the appropriate DDS entities, such as the :ref:`dds_layers_subscription_datareader` and :ref:`dds_layers_publication_datawriter`. More information about Safe DDS execution can be found at :ref:`architecture_execution` section. By spinning the DDS entities, the application is now able to publish messages at regular intervals. The DDS :ref:`dds_layers_subscription_datareader` created will receive the messages from local and remote DDS DomainParticipants and will notify the ``HelloWorldListener`` class when a new message is received. Running the application ----------------------- To run the application, first navigate to the project directory, create a build folder (``GETTING_STARTED_FOLDER``` on the example) and generate the build files with CMake. .. literalinclude:: ../code/build_documentation_code.sh :language: bash :start-after: # INSTALLATION_CMAKE_GETTING_STARTED :end-before: #! INSTALLATION_CMAKE_GETTING_STARTED :dedent: 4 This command will configure the project with the default settings, including the path to the Safe DDS library, and it will then build the application. Once the build is complete, the application can be run by executing the binary file from the build directory: .. code-block:: bash ./safedds_getting_started If the application is successfully connected to the network and running, the console output should show messages similar to the following: .. code-block:: bash [DW: 0] Message: Hello World 0 with index: 0 [DW: 0] Message: Hello World 1 with index: 1 [DW: 0] Message: Hello World 2 with index: 2 [DW: 0] Message: Hello World 3 with index: 3 [DW: 0] Message: Hello World 4 with index: 4 [DW: 0] Message: Hello World 5 with index: 5 [DW: 16777216] Message: HelloWorld with index: 2 [DW: 16777216] Message: HelloWorld with index: 3 [DW: 16777216] Message: HelloWorld with index: 4 [DW: 16777216] Message: HelloWorld with index: 5 [DW: 16777216] Message: HelloWorld with index: 6 [DW: 16777216] Message: HelloWorld with index: 7 [DW: 16777216] Message: HelloWorld with index: 8 [DW: 16777216] Message: HelloWorld with index: 9 [DW: 0] Message: Hello World 6 with index: 6 [DW: 16777216] Message: HelloWorld with index: 10 [DW: 0] Message: Hello World 7 with index: 7 [DW: 0] Message: Hello World 8 with index: 8 [DW: 0] Message: Hello World 9 with index: 9 The program will continue to publish messages every second until it is manually stopped. Further reading --------------- An example on how to integrate **Safe DDS with ROS 2** can be found in the :ref:`getting_started_ros2` section. An example on how to create a **Safe DDS** application with static memory management :ref:`getting_started_static_api` section. .. toctree:: :maxdepth: 1 :hidden: ./getting_started_ros2 ./getting_started_static_api