【AimRT】AimRT Hello World

news2025/1/7 12:07:16

目录

  • 一、工程结构
  • 二、源码说明
    • /CMakeLists.txt
    • /cmake/GetAimRT.cmake
    • /src/CMakeLists.txt
    • /src/module/helloworld_module/CMakeLists.txt
    • /src/app/helloworld_app/CMakeLists.txt
    • /src/install/cfg/helloworld_cfg.yaml
    • /src/module/helloworld_module/helloworld_module.h
    • /src/module/helloworld_module/helloworld_module.cc
    • /src/app/helloworld_app/main.cc
  • 三、编译与运行

官方 Hello World 文档链接:https://docs.aimrt.org/tutorials/quick_start/helloworld_cpp.html

这里对其增加一些说明。

目前 AimRT 仅支持从源码安装,并且对于第三方依赖,也是通过拉取源码的方式安装,该方式通过 CMake 的FetchContent 实现,虽然该方式可以增强AimRT环境配置的兼容性,但对于封闭网络开发与网络不好的用户不太友好,而且部署一次环境是局部生效的,同一台电脑再新建一个工程还需要拉取源码安装一次。

该 Hello World Demo 涉及以下内容:

  • 基于 CMake FetchContent 通过源码引用 AimRT;
  • 编写一个基础的基于 AimRT CPP 接口的Module
  • 使用基础的日志功能;
  • 使用基础的配置功能;
  • 以 App 模式集成Module
  • 编译项目,并运行进程以执行Module中的逻辑。

一、工程结构

├── CMakeLists.txt                    
├── cmake
│   └── GetAimRT.cmake                # 基于 CMake FetchContent 通过源码引用 AimRT
└── src
    ├── CMakeLists.txt
    ├── install                      # 存放部署时的一些配置、启动脚本等
    │   └── cfg
    │       └── helloworld_cfg.yaml  # AimRT配置文件 
    ├── module                       # 存放业务逻辑代码
    │   └── helloworld_module
    │       ├── CMakeLists.txt
    │       ├── helloworld_module.cc # Module源文件
    │       └── helloworld_module.h  # Module头文件
    └── app                          # 以App模式集成Module
        └── helloworld_app         
            ├── CMakeLists.txt
            └── main.cc

二、源码说明

/CMakeLists.txt

根 CMake ,用于构建工程。

# 指定项目所需的最低CMake版本
cmake_minimum_required(VERSION 3.24)

# 定义项目的名称为helloworld,并指定该项目将使用C和C++语言
project(helloworld LANGUAGES C CXX)

# 设置项目使用的C++标准为C++20
set(CMAKE_CXX_STANDARD 20)
# 要求CMake确保编译器支持指定的C++标准。
# 如果编译器不支持该标准,CMake配置将失败。
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 禁用编译器特定的扩展
set(CMAKE_CXX_EXTENSIONS OFF)

# 包含一个名为GetAimRT.cmake的CMake模块
# 用于通过源码引用 AimRT
include(cmake/GetAimRT.cmake)

# 添加并处理src子目录
add_subdirectory(src)

/cmake/GetAimRT.cmake

通过源码引用 AimRT

# 包含FetchContent模块,该模块提供了一系列函数和宏,用于从远程仓库获取内容
include(FetchContent)

message("get aimrt ...")

# 使用FetchContent_Declare函数声明一个名为aimrt的外部项目
FetchContent_Declare(
  aimrt
  GIT_REPOSITORY https://github.com/AimRT/aimrt.git # 项目仓库链接
  GIT_TAG v0.9.2) # 项目版本

# 获取aimrt项目属性
# 用于检查项目是否已经被下载、配置和构建
FetchContent_GetProperties(aimrt)

# 检查aimrt项目是否已经下载并准备好用于构建
# 如果项目尚未准备好,则调用FetchContent_MakeAvailable函数下载、配置和构建该项目,
# 并将其添加到当前项目的构建系统中,使其可用
if(NOT aimrt_POPULATED)
  FetchContent_MakeAvailable(aimrt)
endif()

/src/CMakeLists.txt

引用 src 下的各个子目录

add_subdirectory(module/helloworld_module)
add_subdirectory(app/helloworld_app)

/src/module/helloworld_module/CMakeLists.txt

创建helloworld_module静态库

# 递归地查找当前源目录(${CMAKE_CURRENT_SOURCE_DIR})下所有以.cc结尾的文件,
# 并将这些文件的路径列表赋值给变量src
file(GLOB_RECURSE src ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)

# 创建一个名为helloworld_module的静态库目标
add_library(helloworld_module STATIC)
# 为helloworld_module静态库创建一个别名目标helloworld::helloworld_module
# 别名目标允许以更具命名空间风格的方式引用库,这在大型项目中尤其有用,可以避免名称冲突
add_library(helloworld::helloworld_module ALIAS helloworld_module)

# 将之前通过file(GLOB_RECURSE ...)找到的源文件(变量src)添加到helloworld_module目标的私有源文件中
# PRIVATE意味这些文件仅对helloworld_module目标本身可见,不会传播到依赖于它的其他目标
target_sources(helloworld_module PRIVATE ${src})

# 为helloworld_module目标添加公共头文件目录
# 公共头文件目录意味着这些目录不仅可用于构建helloworld_module本身,
# 还可用于构建依赖于helloworld_module的任何目标
target_include_directories(
  helloworld_module
  PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)

# 指定helloworld_module目标需要链接的库
target_link_libraries(
  helloworld_module
  # yaml-cpp库是私有依赖项,仅用于构建helloworld_module本身,不会传播到依赖于它的其他目标
  PRIVATE yaml-cpp::yaml-cpp 
  # 公共依赖项,不仅用于构建helloworld_module,还用于构建依赖于helloworld_module的任何目标
  PUBLIC aimrt::interface::aimrt_module_cpp_interface)

/src/app/helloworld_app/CMakeLists.txt

创建helloworld_app可执行文件

# 递归地查找当前源目录(${CMAKE_CURRENT_SOURCE_DIR})下所有以.cc结尾的文件,
# 并将这些文件的路径列表赋值给变量src
file(GLOB_RECURSE src ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)

# 添加名为helloworld_app的可执行文件
add_executable(helloworld_app)

# 为helloworld_app目标指定源文件
target_sources(helloworld_app PRIVATE ${src})

# 为helloworld_app目标指定头文件
target_include_directories(
  helloworld_app
  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

# 为helloworld_app目标指定链接库
target_link_libraries(
  helloworld_app
  PRIVATE aimrt::runtime::core helloworld::helloworld_module)

/src/install/cfg/helloworld_cfg.yaml

配置文件

aimrt:
  log: # log配置
    core_lvl: Debug # 内核日志等级,可选项:Trace/Debug/Info/Warn/Error/Fatal/Off,不区分大小写
    backends: # 日志后端
      - type: console # 控制台日志
        options:
          color: true # 是否要彩色打印
          module_filter: "(.*)" # 支持以正则表达式的形式,来配置哪些模块的日志可以通过本后端处理
          pattern: "[%c.%f][%l][%t][%n][%G:%R @%F] %v" # 日志格式化输出
      - type: rotate_file # 将日志打印到文件中
        options:
          path: ./log # 日志文件存放目录
          filename: examples_cpp_hello_world.log # 日志文件名称

# 模块自定义业务配置,以模块名称为节点名
HelloWorldModule:
  name: "HelloWorldModule"
  array: 
    - name: hello
      enable: true
    - name: world
      enable: false

/src/module/helloworld_module/helloworld_module.h

Module头文件

// 防止头文件在当前编译单元中被多次引用
#pragma once

#include "aimrt_module_cpp_interface/module_base.h"

// 定义一个 HelloWorldModule 类,继承自aimrt::ModuleBase
class HelloWorldModule : public aimrt::ModuleBase
{
public:
    HelloWorldModule() = default;
    ~HelloWorldModule() override = default;

    // 模块信息,包括name、version、author、description等
    aimrt::ModuleInfo Info() const override
    {
        return aimrt::ModuleInfo{.name = "HelloWorldModule",
                                 .major_version = 0,
                                 .minor_version = 1,
                                 .patch_version = 0,
                                 .build_version = 0,
                                 .author = "vistar",
                                 .description = "AimRT hello world model"};
    }

    // 初始化模块资源
    bool Initialize(aimrt::CoreRef core) override;
    // 启动模块
    bool Start() override;
    // 关闭模块
    void Shutdown() override;

private:
    // 返回一个日志记录器实例
    auto GetLogger() { return core_.GetLogger(); }

private:
    aimrt::CoreRef core_;
    aimrt::parameter::ParameterHandleRef parameter_handle_;
};

/src/module/helloworld_module/helloworld_module.cc

Module源文件

#include "helloworld_module/helloworld_module.h"
#include "yaml-cpp/yaml.h"

bool HelloWorldModule::Initialize(aimrt::CoreRef core)
{
    // Save aimrt framework handle
    core_ = core;

    // Log
    AIMRT_INFO("Init HelloWorldModule.");

    try
    {
        // Read cfg
        auto file_path = core_.GetConfigurator().GetConfigFilePath();
        if (!file_path.empty())
        {
            // 将配置写入到临时文件中,使用YAML-CPP加载配置
            YAML::Node config = YAML::LoadFile(file_path.data());
            
            std::string moduleName = config["name"].as<std::string>();
            AIMRT_INFO("moduleName: {}", moduleName);

            for (const auto &itemNode : config["array"])
            {
                std::string itemName = itemNode["name"].as<std::string>();
                bool enable = itemNode["enable"].as<bool>();
                AIMRT_INFO("name: {}, enable: {}", itemName, enable);
            }
        }
    }
    catch (const std::exception &e)
    {
        AIMRT_ERROR("Init failed, {}", e.what());
        return false;
    }

    AIMRT_INFO("Init HelloWorldModule succeeded.");

    return true;
}

bool HelloWorldModule::Start()
{
    AIMRT_INFO("Start HelloWorldModule succeeded.");
    return true;
}

void HelloWorldModule::Shutdown()
{
    AIMRT_INFO("Shutdown HelloWorldModule succeeded.");
}

/src/app/helloworld_app/main.cc

#include <csignal>
#include <iostream>

#include "core/aimrt_core.h"
#include "helloworld_module/helloworld_module.h"

using namespace aimrt::runtime::core;

AimRTCore *global_core_ptr_ = nullptr;

// 信号处理函数
void SignalHandler(int sig)
{
    if (global_core_ptr_ && (sig == SIGINT || sig == SIGTERM))
    {
        global_core_ptr_->Shutdown();
        return;
    }
    raise(sig);
};

int32_t main(int32_t argc, char **argv)
{
    // 注册 ctrl+c 信号监听,用 SignalHandler 函数处理
    signal(SIGINT, SignalHandler);
    // 注册 kill 信号监听,用 SignalHandler 函数处理
    signal(SIGTERM, SignalHandler);

    std::cout << "AimRT start." << std::endl;

    try
    {
        // 实例化 AimRTCore
        AimRTCore core;
        global_core_ptr_ = &core;

        // register module
        HelloWorldModule helloworld_module;
        core.GetModuleManager().RegisterModule(helloworld_module.NativeHandle());

        // 通过命令行参数读取配置文件路径
        AimRTCore::Options options;
        options.cfg_file_path = argv[1];

        // 初始化AimRT,初始化注册的 Module
        core.Initialize(options);
        // 启动AimRT,启动注册的 Module
        // 阻塞主线程等待结束
        core.Start();

        core.Shutdown();

        global_core_ptr_ = nullptr;
    }
    catch (const std::exception &e)
    {
        std::cout << "AimRT run with exception and exit. " << e.what() << std::endl;
        return -1;
    }

    std::cout << "AimRT exit." << std::endl;
    return 0;
}

三、编译与运行

编译工程和普通编译CMake工程操作一样:

# 在根CMakeList.txt同级目录执行
# 生成构建文件,配置项目
cmake -B build

# 编译和链接可执行文件和库文件
cd build
make -j

运行AimRT可执行文件,需要传入配置文件。

编译完成后,将生成的可执行文件helloworld_app和配置文件helloworld_cfg.yaml拷贝到一个目录下,然后执行以下命令运行进程:

./helloworld_app helloworld_cfg.yaml

欢迎加QQ群,一起讨论学习:894013891

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机场安全项目|基于改进 YOLOv8 的机场飞鸟实时目标检测方法

目录 论文信息 背景 摘要 YOLOv8模型结构 模型改进 FFC3 模块 CSPPF 模块 数据集增强策略 实验结果 消融实验 对比实验 结论 论文信息 《科学技术与工程》2024年第24卷第32期刊载了中国民用航空飞行学院空中交通管理学院孔建国, 张向伟, 赵志伟, 梁海军的论文——…

《Rust权威指南》学习笔记(二)

枚举enum 1.枚举的定义和使用如下图所示&#xff1a; 定义时还可以给枚举的成员指定数据类型&#xff0c;例如&#xff1a;enum IpAddr{V4(u8, u8, u8, u8),V6(String),}。枚举的变体都位于标识符的命名空间下&#xff0c;使用::进行分隔。 2.一个特殊的枚举Option&#xff0…

OSI模型的网络层中产生拥塞的主要原因?

&#xff08; 1 &#xff09;缓冲区容量有限&#xff1b;&#xff08; 1.5 分&#xff09; &#xff08; 2 &#xff09;传输线路的带宽有限&#xff1b;&#xff08; 1.5 分&#xff09; &#xff08; 3 &#xff09;网络结点的处理能力有限&#xff1b;&#xff08; 1 分…

linux上安装MySQL教程

1.准备好MySQL压缩包&#xff0c;并进行解压 tar -xvf mysql-5.7.28-1.el7.x86_64.rpm-bundle.tar -C /usr/local 2.检查是否有mariadb数据库 rpm -aq|grep mariadb 关于mariadb:是MySQL的一个分支&#xff0c;主要由开源社区在维护&#xff0c;采用GPL授权许可 MariaDB的目…

R语言中的时间序列分析·

1 数据集说明 AirPassengers 1949~1960年每月乘坐飞机的乘客数 JohnsonJohnson Johnson&Johnson每股季度收入 nhtemp 康涅狄格州纽黑文地区从1912年至1971年每年的平均气温 Nile 尼罗河的流量 sunspots 1749年~1983年月平均太阳黑子数 2 相关包 xts、forecast、tser…

LookingGlass使用

背景 Looking Glass 是一款开源应用程序&#xff0c;可以直接使用显卡直通的windows虚拟机。 常见环境是Linux hostwindows guest&#xff0c;基本部署结构图&#xff1a; 编译 git clone --recursive https://github.com/gnif/LookingGlass.git编译client mkdir client/b…

HCIA-Access V2.5_7_3_XG(S)原理_关键技术

为什么需要测距 因为上行链路只有一根纤,而且每一个ONU到OLT的距离是不一样的,虽然上行通过TDMA技术,让每一个ONU在不同的时间段发送数据,但是仍然有可能在同一时刻到达分光器,产生数据冲突。 有测距的信元传输 所以为了避免碰撞冲突,通过ONU在注册的时候就会启动测距…

四、VSCODE 使用GIT插件

VSCODE 使用GIT插件 一下载git插件与git Graph插件二、git插件使用三、文件提交到远程仓库四、git Graph插件 一下载git插件与git Graph插件 二、git插件使用 git插件一般VSCode自带了git&#xff0c;就是左边栏目的图标 在下载git软件后vscode的git插件会自动识别当前项目 …

RISC-V学习笔记

1.RISC ISA1个基本整数指令集多个可选的扩展指令集&#xff0c;如RV32I表示支持32位整数指令集。I表示基本指令集&#xff0c;M表示整数乘法与除法指令集&#xff0c;A表示存储器原子指令集&#xff0c;F表示单精度浮点指令集&#xff0c;D表示双精度浮点指令集等&#xff0c;C…

strapi中使用Documentation插件

Swagger UI 自动生成并展示了 API 的文档&#xff0c;这些文档是根据 OpenAPI Specification (OAS) 格式编写的。它提供了对 API 端点、请求方法&#xff08;GET, POST, PUT, DELETE 等&#xff09;、参数、响应格式等详细信息的描述 安装 npm run strapi install documentat…

AI来帮忙:蛋白纯化不用慌

在当今生物学研究的前沿领域&#xff0c;从探索疾病的发病机制&#xff0c;到新型药物的研发&#xff0c;再到生物工程产品的制造&#xff0c;高纯度、高活性的蛋白质都是不可或缺的基石。 科研人员在蛋白纯化的征程中&#xff0c;时常被诸多难题困扰。一方面&#xff0c;生物…

SpringCloud系列教程:微服务的未来(六)docker教程快速入门、常用命令

对于开发人员和运维工程师而言&#xff0c;掌握 Docker 的基本概念和常用命令是必不可少的。本篇文章将带你快速入门 Docker&#xff0c;并介绍一些最常用的命令&#xff0c;帮助你更高效地进行开发、测试和部署。 目录 前言 快速入门 docker安装 配置镜像加速 部署Mysql …

基于单片机中药存放环境监测系统的实现

基于单片机中药存放环境监测系统的实现 项目开发背景 随着现代中药的广泛应用&#xff0c;中药材的存储环境对其质量有着至关重要的影响。温湿度、烟雾、火灾等环境因素&#xff0c;若不加以控制&#xff0c;将会导致中药材失效或变质。因此&#xff0c;设计一个基于单片机的…

casaos安装最新版homeassistant-arm

进入cosOS界面点自定义安装 Docker镜像:homeassistant/armv7-homeassistant Tag:2024.12.2 标题&#xff1a;Home Assistant 图片路径&#xff1a;https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStoremain/Apps/HomeAssistant/icon.png Web UI&#xff1a;http&…

Fabric环境部署-安装Go

安装go语言环境 国内镜像&#xff1a;Go下载 - Go语言中文网 - Golang中文社区 1.选择版本下载后解压&#xff1a;注意go1.11.linux-amd64.tar.gz换成你下的 sudo tar zxvf go1.21.linux-amd64.tar.gz -C /usr/local 2.. 创建Go目录 mkdir $HOME/go 3. 用vi打开~./bashrc&…

慧集通(DataLinkX)iPaaS集成平台-主数据映射管理(多系统间基础档案的映射)

主数据管理 主数据管理主要是解决不同业务系统之间历史数据不统一的问题&#xff0c;在该功能下主要分为三个模块分别为数据对象、应用系统、数据映射&#xff1b; 其中数据对象指的是我们的不同的对象&#xff0c;如&#xff1a;部门、人员、职级、科目、供应商等等&#xff…

Hoverfly 任意文件读取漏洞(CVE-2024-45388)

漏洞简介 Hoverfly 是一个为开发人员和测试人员提供的轻量级服务虚拟化/API模拟/API模拟工具。其 /api/v2/simulation​ 的 POST 处理程序允许用户从用户指定的文件内容中创建新的模拟视图。然而&#xff0c;这一功能可能被攻击者利用来读取 Hoverfly 服务器上的任意文件。尽管…

基于单片机的公交车报站系统设计

引言&#xff1a;单片机应用实践是电类相关专业一门必修的专业技术基础课&#xff0c;其教学目的就是为了使学生能深入了解模拟电路、数字电路、EDA 技术、传感器、单片机原理及其相关接口的综合应用技术&#xff0c;为此我们选了一个典型的实践题目- 公交车报站系统设计&#…

基于Java的超级玛丽游戏的设计与实现【源码+文档+部署讲解】

目 录 1、绪论 1.1背景以及现状 1.2 Java语言的特点 1.3 系统运行环境及开发软件&#xff1a; 1.4 可行性的分析 1.4.1 技术可行性 1.4.2 经济可行性 1.4.3 操作可行性 2、 需求分析 2.1 用户需求分析 2.2功能需求分析 2.3界面设计需求分析…

关于数组的一些应用--------数组作函数的返回值(斐波那契数列数列的实现)

数组在作为函数的返回值&#xff0c;一个很经典的例子就是获取斐波那契数列的前N项 代码思路&#xff1a; 设计思路 输入&#xff1a; 输入一个整数 n&#xff0c;表示要生成斐波那契数列的长度。 输出&#xff1a; 输出一个长度为 n 的整数数组&#xff0c;其中每个元素为斐…