diff --git a/README.md b/README.md index c6f900c..2ca767e 100755 --- a/README.md +++ b/README.md @@ -8,9 +8,12 @@ English | [中文](README.zh_CN.md) ## Sample List -| Sample | Description | Level | -| :----------------------------------- | :------------------------------------------------------------------------------------------------------------- | :----- | -| [helloworld](./helloworld) | A simple example demonstrating how to use AimRT framework | :star: | -| [my_pb_channel](./my_pb_channel) | A simple example demonstrating publisher-subscriber communication using the Channel API with Protobuf messages | :star: | -| [my_ros2_channel](./my_ros2_channel) | A simple example demonstrating publisher-subscriber communication using the Channel API with ROS2 messages | :star: | -| [my_pb_rpc](./my_pb_rpc) | A simple example demonstrating publisher-subscriber communication using the Rpc API with Protobuf messages | :star: | +| Example | Description | Level | +| :----------------------------------- | :--------------------------------------------------------------------------------------------------------- | :----------- | +| [helloworld](./helloworld) | A simple example demonstrating how to use AimRT framework in app mode | :star: | +| [helloworld_pkg](./helloworld_pkg) | A simple example demonstrating how to use AimRT framework in pkg mode | :star: | +| [my_pb_channel](./my_pb_channel) | A simple example demonstrating publisher-subscriber communication using Channel API with Protobuf messages | :star: | +| [my_ros2_channel](./my_ros2_channel) | A simple example demonstrating publisher-subscriber communication using Channel API with ROS2 messages | :star: | +| [my_pb_rpc](./my_pb_rpc) | A simple example demonstrating request-response communication using Rpc API with Protobuf messages | :star: | +| [my_ros2_rpc](./my_ros2_rpc) | A simple example demonstrating request-response communication using Rpc API with ROS2 messages | :star: | +| [human_detector](./human_detector) | Publishes camera data via Channel API and performs face detection using OpenCV | :star::star: | diff --git a/README.zh_CN.md b/README.zh_CN.md index 6697ab0..b3cd55a 100755 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -8,13 +8,12 @@ ## 示例列表 -| 示例 | 描述 | 级别 | -| :----------------------------------- | :----------------------------------------------------------------------- | :----- | -| [helloworld](./helloworld) | 演示如何使用 AimRT 框架的 app 模式的简单示例 | :star: | -| [helloworld_pkg](./helloworld_pkg) | 演示如何使用 AimRT 框架的 pkg 模式的简单示例 | :star: | -| [my_pb_channel](./my_pb_channel) | 演示使用 Channel API 进行发布者-订阅者通信的简单示例,使用 Protobuf 消息 | :star: | -| [my_ros2_channel](./my_ros2_channel) | 演示使用 Channel API 进行发布者-订阅者通信的简单示例,使用 ROS2 消息 | :star: | -| [my_pb_rpc](./my_pb_rpc) | 演示使用 Rpc API 进行发布者-订阅者通信的简单示例,使用 Protobuf 消息 | :star: | -| [my_ros2_rpc](./my_ros2_rpc) | 演示使用 Rpc API 进行发布者-订阅者通信的简单示例,使用 ROS2 消息 | :star: | - -## 贡献 +| 示例 | 描述 | 级别 | +| :----------------------------------- | :------------------------------------------------------------------------------------ | :------------ | +| [helloworld](./helloworld) | 演示如何使用 AimRT 框架的 app 模式的简单示例 | :star: | +| [helloworld_pkg](./helloworld_pkg) | 演示如何使用 AimRT 框架的 pkg 模式的简单示例 | :star: | +| [my_pb_channel](./my_pb_channel) | 演示使用 Channel API 进行发布者-订阅者通信的简单示例,使用 Protobuf 消息 | :star: | +| [my_ros2_channel](./my_ros2_channel) | 演示使用 Channel API 进行发布者-订阅者通信的简单示例,使用 ROS2 消息 | :star: | +| [my_pb_rpc](./my_pb_rpc) | 演示使用 Rpc API 进行发布者-订阅者通信的简单示例,使用 Protobuf 消息 | :star: | +| [my_ros2_rpc](./my_ros2_rpc) | 演示使用 Rpc API 进行发布者-订阅者通信的简单示例,使用 ROS2 消息 | :star: | +| [human_detector](./human_detector) | 演示使用 Channel API 通过发布订阅传输系统摄像头数据,并使用 OpenCV 进行人脸识别的示例 | :star: :star: | diff --git a/helloworld/cmake/GetAimRT.cmake b/helloworld/cmake/GetAimRT.cmake index 6fad1d6..c957430 100755 --- a/helloworld/cmake/GetAimRT.cmake +++ b/helloworld/cmake/GetAimRT.cmake @@ -6,7 +6,7 @@ include(FetchContent) message(STATUS "get aimrt ...") set(aimrt_DOWNLOAD_URL - "https://github.com/AimRT/AimRT/archive/refs/tags/v1.0.0.tar.gz" + "https://github.com/AimRT/AimRT/archive/refs/tags/v1.4.0.tar.gz" CACHE STRING "") if(aimrt_LOCAL_SOURCE) @@ -27,6 +27,7 @@ function(get_aimrt) FetchContent_GetProperties(aimrt) if(NOT aimrt_POPULATED) set(AIMRT_BUILD_RUNTIME ON) + set(AIMRT_BUILD_WITH_PROTOBUF ON) FetchContent_MakeAvailable(aimrt) endif() diff --git a/helloworld/src/CMakeLists.txt b/helloworld/src/CMakeLists.txt index 5ccf0bb..97c5b57 100644 --- a/helloworld/src/CMakeLists.txt +++ b/helloworld/src/CMakeLists.txt @@ -3,12 +3,13 @@ add_subdirectory(module/helloworld_module) -add_subdirectory(app/helloworld_app) +add_subdirectory(pkg/helloworld_pkg) add_custom_target( ${PROJECT_NAME}_build_all ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/install/bin ${CMAKE_BINARY_DIR} - DEPENDS helloworld_app) + DEPENDS aimrt::runtime::main + helloworld_pkg) # Install if(AIMRT_SAMPLES_INSTALL) diff --git a/helloworld/src/app/helloworld_app/CMakeLists.txt b/helloworld/src/app/helloworld_app/CMakeLists.txt deleted file mode 100644 index 6793d3d..0000000 --- a/helloworld/src/app/helloworld_app/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2023, AgiBot Inc. -# All rights reserved. - -# Set file collection -file(GLOB_RECURSE src ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) - -# Add target -add_executable(helloworld_app) - -# Set source file of target -target_sources(helloworld_app PRIVATE ${src}) - -# Set include path of target -target_include_directories( - helloworld_app - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - -# Set link libraries of target -target_link_libraries( - helloworld_app - PRIVATE aimrt::runtime::core - helloworld::helloworld_module) - -if(AIMRT_SAMPLES_INSTALL) - install(TARGETS helloworld_app RUNTIME DESTINATION bin) -endif() diff --git a/helloworld/src/app/helloworld_app/main.cc b/helloworld/src/app/helloworld_app/main.cc deleted file mode 100644 index 83af69f..0000000 --- a/helloworld/src/app/helloworld_app/main.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2023, AgiBot Inc. -// All rights reserved. - -#include -#include - -#include "core/aimrt_core.h" -#include "helloworld_module/helloworld_module.h" - -using namespace aimrt::runtime::core; - -AimRTCore *global_core_ptr_ = nullptr; - -// Handles SIGINT (Ctrl+C) and SIGTERM signals for graceful shutdown -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) { - // Register signal handlers - signal(SIGINT, SignalHandler); - signal(SIGTERM, SignalHandler); - - std::cout << "AimRT start." << std::endl; - - try { - AimRTCore core; - global_core_ptr_ = &core; - - // register module you want to use - HelloWorldModule helloworld_module; - core.GetModuleManager().RegisterModule(helloworld_module.NativeHandle()); - - // get configuration file path from command line argument - AimRTCore::Options options; - options.cfg_file_path = argv[1]; - - // Initialization phase - core.Initialize(options); - - // Runtime phase - core.Start(); - - // Cleanup and termination phase - 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; -} diff --git a/helloworld/src/install/bin/cfg/helloworld_cfg.yaml b/helloworld/src/install/bin/cfg/helloworld_cfg.yaml index c118c16..2ab5347 100755 --- a/helloworld/src/install/bin/cfg/helloworld_cfg.yaml +++ b/helloworld/src/install/bin/cfg/helloworld_cfg.yaml @@ -1,21 +1,26 @@ -# AimRT core configuration aimrt: - log: # log configuration - core_lvl: INFO # core log level, options: Trace/Debug/Info/Warn/Error/Fatal/Off, case-insensitive - backends: # log backends - - type: console # print to console + log: + core_lvl: INFO # Trace/Debug/Info/Warn/Error/Fatal/Off + backends: + - type: console + - type: rotate_file options: - color: true # colored print - - type: rotate_file # print to file and rotate + path: ./log + filename: helloworld.log + max_file_size_m: 4 + max_file_num: 10 + executor: + executors: + - name: work_executor + type: asio_thread options: - path: ./log # log file path - filename: helloworld.log # log file name - max_file_size_m: 4 # log file max size, unit: MB - max_file_num: 10 # max log file num, 0 means unlimited + thread_num: 4 + module: + pkgs: + - path: ./libhelloworld_pkg.so + enable_modules: [HelloWorldModule] # Custom module configuration -# the framework will generate a temporary configuration file for each module, -# and the developer can get the configuration file path through the Configurator interface. HelloWorldModule: - key1: val1 - key2: val2 + param1: val1 + param2: 2 diff --git a/helloworld/src/install/bin/start_helloworld.sh b/helloworld/src/install/bin/start_helloworld.sh index 5d2b073..c90b017 100755 --- a/helloworld/src/install/bin/start_helloworld.sh +++ b/helloworld/src/install/bin/start_helloworld.sh @@ -1,3 +1,3 @@ #!/bin/sh -./helloworld_app ./cfg/helloworld_cfg.yaml +./aimrt_main --cfg_file_path=./cfg/helloworld_cfg.yaml diff --git a/helloworld/src/module/helloworld_module/CMakeLists.txt b/helloworld/src/module/helloworld_module/CMakeLists.txt index fb34b43..80e02e3 100644 --- a/helloworld/src/module/helloworld_module/CMakeLists.txt +++ b/helloworld/src/module/helloworld_module/CMakeLists.txt @@ -6,7 +6,6 @@ file(GLOB_RECURSE src ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) # Add target add_library(helloworld_module STATIC) -add_library(helloworld::helloworld_module ALIAS helloworld_module) # Set source file of target target_sources(helloworld_module PRIVATE ${src}) diff --git a/helloworld/src/module/helloworld_module/helloworld_module.cc b/helloworld/src/module/helloworld_module/helloworld_module.cc index 4ce29cf..cf14c1d 100644 --- a/helloworld/src/module/helloworld_module/helloworld_module.cc +++ b/helloworld/src/module/helloworld_module/helloworld_module.cc @@ -5,38 +5,74 @@ #include "yaml-cpp/yaml.h" // IWYU pragma: keep bool HelloWorldModule::Initialize(aimrt::CoreRef core) { - core_ = core; + ctx_ptr_ = std::make_shared(core); + ctx_ptr_->LetMe(); try { + // Write your other initialization logic here ... // Read custom module configuration - auto file_path = core_.GetConfigurator().GetConfigFilePath(); + auto file_path = ctx_ptr_->GetConfigFilePath(); if (!file_path.empty()) { YAML::Node cfg_node = YAML::LoadFile(file_path.data()); - for (const auto& itr : cfg_node) { - auto k = itr.first.as(); - auto v = itr.second.as(); - AIMRT_INFO("cfg [{} : {}]", k, v); - } + param1_ = cfg_node["param1"].as(); + param2_ = cfg_node["param2"].as(); } - // Write your other initialization logic here ... + + // Get executor handle + executor_ = ctx_ptr_->CreateExecutor("work_executor"); + + timer_ = aimrt::executor::CreateTimer( + executor_, + std::chrono::milliseconds(1000), + [this]() { + ctx_ptr_->LetMe(); + Task(); }, + false); } catch (const std::exception& e) { AIMRT_ERROR("Init failed, {}", e.what()); return false; } - - AIMRT_INFO("Init succeeded."); - return true; } bool HelloWorldModule::Start() { // Write your runtime logic here - AIMRT_INFO("Start succeeded."); + // use timer + timer_->Reset(); + + // use executor + executor_.Execute([this]() { ctx_ptr_->LetMe(); LoopTask(); }); + + // use co_task + scope_.spawn(aimrt::co::On(aimrt::co::InlineScheduler(), CoLoopTask())); return true; } void HelloWorldModule::Shutdown() { // Write your resource release logic here - AIMRT_INFO("Shutdown succeeded."); + ctx_ptr_->StopRunning(); + timer_->Cancel(); + aimrt::co::SyncWait(scope_.complete()); +} + +void HelloWorldModule::Task() { + AIMRT_INFO("Single Task param1: {}, param2: {}", param1_, param2_); +} + +void HelloWorldModule::LoopTask() { + while (ctx_ptr_->Running()) { + AIMRT_WARN("Loop Task param1: {}, param2: {}", param1_, param2_); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } +} + +aimrt::co::Task HelloWorldModule::CoLoopTask() { + auto scheduler = aimrt::co::AimRTScheduler(executor_); + while (ctx_ptr_->Running()) { + ctx_ptr_->LetMe(); + AIMRT_ERROR("CoLoop Task param1: {}, param2: {}", param1_, param2_); + co_await aimrt::co::ScheduleAfter(scheduler, std::chrono::milliseconds(1000)); + } + co_return; } diff --git a/helloworld/src/module/helloworld_module/helloworld_module.h b/helloworld/src/module/helloworld_module/helloworld_module.h index a87cb7c..2a637ce 100644 --- a/helloworld/src/module/helloworld_module/helloworld_module.h +++ b/helloworld/src/module/helloworld_module/helloworld_module.h @@ -3,7 +3,7 @@ #pragma once -#include "aimrt_module_cpp_interface/module_base.h" +#include "aimrt_module_cpp_interface/aimrt_module_cpp_interface.h" class HelloWorldModule : public aimrt::ModuleBase { public: @@ -19,8 +19,22 @@ class HelloWorldModule : public aimrt::ModuleBase { void Shutdown() override; private: - auto GetLogger() { return core_.GetLogger(); } + void Task(); + void LoopTask(); + aimrt::co::Task CoLoopTask(); private: - aimrt::CoreRef core_; + std::shared_ptr ctx_ptr_; + + std::string param1_; + int param2_; + + // 通用执行器 + aimrt::executor::ExecutorRef executor_; + + // 定时器 + std::shared_ptr timer_; + + // 协程作用域 + aimrt::co::AsyncScope scope_; }; diff --git a/helloworld_pkg/src/pkg/helloworld_pkg/CMakeLists.txt b/helloworld/src/pkg/helloworld_pkg/CMakeLists.txt similarity index 78% rename from helloworld_pkg/src/pkg/helloworld_pkg/CMakeLists.txt rename to helloworld/src/pkg/helloworld_pkg/CMakeLists.txt index d4d5b54..0cb5657 100644 --- a/helloworld_pkg/src/pkg/helloworld_pkg/CMakeLists.txt +++ b/helloworld/src/pkg/helloworld_pkg/CMakeLists.txt @@ -6,7 +6,6 @@ file(GLOB_RECURSE src ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) # Add target add_library(${CUR_TARGET_NAME} SHARED) -add_library(helloworld::${CUR_TARGET_NAME} ALIAS ${CUR_TARGET_NAME}) # Set source file of target target_sources(${CUR_TARGET_NAME} PRIVATE ${src}) @@ -15,4 +14,4 @@ target_sources(${CUR_TARGET_NAME} PRIVATE ${src}) target_link_libraries( ${CUR_TARGET_NAME} PRIVATE aimrt::interface::aimrt_pkg_c_interface - helloworld::helloworld_module) + helloworld_module) diff --git a/helloworld_pkg/src/pkg/helloworld_pkg/pkg_main.cc b/helloworld/src/pkg/helloworld_pkg/pkg_main.cc similarity index 92% rename from helloworld_pkg/src/pkg/helloworld_pkg/pkg_main.cc rename to helloworld/src/pkg/helloworld_pkg/pkg_main.cc index ebd4d19..eb1c0ff 100644 --- a/helloworld_pkg/src/pkg/helloworld_pkg/pkg_main.cc +++ b/helloworld/src/pkg/helloworld_pkg/pkg_main.cc @@ -3,6 +3,7 @@ static std::tuple> aimrt_module_register_array[]{ // Here register all modules in the package - {"HelloWorldModule", []() -> aimrt::ModuleBase* { return new HelloWorldModule(); }}}; + {"HelloWorldModule", []() -> aimrt::ModuleBase* { return new HelloWorldModule(); }}, +}; AIMRT_PKG_MAIN(aimrt_module_register_array) diff --git a/helloworld_pkg/CMakeLists.txt b/helloworld_pkg/CMakeLists.txt deleted file mode 100644 index bc43c42..0000000 --- a/helloworld_pkg/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2023, AgiBot Inc. -# All rights reserved. - -cmake_minimum_required(VERSION 3.24) - -project(helloworld LANGUAGES C CXX) - -# Set cmake path -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) - -# Some necessary settings -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -# Set default build type as Release -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif() - -set(INSTALL_CONFIG_NAME ${PROJECT_NAME}-config) - -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) - -set(FETCHCONTENT_BASE_DIR ${CMAKE_SOURCE_DIR}/_deps) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -# Include cmake module -include(GetAimRT) - -add_subdirectory(src) - -if(AIMRT_SAMPLES_INSTALL) - # Install - install( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake - DESTINATION ./ - FILES_MATCHING - PATTERN "*.cmake") -endif() diff --git a/helloworld_pkg/README.md b/helloworld_pkg/README.md deleted file mode 100755 index e69de29..0000000 diff --git a/helloworld_pkg/build.sh b/helloworld_pkg/build.sh deleted file mode 100755 index 98fcec3..0000000 --- a/helloworld_pkg/build.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -# exit on error and print each command -set -e - -if [ -d ./build/install ]; then - rm -rf ./build/install -fi - -# cmake -cmake -B build \ - -DCMAKE_BUILD_TYPE=Release \ - -DAIMRT_SAMPLES_INSTALL=ON \ - -DCMAKE_INSTALL_PREFIX=./build/install \ - $@ - -cmake --build build --config Release --target install --parallel $(nproc) diff --git a/helloworld_pkg/cmake/GetAimRT.cmake b/helloworld_pkg/cmake/GetAimRT.cmake deleted file mode 100755 index 6fad1d6..0000000 --- a/helloworld_pkg/cmake/GetAimRT.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2023, AgiBot Inc. -# All rights reserved. - -include(FetchContent) - -message(STATUS "get aimrt ...") - -set(aimrt_DOWNLOAD_URL - "https://github.com/AimRT/AimRT/archive/refs/tags/v1.0.0.tar.gz" - CACHE STRING "") - -if(aimrt_LOCAL_SOURCE) - FetchContent_Declare( - aimrt - SOURCE_DIR ${aimrt_LOCAL_SOURCE} - OVERRIDE_FIND_PACKAGE) -else() - FetchContent_Declare( - aimrt - URL ${aimrt_DOWNLOAD_URL} - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - OVERRIDE_FIND_PACKAGE) -endif() - -# Wrap it in a function to restrict the scope of the variables -function(get_aimrt) - FetchContent_GetProperties(aimrt) - if(NOT aimrt_POPULATED) - set(AIMRT_BUILD_RUNTIME ON) - - FetchContent_MakeAvailable(aimrt) - endif() -endfunction() - -get_aimrt() diff --git a/helloworld_pkg/src/CMakeLists.txt b/helloworld_pkg/src/CMakeLists.txt deleted file mode 100644 index 049a378..0000000 --- a/helloworld_pkg/src/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2023, AgiBot Inc. -# All rights reserved. - -add_subdirectory(module/helloworld_module) - -add_subdirectory(pkg/helloworld_pkg) - -add_custom_target( - ${PROJECT_NAME}_build_all ALL - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/install/bin ${CMAKE_BINARY_DIR} - DEPENDS aimrt::runtime::main - helloworld::helloworld_pkg) - -# Install -if(AIMRT_SAMPLES_INSTALL) - install( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/install/bin - DESTINATION . - USE_SOURCE_PERMISSIONS) -endif() diff --git a/helloworld_pkg/src/install/bin/cfg/helloworld_cfg.yaml b/helloworld_pkg/src/install/bin/cfg/helloworld_cfg.yaml deleted file mode 100755 index 2ba65b4..0000000 --- a/helloworld_pkg/src/install/bin/cfg/helloworld_cfg.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# AimRT core configuration -aimrt: - log: # log configuration - core_lvl: INFO # core log level, options: Trace/Debug/Info/Warn/Error/Fatal/Off, case-insensitive - backends: # log backends - - type: console # print to console - options: - color: true # colored print - - type: rotate_file # print to file and rotate - options: - path: ./log # log file path - filename: helloworld.log # log file name - max_file_size_m: 4 # log file max size, unit: MB - max_file_num: 10 # max log file num, 0 means unlimited - module: - pkgs: - - path: ./libhelloworld_pkg.so - enable_modules: [HelloWorldModule] - modules: - - name: HelloWorldModule - log_lvl: INFO - -# Custom module configuration -# the framework will generate a temporary configuration file for each module, -# and the developer can get the configuration file path through the Configurator interface. -HelloWorldModule: - key1: val1 - key2: val2 diff --git a/helloworld_pkg/src/install/bin/start_helloworld.sh b/helloworld_pkg/src/install/bin/start_helloworld.sh deleted file mode 100755 index c90b017..0000000 --- a/helloworld_pkg/src/install/bin/start_helloworld.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -./aimrt_main --cfg_file_path=./cfg/helloworld_cfg.yaml diff --git a/helloworld_pkg/src/module/helloworld_module/CMakeLists.txt b/helloworld_pkg/src/module/helloworld_module/CMakeLists.txt deleted file mode 100644 index 74c433c..0000000 --- a/helloworld_pkg/src/module/helloworld_module/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Set target name -set(CUR_TARGET_NAME "helloworld_module") - -# Set file collection -file(GLOB_RECURSE src ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) - -# Add target -add_library(${CUR_TARGET_NAME} STATIC) -add_library(helloworld::${CUR_TARGET_NAME} ALIAS ${CUR_TARGET_NAME}) - -# Set source file of target -target_sources(${CUR_TARGET_NAME} PRIVATE ${src}) - -# Set include path of target -target_include_directories( - ${CUR_TARGET_NAME} - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..) - -# Set link libraries of target -target_link_libraries( - ${CUR_TARGET_NAME} - PRIVATE yaml-cpp::yaml-cpp - PUBLIC aimrt::interface::aimrt_module_cpp_interface) diff --git a/helloworld_pkg/src/module/helloworld_module/helloworld_module.cc b/helloworld_pkg/src/module/helloworld_module/helloworld_module.cc deleted file mode 100644 index 4ce29cf..0000000 --- a/helloworld_pkg/src/module/helloworld_module/helloworld_module.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2023, AgiBot Inc. -// All rights reserved. - -#include "helloworld_module/helloworld_module.h" -#include "yaml-cpp/yaml.h" // IWYU pragma: keep - -bool HelloWorldModule::Initialize(aimrt::CoreRef core) { - core_ = core; - - try { - // Read custom module configuration - auto file_path = core_.GetConfigurator().GetConfigFilePath(); - if (!file_path.empty()) { - YAML::Node cfg_node = YAML::LoadFile(file_path.data()); - for (const auto& itr : cfg_node) { - auto k = itr.first.as(); - auto v = itr.second.as(); - AIMRT_INFO("cfg [{} : {}]", k, v); - } - } - // Write your other initialization logic here ... - - } catch (const std::exception& e) { - AIMRT_ERROR("Init failed, {}", e.what()); - return false; - } - - AIMRT_INFO("Init succeeded."); - - return true; -} - -bool HelloWorldModule::Start() { - // Write your runtime logic here - AIMRT_INFO("Start succeeded."); - return true; -} - -void HelloWorldModule::Shutdown() { - // Write your resource release logic here - AIMRT_INFO("Shutdown succeeded."); -} diff --git a/helloworld_pkg/src/module/helloworld_module/helloworld_module.h b/helloworld_pkg/src/module/helloworld_module/helloworld_module.h deleted file mode 100644 index a87cb7c..0000000 --- a/helloworld_pkg/src/module/helloworld_module/helloworld_module.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2023, AgiBot Inc. -// All rights reserved. - -#pragma once - -#include "aimrt_module_cpp_interface/module_base.h" - -class HelloWorldModule : public aimrt::ModuleBase { - public: - HelloWorldModule() = default; - ~HelloWorldModule() override = default; - - // Override the following functions from ModuleBase - - aimrt::ModuleInfo Info() const override { return aimrt::ModuleInfo{.name = "HelloWorldModule"}; } - - bool Initialize(aimrt::CoreRef core) override; - bool Start() override; - void Shutdown() override; - - private: - auto GetLogger() { return core_.GetLogger(); } - - private: - aimrt::CoreRef core_; -}; diff --git a/my_pb_channel/cmake/GetAimRT.cmake b/my_pb_channel/cmake/GetAimRT.cmake index 2f00dae..c957430 100755 --- a/my_pb_channel/cmake/GetAimRT.cmake +++ b/my_pb_channel/cmake/GetAimRT.cmake @@ -6,7 +6,7 @@ include(FetchContent) message(STATUS "get aimrt ...") set(aimrt_DOWNLOAD_URL - "https://github.com/AimRT/AimRT/archive/refs/tags/v1.0.0.tar.gz" + "https://github.com/AimRT/AimRT/archive/refs/tags/v1.4.0.tar.gz" CACHE STRING "") if(aimrt_LOCAL_SOURCE) diff --git a/my_pb_channel/src/CMakeLists.txt b/my_pb_channel/src/CMakeLists.txt index 08c5c95..b7d9068 100755 --- a/my_pb_channel/src/CMakeLists.txt +++ b/my_pb_channel/src/CMakeLists.txt @@ -6,12 +6,13 @@ add_subdirectory(protocols) add_subdirectory(module/normal_publisher_module) add_subdirectory(module/normal_subscriber_module) -add_subdirectory(app/my_pb_channel_app) +add_subdirectory(pkg/my_pb_channel_pkg) add_custom_target( ${PROJECT_NAME}_build_all ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/install/bin ${CMAKE_BINARY_DIR} - DEPENDS my_pb_channel_app) + DEPENDS aimrt::runtime::main + my_pb_channel_pkg) # Install if(AIMRT_SAMPLES_INSTALL) diff --git a/my_pb_channel/src/app/my_pb_channel_app/CMakeLists.txt b/my_pb_channel/src/app/my_pb_channel_app/CMakeLists.txt deleted file mode 100755 index ce45ece..0000000 --- a/my_pb_channel/src/app/my_pb_channel_app/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2023, AgiBot Inc. -# All rights reserved. - -# Set file collection -file(GLOB_RECURSE src ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) - -# Add target -add_executable(my_pb_channel_app) - -# Set source file of target -target_sources(my_pb_channel_app PRIVATE ${src}) - -# Set include path of target -target_include_directories( - my_pb_channel_app - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - -# Set link libraries of target -target_link_libraries( - my_pb_channel_app - PRIVATE aimrt::runtime::core - my_pb_channel::normal_publisher_module - my_pb_channel::normal_subscriber_module) - -if(AIMRT_SAMPLES_INSTALL) - install(TARGETS my_pb_channel_app RUNTIME DESTINATION bin) -endif() diff --git a/my_pb_channel/src/app/my_pb_channel_app/main.cc b/my_pb_channel/src/app/my_pb_channel_app/main.cc deleted file mode 100755 index 3eaa374..0000000 --- a/my_pb_channel/src/app/my_pb_channel_app/main.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2023, AgiBot Inc. -// All rights reserved. - -#include -#include - -#include "core/aimrt_core.h" -#include "normal_publisher_module/normal_publisher_module.h" -#include "normal_subscriber_module/normal_subscriber_module.h" - -using namespace aimrt::runtime::core; - -AimRTCore *global_core_ptr_ = nullptr; - -// Handles SIGINT (Ctrl+C) and SIGTERM signals for graceful shutdown -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) { - // Register signal handlers - signal(SIGINT, SignalHandler); - signal(SIGTERM, SignalHandler); - - std::cout << "AimRT start." << std::endl; - - try { - AimRTCore core; - global_core_ptr_ = &core; - - // Register module you want to use: - // here we register two modules: normal_publisher_module and normal_subscriber_module - NormalPublisherModule normal_publisher_module; - core.GetModuleManager().RegisterModule(normal_publisher_module.NativeHandle()); - - NormalSubscriberModule normal_subscriber_module; - core.GetModuleManager().RegisterModule(normal_subscriber_module.NativeHandle()); - - // get configuration file path from command line argument - AimRTCore::Options options; - options.cfg_file_path = argv[1]; - - // Initialization phase - core.Initialize(options); - - // Runtime phase - core.Start(); - - // Cleanup and termination phase - 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; -} diff --git a/my_pb_channel/src/install/bin/cfg/my_pb_channel_cfg.yaml b/my_pb_channel/src/install/bin/cfg/my_pb_channel_cfg.yaml index 0d13f29..b2970bb 100755 --- a/my_pb_channel/src/install/bin/cfg/my_pb_channel_cfg.yaml +++ b/my_pb_channel/src/install/bin/cfg/my_pb_channel_cfg.yaml @@ -1,40 +1,29 @@ # AimRT core configuration aimrt: - log: # log configuration - core_lvl: INFO # core log level, options: Trace/Debug/Info/Warn/Error/Fatal/Off, case-insensitive - default_module_lvl: INFO # module default log level - backends: # log backends - - type: console # print to console - options: - color: true # colored print - - type: rotate_file # print to file and rotate - options: - path: ./log # log file path - filename: my_pb_channel.log # log file name - max_file_size_m: 4 # log file max size, unit: MB - max_file_num: 10 # max log file num, 0 means unlimited - executor: # executor configuration - executors: # you want to create executors here - - name: work_thread_pool # name + log: + backends: + - type: console + + executor: + executors: + - name: work_thread_pool type: asio_thread options: - thread_num: 2 # thread num - channel: # channel configuration - backends: # channel backends - - type: local # use local backend - options: - subscriber_use_inline_executor: false # not use inline executor in subscriber - subscriber_executor: work_thread_pool # executor your callback function in subscriber_executor(must be created in executor section) - pub_topics_options: # publish endpoint options - - topic_name: "(.*)" # select some topic (support regex) - enable_backends: [local] # this topic be configured to use local backend only - sub_topics_options: # publish endpoint options - - topic_name: "(.*)" # select some topic (support regex) - enable_backends: [local] # this topic be configured to use local backend only + thread_num: 2 + channel: + backends: + - type: local + pub_topics_options: + - topic_name: "(.*)" + enable_backends: [local] + sub_topics_options: + - topic_name: "(.*)" + enable_backends: [local] + module: + pkgs: + - path: ./libmy_pb_channel_pkg.so + enable_modules: [NormalPublisherModule, NormalSubscriberModule] -# Custom module configuration -# the framework will generate a temporary configuration file for each module, -# and the developer can get the configuration file path through the Configurator interface. NormalPublisherModule: topic_name: "example/test_topic" channel_frq: 1 diff --git a/my_pb_channel/src/install/bin/start_my_pb_channel.sh b/my_pb_channel/src/install/bin/start_my_pb_channel.sh index d0e6033..08554c1 100755 --- a/my_pb_channel/src/install/bin/start_my_pb_channel.sh +++ b/my_pb_channel/src/install/bin/start_my_pb_channel.sh @@ -1,5 +1,4 @@ #!/bin/sh -cd $(dirname $0) -./my_pb_channel_app ./cfg/my_pb_channel_cfg.yaml +./aimrt_main --cfg_file_path=./cfg/my_pb_channel_cfg.yaml diff --git a/my_pb_channel/src/module/normal_publisher_module/normal_publisher_module.cc b/my_pb_channel/src/module/normal_publisher_module/normal_publisher_module.cc index fb177bd..df05008 100755 --- a/my_pb_channel/src/module/normal_publisher_module/normal_publisher_module.cc +++ b/my_pb_channel/src/module/normal_publisher_module/normal_publisher_module.cc @@ -7,14 +7,13 @@ #include "yaml-cpp/yaml.h" -#include "event.pb.h" - bool NormalPublisherModule::Initialize(aimrt::CoreRef core) { - core_ = core; + ctx_ptr_ = std::make_shared(core); + ctx_ptr_->LetMe(); try { // Read cfg - auto file_path = core_.GetConfigurator().GetConfigFilePath(); + auto file_path = ctx_ptr_->GetConfigFilePath(); if (!file_path.empty()) { YAML::Node cfg_node = YAML::LoadFile(std::string(file_path)); topic_name_ = cfg_node["topic_name"].as(); @@ -22,86 +21,50 @@ bool NormalPublisherModule::Initialize(aimrt::CoreRef core) { } // Get executor handle with name "work_thread_pool",(it must be registered in aimrt config file) - executor_ = core_.GetExecutorManager().GetExecutor("work_thread_pool"); - AIMRT_CHECK_ERROR_THROW(executor_ && executor_.SupportTimerSchedule(), - "Get executor 'work_thread_pool' failed."); - - // Register publish(it contains two steps) - // Step1: get publisher handle with topic name - publisher_ = core_.GetChannelHandle().GetPublisher(topic_name_); - AIMRT_CHECK_ERROR_THROW(publisher_, "Get publisher for topic '{}' failed.", topic_name_); + executor_ = ctx_ptr_->CreateExecutor("work_thread_pool"); - // Step2: register publish type - bool ret = aimrt::channel::RegisterPublishType(publisher_); - AIMRT_CHECK_ERROR_THROW(ret, "Register publish type failed."); + // Register publish + publisher_ = ctx_ptr_->CreatePublisher(topic_name_); } catch (const std::exception& e) { AIMRT_ERROR("Init failed, {}", e.what()); return false; } - - AIMRT_INFO("Init succeeded."); - return true; } bool NormalPublisherModule::Start() { - try { - run_flag_ = true; - // Start main loop in executor_ - executor_.Execute(std::bind(&NormalPublisherModule::MainLoop, this)); - } catch (const std::exception& e) { - AIMRT_ERROR("Start failed, {}", e.what()); - return false; - } + executor_.Execute([this]() { + ctx_ptr_->LetMe(); + MainLoop(); + }); - AIMRT_INFO("Start succeeded."); return true; } void NormalPublisherModule::Shutdown() { - try { - if (run_flag_) { - run_flag_ = false; - stop_sig_.get_future().wait(); - } - } catch (const std::exception& e) { - AIMRT_ERROR("Shutdown failed, {}", e.what()); - return; - } - - AIMRT_INFO("Shutdown succeeded."); + ctx_ptr_->StopRunning(); } // Main loop void NormalPublisherModule::MainLoop() { - try { - AIMRT_INFO("Start MainLoop."); - - uint32_t count = 0; - while (run_flag_) { - std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(1000 / channel_frq_))); + uint32_t count = 0; + while (ctx_ptr_->Running()) { + std::this_thread::sleep_for(std::chrono::milliseconds(static_cast(1000 / channel_frq_))); - count++; - AIMRT_INFO("Loop count : {} -------------------------", count); + count++; + AIMRT_INFO("Loop count : {} -------------------------", count); - // full pb event - aimrt_samples::protocols::EventMsg msg; - msg.mutable_header()->set_time_stamp(std::chrono::system_clock::now().time_since_epoch().count()); - msg.mutable_header()->set_frame_id("test_frame"); - msg.mutable_header()->set_sequence_num(count); - msg.set_msg("count: " + std::to_string(count)); + // full pb event + aimrt_samples::protocols::EventMsg msg; + msg.mutable_header()->set_time_stamp(std::chrono::system_clock::now().time_since_epoch().count()); + msg.mutable_header()->set_frame_id("test_frame"); + msg.mutable_header()->set_sequence_num(count); + msg.set_msg("count: " + std::to_string(count)); - AIMRT_INFO("Publish new pb event, data: {}", aimrt::Pb2CompactJson(msg)); + AIMRT_INFO("Publish new pb event, data: {}", aimrt::Pb2CompactJson(msg)); - // publish pb event - aimrt::channel::Publish(publisher_, msg); - } - - AIMRT_INFO("Exit MainLoop."); - } catch (const std::exception& e) { - AIMRT_ERROR("Exit MainLoop with exception, {}", e.what()); + // publish pb event + publisher_.Publish(msg); } - - stop_sig_.set_value(); } diff --git a/my_pb_channel/src/module/normal_publisher_module/normal_publisher_module.h b/my_pb_channel/src/module/normal_publisher_module/normal_publisher_module.h index 4b1042f..4a59b91 100755 --- a/my_pb_channel/src/module/normal_publisher_module/normal_publisher_module.h +++ b/my_pb_channel/src/module/normal_publisher_module/normal_publisher_module.h @@ -3,10 +3,8 @@ #pragma once -#include -#include - -#include "aimrt_module_cpp_interface/module_base.h" +#include "aimrt_module_cpp_interface/aimrt_module_cpp_interface.h" +#include "event.pb.h" class NormalPublisherModule : public aimrt::ModuleBase { public: @@ -14,7 +12,6 @@ class NormalPublisherModule : public aimrt::ModuleBase { ~NormalPublisherModule() override = default; // Override the following functions from ModuleBase - aimrt::ModuleInfo Info() const override { return aimrt::ModuleInfo{.name = "NormalPublisherModule"}; } @@ -24,18 +21,15 @@ class NormalPublisherModule : public aimrt::ModuleBase { void Shutdown() override; private: - auto GetLogger() { return core_.GetLogger(); } - void MainLoop(); private: - aimrt::CoreRef core_; - aimrt::executor::ExecutorRef executor_; + std::shared_ptr ctx_ptr_; - std::atomic_bool run_flag_ = false; - std::promise stop_sig_; + aimrt::executor::ExecutorRef executor_; std::string topic_name_ = "test_topic"; double channel_frq_ = 0.5; - aimrt::channel::PublisherRef publisher_; + + aimrt::context::res::Publisher publisher_; }; diff --git a/my_pb_channel/src/module/normal_subscriber_module/normal_subscriber_module.cc b/my_pb_channel/src/module/normal_subscriber_module/normal_subscriber_module.cc index 068d2a8..8c0e6dc 100755 --- a/my_pb_channel/src/module/normal_subscriber_module/normal_subscriber_module.cc +++ b/my_pb_channel/src/module/normal_subscriber_module/normal_subscriber_module.cc @@ -4,47 +4,36 @@ #include "normal_subscriber_module/normal_subscriber_module.h" #include "aimrt_module_protobuf_interface/channel/protobuf_channel.h" #include "aimrt_module_protobuf_interface/util/protobuf_tools.h" - #include "yaml-cpp/yaml.h" bool NormalSubscriberModule::Initialize(aimrt::CoreRef core) { - core_ = core; + ctx_ptr_ = std::make_shared(core); + ctx_ptr_->LetMe(); try { // Read cfg - auto file_path = core_.GetConfigurator().GetConfigFilePath(); + auto file_path = ctx_ptr_->GetConfigFilePath(); if (!file_path.empty()) { YAML::Node cfg_node = YAML::LoadFile(std::string(file_path)); topic_name_ = cfg_node["topic_name"].as(); } - // Register subscriber(it contains two steps) - // Step1: get subscriber handle with topic name - subscriber_ = core_.GetChannelHandle().GetSubscriber(topic_name_); - AIMRT_CHECK_ERROR_THROW(subscriber_, "Get subscriber for topic '{}' failed.", topic_name_); - - // Step2: register callback function for subscriber (aimrt_samples::protocols::EventMsg is the message type) - bool ret = aimrt::channel::Subscribe( - subscriber_, - std::bind(&NormalSubscriberModule::EventHandle, this, std::placeholders::_1, std::placeholders::_2)); - AIMRT_CHECK_ERROR_THROW(ret, "Subscribe failed."); + // Register subscriber + subscriber_ = ctx_ptr_->CreateSubscriber(topic_name_, + std::bind(&NormalSubscriberModule::EventHandle, this, std::placeholders::_1, std::placeholders::_2)); } catch (const std::exception& e) { AIMRT_ERROR("Init failed, {}", e.what()); return false; } - AIMRT_INFO("Init succeeded."); - return true; } bool NormalSubscriberModule::Start() { return true; } -void NormalSubscriberModule::Shutdown() {} +void NormalSubscriberModule::Shutdown() { ctx_ptr_->StopRunning(); } -// This is the callback function for subscriber. When new message arrives, this function will be called. -// aimrt_samples::protocols::EventMsg is the message type (you can define your own message type). void NormalSubscriberModule::EventHandle( aimrt::channel::ContextRef ctx, const std::shared_ptr& data) { diff --git a/my_pb_channel/src/module/normal_subscriber_module/normal_subscriber_module.h b/my_pb_channel/src/module/normal_subscriber_module/normal_subscriber_module.h index 9caa9dc..67d31b8 100755 --- a/my_pb_channel/src/module/normal_subscriber_module/normal_subscriber_module.h +++ b/my_pb_channel/src/module/normal_subscriber_module/normal_subscriber_module.h @@ -3,7 +3,7 @@ #pragma once -#include "aimrt_module_cpp_interface/module_base.h" +#include "aimrt_module_cpp_interface/aimrt_module_cpp_interface.h" #include "event.pb.h" @@ -22,14 +22,12 @@ class NormalSubscriberModule : public aimrt::ModuleBase { void Shutdown() override; private: - auto GetLogger() { return core_.GetLogger(); } - void EventHandle(aimrt::channel::ContextRef ctx, const std::shared_ptr& data); private: - aimrt::CoreRef core_; + std::shared_ptr ctx_ptr_; std::string topic_name_ = "test_topic"; - aimrt::channel::SubscriberRef subscriber_; + aimrt::context::res::Subscriber subscriber_; }; diff --git a/my_pb_channel/src/pkg/my_pb_channel_pkg/CMakeLists.txt b/my_pb_channel/src/pkg/my_pb_channel_pkg/CMakeLists.txt new file mode 100644 index 0000000..472247a --- /dev/null +++ b/my_pb_channel/src/pkg/my_pb_channel_pkg/CMakeLists.txt @@ -0,0 +1,18 @@ +# Set target name +set(CUR_TARGET_NAME "my_pb_channel_pkg") + +# Set file collection +file(GLOB_RECURSE src ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +# Add target +add_library(${CUR_TARGET_NAME} SHARED) + +# Set source file of target +target_sources(${CUR_TARGET_NAME} PRIVATE ${src}) + +# Set link libraries of target +target_link_libraries( + ${CUR_TARGET_NAME} + PRIVATE aimrt::interface::aimrt_pkg_c_interface + my_pb_channel::normal_publisher_module + my_pb_channel::normal_subscriber_module) diff --git a/my_pb_channel/src/pkg/my_pb_channel_pkg/pkg_main.cc b/my_pb_channel/src/pkg/my_pb_channel_pkg/pkg_main.cc new file mode 100644 index 0000000..0761d49 --- /dev/null +++ b/my_pb_channel/src/pkg/my_pb_channel_pkg/pkg_main.cc @@ -0,0 +1,11 @@ +#include "aimrt_pkg_c_interface/pkg_macro.h" +#include "normal_publisher_module/normal_publisher_module.h" +#include "normal_subscriber_module/normal_subscriber_module.h" + +static std::tuple> aimrt_module_register_array[]{ + // Here register all modules in the package + {"NormalPublisherModule", []() -> aimrt::ModuleBase* { return new NormalPublisherModule(); }}, + {"NormalSubscriberModule", []() -> aimrt::ModuleBase* { return new NormalSubscriberModule(); }}, +}; + +AIMRT_PKG_MAIN(aimrt_module_register_array)