### Timer Module Initialization and Start Example Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/executor.html Demonstrates initializing a TimerModule, obtaining a timer-capable executor, and creating a timer with a task that logs execution count and cancels after 10 executions. It also shows resetting the timer at specific intervals using `ExecuteAfter`. ```cpp bool TimerModule::Initialize(aimrt::CoreRef core) { core_ = core; timer_executor_ = core_.GetExecutorManager().GetExecutor("timer_executor"); AIMRT_CHECK_ERROR_THROW(timer_executor_, "Can not get timer_executor"); AIMRT_CHECK_ERROR_THROW(timer_executor_.SupportTimerSchedule(), "timer_executor does not support timer schedule"); return true; } bool TimerModule::Start() { using namespace std::chrono_literals; auto start_time = timer_executor_.Now(); auto task = [logger = core_.GetLogger(), start_time](aimrt::executor::TimerBase& timer) { static int count = 0; auto now = timer.Executor().Now(); auto timepoint = std::chrono::duration_cast(now - start_time).count(); AIMRT_HL_INFO(logger, "Executed {} times, execute timepoint: {} ms", ++count, timepoint); if (count >= 10) { timer.Cancel(); AIMRT_HL_INFO(logger, "Timer cancelled at timepoint: {} ms", timepoint); } }; timer_ = aimrt::executor::CreateTimer(timer_executor_, 100ms, std::move(task)); AIMRT_INFO("Timer created at timepoint: 0 ms"); timer_executor_.ExecuteAfter(350ms, [this, logger = core_.GetLogger()]() { timer_->Reset(); AIMRT_HL_INFO(logger, "Timer reset at timepoint: 350 ms"); }); timer_executor_.ExecuteAfter(600ms, [this, logger = core_.GetLogger()]() { timer_->Reset(); AIMRT_HL_INFO(logger, "Timer reset at timepoint: 600 ms"); }); return true; } void TimerModule::Shutdown() { timer_->Cancel(); } ``` -------------------------------- ### Python RPC Client Call Example Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_py/rpc.html This example shows the complete process of setting up and making an RPC call using the AimRT Python client. It includes initialization, module creation, client registration, starting the core, and executing a synchronous RPC call with context and request objects. ```python import aimrt_py import threading import time import datetime from google.protobuf.json_format import MessageToJson import rpc_pb2 import rpc_aimrt_rpc_pb2 def main(): aimrt_core = aimrt_py.Core() # Initialize core_options = aimrt_py.CoreOptions() core_options.cfg_file_path = "path/to/cfg/xxx_cfg.yaml" aimrt_core.Initialize(core_options) # Create Module module_handle = aimrt_core.CreateModule("NormalRpcClientPyModule") # Register rpc client rpc_handle = module_handle.GetRpcHandle() ret = rpc_aimrt_rpc_pb2.ExampleServiceProxy.RegisterClientFunc(rpc_handle) assert ret, "Register client failed." # Start thread = threading.Thread(target=aimrt_core.Start) thread.start() # Sleep for seconds time.sleep(1) # Call rpc proxy = rpc_aimrt_rpc_pb2.ExampleServiceProxy(rpc_handle) req = rpc_pb2.GetFooDataReq() req.msg = "example msg" ctx = aimrt_py.RpcContext() ctx.SetTimeout(datetime.timedelta(seconds=30)) ctx.SetMetaValue("key1", "value1") status, rsp = proxy.GetFooData(ctx, req) aimrt_py.info(module_handle.GetLogger(), f"Call rpc done, " f"status: {status.ToString()}, " f"req: {MessageToJson(req)}, " f"rsp: {MessageToJson(rsp)}") # Shutdown aimrt_core.Shutdown() thread.join() if __name__ == '__main__': main() ``` -------------------------------- ### Basic RPC Configuration Example Source: https://docs.aimrt.org/v1.6.0/tutorials/cfg/rpc.html This example demonstrates a basic configuration for RPC backends, client routing, and server routing using 'local' and 'mqtt' backends. ```yaml aimrt: rpc: backends: - type: local - type: mqtt clients_options: - func_name: "(.*)" enable_backends: [local] enable_filters: [] servers_options: - func_name: "(.*)" enable_backends: [local] enable_filters: [] ``` -------------------------------- ### Timer Usage Example Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/executor.html A practical example demonstrating the initialization of a module, creation of a timer, and dynamic resetting of the timer's schedule. ```APIDOC ## Timer Usage Example ### Description This example illustrates how to initialize a module that utilizes timers, create a timer with a specific task, and dynamically adjust the timer's schedule using `Reset()` calls triggered by other executor tasks. ### Code Snippet ```cpp // Assume TimerModule class and its members (core_, timer_executor_, timer_) are defined elsewhere. bool TimerModule::Initialize(aimrt::CoreRef core) { core_ = core; // Get an executor that supports timer scheduling. timer_executor_ = core_.GetExecutorManager().GetExecutor("timer_executor"); AIMRT_CHECK_ERROR_THROW(timer_executor_, "Can not get timer_executor"); AIMRT_CHECK_ERROR_THROW(timer_executor_.SupportTimerSchedule(), "timer_executor does not support timer schedule"); return true; } bool TimerModule::Start() { using namespace std::chrono_literals; auto start_time = timer_executor_.Now(); // Define the timer task. auto task = [logger = core_.GetLogger(), start_time](aimrt::executor::TimerBase& timer) { static int count = 0; auto now = timer.Executor().Now(); auto timepoint = std::chrono::duration_cast(now - start_time).count(); AIMRT_HL_INFO(logger, "Executed {} times, execute timepoint: {} ms", ++count, timepoint); // Cancel the timer after 10 executions. if (count >= 10) { timer.Cancel(); AIMRT_HL_INFO(logger, "Timer cancelled at timepoint: {} ms", timepoint); } }; // Create the timer with a 100ms period. timer_ = aimrt::executor::CreateTimer(timer_executor_, 100ms, std::move(task)); AIMRT_INFO("Timer created at timepoint: 0 ms"); // Schedule a task to reset the timer after 350ms. timer_executor_.ExecuteAfter(350ms, [this, logger = core_.GetLogger()]() { timer_->Reset(); AIMRT_HL_INFO(logger, "Timer reset at timepoint: 350 ms"); }); // Schedule another task to reset the timer after 600ms. timer_executor_.ExecuteAfter(600ms, [this, logger = core_.GetLogger()]() { timer_->Reset(); AIMRT_HL_INFO(logger, "Timer reset at timepoint: 600 ms"); }); return true; } void TimerModule::Shutdown() { // Ensure the timer is cancelled upon shutdown. if (timer_) { timer_->Cancel(); } } ``` ``` -------------------------------- ### Install Rust Environment for Zenoh Plugin Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Installs curl and then uses it to download and execute the official Rust installation script, setting up the Rust environment required for the Zenoh plugin. ```bash sudo apt install curl curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -------------------------------- ### Install Build Essentials (make, gcc, g++) Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Installs the necessary build tools, including make, gcc, and g++, which are required for compiling C++ projects like AimRT. ```bash sudo apt install make gcc g++ ``` -------------------------------- ### Command to Start AimRT Runtime with Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/runtime.html Demonstrates the command-line usage for starting the AimRT runtime executable (`aimrt_main`) with a specified configuration file path. This is the primary method for launching AimRT applications that utilize Pkg modules. ```bash ./aimrt_main --cfg_file_path=/path/to/your/cfg/xxx_cfg.yaml ``` -------------------------------- ### MQTT Plugin Server Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/mqtt_plugin.html Example configuration for an AimRT server utilizing the MQTT plugin for RPC. This setup allows the server to receive and process RPC requests via MQTT. ```yaml aimrt: plugin: plugins: - name: mqtt_plugin path: ./libaimrt_mqtt_plugin.so options: broker_addr: tcp://127.0.0.1:1883 client_id: example_server max_pkg_size_k: 1024 rpc: backends: - type: mqtt options: servers_options: - func_name: "(.*)" allow_share: true qos: 0 servers_options: - func_name: "(.*)" enable_backends: [mqtt] ``` -------------------------------- ### Minimal AimRT Build Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Configures and builds AimRT with minimal dependencies, enabling examples and runtime components but disabling tests and CLI tools. This is a starting point for building AimRT. ```bash cmake -B build \ -DCMAKE_BUILD_TYPE=Release \ -DAIMRT_INSTALL=ON \ -DCMAKE_INSTALL_PREFIX=./build/install \ -DAIMRT_BUILD_TESTS=OFF \ -DAIMRT_BUILD_EXAMPLES=ON \ -DAIMRT_BUILD_PROTOCOLS=ON \ -DAIMRT_BUILD_DOCUMENT=OFF \ -DAIMRT_BUILD_RUNTIME=ON \ -DAIMRT_BUILD_CLI_TOOLS=OFF \ -DAIMRT_BUILD_PYTHON_RUNTIME=OFF \ -DAIMRT_USE_FMT_LIB=ON \ -DAIMRT_BUILD_WITH_PROTOBUF=ON \ -DAIMRT_USE_LOCAL_PROTOC_COMPILER=OFF \ -DAIMRT_USE_PROTOC_PYTHON_PLUGIN=OFF \ -DAIMRT_BUILD_WITH_ROS2=OFF \ -DAIMRT_BUILD_NET_PLUGIN=ON \ -DAIMRT_BUILD_MQTT_PLUGIN=OFF \ -DAIMRT_BUILD_ZENOH_PLUGIN=OFF \ -DAIMRT_BUILD_ICEORYX_PLUGIN=OFF \ -DAIMRT_BUILD_ROS2_PLUGIN=OFF \ -DAIMRT_BUILD_RECORD_PLAYBACK_PLUGIN=ON \ -DAIMRT_BUILD_TIME_MANIPULATOR_PLUGIN=ON \ -DAIMRT_BUILD_PARAMETER_PLUGIN=ON \ -DAIMRT_BUILD_LOG_CONTROL_PLUGIN=ON \ -DAIMRT_BUILD_SERVICE_INTROSPECTION_PLUGIN=ON \ -DAIMRT_BUILD_TOPIC_LOGGER_PLUGIN=ON \ -DAIMRT_BUILD_OPENTELEMETRY_PLUGIN=ON \ -DAIMRT_BUILD_GRPC_PLUGIN=ON \ -DAIMRT_BUILD_PYTHON_PACKAGE=OFF cmake --build build --config Release --target all -j ``` -------------------------------- ### Install OpenSSL for MQTT Plugin Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Installs the libssl-dev package, which provides the OpenSSL development libraries needed for AimRT's MQTT plugin. ```bash sudo apt install libssl-dev ``` -------------------------------- ### Install CMake using Official Script Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Downloads and installs a specific version of CMake using its official installation script. This method ensures a compatible CMake version if the system's default is too old. ```bash wget https://github.com/Kitware/CMake/releases/download/v3.30.4/cmake-3.30.4-linux-x86_64.sh sudo bash cmake-3.30.4-linux-x86_64.sh --prefix=/usr/local --skip-license ``` -------------------------------- ### MQTT Plugin Configuration Example Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/mqtt_plugin.html This snippet shows how to configure the MQTT plugin in a YAML file. Ensure the broker address is valid and the client ID is unique. ```yaml aimrt: plugin: plugins: - name: mqtt_plugin path: ./libaimrt_mqtt_plugin.so options: broker_addr: tcp://127.0.0.1:1883 client_id: example_mqtt_client max_pkg_size_k: 1024 ``` -------------------------------- ### Launch AimRT Process with Pkg Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/runtime.html This example shows how to launch the AimRT runtime executable (`aimrt_main`) with a configuration file that specifies the path to a Pkg dynamic library. This allows the runtime to load and utilize modules from the Pkg. ```yaml aimrt: module: pkgs: - path: /path/to/your/pkg/libxxx_pkg.so ``` -------------------------------- ### Install Python and Pip for CMake Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Installs Python 3 and pip, which are required for installing CMake via pip. This is an alternative to downloading the CMake binary directly. ```bash sudo apt install python3 python3-pip pip install cmake --upgrade ``` -------------------------------- ### Set up ROS2 Humble Environment Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Sources the ROS2 Humble setup script to configure the environment for ROS2 integration with AimRT. This is necessary for using ROS2-related features and plugins. ```bash source /opt/ros/humble/setup.bash ``` -------------------------------- ### Install Iceoryx ACL Library Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Installs the libacl1-dev package, which is a required dependency for AimRT's Iceoryx plugin. ```bash sudo apt install libacl1-dev ``` -------------------------------- ### Synchronous RPC Call Example Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/rpc.html Demonstrates how to make a synchronous RPC call using a `SyncProxy`. This involves registering the client, creating a proxy instance, preparing request and response objects, setting up context with timeout, and invoking the RPC method. ```cpp #include "rpc.aimrt_rpc.pb.h" bool HelloWorldModule::Initialize(aimrt::CoreRef core) { core_ = core; // Step 1: RegisterClientFunc aimrt::protocols::example::RegisterExampleServiceClientFunc(core_.GetRpcHandle()); return true; } // Step 2: Call rpc void HelloWorldModule::Foo() { // Step 2-1: Create a proxy ExampleServiceSyncProxy proxy(core_.GetRpcHandle()); // Step 2-2: Create req and rsp ExampleReq req; ExampleRsp rsp; req.set_msg("hello world"); // Step 2-3: Create context auto ctx = proxy.NewContextSharedPtr(); ctx->SetTimeout(std::chrono::seconds(3)); // Step 2-4: Call rpc auto status = proxy.ExampleFunc(ctx, req, rsp); // Step 2-5: Parse rsp if (status.OK()) { auto msg = rsp.msg(); // ... } else { // ... } } ``` -------------------------------- ### MQTT Plugin Client Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/mqtt_plugin.html Example configuration for an AimRT client using the MQTT plugin for RPC. Ensure the broker address and client ID are correctly set. ```yaml aimrt: plugin: plugins: - name: mqtt_plugin path: ./libaimrt_mqtt_plugin.so options: broker_addr: tcp://127.0.0.1:1883 client_id: example_client max_pkg_size_k: 1024 executor: executors: - name: timeout_handle type: time_wheel rpc: backends: - type: mqtt options: timeout_executor: timeout_handle clients_options: - func_name: "(.*)" qos: 0 clients_options: - func_name: "(.*)" enable_backends: [mqtt] ``` -------------------------------- ### Install Python Package Build Dependencies Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Installs Python 3 and essential packaging libraries (build, setuptools, wheel) needed for creating AimRT's Python wheel package. ```bash sudo apt install python3 python3-pip pip install build setuptools wheel --upgrade ``` -------------------------------- ### Proxy Plugin Configuration Example Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/proxy_plugin.html This configuration demonstrates how to set up the proxy_plugin to forward messages from an HTTP backend topic to Zenoh and ROS 2 backend topics. It specifies the type support package, the proxy action name, the executor, and the topic metadata including subscription and publication details. ```yaml aimrt: plugin: plugins: - name: proxy_plugin path: ./libaimrt_proxy_plugin.so options: type_support_pkgs: - path: ./libexample_pb_ts.so proxy_actions: - name: my_proxy options: executor: proxy_plugin_executor topic_meta_list: - sub_topic_name: test_topic_http pub_topic_name: [test_topic_zenoh, test_topic_ros2] msg_type: pb:aimrt.protocols.example.ExampleEventMsg - name: zenoh_plugin path: ./libaimrt_zenoh_plugin.so - name: ros2_plugin path: ./libaimrt_ros2_plugin.so options: node_name: example_ros2_pb_chn_publisher_node executor_type: MultiThreaded # SingleThreaded/StaticSingleThreaded/MultiThreaded/EventsExecutor executor_thread_num: 2 - name: net_plugin path: ./libaimrt_net_plugin.so options: thread_num: 4 http_options: listen_ip: 127.0.0.1 listen_port: 50081 channel: backends: - type: http - type: zenoh - type: ros2 sub_topics_options: - topic_name: test_topic_http enable_backends: [http] pub_topics_options: - topic_name: test_topic_zenoh enable_backends: [zenoh] - topic_name: test_topic_ros2 enable_backends: [ros2] # ... ``` -------------------------------- ### Zenoh Plugin Configuration Example Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/zenoh_plugin.html This configuration snippet shows how to enable and configure the Zenoh plugin within the AimRT framework, specifying the plugin path and options like the native configuration file path. ```yaml aimrt: plugin: plugins: - name: zenoh_plugin path: ./libaimrt_zenoh_plugin.so options: native_cfg_path: ./cfg/zenoh_native_config.json5 ``` -------------------------------- ### C++ Hello World Application with Signal Handling Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/helloworld_cpp.html This C++ main function sets up signal handlers for graceful shutdown, registers a HelloWorldModule, initializes and starts the AimRT core, and handles potential exceptions. ```cpp #include #include #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) { signal(SIGINT, SignalHandler); signal(SIGTERM, SignalHandler); std::cout << "AimRT start." << std::endl; try { 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]; core.Initialize(options); 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; } ``` -------------------------------- ### Install Python 3 Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Installs Python 3, which is a minimum requirement for AimRT and is used for various Python-related features. ```bash sudo apt install python3 ``` -------------------------------- ### Verify ROS2 Environment Setup Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Checks if the ROS2 environment variables have been correctly set by printing and filtering the environment. This helps confirm that ROS2 integration will work. ```bash printenv | grep -i ROS ``` -------------------------------- ### Zenoh Plugin Server Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/zenoh_plugin.html Example configuration for a Zenoh RPC server. Includes plugin loading, native configuration path, and server-side RPC options such as timeout executor and function name matching with shared memory enabled. ```yaml aimrt: plugin: plugins: - name: zenoh_plugin path: ./libaimrt_zenoh_plugin.so options: native_cfg_path: ./cfg/zenoh_native_config.json5 rpc: backends: - type: zenoh options: timeout_executor: timeout_handle servers_options: - func_name: "(.*)" shm_enabled: true servers_options: - func_name: "(.*)" enable_backends: [zenoh] ``` -------------------------------- ### Zenoh Plugin Publisher Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/zenoh_plugin.html Configure the Zenoh plugin as a publisher. This example sets up the plugin with a shared memory pool size and defines publishing options for topics, including enabling Zenoh backends for specific topics. ```yaml aimrt: plugin: plugins: - name: zenoh_plugin path: ./libaimrt_zenoh_plugin.so options: shm_pool_size: 1024 channel: backends: - type: zenoh options: pub_topics_options: - topic_name: "(.*)" shm_enabled: false pub_topics_options: - topic_name: "(.*)" enable_backends: [zenoh] ``` -------------------------------- ### Configure AimRT Guard Thread Source: https://docs.aimrt.org/v1.6.0/tutorials/cfg/guard_thread.html This example demonstrates how to configure the AimRT guard thread with custom settings for its name, scheduling policy, CPU binding, and queue task threshold. ```yaml aimrt: guard_thread: name: guard_thread thread_sched_policy: SCHED_FIFO:80 thread_bind_cpu: [0, 1] queue_threshold: 10000 ``` -------------------------------- ### Timer Behavior Overview Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/executor.html Explains the lifecycle and operational characteristics of timers, including automatic start, cancellation, resetting, and handling of missed execution cycles. ```APIDOC ## Timer Behavior Overview ### Automatic Start * Timers are automatically started upon creation by default (`auto_start = true`). This is equivalent to calling `Reset()` immediately after creation. * If `auto_start` is set to `false`, the timer is created in a cancelled state. ### Cancellation * Calling `Cancel()` will stop the timer and set its state to cancelled, regardless of whether it was previously started. ### Resetting * Calling `Reset()` will un-cancel the timer, reset its cancelled state, and reschedule the next execution. The next execution time is calculated as the current time plus the timer's period. * `Reset()` can be used to update the timer's task or period. Subsequent calls to `Reset()` will use the latest configuration. ### Missed Executions * If a timer task takes longer to execute than the timer's period, or if the executor experiences blocking operations, missed execution cycles will not be compensated. * Instead, the timer will simply schedule the next execution for the subsequent period after the current task completes. For example, if a timer with a 1000ms period starts at 0ms and finishes at 1500ms, missing the 1000ms execution, the next execution will be scheduled for 2000ms, not 1000ms. ``` -------------------------------- ### Zenoh Plugin Subscriber Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/zenoh_plugin.html Configure the Zenoh plugin as a subscriber. This example specifies a path to a native Zenoh configuration file and defines subscription options, enabling Zenoh backends for specific topics. ```yaml aimrt: plugin: plugins: - name: zenoh_plugin path: ./libaimrt_zenoh_plugin.so options: native_cfg_path: ./cfg/zenoh_native_config.json5 channel: backends: - type: zenoh sub_topics_options: - topic_name: "(.*)" enable_backends: [zenoh] ``` -------------------------------- ### Zenoh Plugin Client Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/zenoh_plugin.html Example configuration for a Zenoh RPC client. Specifies plugin loading, native configuration path, shared memory pool size, and client-side RPC options including timeout executor and function name matching. ```yaml aimrt: plugin: plugins: - name: zenoh_plugin path: ./libaimrt_zenoh_plugin.so options: native_cfg_path: ./cfg/zenoh_native_config.json5 shm_pool_size: 10240 executor: executors: - name: timeout_handle type: time_wheel options: bind_executor: work_thread_pool rpc: backends: - type: zenoh options: timeout_executor: timeout_handle clients_options: - func_name: "(.*)" shm_enabled: false clients_options: - func_name: "(.*)" enable_backends: [zenoh] ``` -------------------------------- ### Install Python CLI Tools Dependencies Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Installs Python 3 and necessary pip packages (pyinstaller, jinja2, pyyaml) required for building AimRT's command-line interface tools. ```bash sudo apt install python3 python3-pip pip install pyinstaller jinja2 pyyaml --upgrade ``` -------------------------------- ### Local RPC Backend with Timeout Executor Source: https://docs.aimrt.org/v1.6.0/tutorials/cfg/rpc.html This example configures the 'local' RPC backend to use a specific executor for handling timeouts, applicable when clients and servers are in different packages. ```yaml aimrt: executor: executors: - name: timeout_handle type: time_wheel rpc: backends: - type: local options: timeout_executor: timeout_handle clients_options: - func_name: "(.*)" enable_backends: [local] servers_options: - func_name: "(.*)" enable_backends: [local] ``` -------------------------------- ### Independent Logger Usage with SimpleLogger Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/logger.html Utilize the `SimpleLogger` from `util/log_util.h` for synchronous console logging. This example demonstrates various logging macros with C++20 format specifiers. ```cpp #include "util/log_util.h" int Main() { // Use a simple log handle provided in 'util/log_util.h', which will synchronously print logs on the console auto lgr = aimrt::common::util::SimpleLogger(); uint32_t n = 42; std::string s = "Hello world"; // Normal log macro AIMRT_HANDLE_LOG(lgr, aimrt::common::util::kLogLevelInfo, "This is a test log, n = {}, s = {}", n, s); AIMRT_HL_TRACE(lgr, "This is a test trace log, n = {}, s = {}", n, s); AIMRT_HL_DEBUG(lgr, "This is a test debug log, n = {}, s = {}", n, s); AIMRT_HL_INFO(lgr, "This is a test info log, n = {}, s = {}", n, s); AIMRT_HL_WARN(lgr, "This is a test warn log, n = {}, s = {}", n, s); AIMRT_HL_ERROR(lgr, "This is a test error log, n = {}, s = {}", n, s); AIMRT_HL_FATAL(lgr, "This is a test fatal log, n = {}, s = {}", n, s); // Check the expression and print the log only when it is false AIMRT_HL_CHECK_ERROR(lgr, n == 41, "Expression is not right, n = {}", n); // Print logs and throw exceptions AIMRT_HL_ERROR_THROW(lgr, "This is a test error log, n = {}, s = {}", n, s); // Check the expression, print the log and throw an exception when it is false AIMRT_HL_CHECK_TRACE_THROW(lgr, n == 41, "Expression is not right, n = {}", n); // ... } ``` -------------------------------- ### Debug GRPC Service with grpcurl Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/grpc_plugin.html Use grpcurl to send messages to a GRPC service for debugging. This example shows how to specify plaintext protocol, import paths, proto files, message content, and timeout. ```bash grpcurl -plaintext \ -import-path /path/to/aimrt/src/protocols/example \ -proto rpc.proto \ -d '{"msg": "test msg"}' \ -max-time 1.0 \ localhost:50050 aimrt.protocols.example.ExampleService/GetFooData \ -vv ``` -------------------------------- ### HTTP Message Publishing with Curl Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/net_plugin.html Example of sending a message to the HTTP channel backend using curl. This demonstrates the POST request format, content-type header, and URL structure. ```bash curl -i \ -H 'content-type:application/json' \ -X POST 'http://127.0.0.1:50080/channel/test_topic/pb%3Aaimrt.protocols.example.ExampleEventMsg' \ -d '{"msg": "test msg", "num": 123}' ``` -------------------------------- ### Custom Logger Interface Example Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/logger.html Define a custom logger class that implements the `GetLogLevel` and `Log` methods. This structure is compatible with AimRT's logging macros. ```cpp class YourLogger { public: uint32_t GetLogLevel() const { // ... } void Log(uint32_t lvl, uint32_t line, const char* file_name, const char* function_name, const char* log_data, size_t log_data_size) const { // ... } }; ``` -------------------------------- ### Python RPC Server Implementation with AimRT Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_py/rpc.html Implement a synchronous RPC service by inheriting from the generated service base class. Handle requests within the `handle` method, ensuring all operations are blocking and return a response. This example demonstrates service registration and core initialization. ```python import aimrt_py import threading import signal from google.protobuf.json_format import MessageToJson import rpc_pb2 import rpc_aimrt_rpc_pb2 global_aimrt_core = None def signal_handler(sig, frame): global global_aimrt_core if (global_aimrt_core and (sig == signal.SIGINT or sig == signal.SIGTERM)): global_aimrt_core.Shutdown() return sys.exit(0) class ExampleServiceImpl(rpc_aimrt_rpc_pb2.ExampleService): def __init__(self, logger): super().__init__() self.logger = logger @staticmethod def PrintMetaInfo(logger, ctx_ref): meta_keys = ctx_ref.GetMetaKeys() for key in meta_keys: aimrt_py.info(logger, f"meta key: {key}, value: {ctx_ref.GetMetaValue(key)}") def GetFooData(self, ctx_ref, req): rsp = rpc_pb2.GetFooDataRsp() rsp.msg = "echo " + req.msg ExampleServiceImpl.PrintMetaInfo(self.logger, ctx_ref) aimrt_py.info(self.logger, f"Server handle new rpc call. " f"context: {ctx_ref.ToString()}, " f"req: {MessageToJson(req)}, " f"return rsp: {MessageToJson(rsp)}") return aimrt_py.RpcStatus(), rsp def main(): signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) aimrt_core = aimrt_py.Core() global global_aimrt_core global_aimrt_core = aimrt_core # Initialize core_options = aimrt_py.CoreOptions() core_options.cfg_file_path = "path/to/cfg/xxx_cfg.yaml" aimrt_core.Initialize(core_options) # Create Module module_handle = aimrt_core.CreateModule("NormalRpcServerPymodule") # Register rpc service service = ExampleServiceImpl(module_handle.GetLogger()) ret = module_handle.GetRpcHandle().RegisterService(service) assert ret, "Register service failed." # Start thread = threading.Thread(target=aimrt_core.Start) thread.start() while thread.is_alive(): thread.join(1.0) if __name__ == '__main__': main() ``` -------------------------------- ### Post Tasks to a Thread-Safe Executor Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/executor.html Demonstrates posting multiple tasks to a thread-safe executor. Tasks executed on this type of executor do not require explicit locking for thread safety. The example includes a delay to observe the final count. ```cpp #include "aimrt_module_cpp_interface/module_base.h" class HelloWorldModule : public aimrt::ModuleBase { public: bool Initialize(aimrt::CoreRef core) override { core_ = core; return true; } bool Start() override { // Get an executor handle named 'thread_safe_executor' auto thread_safe_executor = core_.GetExecutorManager().GetExecutor("thread_safe_executor"); // Check AIMRT_CHECK_ERROR_THROW(thread_safe_executor && thread_safe_executor.ThreadSafe(), "Can not get thread_safe_executor"); // Post some tasks to this executor uint32_t n = 0; for (uint32_t ii = 0; ii < 10000; ++ii) { thread_safe_executor_.Execute([&n]() { n++; }); } std::this_thread::sleep_for(std::chrono::seconds(5)); AIMRT_INFO("Value of n is {}", n); } // ... private: aimrt::CoreRef core_; }; ``` -------------------------------- ### Run the Hello World Application Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/helloworld_cpp.html Command to execute the compiled application. Pass the configuration file path as a command-line argument. ```bash ./helloworld_app ./helloworld_cfg.yaml ``` -------------------------------- ### Create RPC Server and Serve on Executor Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/context.html Initialize an RPC server and use ServeOn to handle requests on a specified executor. This is recommended for heavier tasks to avoid blocking. ```cpp // Initialize 阶段创建服务端,使用 ServeOn 在指定执行器上处理请求 auto work_executor = ctx_->CreateExecutor("work_thread_pool"); auto server = ctx_->CreateServer(); server->GetFooData.ServeOn(work_executor, [this](aimrt::rpc::ContextRef ctx, const aimrt::protocols::example::GetFooDataReq& req, aimrt::protocols::example::GetFooDataRsp& rsp) { AIMRT_INFO("Handle GetFooData on executor: {}", aimrt::Pb2CompactJson(req)); rsp.set_msg("echo " + req.msg()); return aimrt::rpc::Status(); }); ``` -------------------------------- ### Create RPC Server and Serve Inline Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/context.html Initialize an RPC server and use ServeInline to handle requests directly on the backend executor. This method is not recommended for heavy tasks. ```cpp // Initialize 阶段创建服务端,使用 ServeInline 在后端执行器上处理(不推荐) auto server = ctx_->CreateServer(); server->GetBarData.ServeInline( [this](aimrt::rpc::ContextRef ctx, const aimrt::protocols::example::GetBarDataReq& req, aimrt::protocols::example::GetBarDataRsp& rsp) { AIMRT_INFO("Handle GetBarData: {}", aimrt::Pb2CompactJson(req)); rsp.set_msg("echo " + req.msg()); return aimrt::rpc::Status(); }); ``` -------------------------------- ### CreateTimer Function Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/executor.html Creates a timer with a specified executor, execution period, and task. The timer can be configured to start automatically. ```APIDOC ## CreateTimer ### Description Creates a timer that executes a given task periodically. The timer requires an executor that supports timer scheduling. ### Signature ```cpp template std::shared_ptr CreateTimer(ExecutorRef executor, std::chrono::nanoseconds period, TaskType&& task, bool auto_start = true); ``` ### Parameters * **executor** (`ExecutorRef`) - The executor to use for scheduling and executing the timer task. Must support timer scheduling (`SupportTimerSchedule() == true`). * **period** (`std::chrono::nanoseconds`) - The interval between timer task executions. * **task** (`TaskType&&`) - A callable object (e.g., `std::function`, lambda) representing the task to be executed. The task must have one of the following signatures: `void()`, `void(TimerBase&)`, or `void(const TimerBase&)`. * **auto_start** (`bool`, optional) - If `true` (default), the timer starts automatically upon creation. If `false`, the timer is created in a cancelled state. ### Return Value Returns a `std::shared_ptr` to the newly created timer object. ``` -------------------------------- ### 使用备用下载地址下载依赖 Source: https://docs.aimrt.org/v1.6.0/tutorials/concepts/cmake.html 当网络不佳导致从默认地址下载依赖失败时,可以通过设置 AIMRT_DOWNLOAD_FLAGS 环境变量来使用备选下载地址。首先需要 source 一个 bashrc 文件,然后将该环境变量添加到 CMake 生成命令中。 ```bash # Set AIMRT_DOWNLOAD_FLAGS to download from mirror site source url_cn.bashrc # Add AIMRT_DOWNLOAD_FLAGS to cmake generate command cmake -Bbuild ... $AIMRT_DOWNLOAD_FLAGS ``` -------------------------------- ### Post a Simple Task to an Executor Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/executor.html Obtain an executor handle and post a simple task for execution. Ensure the executor name is valid. ```cpp #include "aimrt_module_cpp_interface/module_base.h" class HelloWorldModule : public aimrt::ModuleBase { public: bool Initialize(aimrt::CoreRef core) override { core_ = core; return true; } bool Start() override { // Get an executor handle named 'work_executor' auto work_executor = core_.GetExecutorManager().GetExecutor("work_executor"); // Check AIMRT_CHECK_ERROR_THROW(work_executor, "Can not get work_executor"); // Post a task to this executor work_executor.Execute([this]() { AIMRT_INFO("This is a simple task"); }); } // ... private: aimrt::CoreRef core_; }; ``` -------------------------------- ### Implement Time-Scheduled Task Execution Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/executor.html Demonstrates how to use the Time Schedule interface to implement a timed loop. Tasks are scheduled to execute repeatedly after a specified delay. ```cpp #include "aimrt_module_cpp_interface/module_base.h" class HelloWorldModule : public aimrt::ModuleBase { public: bool Initialize(aimrt::CoreRef core) override { core_ = core; // Get an executor handle named 'time_schedule_executor' auto time_schedule_executor_ = core_.GetExecutorManager().GetExecutor("time_schedule_executor"); // Check AIMRT_CHECK_ERROR_THROW(time_schedule_executor_ && time_schedule_executor_.SupportTimerSchedule(), "Can not get time_schedule_executor"); return true; } // Task void ExecutorModule::TimeScheduleDemo() { // Check shutdown if (!run_flag_) return; AIMRT_INFO("Loop count : {}", loop_count_++); // Execute itself time_schedule_executor_.ExecuteAfter( std::chrono::seconds(1), std::bind(&ExecutorModule::TimeScheduleDemo, this)); } bool Start() override { TimeScheduleDemo(); } void ExecutorModule::Shutdown() { run_flag_ = false; std::this_thread::sleep_for(std::chrono::seconds(1)); } // ... private: aimrt::CoreRef core_; bool run_flag_ = true; uint32_t loop_count_ = 0; aimrt::executor::ExecutorRef time_schedule_executor_; }; ``` -------------------------------- ### Build with Gitee Mirror for FetchContent Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/build_from_source_ubuntu.html Builds AimRT while redirecting FetchContent downloads to a Gitee mirror using a custom bashrc file. This is useful for improving download speeds in regions with poor network connectivity to GitHub. ```bash source url_cn.bashrc ./build.sh $AIMRT_DOWNLOAD_FLAGS ``` -------------------------------- ### AimRT Runtime Logger Usage in a Module Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/logger.html Example of how a module developer can obtain and use the `aimrt::logger::LoggerRef` handle obtained from `CoreRef::GetLogger()` to log messages within the module. ```cpp #include "aimrt_module_cpp_interface/module_base.h" class HelloWorldModule : public aimrt::ModuleBase { public: bool Initialize(aimrt::CoreRef core) override { logger_ = core_.GetLogger(); uint32_t n = 42; std::string s = "Hello world"; AIMRT_TRACE("This is a test trace log, n = {}, s = {}", n, s); AIMRT_DEBUG("This is a test debug log, n = {}, s = {}", n, s); AIMRT_INFO("This is a test info log, n = {}, s = {}", n, s); AIMRT_WARN("This is a test warn log, n = {}, s = {}", n, s); AIMRT_ERROR("This is a test error log, n = {}, s = {}", n, s); AIMRT_FATAL("This is a test fatal log, n = {}, s = {}", n, s); } private: auto GetLogger() { return logger_; } private: aimrt::logger::LoggerRef logger_; }; ``` -------------------------------- ### Independent Logger Usage with Implicit Logger Handle Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_cpp/logger.html Leverage the `GetLogger()` interface for concise logging when a default logger is available. This example shows macros that implicitly use the logger returned by `GetLogger()`. ```cpp #include "util/log_util.h" auto GetLogger() { return aimrt::common::util::SimpleLogger(); } int Main() { uint32_t n = 42; std::string s = "Hello world"; // Normal log macro AIMRT_TRACE("This is a test trace log, n = {}, s = {}", n, s); AIMRT_DEBUG("This is a test debug log, n = {}, s = {}", n, s); AIMRT_INFO("This is a test info log, n = {}, s = {}", n, s); AIMRT_WARN("This is a test warn log, n = {}, s = {}", n, s); AIMRT_ERROR("This is a test error log, n = {}, s = {}", n, s); AIMRT_FATAL("This is a test fatal log, n = {}, s = {}", n, s); // Check the expression and print the log only when it is false AIMRT_CHECK_ERROR(n == 41, "Expression is not right, n = {}", n); // Print logs and throw exceptions AIMRT_ERROR_THROW("This is a test error log, n = {}, s = {}", n, s); // Check the expression, print the log and throw an exception when it is false AIMRT_CHECK_TRACE_THROW(n == 41, "Expression is not right, n = {}", n); // ... } ``` -------------------------------- ### Define Protobuf RPC Service Source: https://docs.aimrt.org/v1.6.0/tutorials/interface_py/rpc.html Define message structures and RPC services in a .proto file. This is the first step in using Protobuf for RPC. ```protobuf syntax = "proto3"; package example; message ExampleReq { string msg = 1; int32 num = 2; } message ExampleRsp { uint64 code = 1; string msg = 2; } service ExampleService { rpc ExampleFunc(ExampleReq) returns (ExampleRsp); } ``` -------------------------------- ### YAML Configuration for HelloWorldModule Source: https://docs.aimrt.org/v1.6.0/tutorials/quick_start/helloworld_cpp.html This YAML file defines configuration settings for the AimRT log and the HelloWorldModule. It specifies log levels and custom parameters for the module. ```yaml aimrt: log: # log配置 core_lvl: INFO # 内核日志等级,可选项:Trace/Debug/Info/Warn/Error/Fatal/Off,不区分大小写 backends: # 日志后端 - type: console # 控制台日志 # 模块自定义配置,框架会为每个模块生成临时配置文件,开发者通过Configurator接口获取该配置文件路径 HelloWorldModule: key1: val1 key2: val2 ``` -------------------------------- ### Configure GRPC Server Backend Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/grpc_plugin.html Configure the GRPC plugin as an RPC server. Specify the listen IP and port for incoming RPC requests. Ensure the listen port is not occupied. ```yaml aimrt: plugin: plugins: - name: grpc_plugin path: ./libaimrt_grpc_plugin.so options: thread_num: 4 listen_ip: 127.0.0.1 listen_port: 50080 rpc: backends: - type: grpc servers_options: - func_name: "(.*)" enable_backends: [grpc] ``` -------------------------------- ### Basic aimrt.log Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/cfg/log.html A simple configuration for the aimrt.log module, setting core and default module log levels and defining console and rotate_file backends. ```yaml aimrt: log: core_lvl: INFO default_module_lvl: INFO backends: - type: console - type: rotate_file options: path: ./log filename: examples_cpp_executor_real_time.log ``` -------------------------------- ### HTTP Channel Publisher Configuration Source: https://docs.aimrt.org/v1.6.0/tutorials/plugins/net_plugin.html Configure the HTTP channel backend for publishing messages. Specify topic names and the list of server URLs to send messages to. ```yaml aimrt: plugin: plugins: - name: net_plugin path: ./libaimrt_net_plugin.so options: thread_num: 4 channel: backends: - type: http options: pub_topics_options: - topic_name: "(.*)" server_url_list: ["127.0.0.1:50080"] pub_topics_options: - topic_name: "(.*)" enable_backends: [http] ```