### Timer Usage Example Source: https://docs.aimrt.org/tutorials/interface_cpp/executor.html A practical example demonstrating the initialization, starting, resetting, and cancellation of a timer within a module. ```APIDOC ## Timer Usage Example ### Description This example illustrates how to set up and manage a timer within a `TimerModule`. It shows obtaining an executor, creating a timer with a lambda task, and using `Reset()` to reschedule the timer at different time points. ### Code Snippet ```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(); } ``` ``` -------------------------------- ### Timer Module Initialization and Start Source: https://docs.aimrt.org/tutorials/interface_cpp/executor.html Demonstrates initializing a TimerModule by getting a timer-capable executor and starting a timer with a task that logs execution count and cancels after 10 executions. ```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/tutorials/interface_py/rpc.html This snippet shows a complete example of setting up and making an RPC call using the AimRT Python SDK. 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() ``` -------------------------------- ### Install Zenoh plugin dependencies (curl and Rust) Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Installs 'curl' to download the Rust installation script and then executes the script to set up the Rust environment, which is required for the Zenoh plugin. ```bash sudo apt install curl curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -------------------------------- ### Install MQTT plugin dependency (openssl) Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Installs the 'openssl' development library, which is a prerequisite for building the MQTT plugin for AimRT. ```bash sudo apt install libssl-dev ``` -------------------------------- ### Start OpenTelemetry Collector Source: https://docs.aimrt.org/tutorials/plugins/opentelemetry_plugin.html Start the OpenTelemetry collector using a configuration file. Alternatively, use Docker for deployment. ```bash otelcol --config=my-otel-collector-config.yaml ``` -------------------------------- ### Basic RPC Configuration Source: https://docs.aimrt.org/tutorials/cfg/rpc.html A simple example demonstrating the basic structure for configuring RPC backends, client options, and server options. ```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: [] ``` -------------------------------- ### Install aimrt_cli via Python Environment Source: https://docs.aimrt.org/tutorials/cli_tool/cli_tool.html Install the aimrt_cli tool into your Python environment by building a wheel from source and then using pip. Ensure the installation directory is in your PATH. ```bash cd /src/tools/aimrt_cli python -m build --wheel pip install dist/aimrt_cli-*.whl ``` -------------------------------- ### Local RPC Backend with Timeout Executor Source: https://docs.aimrt.org/tutorials/cfg/rpc.html Example configuring the 'local' RPC backend with a specific timeout executor. This setup is relevant when Client and Server are in different Pkgs. ```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] ``` -------------------------------- ### Install build essentials (make, gcc, g++) Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Installs the necessary build tools: make, gcc, and g++. The default GCC version on Ubuntu 22.04 (11.4) is compatible with AimRT. ```bash sudo apt install make gcc g++ ``` -------------------------------- ### Configure Module Loading and Settings Source: https://docs.aimrt.org/tutorials/cfg/module.html This example demonstrates how to configure the loading of Pkg dynamic libraries and specify settings for individual modules. It includes paths to libraries, which modules to enable or disable, logging levels, and custom configuration file paths for modules. ```yaml aimrt: module: pkgs: - path: /path/to/libxxx_pkg.so enable_modules: [FooModule, BarModule] modules: - name: FooModule enable: True log_lvl: INFO cfg_file_path: /path/to/foo_module_cfg.yaml - name: BarModule enable: True log_lvl: WARN BarModule: foo_key: foo_val bar_key: bar_val ``` -------------------------------- ### Install Iceoryx plugin dependency (acl) Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Installs the 'acl' library, which is a required dependency for building the Iceoryx plugin for AimRT. ```bash sudo apt install libacl1-dev ``` -------------------------------- ### Start OpenTelemetry Collector with Docker Source: https://docs.aimrt.org/tutorials/plugins/opentelemetry_plugin.html Run the OpenTelemetry collector as a Docker container, mounting a configuration file and exposing necessary ports. ```bash docker run -itd -p 4317:4317 -p 4318:4318 -v /path/to/my-otel-collector-config.yaml:/etc/otelcol/config.yaml otel/opentelemetry-collector ``` -------------------------------- ### Synchronous RPC Call Example Source: https://docs.aimrt.org/tutorials/interface_cpp/rpc.html Demonstrates how to make a synchronous RPC call using the `ExampleServiceSyncProxy`. This involves registering the client, creating a proxy, preparing request and response objects, setting up a context with timeout, making the call, and handling the response. ```APIDOC ## Synchronous RPC Call Example (Protobuf) ### Description This example shows how to use a synchronous RPC client with protobuf. ### Steps 1. **Include Header**: Include the generated RPC header (e.g., `xxx.aimrt_rpc.pb.h`). 2. **Register Client**: Call `RegisterClientFunc` during initialization. 3. **Create Proxy**: Instantiate a synchronous proxy (e.g., `ExampleServiceSyncProxy`) with an `RpcHandleRef`. 4. **Prepare Request/Response**: Create and populate request objects, and prepare response objects. 5. **Create Context**: Optionally create a context and set properties like timeout. 6. **Make RPC Call**: Call the proxy method, passing the context, request, and response objects. The call blocks until the RPC completes. 7. **Handle Response**: Check the status and process the response. ### Code Example ```cpp #include "rpc.aimrt_rpc.pb.h" // Assuming HelloWorldModule and core_ are defined elsewhere 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(); // ... process message ... } else { // ... handle error ... } } ``` ``` -------------------------------- ### Set up ROS2 Humble environment Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Sources the ROS2 Humble setup script to configure the environment variables necessary for AimRT's ROS2 integration. This command must be run in the current shell session. ```bash source /opt/ros/humble/setup.bash ``` -------------------------------- ### Install CMake using official script Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Downloads and installs the latest CMake version from the official GitHub releases using a provided script. This method ensures you have a compatible version for AimRT. ```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 ``` -------------------------------- ### Start Jaeger Docker Instance Source: https://docs.aimrt.org/tutorials/plugins/opentelemetry_plugin.html Launch a Jaeger all-in-one Docker instance for distributed tracing. This instance listens on multiple ports for OTLP and Zipkin protocols. ```bash docker run -d \ -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \ -p 16686:16686 \ -p 4317:4317 \ -p 4318:4318 \ -p 9411:9411 \ jaegertracing/all-in-one:latest ``` -------------------------------- ### Install Python package build dependencies Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Installs pip and the necessary Python libraries (build, setuptools, wheel) for packaging AimRT Python interfaces into a wheel (.whl) file. This is required when building the Python package. ```bash sudo apt install python3 python3-pip pip install build setuptools wheel --upgrade ``` -------------------------------- ### Install Python CLI tools dependencies Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Installs pip and the required Python libraries (pyinstaller, jinja2, pyyaml) for building the AimRT CLI tools. Ensure Python 3 is installed prior to running this command. ```bash sudo apt install python3 python3-pip pip install pyinstaller jinja2 pyyaml --upgrade ``` -------------------------------- ### Pkg Mode C++ Macro Implementation Source: https://docs.aimrt.org/tutorials/interface_cpp/runtime.html This C++ example shows how to use the `AIMRT_PKG_MAIN` macro to simplify Pkg creation. It involves defining a static array of tuples, where each tuple contains a module name and a factory function to create the module instance. ```cpp #include "aimrt_pkg_c_interface/pkg_macro.h" #include "bar_module.h" #include "foo_module.h" static std::tuple> aimrt_module_register_array[]{ {"FooModule", []() -> aimrt::ModuleBase* { return new FooModule(); }}, {"BarModule", []() -> aimrt::ModuleBase* { return new BarModule(); }}}; AIMRT_PKG_MAIN(aimrt_module_register_array) ``` -------------------------------- ### Zenoh Plugin Configuration Example Source: https://docs.aimrt.org/tutorials/plugins/zenoh_plugin.html This configuration snippet shows how to enable 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 ``` -------------------------------- ### Install CMake via pip Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Installs CMake version 3.24 or higher using pip, as the default Ubuntu version is insufficient. Ensure python3 and python3-pip are installed first. ```bash sudo apt install python3 python3-pip pip install cmake --upgrade ``` -------------------------------- ### ROS2 Publisher Configuration Source: https://docs.aimrt.org/tutorials/plugins/ros2_plugin.html Configure the ROS2 backend for publishing messages. This example sets up a publisher node with specific QoS settings for all topics matching the regex "(.*)". ```yaml aimrt: plugin: plugins: - name: ros2_plugin path: ./libaimrt_ros2_plugin.so options: node_name: example_ros2_pub_node executor_type: MultiThreaded executor_thread_num: 4 channel: backends: - type: ros2 options: pub_topics_options: - topic_name: "(.*)" use_serialized: false qos: history: keep_last depth: 10 reliability: reliable durability: volatile deadline: -1 lifespan: -1 liveliness: automatic liveliness_lease_duration: -1 pub_topics_options: - topic_name: "(.*)" enable_backends: [ros2] ``` -------------------------------- ### Verify ROS2 environment setup Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Checks if the ROS2 environment variables have been correctly set by filtering the output of the 'printenv' command. This is a verification step after sourcing the ROS2 setup script. ```bash printenv | grep -i ROS ``` -------------------------------- ### Install Python 3 Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Installs Python 3, which is a minimum requirement for AimRT and its Python-related features. This command is necessary if Python 3 is not already present on the system. ```bash sudo apt install python3 ``` -------------------------------- ### Create Module and Publish Channel Message Source: https://docs.aimrt.org/tutorials/interface_cpp/runtime.html This C++ example demonstrates creating an AimRTCore instance, initializing it, creating a module using CoreRef, registering a message type, publishing a message, and then shutting down the core. It's suitable for creating small tools or quick utilities. ```cpp #include "core/aimrt_core.h" #include "aimrt_module_cpp_interface/core.h" #include "aimrt_module_protobuf_interface/channel/protobuf_channel.h" #include "event.pb.h" int32_t main(int32_t argc, char** argv) { // Create AimRTCore ins AimRTCore core; // Initialize AimRTCore ins AimRTCore::Options options; options.cfg_file_path = "path/to/cfg/xxx_cfg.yaml"; core.Initialize(options); // Create module aimrt::CoreRef core_handle(core.GetModuleManager().CreateModule("HelloWorldModule")); // Register a msg type for publish auto publisher = core_handle.GetChannelHandle().GetPublisher("test_topic"); aimrt::channel::RegisterPublishType(publisher); // Start AimRTCore ins auto fu = core.AsyncStart(); // Publish a message ExampleEventMsg msg; msg.set_msg("example msg"); aimrt::channel::Publish(publisher, msg); // Wait for seconds std::this_thread::sleep_for(std::chrono::seconds(5)); // Shutdown AimRTCore ins core.Shutdown(); // Wait for complete shutdown fu.wait(); return 0; } ``` -------------------------------- ### Timer Behavior Overview Source: https://docs.aimrt.org/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 ### Behavior Details - **Automatic Start**: Timers are automatically started upon creation by default (equivalent to calling `Reset()`). If `auto_start` is set to `false` during creation, the timer will be 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 and reschedule its next execution. The next execution time is calculated as the current time plus the timer's `period`. - **Task Overwriting**: Subsequent calls to `Reset()` can effectively overwrite the timer's task or its scheduling parameters, as the timer is re-initialized with the new configuration. - **Missed Cycles**: If the task execution takes longer than the timer's period, or if the executor experiences blocking operations, the timer will not compensate for missed execution cycles. Instead, it will reschedule the next execution for the subsequent period after the current task completes. For example, if a timer with a 1000ms period has a task that takes 1500ms to execute, and it was scheduled for 0ms, it will execute at 0ms, finish at 1500ms, miss the 1000ms slot, and the next execution will be rescheduled for 2000ms. ``` -------------------------------- ### ROS2 Subscriber Configuration Source: https://docs.aimrt.org/tutorials/plugins/ros2_plugin.html Configure the ROS2 backend for subscribing to messages. This example sets up a subscriber node with specific QoS settings for all topics matching the regex "(.*)". ```yaml aimrt: plugin: plugins: - name: ros2_plugin path: ./libaimrt_ros2_plugin.so options: node_name: example_ros2_sub_node executor_type: MultiThreaded executor_thread_num: 4 channel: backends: - type: ros2 options: sub_topics_options: - topic_name: "(.*)" use_serialized: false qos: history: keep_last depth: 10 reliability: reliable durability: volatile deadline: -1 lifespan: -1 liveliness: automatic liveliness_lease_duration: -1 sub_topics_options: - topic_name: "(.*)" enable_backends: [ros2] ``` -------------------------------- ### Minimal AimRT build configuration and compilation Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Configures and builds AimRT with minimal dependencies, disabling tests and documentation, but enabling examples and core runtime components. This command sets up the build environment and then compiles the project. ```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 ``` -------------------------------- ### Setting Target Server MQTT ID in Context Source: https://docs.aimrt.org/tutorials/plugins/mqtt_plugin.html Example of setting the target server's MQTT ID in the context for a specific RPC call. This ensures the request is routed to the intended server. ```cpp auto ctx_ptr = proxy->NewContextSharedPtr(); // mqtt://{{target server mqtt id}} ctx_ptr->SetToAddr("mqtt://target_server_mqtt_id"); auto status = proxy->Foo(ctx_ptr, req, rsp); ``` -------------------------------- ### Configure time_wheel Executor Source: https://docs.aimrt.org/tutorials/cfg/executor.html Example of configuring a time_wheel executor, including binding it to another executor, setting tick interval, wheel sizes, and thread scheduling policies. The thread safety depends on the bound executor. ```yaml aimrt: executor: executors: - name: test_tbb_thread_executor type: tbb_thread options: thread_num: 2 - name: test_time_wheel_executor type: time_wheel options: bind_executor: test_tbb_thread_executor dt_us: 1000 wheel_size: [1000, 600] thread_sched_policy: SCHED_FIFO:80 thread_bind_cpu: [0] ``` -------------------------------- ### C++ AimRT Application with Signal Handling Source: https://docs.aimrt.org/tutorials/quick_start/helloworld_cpp.html This C++ code sets up a basic AimRT application. It includes signal handlers for SIGINT and SIGTERM to ensure graceful shutdown by calling `core.Shutdown()`. The application registers a HelloWorldModule, initializes the core with a configuration file path, starts the runtime, and then shuts it down. ```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; } ``` -------------------------------- ### Synchronous RPC Client Initialization and Call Source: https://docs.aimrt.org/tutorials/interface_cpp/rpc.html Demonstrates the steps for using a synchronous RPC interface, including registering the client, creating a proxy, and making a blocking RPC call. ```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 { // ... } } ``` -------------------------------- ### Create RPC Server and Serve on Executor Source: https://docs.aimrt.org/tutorials/interface_cpp/context.html Initializes an RPC server and uses ServeOn to handle requests on a specified executor. This is suitable for offloading heavier tasks from the main thread. ```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/tutorials/interface_cpp/context.html Initializes an RPC server and uses 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(); }); ``` -------------------------------- ### Launch AimRT Process with Pkg Support Source: https://docs.aimrt.org/tutorials/interface_cpp/runtime.html This command demonstrates how to launch the AimRT process using the `aimrt_main` executable. It specifies the configuration file path, which should include the path to the Pkg dynamic library. ```bash ./aimrt_main --cfg_file_path=/path/to/your/cfg/xxx_cfg.yaml ``` -------------------------------- ### CreateTimer Function Source: https://docs.aimrt.org/tutorials/interface_cpp/executor.html Creates a timer with a specified execution period and task. The timer can be configured to start automatically. ```APIDOC ## CreateTimer Function ### Description Creates a timer that executes a given task at a specified interval. The timer can be optionally started automatically upon creation. ### Signature ```cpp namespace aimrt::executor { template std::shared_ptr CreateTimer(ExecutorRef executor, std::chrono::nanoseconds period, TaskType&& task, bool auto_start = true); } // namespace aimrt::executor ``` ### Parameters - **executor** (`ExecutorRef`): The executor handle to be used for scheduling the timer. This executor must support timer scheduling (i.e., `SupportTimerSchedule()` returns `true`). - **period** (`std::chrono::nanoseconds`): The interval at which the timer task should be executed. - **task** (`TaskType&&`): A callable object (e.g., `std::function`, lambda, `std::bind`) representing the task to be executed. The task must match one of the following signatures: - `void()` - `void(TimerBase&)` - `void(const TimerBase&)` - **auto_start** (`bool`, optional, defaults to `true`): If `true`, the timer starts automatically upon creation. If `false`, the timer is created in a cancelled state. ``` -------------------------------- ### Full AimRT build with Gitee mirror for FetchContent Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Builds AimRT using the build.sh script, but first sources a script to redirect FetchContent downloads to a Gitee mirror. This is useful for improving download speeds or reliability in regions with poor network access to GitHub. ```bash source url_cn.bashrc ./build.sh $AIMRT_DOWNLOAD_FLAGS ``` -------------------------------- ### OpenTelemetry Collector Configuration Source: https://docs.aimrt.org/tutorials/plugins/opentelemetry_plugin.html Configure the OpenTelemetry collector to receive, process, and export telemetry data. This example uses OTLP for receiving and OTLP/HTTP for exporting. ```yaml receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: timeout: 5s send_batch_size: 1024 exporters: otlphttp: endpoint: http://xx.xx.xx.xx:4318 service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [otlphttp] ``` -------------------------------- ### Basic Executor Task Submission Source: https://docs.aimrt.org/tutorials/interface_cpp/executor.html Demonstrates how to obtain an executor handle and submit 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_; }; ``` -------------------------------- ### Get Time Manipulator Executor Ratio Source: https://docs.aimrt.org/tutorials/plugins/time_manipulator_plugin.html Use this to retrieve the current time ratio of a specific time manipulator executor. The executor must be active. ```bash curl -i \ -H 'content-type:application/json' \ -X POST 'http://127.0.0.1:50080/rpc/aimrt.protocols.time_manipulator_plugin.TimeManipulatorService/GetTimeRatio' \ -d '{"executor_name": "time_schedule_executor"}' ``` ```json HTTP/1.1 200 OK Content-Type: application/json Content-Length: 34 {"time_ratio":1,"code":0,"msg":""} ``` -------------------------------- ### Create Client Context from Server Context using Proxy Source: https://docs.aimrt.org/tutorials/interface_cpp/rpc.html Shows an alternative method to create a client-side context from a server-side context using the `Proxy::NewContextSharedPtr` method, facilitating context propagation. ```cpp ExampleServiceSyncProxy proxy; // RPC server handle function aimrt::rpc::Status ExampleServiceSyncServiceImpl::GetBarData( aimrt::rpc::ContextRef server_ctx, const GetBarDataReq& bar_req, GetBarDataRsp& bar_rsp) { GetFooDataReq foo_req; GetFooDataRsp foo_rsp; auto client_ctx = proxy.NewContextSharedPtr(server_ctx); auto foo_status = proxy.GetFooData(client_ctx, req, rsp); // ... return aimrt::rpc::Status(); } ``` -------------------------------- ### Call GetRecordActionStatus (All Actions) via HTTP Source: https://docs.aimrt.org/tutorials/plugins/record_playback_plugin.html Example using curl to call the GetRecordActionStatus RPC endpoint via HTTP, querying the status of all record actions. ```bash data='{}' curl -i \ -H 'content-type:application/json' \ -X POST 'http://127.0.0.1:50080/rpc/aimrt.protocols.record_playback_plugin.RecordPlaybackService/GetRecordActionStatus' \ -d "$data" ``` -------------------------------- ### HTTP Message Publishing with Curl Source: https://docs.aimrt.org/tutorials/plugins/net_plugin.html Example of publishing a message to the HTTP channel backend using curl. This demonstrates sending a JSON payload to a specified topic. ```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}' ``` -------------------------------- ### Public RPC Proxy Base Interface Source: https://docs.aimrt.org/tutorials/interface_cpp/rpc.html Defines common methods for all RPC proxies, such as getting the RPC type, setting/getting the service name, and managing contexts. ```cpp class ProxyBase { public: std::string_view RpcType() const; void SetServiceName(std::string_view service_name); std::string_view ServiceName() const; std::shared_ptr NewContextSharedPtr(ContextRef ctx_ref = ContextRef()) const; void SetDefaultContextSharedPtr(const std::shared_ptr& ctx_ptr); std::shared_ptr GetDefaultContextSharedPtr() const; }; class XXXProxy : public aimrt::rpc::CoProxyBase { public: explicit XXXProxy(aimrt::rpc::RpcHandleRef rpc_handle_ref); static bool RegisterClientFunc(aimrt::rpc::RpcHandleRef rpc_handle_ref); static bool RegisterClientFunc(aimrt::rpc::RpcHandleRef rpc_handle_ref, std::string_view service_name); // ... } ``` -------------------------------- ### GetRecordActionStatus RPC Source: https://docs.aimrt.org/tutorials/plugins/record_playback_plugin.html The GetRecordActionStatus RPC allows you to query the recording status of one or all record actions. You can specify action names in the request, or leave it empty to get the status for all actions. ```APIDOC ## GetRecordActionStatus ### Description Retrieves the current recording status for specified or all record actions. ### Method POST ### Endpoint `/rpc/aimrt.protocols.record_playback_plugin.RecordPlaybackService/GetRecordActionStatus` ### Parameters #### Request Body - **action_names** (array of strings) - Optional - A list of record action names to query. If empty, the status for all record actions is returned. ### Request Example (All Actions) ```json { "action_names": [] } ``` ### Request Example (Specific Action) ```json { "action_names": ["my_signal_record"] } ``` ### Response #### Success Response (200) - **common_rsp** (object) - Common response structure. - **record_action_status_list** (array of objects) - A list of record action statuses. - **action_name** (string) - The name of the record action. - **record_enabled** (boolean) - The global recording status for this action. - **topic_meta_list** (array of objects) - A list of topic statuses within the action. - **topic_name** (string) - The name of the topic. - **msg_type** (string) - The message type of the topic. - **record_enabled** (boolean) - The recording status for this specific topic. - **sample_freq** (number) - The sampling frequency for this topic. ``` -------------------------------- ### Thread-Safe Executor Task Submission Source: https://docs.aimrt.org/tutorials/interface_cpp/executor.html Shows how to submit tasks to a thread-safe executor. Tasks submitted to such executors do not require explicit locking for thread safety. The example increments a counter concurrently. ```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_; }; ``` -------------------------------- ### MQTT Publisher Configuration Source: https://docs.aimrt.org/tutorials/plugins/mqtt_plugin.html Configure the MQTT plugin as a publisher. Ensure the broker address, client ID, and maximum package size are set. Define rules for publishing topics, including the topic name (supporting regex) and QoS level. ```yaml aimrt: plugin: plugins: - name: mqtt_plugin path: ./libaimrt_mqtt_plugin.so options: broker_addr: tcp://127.0.0.1:1883 client_id: example_publisher max_pkg_size_k: 1024 channel: backends: - type: mqtt options: pub_topics_options: - topic_name: "(.*)" qos: 2 pub_topics_options: - topic_name: "(.*)" enable_backends: [mqtt] ``` -------------------------------- ### ProxyBase Public Interface Source: https://docs.aimrt.org/tutorials/interface_cpp/rpc.html The `ProxyBase` class provides common interfaces for all Proxies, including methods for retrieving RPC type, setting and getting service names, and managing default contexts. ```APIDOC ## ProxyBase Class ### Description Provides common interfaces for all Proxies. ### Methods - `std::string_view RpcType() const;` - Gets the RPC type. - `void SetServiceName(std::string_view service_name);` - Sets the RPC service name. - `std::string_view ServiceName() const;` - Gets the RPC service name. - `std::shared_ptr NewContextSharedPtr(ContextRef ctx_ref = ContextRef()) const;` - Creates a new shared context pointer. - `void SetDefaultContextSharedPtr(const std::shared_ptr& ctx_ptr);` - Sets the default context shared pointer. - `std::shared_ptr GetDefaultContextSharedPtr() const;` - Gets the default context shared pointer. ``` -------------------------------- ### Full AimRT build using build.sh script Source: https://docs.aimrt.org/tutorials/quick_start/build_from_source_ubuntu.html Executes the main build script for AimRT, which handles the complete build process including fetching all necessary dependencies. This is the recommended method for a full build. ```bash ./build.sh ``` -------------------------------- ### Call GetRecordActionStatus (Specific Action) via HTTP Source: https://docs.aimrt.org/tutorials/plugins/record_playback_plugin.html Example using curl to call the GetRecordActionStatus RPC endpoint via HTTP, specifying a particular record action ('my_signal_record') to query its status. ```bash data='{ "action_names": ["my_signal_record"] }' curl -i \ -H 'content-type:application/json' \ -X POST 'http://127.0.0.1:50080/rpc/aimrt.protocols.record_playback_plugin.RecordPlaybackService/GetRecordActionStatus' \ -d "$data" ``` -------------------------------- ### YAML Configuration for HelloWorldModule Source: https://docs.aimrt.org/tutorials/quick_start/helloworld_cpp.html This YAML file defines configuration settings for the AimRT application. It includes settings for logging levels and backends, as well as custom configuration parameters for the HelloWorldModule, such as 'key1' and 'key2'. ```yaml aimrt: log: # log配置 core_lvl: INFO # 内核日志等级,可选项:Trace/Debug/Info/Warn/Error/Fatal/Off,不区分大小写 backends: # 日志后端 - type: console # 控制台日志 # 模块自定义配置,框架会为每个模块生成临时配置文件,开发者通过Configurator接口获取该配置文件路径 HelloWorldModule: key1: val1 key2: val2 ``` -------------------------------- ### Configure tbb_thread Executor Source: https://docs.aimrt.org/tutorials/cfg/executor.html Example of configuring a tbb_thread executor with specific options like thread count, scheduling policy, and CPU binding. Ensure thread_num is set to 1 for thread-safe execution. ```yaml aimrt: executor: executors: - name: test_tbb_thread_executor type: tbb_thread options: thread_num: 2 thread_sched_policy: SCHED_FIFO:80 thread_bind_cpu: [0, 1] timeout_alarm_threshold_us: 1000 queue_threshold: 10000 ``` -------------------------------- ### Task Submission with Dynamic Latch Source: https://docs.aimrt.org/tutorials/interface_cpp/executor.html Demonstrates submitting tasks to an executor and using a `DynamicLatch` to synchronize completion. It's recommended to use `CloseAndWait` for simplicity. ```cpp auto exec = core_.GetExecutorManager().GetExecutor("work_executor"); aimrt::util::DynamicLatch latch; for (int i = 0; i < 1000; ++i) { bool accepted = exec.Execute(latch, [i]() noexcept { }); if (!accepted) { break; } } // 推荐直接使用 CloseAndWait,一步到位,简洁高效 latch.CloseAndWait(); // 如需分步骤,可先 Close 再 Wait // latch.Close(); // latch.Wait(); ``` -------------------------------- ### Configure Main Thread Settings Source: https://docs.aimrt.org/tutorials/cfg/main_thread.html Use this configuration to set the name, scheduling policy, and CPU binding for the main thread. Refer to Common Information for details on thread binding. ```yaml aimrt: main_thread: name: main_thread thread_sched_policy: SCHED_FIFO:80 thread_bind_cpu: [0, 1] ``` -------------------------------- ### Get Time Manipulator Executor Time Ratio Source: https://docs.aimrt.org/tutorials/plugins/time_manipulator_plugin.html The GetTimeRatio API retrieves the current time ratio of a specified time_manipulator executor. It requires the executor name and returns the time ratio along with status information. ```APIDOC ## GetTimeRatio GetTimeRatio ### Description Retrieves the current time ratio of a specific time_manipulator executor. ### Method POST ### Endpoint /rpc/aimrt.protocols.time_manipulator_plugin.TimeManipulatorService/GetTimeRatio ### Parameters #### Request Body - **executor_name** (string) - Required - The name of the executor to get the time ratio from. ### Request Example ```json { "executor_name": "time_schedule_executor" } ``` ### Response #### Success Response (200) - **time_ratio** (double) - The current time ratio. - **code** (uint32) - The status code of the operation. - **msg** (string) - A message indicating the result of the operation. #### Response Example ```json { "time_ratio": 1, "code": 0, "msg": "" } ``` ``` -------------------------------- ### Log and Throw Exception with Default Logger Source: https://docs.aimrt.org/tutorials/interface_cpp/logger.html Logs a message using the default logger handle and then throws an exception. ```cpp AIMRT_ERROR_THROW("Error occurred: {}", msg); ``` -------------------------------- ### Pkg Mode C Interface Definitions Source: https://docs.aimrt.org/tutorials/interface_cpp/runtime.html These are the C interface definitions required for creating a Pkg dynamic library. They define functions to get the number of modules, list module names, create modules, and destroy modules. ```c #ifdef __cplusplus extern "C" { #endif // Get the num of modules in the pkg size_t AimRTDynlibGetModuleNum(); // Get the list of module names in the pkg const aimrt_string_view_t* AimRTDynlibGetModuleNameList(); // Create a module with the name const aimrt_module_base_t* AimRTDynlibCreateModule(aimrt_string_view_t module_name); // Destroy module void AimRTDynlibDestroyModule(const aimrt_module_base_t* module_ptr); #ifdef __cplusplus } #endif ``` -------------------------------- ### Configure AimRT Guard Thread Source: https://docs.aimrt.org/tutorials/cfg/guard_thread.html Example of configuring the guard thread with a custom name, FIFO scheduling policy, CPU binding, and queue threshold. Ensure thread scheduling policies and CPU binding are supported by your operating system. ```yaml aimrt: guard_thread: name: guard_thread thread_sched_policy: SCHED_FIFO:80 thread_bind_cpu: [0, 1] queue_threshold: 10000 ```