7.1. Hello World

Important

|fa-windows| This tutorial will only work with eCAL 5.7.3 and upwards. It will not work with older versions that were published as .msi installer (it missed some libraries).

Please switch to Ubuntu, if you are using an old eCAL Version.

After you have learned a lot about the pre-compiled applications that come with eCAL, let’s create our own! In the good habit of every tutorial, we will write a Hello World Application, that sends the string “Hello World” to an eCAL topic.

eCAL uses CMake as a cross-platform build toolchain. We will explain the CMake commands needed for the tutorial, but not extensively dive into CMake.

7.1.1. Dependencies

First, you have to install some more development dependencies:

7.1.2. Hello World Publisher

Somewhere on your hard drive create an empty directory and create a file CMakeLists.txt and main.cpp with the following content:

  • |fa-file-alt| CMakeLists.txt:

     1cmake_minimum_required(VERSION 3.0)
     2set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
     3
     4project(hello_world_snd)
     5
     6set(CMAKE_CXX_STANDARD 14)
     7set(CMAKE_CXX_STANDARD_REQUIRED ON)
     8
     9find_package(eCAL REQUIRED)
    10
    11set(source_files
    12  main.cpp
    13)
    14
    15add_executable(${PROJECT_NAME} ${source_files})
    16
    17target_link_libraries(${PROJECT_NAME}
    18  eCAL::core
    19)
    

    Note

    What is happening here?

    Line 2 makes CMake prefer installed config files instead of generic find scripts. This is important for Windows, where eCAL installs Protobuf, HDF5 etc.

    Line 4 creates a project “hello_world_snd”. This will also be the name of the executable (line 15).

    Line 6-7 set the C++ standard to C++14

    Line 9 tells CMake to find the eCAL installation. Line 17-19 will link the executable against it.

    Line 11-13 create a list of all our source files, which currently only contains main.cpp. We add that source file for compiling our executable in line 15.

    Line 17-19 link our executable against the eCAL core library.

  • |fa-file-alt| main.cpp:

     1#include <ecal/ecal.h>
     2#include <ecal/msg/string/publisher.h>
     3
     4#include <iostream>
     5#include <thread>
     6
     7int main(int argc, char** argv)
     8{
     9  // Initialize eCAL. The name of our Process will be "Hello World Publisher"
    10  eCAL::Initialize(argc, argv, "Hello World Publisher");
    11
    12  // Create a String Publisher that publishes on the topic "hello_world_topic"
    13  eCAL::string::CPublisher<std::string> publisher("hello_world_topic");
    14
    15  // Create a counter, so something changes in our message
    16  int counter = 0;
    17
    18  // Infinite loop (using eCAL::Ok() will enable us to gracefully shutdown the
    19  // Process from another application)
    20  while (eCAL::Ok())
    21  {
    22    // Create a message with a counter an publish it to the topic
    23    std::string message = "Hello World " + std::to_string(++counter);
    24    std::cout << "Sending message: " << message << std::endl;
    25    publisher.Send(message);
    26
    27    // Sleep 500 ms
    28    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    29  }
    30
    31  // finalize eCAL API
    32  eCAL::Finalize();
    33}
    

    Note

    What is happening here?

    Line 1 includes the basic eCAL header. As we want to publish raw strings, line 2 includes the eCAL String-Publisher. eCAL Supports multiple message formats.

    Line 10 initialized eCAL. You always have to initialize eCAL before using its API. The name of our eCAL Process will be “Hello World Publisher”. This name will be visible in the eCAL Monitor, once the Process is running.

    Line 13 creates an eCAL Publisher. An eCAL Process can create multiple publishers (and multiple subscribers). The topic we are publishing on will be “hello_world_topic”.

    The while loop from line 20 will cause an infinite publish-loop. eCAL supports a stop-signal; when an eCAL Process is stopped, eCAL::Ok() will return false.

    Line 25 will publish our message and send it to other eCAL Processes that have subscribed on the topic.

    Line 32 de-initializes eCAL. You should always do that before your application exits.

Now that you have the source code ready, create a _build directory and build the code!

  • |fa-windows| Windows:

    mkdir _build
    cd _build
    cmake .. -A x64
    cmake --build . --parallel
    
  • |fa-ubuntu| Ubuntu:

    mkdir _build
    cd _build
    cmake ..
    make
    

Now execute the hello_world_snd (.exe) and take a look at the eCAL Monitor! You will see the “Hello World Publisher” process and the “hello_world_topic”.

eCAL Monitor Hello World

7.1.3. Hello World Subscriber

Again, create a new directory somewhere and add create the CMakeLists.txt and main.cpp with the following content:

  • |fa-file-alt| CMakeLists.txt:

     1cmake_minimum_required(VERSION 3.0)
     2set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
     3
     4project(hello_world_rec)
     5
     6set(CMAKE_CXX_STANDARD 14)
     7set(CMAKE_CXX_STANDARD_REQUIRED ON)
     8
     9find_package(eCAL REQUIRED)
    10
    11set(source_files
    12  main.cpp
    13)
    14
    15add_executable(${PROJECT_NAME} ${source_files})
    16
    17target_link_libraries(${PROJECT_NAME}
    18  eCAL::core
    19)
    

    Note

    What is happening here?

    Line 4 creates a project “hello_world_rec”. This is the only difference to the hello_world_snd Project.

  • |fa-file-alt| main.cpp:

     1#include <ecal/ecal.h>
     2#include <ecal/msg/string/subscriber.h>
     3
     4#include <iostream>
     5#include <thread>
     6
     7// Callback for receiving messages
     8void HelloWorldCallback(const std::string& message)
     9{
    10  std::cout << "Received Message: " << message << std::endl;
    11}
    12
    13int main(int argc, char** argv)
    14{
    15  // Initialize eCAL
    16  eCAL::Initialize(argc, argv, "Hello World Subscriber");
    17
    18  // Create a subscriber that listenes on the "hello_world_topic"
    19  eCAL::string::CSubscriber<std::string> subscriber("hello_world_topic");
    20
    21  // Set the Callback
    22  subscriber.AddReceiveCallback(std::bind(&HelloWorldCallback, std::placeholders::_2));
    23
    24  // Just don't exit
    25  while (eCAL::Ok())
    26  {
    27    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    28  }
    29
    30  // finalize eCAL API
    31  eCAL::Finalize();
    32}
    

    Note

    What is happening here?

    Line 8-11 Is the receive callback. This method will be called whenever a new message arrives.

    Line 19 creates an eCAL subscriber that listens to the “hello_world_topic”.

    Line 22 adds the receive callback from above to the subscriber, so it can be called.

    Important

    eCAL Receive callbacks run in the subscriber’s receive thread. While the callback is running, the subscriber cannot receive new data. So, if your callback needs really long to compute, you may have to decouple your computations to not lose messages.

Now that you have the source code ready, create a _build directory and build the code!

  • |fa-windows| Windows:

    mkdir _build
    cd _build
    cmake .. -A x64
    cmake --build . --parallel
    
  • |fa-ubuntu| Ubuntu:

    mkdir _build
    cd _build
    cmake ..
    make
    

When you now execute hello_world_snd and hello_world_rec, the receiver application will receive the messages sent by the sender.

eCAL Hello World sender and receiver

In the next chapter you will learn how to properly structure your messages with protobuf!

7.1.4. Files

|fa-folder-open|
├─ |fa-folder-open| hello_world_snd
│  ├─ |fa-file-alt| CMakeLists.txt
│  └─ |fa-file-alt| main.cpp
│
└─ |fa-folder-open| hello_world_rec
   ├─ |fa-file-alt| CMakeLists.txt
   └─ |fa-file-alt| main.cpp