• eCal 基础安装和使用


    参考文章:
    自动驾驶通信中间件ecal源码分析—1. 什么是ecal

    1、安装

    使用官网提供的指令安装

    主要参考官网进行安装, https://eclipse-ecal.github.io/ecal/index.html
    主要这里兼容的主要系统:
    Ubuntu 18.04
    Ubuntu 20.04
    Ubuntu 22.04
    这里我使用的是树莓派安装的ubuntu18.04
    使用官网提供的指令直接安装:

    sudo add-apt-repository ppa:ecal/ecal-latest
    sudo apt-get update
    sudo apt-get install ecal
    
    • 1
    • 2
    • 3

    安装完成后测试:

    在 Ubuntu 上从终端调用该应用程序定期将一些文本打印到终端。在后台,应用程序创建了一个主题人员并向其发送数据:

    ecal_sample_person_snd
    
    • 1

    接收部分:订阅者订阅了主题人员并将其接收的所有数据打印到终端:

    ecal_sample_person_rec
    
    • 1

    运行过程:
    在这里插入图片描述

    2、基础demo hello word

    (1)、事前准备:

    需要安装protobuf通信组件
    可以参考之前的文章:https://editor.csdn.net/md/?articleId=127388599
    这里按照官网的教程直接使用下面的指令进行安装即可:

    sudo apt install cmake g++ libprotobuf-dev protobuf-compiler
    
    • 1

    (2)、建立目录文件

    需要一个bulid文件夹,一个cmake文件和一个main文件:

    mkdir bulid
    touch main.cpp CMakelists.txt
    
    • 1
    • 2

    .
    ├── bulid/
    ├── CMakeLists.txt
    └── main.cpp
    在这里插入图片描述

    (3)、cmake:

    安装cmake:
    参考:https://editor.csdn.net/md/?articleId=126542158
    可以直接使用指令安装:

    sudo apt install cmake
    
    • 1
    sudo cmake --version
    
    • 1

    Cmakelists文件:

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

    (4)、测试cmake

    cd bulid
    cmake ..
    
    • 1
    • 2

    a、遇到cmake执行报错:
    在这里插入图片描述

    CMake Error at CMakeLists.txt:4 (project):
    No CMAKE_CXX_COMPILER could be found.

    CMAKE_CXX_COMPILER 没有找到;原因是没有安装gcc和g++编译环境。
    解决:

    sudo apt-get update
    sudo apt-get install -y build-essential
    
    • 1
    • 2

    安装上就行了。

    b、遇到Cmake问题报错2
    在这里插入图片描述

    CMake Error at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
    Could NOT find Protobuf (missing: Protobuf_LIBRARIES Protobuf_INCLUDE_DIR)
    Call Stack (most recent call first):
    /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
    /usr/share/cmake-3.22/Modules/FindProtobuf.cmake:650 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
    /usr/lib/aarch64-linux-gnu/cmake/eCAL/eCALConfig.cmake:67 (find_package)
    CMakeLists.txt:9 (find_package)

    这里是说没有找到protobuf,需要先进行安装

    sudo apt install cmake g++ libprotobuf-dev protobuf-compiler
    
    • 1

    安装完成后解决了。

    (5)、消息发布端main.cpp

    代买实现了一个ecal的发布器,按照延时发布消息。

    #include 
    #include 
    
    #include 
    #include 
    
    int main(int argc, char** argv)
    {
      // 初始化eCAL。我们的进程的名字是"Hello World Publisher"
      eCAL::Initialize(argc, argv, "Hello World Publisher");
    
      // 创建在主题“hello_world_topic”上发布的字符串发布器
      eCAL::string::CPublisher<std::string> publisher("hello_world_topic");
    
      // 创建一个计数器,这样我们的消息就会发生变化
      int counter = 0;
    
      // 无限循环(使用eCAL::Ok()将使我们能够从另一个应用程序优雅地关闭Process)
      while (eCAL::Ok())
      {
        // 创建带有计数器的消息并将其发布到主题
        std::string message = "Hello World " + std::to_string(++counter);
        std::cout << "Sending message: " << message << std::endl;
        publisher.Send(message);
    
        // Sleep 500 ms
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
      }
    
      // finalize eCAL API
      eCAL::Finalize();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    编写好main文件后:

    cd bulid
    cmake ..
    make
    ./hello_world_snd 
    
    • 1
    • 2
    • 3
    • 4

    应该问题不大,最后的结果:
    在这里插入图片描述
    官网对代码的解释:

    第 1 行包含基本的 eCAL 标头。 当我们要发布原始字符串时,第 2 行包含 eCAL 字符串发布服务器。 eCAL 支持多种消息格式。
    第 10 行初始化了 eCAL。 在使用 API 之前,始终必须初始化 eCAL。 我们的eCAL流程的名称将是“Hello World Publisher”。 进程运行后,此名称将在 eCAL 监视器中可见。
    第 13 行创建一个 eCAL 发布服务器。 eCAL 进程可以创建多个发布者(和多个订阅者)。 我们发布的主题将是“hello_world_topic”。
    从第 20 行开始的 while 循环将导致无限发布循环。 eCAL 支持停止信号;当 eCAL 进程停止时,将返回 false。eCAL::Ok()
    第 25 行将发布我们的消息并将其发送到已订阅该主题的其他 eCAL 进程。
    第 32 行取消初始化 eCAL。应始终在应用程序退出之前执行此操作。

    (6)、消息接收部分

    这里需要新建一个和上文消息发布的目录一致的另一个目录

    消息接收部分的cmake文件:

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

    消息接收部分的main代码:

    #include 
    #include 
    
    #include 
    #include 
    
    // 接收消息的回调函数
    void HelloWorldCallback(const std::string& message)
    {
      std::cout << "Received Message: " << message << std::endl;
    }
    
    int main(int argc, char** argv)
    {
      // 初始化eCAL
      eCAL::Initialize(argc, argv, "Hello World Subscriber");
    
      // 创建监听“hello_world_topic”的订阅者
      eCAL::string::CSubscriber<std::string> subscriber("hello_world_topic");
    
      // 设置回调
      subscriber.AddReceiveCallback(std::bind(&HelloWorldCallback, std::placeholders::_2));
    
      // Just don't exit
      while (eCAL::Ok())
      {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
      }
    
      // finalize eCAL API
      eCAL::Finalize();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    编译运行

    cd bulid
    cmake ..
    make
    
    • 1
    • 2
    • 3

    (7)、测试运行

    打开两个终端,先运行发布消息,然后另一个终端运行订阅程序:
    发布

    ./hello_world_snd
    
    • 1

    订阅

    ./hello_world_rec 
    
    • 1

    可以看到通信成功
    在这里插入图片描述

    3、eCal 发布订阅 protobuf

    使用字符串非常适合具有文本表示形式的简单数据。 但是数据通常会更加复杂,因此需要某种协议来定义数据的结构。
    使用Google protobuf,因为:
    它解决了如何为您序列化和反序列化数据的问题
    您可以获得开箱即用的向下兼容性(如果您遵循指南)
    它由谷歌维护,API稳定
    eCAL监视器可以显示数据的良好反射视图

    新建一个文件目录:

    mkdir protobuf_rec protobuf_snd proto_messages
    
    • 1

    在这里插入图片描述

    首先需要先制作一个protobuf文件,打开 proto_messages/hello_world.proto

    syntax = "proto3";
    
    package proto_messages;
    
    message HelloWorld
    {
      string name      = 1;
      uint32 id        = 2;
      string msg       = 3;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (1)、数据发送端

    cmake文件

    cmake_minimum_required(VERSION 3.0)
    set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) # 如果未指定任何模式,则告诉 find_package() 在“模块”模式之前尝试“配置”模式。
    
    project(protobuf_snd) # 指定project name
    
    set(CMAKE_CXX_STANDARD 14) # 指定C++版本
    set(CMAKE_CXX_STANDARD_REQUIRED ON) # 设置指定的C++编译器版本是必须的,如果不设置,或者为OFF,则指定版本不可用时,会使用上一版本。
    
    find_package(eCAL REQUIRED) # 查找依赖包 eCAL
    find_package(Protobuf REQUIRED) # 查找依赖包 Protobuf
    
    set(source_files
      main.cpp
    )
    
    set(protobuf_files
        ${CMAKE_CURRENT_SOURCE_DIR}/../proto_messages/hello_world.proto
    )
    
    add_executable(${PROJECT_NAME} ${source_files}) # 添加一个可执行文件构建目标
    
    PROTOBUF_TARGET_CPP(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../proto_messages/ ${protobuf_files}) # 链接到目标头文件和源文件
    
    target_link_libraries(${PROJECT_NAME}   # 将目标文件与库文件进行链接。
      eCAL::core
      protobuf::libprotobuf
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    源文件main.cpp

    #include 
    #include 
    
    #include 
    #include 
    
    #include "hello_world.pb.h"
    
    int main(int argc, char** argv)
    {
      // 初始化eCAL并创建一个protobuf发布者
      eCAL::Initialize(argc, argv, "Hello World Protobuf Publisher");
      eCAL::protobuf::CPublisher<proto_messages::HelloWorld> publisher("hello_world_protobuf");
    
      // 要求用户输入他的名字
      std::cout << "Please enter your name: ";
      std::string name;
      std::getline(std::cin, name);
    
      unsigned int id = 0;
    
      // 无限循环(使用eCAL::Ok()将使我们能够从另一个应用程序优雅地关闭Process)
      while (eCAL::Ok())
      {
        // 让用户输入消息
        std::cout << "Type the message you want to send: ";
        std::string message;
        std::getline(std::cin, message);
    
        // 创建一个protobuf消息对象
        proto_messages::HelloWorld hello_world_message;
        hello_world_message.set_name(name);
        hello_world_message.set_msg (message);
        hello_world_message.set_id  (id++);
    
        // 发送消息
        publisher.Send(hello_world_message);
        std::cout << "Sent message!" << std::endl << std::endl;
      }
    
      // finalize eCAL API
      eCAL::Finalize();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    (2)、数据接收端

    cmake文件:

    cmake_minimum_required(VERSION 3.0)
    set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
    
    project(protobuf_rec)
    
    set(CMAKE_CXX_STANDARD 14)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    find_package(eCAL REQUIRED)
    find_package(Protobuf REQUIRED)
    
    set(source_files
      main.cpp
    )
    
    set(protobuf_files
        ${CMAKE_CURRENT_SOURCE_DIR}/../proto_messages/hello_world.proto
    )
    
    add_executable(${PROJECT_NAME} ${source_files})
    
    PROTOBUF_TARGET_CPP(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../proto_messages/ ${protobuf_files})
    
    target_link_libraries(${PROJECT_NAME}
      eCAL::core
      protobuf::libprotobuf
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    源文件main.cpp

    #include 
    #include 
    
    #include 
    #include 
    
    #include "hello_world.pb.h"
    
    void HelloWorldCallback(const proto_messages::HelloWorld& hello_world_msg)
    {
      std::cout << hello_world_msg.name() << " sent a message with ID "
                << hello_world_msg.id() << ":" << std::endl
                << hello_world_msg.msg() << std::endl << std::endl;
    }
    
    int main(int argc, char** argv)
    {
      // 初始化eCAL并创建一个protobuf订阅者
      eCAL::Initialize(argc, argv, "Hello World Protobuf Subscriber");
      eCAL::protobuf::CSubscriber subscriber("hello_world_protobuf");
    
      // 设置回调
      subscriber.AddReceiveCallback(std::bind(&HelloWorldCallback, std::placeholders::_2));
    
      // 不要退出
      while (eCAL::Ok())
      {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
      }
    
      // finalize eCAL API
      eCAL::Finalize();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    (3)、测试运行

    cd bulid
    cmake ..
    make
    
    • 1
    • 2
    • 3
    ./protobuf_snd
    
    • 1
    ./protobuf_rec 
    
    • 1

    在这里插入图片描述

  • 相关阅读:
    如何进行并发数计算(稳定性测试和压力测试)?
    C语言之自定义类型_结构体篇(2)
    Vue3 + Element-plus + TS —— 动态表格自由编辑
    Qt OpenGL(二十二)——Qt OpenGL 核心模式-VAO和VBO
    【.NET 6+Loki+Grafana】实现轻量级日志可视化服务功能
    MyBatis-Plus入门案例
    Docker、Jenkins 结合 SonarQube 和 Sonar scanner 进行代码质量扫描
    SpringBoot自带模板引擎Thymeleaf使用详解②
    工程企业管理软件源码-综合型项目管理软件
    PYTHON 120道题目详解(115-117)
  • 原文地址:https://blog.csdn.net/qq_44179528/article/details/127684521