7.1.1. String: Hello World#
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. The second part will be all about the subscriber, which will receive the message and print it to the console.
You will see how it is done in the major programming languages we support: C++, C, C# and Python.
For CMake usage tips, please refer to the CMake section of this documentation.
7.1.1.1. Hello World Publisher#
Let’s begin with the publisher side of our “Hello World” application.
The base initialization of the eCAL publisher is the same in all languages:
Before you do anything else, you need to initialize eCAL with
Initialize(..)
.Then you create the publisher and send a message in the frequency you want. In our example we will send the message every 500 ms in an infinite loop. You can add a stop condition to the loop, if you want to send just a limited amount of messages.
After you are done with publishing data and you don’t need eCAL anymore, you can call the
Finalize()
function to clean up the resources and unregister the process.
For simplicity, we will use the same message type in all languages. As this is simple string message, we will use the eCAL string publisher to send.
1// Include the basic eCAL header
2#include <ecal/ecal.h>
3/*
4 We want to publish raw strings, so wie include the string publisher header.
5 eCAL supports multiple message formats.
6*/
7#include <ecal/msg/string/publisher.h>
8
9#include <iostream>
10#include <sstream>
11
12int main()
13{
14 std::cout << "--------------------------" << std::endl;
15 std::cout << " C++: HELLO WORLD SENDER" << std::endl;
16 std::cout << "--------------------------" << std::endl;
17
18 /*
19 Initialize eCAL. You always have to initialize eCAL before using its API.
20 The name of our eCAL Process will be "hello send".
21 This name will be visible in the eCAL Monitor, once the process is running.
22 */
23 eCAL::Initialize("hello send");
24
25 /*
26 Print some eCAL version information.
27 */
28 std::cout << "eCAL " << eCAL::GetVersionString() << " (" << eCAL::GetVersionDateString() << ")" << "\n";
29
30 /*
31 Set the state for the program.
32 You can vary between different states like healthy, warning, critical ...
33 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
34 */
35 eCAL::Process::SetState(eCAL::Process::eSeverity::healthy, eCAL::Process::eSeverityLevel::level1, "I feel good!");
36
37 /*
38 Creating the eCAL Publisher. An eCAL Process can create multiple publishers (and subscribers).
39 The topic we are going to publish is called "hello".
40 */
41 eCAL::string::CPublisher publisher("hello");
42
43 /*
44 Creating an inifite publish-loop.
45 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
46 */
47 int loop_count = 0;
48 while (eCAL::Ok())
49 {
50 /*
51 Build the string you want to send, using a stringstream in this example.
52 */
53 std::stringstream message;
54 message << "HELLO WORLD FROM C++" << " (" << ++loop_count << ")";
55
56 /*
57 Send the content to other eCAL Processes that have subscribed to the topic "hello".
58 */
59 if(publisher.Send(message.str()))
60 std::cout << "Sent string message in C++ \"" << message.str() << "\"" << "\n";
61 else
62 std::cout << "Sending string message in C++ failed!" << "\n";
63
64 /*
65 Sleep for 500 ms so we send with a frequency of 2 Hz.
66 */
67 eCAL::Process::SleepMS(500);
68 }
69
70 /*
71 Deinitialize eCAL.
72 You should always do that before your application exits.
73 */
74 eCAL::Finalize();
75
76 return(0);
77}
1// Include the basic eCAL header
2#include <ecal_c/ecal.h>
3
4#include <stdio.h>
5#include <string.h>
6#include <stdlib.h>
7
8int main()
9{
10 printf("-------------------------------\n");
11 printf(" C: HELLO WORLD SENDER\n");
12 printf("-------------------------------\n");
13
14 /*
15 We create the objects we want to work with.
16 In this case we need a publisher handle and a data type information structure.
17 Additionally we need a string buffer to hold the content we want to send.
18 */
19 eCAL_Publisher* publisher;
20 struct eCAL_SDataTypeInformation data_type_information;
21 char message[256];
22 int loop_count = 0;
23
24 /*
25 Initialize eCAL. You always have to initialize eCAL before using its API.
26 The name of our eCAL Process will be "hello send c".
27 This name will be visible in the eCAL Monitor, once the process is running.
28 */
29 eCAL_Initialize("hello send c", NULL, NULL);
30
31 /*
32 Print some eCAL version information.
33 */
34 printf("eCAL %s (%s)", eCAL_GetVersionString(), eCAL_GetVersionDateString());
35
36 /*
37 Set the state for the program.
38 You can vary between different states like healthy, warning, critical ...
39 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
40 */
41 eCAL_Process_SetState(eCAL_Process_eSeverity_healthy, eCAL_Process_eSeverityLevel_level1, "I feel good!");
42
43 /*
44 We set all data in eCAL_SDataTypeInformation to zero.
45 We want to publish raw strings, so we set the name of the data type information
46 to "string" and the encoding to "utf-8".
47 */
48 memset(&data_type_information, 0, sizeof(struct eCAL_SDataTypeInformation));
49 data_type_information.name = "string";
50 data_type_information.encoding = "utf-8";
51
52 /*
53 Now we create a new publisher that will publish the topic "hello".
54 Furthermore we set the data type information of the publisher.
55 The two additional parameters that could be set (eCAL_PubEventCallbackT and eCAL_Publisher_Configuration)
56 are set to NULL, because for this example we are fine with the default settings.
57 */
58 publisher = eCAL_Publisher_New("hello", &data_type_information, NULL, NULL);
59
60 /*
61 Creating an infinite publish-loop.
62 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL_Ok() will return false.
63 */
64 while(eCAL_Ok())
65 {
66 /*
67 Build the string you want to send, using snprintf in this example.
68 The string will be "HELLO WORLD FROM C (1)", "HELLO WORLD FROM C (2)", ...
69 */
70 snprintf(message, sizeof(message), "HELLO WORLD FROM C (%d)", ++loop_count);
71
72 /*
73 Send the content to other eCAL Processes that have subscribed to the topic "hello".
74 eCAL transports messages as a byte array and length, so for interop with other languages,
75 we will send a non-null terminated strings over the wire.
76 */
77 if(!eCAL_Publisher_Send(publisher, message, strlen(message), NULL))
78 printf("Sent string message in C: \"%s\"\n", message);
79 else
80 printf("Sending string message in C failed!\n");
81
82 /*
83 Sleep for 500 ms so we send with a frequency of 2 Hz.
84 */
85 eCAL_Process_SleepMS(500);
86 }
87
88 /*
89 Now we delete the publisher handle. This is important to free resources.
90 All objects that are created with eCAL_xxx_New() have to be deleted with eCAL_xxx_Delete().
91 */
92 eCAL_Publisher_Delete(publisher);
93
94
95 /*
96 Deinitialize eCAL.
97 You should always do that before your application exits.
98 */
99 eCAL_Finalize();
100
101 return(0);
102}
1using System;
2using System.Threading;
3// Include the eCAL API namespace
4using Eclipse.eCAL.Core;
5
6public class HelloSend
7{
8 public static void Main()
9 {
10 Console.WriteLine("------------------------");
11 Console.WriteLine(" C#: HELLO WORLD SENDER");
12 Console.WriteLine("------------------------");
13
14 /*
15 Initialize eCAL. You always have to initialize eCAL before using its API.
16 The name of our eCAL Process will be "hello send c#".
17 This name will be visible in the eCAL Monitor, once the process is running.
18 */
19 Core.Initialize("hello send c#");
20
21 /*
22 Print eCAL version information.
23 */
24 Console.WriteLine(String.Format("eCAL {0} ({1})\n", Core.GetVersionString(), Core.GetVersionDateString()));
25
26 /*
27 Set the state for the program.
28 You can vary between different states like healthy, warning, critical ...
29 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
30 */
31 Process.SetState(eProcessSeverity.Healthy, eProcessSeverityLevel.Level1, "I feel good!");
32
33 /*
34 Now we create a new publisher that will publish the topic "hello".
35 */
36 StringPublisher publisher = new StringPublisher("hello");
37
38 /*
39 Creating an infinite publish-loop.
40 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL_Ok() will return false.
41 */
42 int loop_count = 0;
43 while (Core.Ok())
44 {
45 /*
46 Construct a message. The message is a string that will be sent to the subscribers.
47 */
48 string message = String.Format("HELLO WORLD FROM C# ({0})", ++loop_count);
49
50 /*
51 Send the message. The message is sent to all subscribers that are currently connected to the topic "hello".
52 */
53 if(publisher.Send(message))
54 Console.WriteLine(String.Format("Sent string message in C#: \"{0}\"", message));
55 else
56 Console.WriteLine("Sending string message in C# failed!");
57
58 /*
59 Sleep for 500ms to send in a frequency of 2 hz.
60 */
61 Thread.Sleep(500);
62 }
63
64 /*
65 Cleanup. Dispose the publisher to free resources.
66 */
67 publisher.Dispose();
68
69 /*
70 Terminate eCAL. This will stop all eCAL processes and free all resources.
71 You should always terminate eCAL when you are done using it.
72 */
73 Core.Terminate();
74 }
75}
1import sys
2import time
3# import the eCAL core API
4import ecal.core.core as ecal_core
5# import the eCAL publisher AP
6from ecal.core.publisher import StringPublisher
7
8def main():
9 print("-------------------------------")
10 print(" Python: HELLO WORLD SENDER")
11 print("-------------------------------")
12
13 # Initialize eCAL. You always have to initialize eCAL before using it.
14 # The name of our eCAL Process will be "hello send python".
15 # This name will be visible in the eCAL Monitor, once the process is running.
16 ecal_core.initialize("hello send python")
17
18 # Print used eCAL version and date
19 print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate()))
20
21 # Set the state for the program.
22 # You can vary between different states like healthy, warning, critical ...
23 # This can be used to communicate the application state to applications like eCAL Monitor/Sys.
24 ecal_core.set_process_state(1, 1, "I feel good!")
25
26 # Creating the eCAL Publisher. An eCAL Process can create multiple publishers (and subscribers).
27 # The topic we are going to publish is called "hello".
28 pub = StringPublisher("hello")
29
30 # We create a message to send that will be altered later to notice different messages.
31 msg = "HELLO WORLD FROM PYTHON"
32
33 loop_count = 0
34 # Creating an inifite publish-loop.
35 # eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
36 while ecal_core.ok():
37 # Prepare the string to send
38 loop_count = loop_count + 1
39 current_message = "{} {:6d}".format(msg, loop_count)
40
41 # Send the content to other eCAL Processes that have subscribed to the topic "hello".
42 pub.send(current_message)
43 print("Sending: {}".format(current_message))
44
45 # Sleep for 500 ms so we send with a frequency of 2 Hz.
46 time.sleep(0.5)
47
48 # Finalize eCAL.
49 # You should always do that before your application exits.
50 ecal_core.finalize()
51
52if __name__ == "__main__":
53 main()
7.1.1.2. Hello World Publisher Files#
Publisher samples ├─ C++ │ └─hello_send.cpp
│ ├─ C │ └─hello_send.c
│ ├─ C# │ └─hello_send_csharp.cs
│ └─ Python └─hello_send.py
7.1.1.3. Hello World Subscriber#
Now let’s have a look at the subscriber side. Basically, the initialization is the same as for the publisher. The only difference is that you need to assign a callback function to the subscriber:
Call
Initialize()
to initialize eCAL.Create the subscriber.
Assign a callback function to the subscriber with
SetReceiveCallback
.Do something to keep the process alive. In our example we will use a simple infinite loop. Process the incoming messages as you wish.
After you are done with receiving data and you don’t need eCAL anymore, you can call the
Finalize()
function to clean up the resources and unregister the process.
1// Include the basic eCAL header
2#include <ecal/ecal.h>
3/*
4 We want to receive raw strings, so wie include the string subscriber header.
5 eCAL supports multiple message formats.
6*/
7#include <ecal/msg/string/subscriber.h>
8
9#include <iostream>
10#include <sstream>
11#include <chrono>
12#include <thread>
13
14int main()
15{
16 std::cout << "----------------------------" << "\n";
17 std::cout << " C++: HELLO WORLD RECEIVER" << "\n";
18 std::cout << "----------------------------" << "\n";
19
20 /*
21 Initialize eCAL. You always have to initialize eCAL before using its API.
22 The name of our eCAL Process will be "hello receive".
23 This name will be visible in the eCAL Monitor, once the process is running.
24 */
25 eCAL::Initialize("hello receive");
26
27 /*
28 Print some eCAL version information.
29 */
30 std::cout << "eCAL " << eCAL::GetVersionString() << " (" << eCAL::GetVersionDateString() << ")" << "\n";
31
32 /*
33 Set the state for the program.
34 You can vary between different states like healthy, warning, critical ...
35 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
36 */
37 eCAL::Process::SetState(eCAL::Process::eSeverity::healthy, eCAL::Process::eSeverityLevel::level1, "I feel good!");
38
39 /*
40 Creating the eCAL Subscriber. An eCAL Process can create multiple subscribers (and publishers).
41 The topic we are going to receive is called "hello".
42 */
43 eCAL::string::CSubscriber subscriber("hello");
44
45 /*
46 Creating a receive callback. The callback will be called whenever a new message is received.
47 */
48 auto message_callback = [](const eCAL::STopicId& publisher_id_, const std::string& message_, long long time_, long long clock_) {
49 std::cout << "---------------------------------------------------" << "\n";
50 std::cout << " Received string message from topic \"" << publisher_id_.topic_name << "\" in C++ " << "\n";
51 std::cout << "---------------------------------------------------" << "\n";
52 std::cout << " Size : " << message_.size() << "\n";
53 std::cout << " Time : " << time_ << "\n";
54 std::cout << " Clock : " << clock_ << "\n";
55 std::cout << " Message : " << message_ << "\n";
56 std::cout << "\n";
57 };
58
59 /*
60 Register the callback with the subscriber so it can be called.
61 */
62 subscriber.SetReceiveCallback(message_callback);
63
64 /*
65 Creating an infinite loop.
66 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
67 */
68 while (eCAL::Ok())
69 {
70 /*
71 Sleep for 500ms to avoid busy waiting.
72 You can use eCAL::Process::SleepMS() to sleep in milliseconds.
73 */
74 eCAL::Process::SleepMS(500);
75 }
76
77 /*
78 Deinitialize eCAL.
79 You should always do that before your application exits.
80 */
81 eCAL::Finalize();
82
83 return(0);
84}
1// Include the basic eCAL header
2#include <ecal_c/ecal.h>
3
4#include <string.h> //memset()
5#include <stdio.h> //printf()
6
7
8/*
9 Here we create the receive callback function.
10 The function will be called whenever a new message is received.
11*/
12void OnReceive(const struct eCAL_STopicId* topic_id_, const struct eCAL_SDataTypeInformation* data_type_information_, const struct eCAL_SReceiveCallbackData* callback_data_, void* user_argument_)
13{
14 /*
15 These are unused arguments for this example.
16 You can use the data type information to check the data type of the received message.
17 The user argument can be used to work with user defined data when the callback is called.
18 */
19 (void)data_type_information_;
20 (void)user_argument_;
21
22 printf("---------------------------------------------------\n");
23 printf(" Received string message from topic \"%s\" in C\n", topic_id_->topic_name);
24 printf("---------------------------------------------------\n");
25 printf(" Size : %zu\n", callback_data_->buffer_size);
26 printf(" Time : %lld\n", callback_data_->send_timestamp);
27 printf(" Clock : %lld\n", callback_data_->send_clock);
28 printf(" Message : %.*s\n", (int)(callback_data_->buffer_size), (char*)(callback_data_->buffer));
29 printf("\n");
30}
31
32int main()
33{
34 printf("-------------------------------\n");
35 printf(" C: HELLO WORLD RECEIVER\n");
36 printf("-------------------------------\n");
37
38 /*
39 We create the objects we want to work with.
40 In this case we need a subscriber handle and a data type information structure.
41 */
42 eCAL_Subscriber *subscriber;
43 struct eCAL_SDataTypeInformation data_type_information;
44
45 /*
46 Initialize eCAL. You always have to initialize eCAL before using its API.
47 The name of our eCAL Process will be "hello receive c".
48 This name will be visible in the eCAL Monitor, once the process is running.
49 */
50 eCAL_Initialize("hello receive c", NULL, NULL);
51
52 /*
53 Print some eCAL version information.
54 */
55 printf("eCAL %s (%s)", eCAL_GetVersionString(), eCAL_GetVersionDateString());
56
57 /*
58 Set the state for the program.
59 You can vary between different states like healthy, warning, critical ...
60 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
61 */
62 eCAL_Process_SetState(eCAL_Process_eSeverity_healthy, eCAL_Process_eSeverityLevel_level1, "I feel good!");
63
64 /*
65 We set all data in eCAL_SDataTypeInformation to zero.
66 We want to receive raw strings, so we set the name of the data type information
67 to "string" and the encoding to "utf-8".
68 */
69 memset(&data_type_information, 0, sizeof(struct eCAL_SDataTypeInformation));
70 data_type_information.name = "string";
71 data_type_information.encoding = "utf-8";
72
73 /*
74 Now we create a new subscriber that will subscribe to the topic "hello".
75 Furthermore we set the data type information of the subscriber.
76 The two additional parameters that could be set (eCAL_SubEventCallbackT and eCAL_Subscriber_Configuration)
77 are set to NULL, because for this example we are fine with the default settings.
78 */
79 subscriber = eCAL_Subscriber_New("hello", &data_type_information, NULL, NULL);
80
81 /*
82 In order to receive message, we need to register a receive callback.
83 The callback will be called whenever a new message is received.
84 */
85 eCAL_Subscriber_SetReceiveCallback(subscriber, OnReceive, NULL);
86
87 /*
88 Creating an infinite loop.
89 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL_Ok() will return false.
90 */
91 while(eCAL_Ok())
92 {
93 /*
94 Sleep for 500ms to avoid busy waiting.
95 You can use eCAL_Process_SleepMS() to sleep in milliseconds.
96 */
97 eCAL_Process_SleepMS(500);
98 }
99
100 /*
101 Now we delete the subscriber handle. This is important to free resources.
102 All objects that are created with eCAL_xxx_New() have to be deleted with eCAL_xxx_Delete().
103 */
104 eCAL_Subscriber_Delete(subscriber);
105
106 /*
107 Deinitialize eCAL.
108 You should always do that before your application exits.
109 */
110 eCAL_Finalize();
111
112 return(0);
113}
1using System;
2// include ecal core namespace
3using Eclipse.eCAL.Core;
4
5public class HelloReceive
6{
7 public static void Main()
8 {
9 Console.WriteLine("--------------------------");
10 Console.WriteLine(" C#: HELLO WORLD RECEIVER");
11 Console.WriteLine("--------------------------");
12
13 /*
14 Initialize eCAL. You always have to initialize eCAL before using its API.
15 The name of our eCAL Process will be "hello receive c#".
16 This name will be visible in the eCAL Monitor, once the process is running.
17 */
18 Core.Initialize("hello receive c#");
19
20 /*
21 Print eCAL version information.
22 */
23 Console.WriteLine(String.Format("eCAL {0} ({1})\n", Core.GetVersionString(), Core.GetVersionDateString()));
24
25 /*
26 Set the state for the program.
27 You can vary between different states like healthy, warning, critical ...
28 This can be used to communicate the application state to applications like eCAL Monitor/Sys.
29 */
30 Process.SetState(eProcessSeverity.Healthy, eProcessSeverityLevel.Level1, "I feel good!");
31
32 /*
33 Creating the eCAL Subscriber. An eCAL Process can create multiple subscribers (and publishers).
34 The topic we are going to receive is called "hello".
35 */
36 StringSubscriber subscriber = new StringSubscriber("hello");
37
38 /*
39 Create and register a receive callback. The callback will be called whenever a new message is received.
40 */
41 subscriber.SetReceiveCallback((publisherId, dataTypeInfo, message) =>
42 {
43 Console.WriteLine("---------------------------------------------------");
44 Console.WriteLine(" Received string message from topic \"{0}\" in C#", publisherId.TopicName);
45 Console.WriteLine("---------------------------------------------------");
46 Console.WriteLine(" Size : n/a");
47 Console.WriteLine(" Time : n/a");
48 Console.WriteLine(" Clock : n/a");
49 Console.WriteLine(" Message : {0}", message);
50 Console.WriteLine("\n");
51 });
52
53 /*
54 Creating an infinite loop.
55 eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
56 */
57 while (Core.Ok())
58 {
59 /*
60 Sleep for 500ms to avoid busy waiting.
61 */
62 System.Threading.Thread.Sleep(500);
63 }
64
65 /*
66 Cleanup. Dispose the subscriber to free resources.
67 */
68 subscriber.Dispose();
69
70 /*
71 Terminate eCAL. This will stop all eCAL processes and free all resources.
72 You should always terminate eCAL before exiting your application.
73 */
74 Core.Terminate();
75 }
76}
1import sys
2import time
3# import the eCAL core API
4import ecal.core.core as ecal_core
5# import the eCAL subscriber API
6from ecal.core.subscriber import StringSubscriber
7
8# Create here the eCAL receive callback. This will be called whenever a new message is received.
9def callback(topic_name, msg, time):
10 print("Received: {} ms {}".format(time, msg))
11
12
13def main():
14 print("-------------------------------")
15 print(" Python: HELLO WORLD RECEIVER")
16 print("-------------------------------")
17
18 # Initialize eCAL. You always have to initialize eCAL before using it.
19 # The name of our eCAL Process will be "hello receive python".
20 # This name will be visible in the eCAL Monitor, once the process is running.
21 ecal_core.initialize("hello receive python")
22
23 # Print used eCAL version and date
24 print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate()))
25
26 # Set the state for the program.
27 # You can vary between different states like healthy, warning, critical ...
28 # This can be used to communicate the application state to applications like eCAL Monitor/Sys.
29 ecal_core.set_process_state(1, 1, "I feel good!")
30
31 # Creating the eCAL Subscriber. An eCAL Process can create multiple subscribers (and publishers).
32 # The topic we are going to receive is called "hello".
33 sub = StringSubscriber("hello")
34
35 # Register the callback with the subscriber so it can be called.
36 sub.set_callback(callback)
37
38 # Creating an infinite loop.
39 # eCAL Supports a stop signal; when an eCAL Process is stopped, eCAL::Ok() will return false.
40 while ecal_core.ok():
41 # Sleep for 500ms to avoid busy waiting.
42 # You can use eCAL::Process::SleepMS() to sleep in milliseconds.
43 time.sleep(0.5)
44
45 # Finalize eCAL.
46 # You should always do that before your application exits.
47 ecal_core.finalize()
48
49if __name__ == "__main__":
50 main()
51
7.1.1.4. Hello World Subscriber Files#
Subscriber samples ├─ C++ │ └─hello_receive.cpp
│ ├─ C │ └─hello_receive.c
│ ├─ C# │ └─hello_receive_csharp.cs
│ └─ Python └─hello_receive.py