5. Secondary Development Program Deployment
This section will provide a complete description of the secondary development tool chain structure and how it is used, as provided by the think-tank.
5.1 Development Tools and Installation
5.1.1 System Requirements
- Operating system: Ubuntu 22.04 LTS or higher (recommended Ubuntu 22.04 LTS)
- Other systems supported:
- MacOS 11.0 (Big Sur) or higher
- Windows 10/11 Professional or enterprise version (WSL2 to be enabled)
- Hardware Configuration
- CPU: 8 cores or more (recommended 16 cores)
- Memory: at least 32GB RAM (recommended 64 GB or more)
- Storage space: at least 100 GB available disk space (for Docker mirrors and containers)
- Network: Stable Internet connection (for downloading mirrors and dependence)
5.1.2 Create the Container Development Environment
It is recommended that the installation and configuration of Docker and vscode be completed on the mainframe before running the installation script.
- Obtaining a compressed package of AimDK-A3-v3.3-Bootstrap at the AimDK Downloading Centre to unpressure the catalogue structure as follows:
- devcontainer.json# Defines the configuration of the development packaging
- Setup_aimde.sh# installation script for the development environment
1. Implementation of script installation and development environment installation
./setup_aimde.sh
Hint: If this is the first time you configure Docker, the system may prompt you to restart the computer to apply the user group permission settings. Once restart is complete, the installation script can be rerun and installed.
- When vscode is automatically opened, the notification at the lower right corner will appear and click Reopen in Container
- Open a new Terminal in vscode, enter setup-init and follow the hint.
- See that Setup accessful represents setup successfully and can start developing and building the project
Copy DevKit package to mount directory
From the AimDK Download CenterGet the AimDK-A3-v3.3-DevKit compressor package and copy the DevKit package to the host mount directory~/sdk/a3/aimde/, the directory will automatically map into the container/workspaces/aimde/Path.
# Execute on host
cp *sdk-package-a3-v3.3.13-0-gb889a630d-2610080917-devkit.tar.gz ~/sdk/a3/aimde/
5.1.3 Container Contents
/sdk directory
The SDK Root Directory, which includes the definition of the communication protocol, the Python package, the use of examples, and the development of the tool chain, the Bazel Building Rules and the pre-record library (x8664/aarch64) to support the compilation, development and deployment of the project.
/sdk
├── aima_protocol/ # SDK communication protocol definitions (Protobuf / ROS 2 messages)
├── aima_protocol_py_pkg/ # Python package for SDK protocols
│ └── aimdk_proto-0.0.0+local-py3-none-any.whl # Wheel that can be installed directly with pip
├── aimdk_examples/ # SDK examples
└── dev_tools/ # Development and build tools
├── x86_64/ # Prebuilt SDK libraries (x86_64)
├── rk3588_aarch64/ # Prebuilt SDK libraries (RK3588/aarch64)
├── rule_ros2/ # Bazel build rules for ROS 2
├── sdk-buildchain/ # Integrated build repository (unified build entry point)
└── third_party_libs/ # Third-party dependencies
/opt/rockship directory
Provision of a cross-compiling tool chain for the RK 3588 platform and a partial tripartite repository.
/opt/rockship
├── rk3588_sysroot # Third-party libraries for ARM
└── rk3588-toolchain # Cross-compilation toolchain
/workspaces/aimde directory
Develops the workspace, which contains the AimDK communications protocol, the example code, and the development packaging configuration.aima_protocolandaimdk_examplesBysetup-initYou can modify, compile and debug directly here from SDK.
/workspaces/aimde
├── aima_protocol # SDK communication protocol definitions (Protobuf / ROS 2 messages)
├── aimdk_examples # SDK examples
└── .devcontainer # Dev Container configuration (image, mounts, environment variables, etc.)
5.2 Update Methods
To meet the needs of different stages of development, and taking into account the efficiency of renewal and environmental stability, SDK provides two flexible ways of updating. As SDK functions continue to overlap, bug fixes and optimizes performance, regular updates can help developers:
- Get the latest API interface and functionality
- Repair of known problems and enhancement of development experience and system stability
- Consistency with official document and example code versions
- Increased efficiency of compilation and operation as a result of optimized performance
Depending on the content of the update, the developer may choose an appropriate update strategy that ensures environmental integrity while improving the efficiency of the update:
Full Mirror Update
Scope of application:
- Major Version Upgrade: Significant changes in core components such as SDK framework, development tool chain, system dependency, etc.
- Environment completely reset: New development environment is needed to remove all historical configurations and caches
- Cross-Video Update: upgrade directly from older version to latest version
- System-level changes: updates of bottom components such as basic vessel mirrors, compilation tool chains, system libraries, etc.
- First deployment: Initial installation of the development environment by new users
Features:
- Ensuring environmental integrity and consistency
- Recent version containing all dependencies and configurations
- Long updating time (required to download and load full mirrors)
- Once the container is rebuilt, unsustained data will be lost.
DevKit package update
Scope of application:
- SDK Toolkit Reciprocal: update only SDK API, library files, development toolkit, etc.
- Quick patch repair: Fix bugs in SDK or add minor features
- Frequent Version Overlay: Development requires frequent testing of different DevKit versions
- Keep Packaging Configuration: Need to maintain the existing packaging environment and personal configuration unchanged
- Small version update: Update from v3.3-rc11 to small version changes such as v3.3-rc12
Features:
- Update fast (replace only)
/sdk/Contents) - Retain container configuration and user data
- Fit for frequent overlaps and tests
- Update SDK toolkit only, not the basic packaging environment
- Reliance on change at the bottom may require a full mirror update
5.2.2 How to Choose an Update Method?
| Update | Recommended modalities |
|---|---|
| SDK Large Version Upgrade (e. g. v3.2 v3.3) | Full Mirror Update |
| SDK small version upgrade (e.g. v3.3-rc11 v3.3-rc12) | DevKit package update |
| Compile Tool Chain Updates | Full Mirror Update |
| API Interface Change or Add | DevKit package update |
| System Reliance Library Upgrade | Full Mirror Update |
| Bug Repair Patch | DevKit package update |
| There's been an anomaly in the container environment. | Full Mirror Update |
5.2.3 Full Image Update
- Update mirror version configuration
Edit.devcontainer/devcontainer.jsonDocumentation, willimageThe field is updated to a new mirror version number:tongyong-public-cn-shanghai.cr.volces.com/sdk/sdk-image-a3-v3.3.13-0-gb889a630d-2610080917:latest
- Reconstruct the container
Execute command in VS Code:
- Press
F1orCtrl+Shift+POpen command panel - Enter and select:Dev Containers: Rebuild and Reopen in Container
5.2.4 DevKit Package Update
- Copy DevKit Package to Mount Directory
From the AimDK Download CenterGet the AimDK-A3-v3.3-DevKit compressor package and copy the DevKit package to the host mount directory~/sdk/a3/aimde/, the directory will automatically map into the container/workspaces/aimde/Path.
# Execute on host
cp *sdk-package-a3-v3.3.13-0-gb889a630d-2610080917-devkit.tar.gz ~/sdk/a3/aimde/
- Replace DevKit packages in containers
Enter the DevContainer terminal and perform the following command:
# Clear Old Version
sudo rm -rf /sdk/*
# Unpress New Version to /sdk/ Directory
sudo tar -xvf /workspaces/aimde/*sdk-package-a3-v3.3.13-0-gb889a630d-2610080917-devkit.tar.gz -C /sdk/
# Cleaning of compressed packages (optional)
rm -rf /workspaces/aimde/*sdk-package-a3-v3.3.13-0-gb889a630d-2610080917-devkit.tar.gz
5.2.5 Update the Workspace Project
When the SDK version is updated, the protocol definition and the example code in the synchronised workspace are required. The following steps are recommended:
1. Delete old version of the table of contents
rm -rf /workspaces/aimde/aima_protocol /workspaces/aimde/aimdk_examples
This operation removes all local changes under these two directories. If changes need to be kept, either backup or submit them to the version library.
2. Re-introduction of the workspace
setup-init
setup-initI'll pull back the latest from SDK.aima_protocolandaimdk_examplesGo to the workspace.
5.2.6 Notes
- Suggest backup of key data and configuration files before updating
- Make sure Docker's service is running properly
- The full mirror update will recreate the container and the data on non-sustainability in the container will be lost
- DevKit update to replace only the SDK toolkit without affecting packaging configuration
5.3 Third-Party Library Management
The commonly used tripartite library on which the framework is built has been pre-integrated in the local development environment (aimde), managed centrally through Bazel rule, which allows users to be introduced as required in the business code without having to download and install them themselves. The framework also supports users to add the tripartite library as needed and to manage and quote in the same way.
5.3.1 Third-Party Library Definition Chain
The three-tier library, from local files to business code, is defined in three layers, with a single function:
/sdk/dev_tools/third_party_libs/external/xxx # Library files (source or prebuilt)
│ 1. sdk_third_party_deps.bzl: register local_repository as a Bazel external repository
▼
@xxx / @xxx_x86_64 / @xxx_aarch64 # External repository
│ 2. integration/BUILD: use alias + select to hide architecture and source differences
▼
@integration//:xxx # Unified SDK entry point
│ 3. aimdk_examples/thirdparty/BUILD: forward aliases to the local application repository
▼
//thirdparty:xxx # Application code depends on this target
5.3.2 Register External Repositories
All tri-banks are stored in one place./sdk/dev_tools/third_party_libs/external/Down, through. /sdk/dev_tools/sdk-buildchain/projects/external/sdk_third_party_deps.bzl Mediumlocal_repositoryRegister:
- The source-based library registers a warehouse, compiled by Bazel according to the current tool chain, which naturally supports multistructures
- The pre-record is registered by structure and the name of the warehouse is as follows:
_x86_64/_aarch64End
def third_party_deps():
# Source Build: Single Repository
native.local_repository(
name = "jsoncpp",
path = "/sdk/dev_tools/third_party_libs/external/jsoncpp",
)
# Pre-compiled: one warehouse per structure
native.local_repository(
name = "boost_x86_64",
path = "/sdk/dev_tools/third_party_libs/external/boost_x86_64",
)
native.local_repository(
name = "boost_aarch64",
path = "/sdk/dev_tools/third_party_libs/external/boost_aarch64",
)
5.3.3 Unified Entry Point
Pass./sdk/dev_tools/sdk-buildchain/BUILDMediumaliasExternal exposure of names not related to structure, pre-recording libraryselectSwitch automatically to target platform:
# Pre-enactment: selection by structure
alias(
name = "boost",
actual = select({
"@integration//toolchains/platforms:is_aarch64": "@boost_aarch64//:boost",
"//conditions:default": "@boost_x86_64//:boost",
}),
visibility = ["//visibility:public"],
)
# Source build: directly forward
alias(
name = "jsoncpp",
actual = "@jsoncpp",
visibility = ["//visibility:public"],
)
5.3.4 Forward Dependencies to the Application Repository
aimdk_examples/thirdparty/BUILDThe following is a retransmission, and the tri-bureau used in this warehouse is clear:
alias(
name = "boost",
actual = "@integration//:boost",
)
alias(
name = "jsoncpp",
actual = "@integration//:jsoncpp",
)
The business code depends on it.//thirdparty:xxx:
cc_binary(
name = "demo",
srcs = ["main.cc"],
deps = [
"//thirdparty:boost",
"//thirdparty:jsoncpp",
],
)
5.3.5 Add a Third-Party Library
- Place library files in
/sdk/dev_tools/third_party_libs/external/(Pre-Book catalogue by structure) - Yes.
sdk_third_party_deps.bzlUseablelocal_repositoryRegistration - Yes.
integration/BUILDAddalias(to be used in the pre-record library)select) - It's in the business room.
thirdparty/BUILDCannot initialise Evolution's mail component.alias
Do not rely directly on the code.
@xxx、@xxx_x86_64、@xxx_aarch64or@integration//:xxxUnanimously.//thirdparty:xxxQuote. When the source or structure of such reliance changes, you need only change the definition upstream and the business code does not change.
5.4 SDK Dependency Description
All SDKs rely on pre-integrated local development environment (aimde) for integrated management through Bazel. Users do not need to download the installation manually, but simply use it as required in the business code.
**Note:**The SDK refers to the header (.h) and dynamic library (.so) where the internal code of the Idea is exposed, and does not include external tripartite dependence.
5.4.1 Architecture Path Definitions
Specify SDK paths for different structures through YAML configuration file:
x86_64 architecture: /sdk/dev_tools/sdk-buildchain/projects/sdk_defs/x86_64.yaml
sdk:
local:
path: /sdk/dev_tools/x86_64/
RK3588 architecture:/sdk/dev_tools/sdk-buildchain/projects/sdk_defs/rk3588_aarch64.yaml
sdk:
local:
path: /sdk/dev_tools/rk3588_aarch64/
5.4.2 SDK Repository Structure
/sdk/dev_tools/{x86_64|rk3588_aarch64}/
├── aimdk/ # Header files generated from Protobuf protocols
├── aimrte/ # HDS header files
├── all_plugins/ # Plugin libraries (mqtt_plugin/ros2_plugin/net_plugin, etc.) and dependencies
├── BUILD # Bazel target definitions for SDK libraries
├── google/ # Common Google Protobuf headers (such as any.pb.h)
├── libzy_aimrt_comm.so # aimrt_comm API shared library
├── libzy_aimrt.so # aimrt API shared library
├── ros2/ # Headers generated from ROS2 protocols
├── src/ # Core headers (aimrt/aimrt_comm/)
└── WORKSPACE # Bazel WORKSPACE file for the SDK repository
5.4.3 Core Libraries
| Library name | Function Description |
|---|---|
| libaimrt | Core library when running, providing basic running time functions (networks, configurations, etc.) |
| libaimrt_comm | Communication layer library with Protobuf/ROS2 protocols and generic tools |
| libhealth_diag_generation | Health diagnostic library, which provides modular health surveillance functions |
| all_plugins | Plugin collection (mqtt\plugin/ros2plugin et al.) |
5.4.4 BUILD Definition Example
# Export all SDK resources
package(default_visibility = ["//visibility:public"])
exports_files(glob(["**/*.h*", "**/*.inl", "**/*.so*"]))
# Core library definition
cc_library(
name = "libaimrt",
includes = [
"src/protocols/plugins/ros2_plugin_proto/common/msg",
],
srcs = ["//:libzy_aimrt.so"],
hdrs = [
"src/common/net/asio_http_cli.h",
"src/runtime/core/util/yaml_tools.h",
# ...
],
linkopts = [
],
defines = [
"BOOST_ASIO_NO_DEPRECATED",
"AIMRT_USE_FMT_LIB"
],
)
cc_library(
name = "libaimrt_comm",
includes = ["ros2/data_proxy", "ros2/audio/StopAudioPlay", ...],
srcs = ["libzy_aimrt_comm.so"],
hdrs = [
"aimdk/protocol/action/arm.pb.h",
"ros2/audio/audio_msgs/msg/volume_type.h",
"src/all_in_one/include/aimrte.h",
# ...
],
deps = [
"@boost_x86_64//:boost",
"@ros2_common_interfaces//:cpp_geometry_msgs",
"@sdk//:libaimrt",
"@sdk//:libhealth_diag_generation",
# ...
],
defines = ["AIMRT_USE_FMT_LIB"],
)
...
cc_library(
name = "libhealth_diag_generation",
srcs = [
],
hdrs = glob(["aimrte/hds/**/*.h"]),
deps = [
],
linkopts = [
],
defines = [
],
)
filegroup(
name = "all_plugins",
srcs = glob(["all_plugins/**"]),
)
cc_library(
name = "agibot_sdk",
deps = [
":libaimrt_comm",
],
)
5.4.5 Use SDK Dependencies in the Application Repository
Introduce SDK Dependence
Pass."//thirdparty:agibot_sdk"Direct quote:
package(default_visibility = ["//visibility:public"])
cc_library(
name = "aimdk_example_module",
srcs = glob([
"*.cpp",
]),
hdrs = glob([
"*.h",
]),
deps = [
"//thirdparty:agibot_sdk",
],
)
Plugin Introduction
Yes.pkg_tarIt's... it's... it's...depsMedium pass.@integration//:all_plugins_tarPacking:
pkg_tar(
name = "aimdk_example_tar",
srcs = [
],
extension = "tar",
mode = "0755",
strip_prefix = ".",
tags = ["tar"],
include_runfiles = True,
deps = [
...
"@integration//:all_plugins_tar",
...
],
)
5.5 Module Development
5.5.1 AimRT Module
AimRT is a communication and running time frame for robotic scenes. The developers write business logicModule, by application (App) loaded into the process by means of communication (Channel release/subscription, RPC), thread (Execctor), log, plugin etc.YAML ProfileDecides that the business code is decoupled from the specific communications backend (iceoryx / ROS2 / HTTP, etc.).
This post is part of our special coverage Syria Elections 2011.aimdk_examples/examples/aimrt/aimdk_examplesFor example, explain how to use it on the basis of AimDKAimRTFramework preparation, compilation and operation of a custom module.
- AimRT Official Course: https://docs.aimrt.org/tutorials/index.html
- AimRT Source: https://github.com/AimRT/AimRT
Contents structure
examples/aimrt/aimdk_examples/
├── app/
│ └── aimdk_example/
│ ├── main.cpp # Program entry point; registers the module
│ └── BUILD # Executable and packaging rules
├── module/
│ └── aimdk_example/
│ ├── aimdk_example.h # Module declaration
│ ├── aimdk_example.cpp # Module implementation
│ └── BUILD # Module library (cc_library)
├── config/
│ └── aimdk_example/
│ ├── aimdk_example_config.yaml # AimRT runtime configuration
│ └── BUILD
└── scripts/
└── aimdk_example/
├── start_aimdk_example.sh # Startup script
└── BUILD
Repository root directoryBUILDMediumaimdk_example_tarResponsible for final installation of configurations, plugins, executables and start-up scriptsbazel-bin/aimdk_example_tar.tar。
examples/native/Next is the example of the original C++/ Python, which is not dependent on the SimRT module frame, which has nothing to do with this paper.
5.5.1.1 Implement the Module
Module Header Files(module/aimdk_example/aimdk_example.h)
#pragma once#include "audio_msgs/msg/audio_capture.hpp"#include "src/all_in_one/include/aimrte.h"namespace aimdk_examples::module::aimdk_example {
class AimdkExampleModule : public aimrte::ctx::ModuleBase {
public:
struct Option {
aimrte::Sub<audio_msgs::msg::AudioCapture> audio_capture_sub{"/audiohal/audio/capture"};
};
public:
AimdkExampleModule();
~AimdkExampleModule() override;
bool OnInitialize() override;
bool OnStart() override;
void OnShutdown() override;
void ReceiveAudioCapture(const std::shared_ptr<const audio_msgs::msg::AudioCapture>& msg);
private:
Option option_;
};
} // namespace aimdk_examples::module::aimdk_example
Highlights:
- You just have to introduce it.
src/all_in_one/include/aimrte.h, you can use the AimRT packageaimrte::Interface. - Message type from the AimDK package (using ROS2 messages here)
audio_msgs::msg::AudioCapture)。 - Focus on resources such as subscribers
OptionIn structure:aimrte::Sub<T>: a subscription handle for a topic;- If you need to move back in a separate thread pool, you can copy it.
aimrte::ExeDeclaration executor.
Module realization(module/aimdk_example/aimdk_example.cpp)
bool AimdkExampleModule::OnInitialize() {
option_.audio_capture_sub = aimrte::ctx::init::Subscriber<audio_msgs::msg::AudioCapture>("/audiohal/audio/capture");
option_.audio_capture_sub.WhenInit().SubscribeInline(std::bind(&AimdkExampleModule::ReceiveAudioCapture, this, std::placeholders::_1));
return true;
}
bool AimdkExampleModule::OnStart() { return true; }
void AimdkExampleModule::OnShutdown() {}
void AimdkExampleModule::ReceiveAudioCapture(const std::shared_ptr<const audio_msgs::msg::AudioCapture>& msg) {
AIMRTE_INFO("stamps: sec={}, nanosec={}", msg->stamps.sec, msg->stamps.nanosec);
AIMRTE_INFO("mic_channels: {}", msg->mic_channels);
AIMRTE_INFO("ref_channels: {}", msg->ref_channels);
AIMRTE_INFO("info: channels={}, sample_rate={}, sample_format={}, coding_format={}",
msg->info.channels, msg->info.sample_rate, msg->info.sample_format, msg->info.coding_format);
AIMRTE_INFO("data: {} bytes", msg->data.data.size());
}
Module life cycle:
| Turn back. | Timing | Typical uses |
|---|---|---|
| OnInitialize() | Initialization phase | Create subscriber/issuer/RPC client and service, read configuration; returns false for initialization failed |
| OnStart() | Start-up phase | Start the business cycle, scheduled tasks, etc. |
| OnShutdown() | Stop phase | Release of resources |
Subscriptions:SubscribeInline(callback)If you need to process a time-consuming logic in a specified thread pool, you canOptionOne of them.aimrte::ExeExecutor (and config file)aimrt.executor. Please refer to the AimRT official document and the AimDK header file.
Log UseAIMRTE_INFO(...)({}Formatting style), log level by profileaimrt.logControl.
5.5.1.2 Module BUILD (module/aimdk_example/BUILD)
cc_library(
name = "aimdk_example_module",
srcs = glob(["*.cpp"]),
hdrs = glob(["*.h"]),
deps = [
"//thirdparty:agibot_sdk", # AimDK/AimRT headers and libraries
],
)
//thirdparty:agibot_sdkReliance on the AimRT and AimDK protocols is provided, and the module can only rely on it.
5.5.1.3 Implement the Application Entry Point (app/aimdk_example/main.cpp)
#include <iostream>#include "examples/aimrt/aimdk_examples/module/aimdk_example/aimdk_example.h"int main(int argc, char** argv) {
std::cout << "Hello, AIMDK!" << std::endl;
aimrte::Cfg cfg(argc, argv, "aimdk_example");
return aimrte::Run(cfg, {{"AimdkExampleModule", std::make_shared<aimdk_examples::module::aimdk_example::AimdkExampleModule>()}});
}
aimrte::CfgParsing command line parameters (started scripted)--cfg_file_path=...)。aimrte::RunReceive the mapping and operation of the module name to the module example;"AimdkExampleModule"It is a modular name that needs to be aligned with the configuration of the module in the configuration document.- If multiple modules are required, continue to add to the map.
app/aimdk_example/BUILDMediumcc_binaryReliance on the modules library and turn executables, configurations, start-up scripts into installation packages:
cc_binary(
name = "aimdk_example",
srcs = ["main.cpp"],
deps = ["//examples/aimrt/aimdk_examples/module/aimdk_example:aimdk_example_module"],
)
5.5.1.4 Configuration File (config/aimdk_example/aimdk_example_config.yaml)
Configure file to determine run-time behaviour, main paragraph:
| Paragraph | Role | This is the case. |
|---|---|---|
| aimrt.configurator | Configuration, temp\cfg_path Configure the storage path for temporary modules | ../config/aimdk_example/tmp |
| aimrt.plugin | Load Plugins | net_plugin、ros2_plugin、iceoryx_plugin |
| aimrt.log | Log Level | core_lvl: INFO,default_module_lvl: Info |
| aimrt.executor | Executor (hide pool) | work_thread_pool(4)、timeout_handle(2) |
| aimrt.channel | Channel Backend and Topic Options | Backend icoryx, ros2; /audiohal/audio/capture only is enabled ros2 (radiohal releases this topic through ROS2, consistent with the original example) |
| aimrt.rpc | RPC Backend | http、ros2 |
Topic and backend needs for code subscriptions withchannelparagraph matches; if a new executor is added, the executor name must be firstaimrt.executorIt's in the code. It's in the code. It's in the code.aimrte::Exe{"name"}Quote.
5.5.1.5 Startup Script and Packaging
Start Script Asscripts/aimdk_example/start_aimdk_example.sh. Pass on startup.--cfg_file_pathPass in.
5.5.1.6 Build and Run
See complete steps for compilation, local operation, deployment to equipment, debuggingBuild and Deployment, the goal of this case is calledaimdk_example:
bash tools/build_module.sh -t aimdk_example -a x86_64
bash tools/run_module.sh -t aimdk_example
When running successfully, the module will be received/audiohal/audio/captureThe time stamp, the number of microphones and reference channels, the logs for sampling information and data length when the message is exported.
5.5.1.7 Add a Custom Module
Add with new modulefooFor example:
- Create Module: New
module/foo/foo.h、foo.cppInheritance.aimrte::ctx::ModuleBaseAnd it's happening.OnInitialize/OnStart/OnShutdown。 - Module BUILD: Simulation
module/aimdk_example/BUILDAddcc_library(e.g.)foo_moduleReliance.//thirdparty:agibot_sdk。 - Registration module: In
app/aimdk_example/BUILDIt's... it's... it's...cc_binary.deps_Other Organiser//examples/aimrt/aimdk_examples/module/foo:foo_module(or create a new one by reference to the BUILD)app/foo/BUILD); inmain.cppMedium#includeHeader file, andaimrte::RunAdding to the map{"FooModule", std::make_shared<...::Foo>()}。 - Update Configuration: If new executor, topic backend options, plugins are added to the YAML corresponding paragraph.
- Build and run
5.5.1.8 Common Communication Patterns
- Release / RPC: Interface is also through
aimrte::ctx::init::Yes.OnInitialize_Other Organisersrc/all_in_one/include/aimrte.h。 - Do not use the AimRT module frametopic/RPC, reference
examples/native/cppandexamples/native/python。
5.5.1.9 Common Issues
- Start and exit / Initialization failed: Inspection
OnInitializeWhether or not to returntrue, and whether the executor and topic used in the code are configured in YAML. - I can't hear you.: confirm that the distribution end is the same topic as the subscription and the same backend (this case subscription is only enabled)
ros2) and on the equipmentaudiohalThe corresponding service is running. - Adjust Log: Modifying configuration
aimrt.log.core_lvl/default_module_lvl。 - Debug: Use
start_aimdk_example.sh -g -p <port>Starts with lldb-server and connects remotely.
5.5.2 Native C++ Development
This post is part of our special coverage Syria Elections 2011.aimdk_examples/examples/native/cppExamples of catalogues,Do not use the AimRT module frame, but as an independent process, directly interacts with robotic services through ROS2 or HTTP. Each example is independent.cc_binary, which can be compiled, packaged and run separately.
5.5.2.1 Directory Structure
Each example catalogue is structured consistently:
cpp/
├── channel/<name>/
│ ├── <name>.cpp # Example source code
│ ├── start_<name>.sh # Startup script
│ └── BUILD # Executable and packaging rules
└── rpc/<name>/
├── <name>.cpp
├── start_<name>.sh
└── BUILD
5.5.2.2 Channel Examples
Could not close temporary folder: %s:heart_beat、tts_status
The two examples have the same structure and only topic differs from the message type:
| Example: | Topic | Protobuf Type |
|---|---|---|
| heart_beat | /aima/heartbeat/pb_3Aaimdk_2Eprotocol_2EProcessHeartbeatChannel | aimdk::protocol::ProcessHeartbeatChannel |
| tts_status | /interaction/tts_status/pb_3Aaimdk_2Eprotocol_2ETTSStatus | aimdk::protocol::TTSStatus |
| Highlights: |
- Use it.
rclcpp::NodeSubscriptionsros2_plugin_proto::msg::RosMsgWrapper. The message is the encapsulation of the EmRT ROS2 plugin for protobuf,serialization_typeYes."pb"It's a long time ago.datais the bytes after the protobuf has been sequenced. - Let's get back to it.
serialization_type == "pb"Again.ParseFromArrayReverse sequence to specific protobuf messages, last usedMessageToJsonStringConverts to JSON output. - From Topic Name
pb_3Aaimdk_2Eprotocol_2E...is the full name of the protobuf type (pb:aimdk.protocol.…) the result of the transliteration of the ROS2 name (:→_3A,.→_2E)。 - QoS Use
KeepLast(10)+best_effort。
rclcpp::QoS qos_profile(rclcpp::KeepLast(10));
qos_profile.best_effort();
subscription_ = create_subscription<ros2_plugin_proto::msg::RosMsgWrapper>(
topic_name_, qos_profile, std::bind(&Xxx::Callback, this, std::placeholders::_1));
5.5.2.3 Subscribe to ROS2 Messages
Subscribe ROS2 messages:joint_state、audio_capture
| Example: | Topic | Message Type | Sources |
|---|---|---|---|
| joint_state | /motion/control/arm_joint_state | sensor_msgs::msg::JointState | ROS2 standard message |
| audio_capture | /audiohal/audio/capture | audio_msgs::msg::AudioCapture | AimDK Customise ROS2 Message |
Direct subscription to ROS2 message type, field printing in echoes (joint_statePrint header / name / position / vulocity / effort;audio_capturePrint time stamp, number of microphones and reference channels, length of sample information and data). |
audio_msgsNot ROS2 self-carried packages, but an AimDK-defined message package, which requires an AimDK-loaded ROS2 message package in the running environment (start scripts will be loaded)/agibot/software/v0/entry/env/env.sh. The same package.audio_msgs::srv::AbandonAudioFocusIt's also a custom service.
5.5.2.4 RPC Examples
HTTP + JSON:GetArmJointState、GetAction
| Example: | URL | Type of request / response |
|---|---|---|
| GetArmJointState | http://10.42.10.12:56322/rpc/aimdk.protocol.MotionControlJointService/GetArmJointState | CommonRequest / JointStateResponse |
| GetAction | http://10.42.10.12:56322/rpc/aimdk.protocol.MotionControlActionService/GetAction | CommonRequest / MotionControlActionResponse |
These two examples send POST requests via libcurl to the HTTP RPC interface for robotic services:
URL rules:http://<device-ip>:<port>/rpc/<fully-qualified-protobuf-service>/<method>。
Call the process (same examples):
- Construct protobuf request, use
MessageToJsonStringTurn to JSON; curlByContent-Type: application/jsonPOST to the corresponding URL, 5 seconds longer;- Check the curl return code and the HTTP status code (up to 200);
- Use it.
JsonStringToMessage(ignore_unknown_fields = true) parsing the response and formatting the output.
Error printing to stderr and ending with exit code 1 when any step fails.
SetAudioVolumeA volume parameter is required, the request is fixedis_mute = false、type = SPEAKRE_BUILT_IN(internal speaker):
./SetAudioVolume 50
Device IP (in code)
10.42.10.12、10.42.10.10) is hard-coded, if the network of equipment requires a change in the source codekUrlRecompiled later.
5.5.2.5 ROS2 Service:AbandonAudioFocus
- Service name:
/audio_5Fmsgs/srv/AbandonAudioFocus(AimDK custom service)audio_msgs::srv::AbandonAudioFocus,_5FYes._It's the transition. - Process: create clit ~ cycle per 2 seconds
wait_for_serviceUntil service is available Fillfocus_requester(pkg_name = "aimdk_examples"、priority = 6、priority_weight = 1)→async_send_request→spin_until_future_completePrintpkg_nameandfocus_gain。 - Use on exit
std::_ExitJust finish the process. Don't do it.rclcpp::shutdown. The source comment explains why:rclcpp::NodeParsing triggered DDS participant destruction with agibot\sdk autobandlibzy_aimrt.soThe internal aso schiduler has a symbol conflict that will be used for the exit phase. This applies only to this type of one-time call tool, and the permanent application is not copied.
5.5.2.6 BUILD Dependencies
| Example type | Dependence |
|---|---|
| Channel (4) | /thirdparty: cpp\rclcpp; heart\beat, tttsstatus //thirdparty:protobuf, /thirdparty: agibot\sdk |
| HTTP RPC (4) | //thirdparty:CURL、//thirdparty:protobuf、//thirdparty:agibot_sdk |
| AbandonAudioFocus | //thirdparty:cpp_rclcpp、//thirdparty:agibot_sdk |
Every one.BUILDDividecc_binaryIn addition, there are three packing targets:
<name>_script: Put it on.start_<name>.shPut it on.scripts/<name>/;<name>_without_bin_tar: only scripts;<name>_bin_flatten_tar: executable and dependent, put onbin/。
Root DirectoryBUILDMedium<name>_tarMerge the two parts into a final installation package.
5.5.2.7 Build
build_module.sh -t <name>It's built.<name>_tarAnd so...-tSend the example name directly:
# x86
bash tools/build_module.sh -t heart_beat -a x86_64
# ARM
bash tools/build_module.sh -t heart_beat -a rk3588_mdu_aarch64
bash tools/build_module.sh -t heart_beat -a rk3588_hdu_aarch64
Available-tValue:heart_beat、tts_status、joint_state、audio_capture、GetArmJointState、GetAction、GetAudioVolume、SetAudioVolume、AbandonAudioFocus。
The product is...bazel-bin/<name>_tar.tar。
5.5.2.8 Run
Local(x86, aimde environment)
bash tools/run_module.sh -t heart_beat
On the device.
After transmitting and decompressing the installation package, use start-up scripts:
bash /agibot/data/ggm/scripts/heart_beat/start_heart_beat.sh
Start script will enter../../binLoad/agibot/software/v0/entry/env/env.sh(or)/opt/ros/jazzy、/opt/ros/humble) the environment, then the executable file is activated and the Ctrl+C (SIGINT/SIGTERM) exits elegantly.
Common parameters:
| Parameters | Annotations |
|---|---|
| -g, --debug | Run in ldb-server debug mode |
| -p, --port | Debug port (default 65001) |
| -h, --help | Help |
start_SetAudioVolume.shI'm gonna need another one.-v, --volume <volume>(Necessary):
bash scripts/SetAudioVolume/start_SetAudioVolume.sh -v 50
5.6 Build and Deployment
This document is a compilation, local operation, and deployment process common to the SimRT module and the original C++ example. Both are done through the same script, the difference being only -t's entry target name.
Target name
| Category | Available |
|---|---|
| AimRT Module | aimdk_example |
| Original C++ Channel | heart_beat、tts_status、joint_state、audio_capture |
| Original C++ RPC | GetArmJointState、GetAction、GetAudioVolume、SetAudioVolume、AbandonAudioFocus |
tools/build_module.sh -t <name>Build root directoryBUILDMedium<name>_tar, the product is...bazel-bin/<name>_tar.tar。
The following is a reference:aimdk_exampleFor example, replace them with other target names.
5.6.1 Build
Select architecture based on target equipment:
# ARM - mdu
bash tools/build_module.sh -t aimdk_example -a rk3588_mdu_aarch64
# ARM - hdu
bash tools/build_module.sh -t aimdk_example -a rk3588_hdu_aarch64
# x86
bash tools/build_module.sh -t aimdk_example -a x86_64
Compiled products:bazel-bin/aimdk_example_tar.tar
build_module.shParameters:
| Parameters | Annotations |
|---|---|
| -t | Target name (which must be filled) |
| -a | Architecture: x8664 (default), rk3588mduaarch64, rk3588hduaarch64 |
| -j | Number of simultaneous compilation and translation tasks |
| -g | Debug compilation (-copt=-g-copt=-O0) |
| -c | Bazel clean-expunge before compilation |
| -e | Append bazel options, such as -e " --config=xx" |
Local Run (x86)
x86 The compiler can run directly in the aimde environment:
bash tools/run_module.sh -t aimdk_example
run_module.shI'll take it.bazel-bin/<name>_tar.tarUnplugged.bazel-bin/<name>_tar/I'll do it again.scripts/<name>/start_<name>.sh。
Parameters:
| Parameters | Annotations |
|---|---|
| -t | Target name (which must be filled), completion of x86 compilation |
| -c | Customise the absolute path of the profile file, only AimRT module available (startup script for original example not accepted -c) |
| -g | Debug Mode |
| -p | Debug port (effective -g) |
Example:bash tools/run_module.sh -t aimdk_example -c $(pwd)/examples/aimrt/aimdk_examples/config/aimdk_example/aimdk_example_config.yaml
run_module.shCould not close temporary folder: %sSetAudioVolumeYes.-v <volume>, enter the decompression directory to run the start-up script directly:bashbash bazel-bin/SetAudioVolume_tar/scripts/SetAudioVolume/start_SetAudioVolume.sh -v 50
5.6.2 Deploy to the Target Device
Pre-deployment request to ensure that the structure of the target equipment used corresponds to the structure (
rk3588_mdu_aarch64orrk3588_hdu_aarch64) Completion of the compilation.
IP, account number, table of contents below are taken from the Example Environment and should be replaced with actual equipment.
5.6.2.1 Transfer the Installation Package
sshpass -p 1 scp \
-o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
-o ConnectTimeout=120 \
-P 22 \
bazel-bin/aimdk_example_tar.tar \
agi@192.168.111.140:/agibot/data/ggm/
5.6.2.2 Log In to the Device and Extract
ssh agi@192.168.111.140 -p 22
cd /agibot/data/ggm
tar -xvf aimdk_example_tar.tar
rm aimdk_example_tar.tar
5.6.2.3 Start
bash /agibot/data/ggm/scripts/aimdk_example/start_aimdk_example.sh
5.6.2.4 Package Layout and Startup Script
The decompressed directory (for example, the AimRT module):
bin/ # Executable and dependencies; AimRT modules also include plugins
config/aimdk_example/ # Configuration file (AimRT modules only)
scripts/aimdk_example/ # Startup script
Original C++ example installation package onlybin/andscripts/<name>/No, I didn't.config/。
Start Scriptscripts/<name>/start_<name>.shConduct:
- Enter
../../bin; - Loading Environment: Priority
/agibot/software/v0/entry/env/env.sh, second/opt/ros/jazzy、/opt/ros/humble; - Start executable;AimRT module extra input
--cfg_file_path=<configuration-file>; - Capture SIGINT / SIGTERM and exit elegantly (wait at most 30 seconds, kill over time).
Start script parameters:
| Parameters | Application | Annotations |
|---|---|---|
| -c, --config | AimRT module only | Custom profile (absolute path), default . ./config/aimdk\example/aimdk\example\config.yaml |
| -g, --debug | All | Run in ldb-server debug mode |
| -p, --port | All | Debug port, default 65001 |
| -h, --help | All | Help |
5.6.2.5 Debugging
- Use it.
-gCompile (with debugging symbols, off optimization):
bash tools/build_module.sh -t aimdk_example -a rk3588_mdu_aarch64 -g
- Start with debug mode after deployment by lldb-server listening port:
bash /agibot/data/ggm/scripts/aimdk_example/start_aimdk_example.sh -g -p 65001
- Connects the port remotely on the developer using the lldb.
5.6.2.6 Common Issues
Target tar does not exist: no x86 compilation of the corresponding target completed before running, execute firstbuild_module.sh -t <name> -a x86_64。- Unable to run after deployment/ structure mismatch: Confirming compilation
-aConsistent with the equipment model (mdu/ hdu), x86 products cannot be deployed to the equipment. Unsupported ARCH_TYPE:-aSupport onlyx86_64、rk3588_mdu_aarch64、rk3588_hdu_aarch64。- Native example passed.
-cWrong report.:-cOnly for the AimRT module.
5.7 Python Packaging and Deployment
This post is part of our special coverage Syria Elections 2011.aimdk_examples/examples/native/pythonHere's an example under the directory, too.Do not use the AimRT module frame, as a stand-alone script through ROS2rclpy) or HTTP(requests) Interacts with robotic services. The Python example is not compiled by Bazel. Runs directly with the Python interpreter.
5.7.1 Directory Structure
python/
├── pyproject.toml # Project dependencies (aimdk-proto, protobuf, requests; see Section 3.3)
├── uv.lock # Dependency lock file (single source of truth)
├── requirements.txt # Intermediate file exported from uv.lock
├── .venv-x86/ .venv-rk3588/ # Virtual environments for each chip (prebuilt before SDK release)
├── channel/
│ └── <name>/{<name>.py, start_<name>.sh}
└── rpc/
└── <name>/{<name>.py, start_<name>.sh}
5.7.2 Channel Examples
Could not close temporary folder: %s:heart_beat、tts_status
| Example: | Topic | Protobuf Type |
|---|---|---|
| heart_beat | /aima/heartbeat/pb_3Aaimdk_2Eprotocol_2EProcessHeartbeatChannel | aimdk::protocol::ProcessHeartbeatChannel |
| tts_status | /interaction/tts_status/pb_3Aaimdk_2Eprotocol_2ETTSStatus | aimdk::protocol::TTSStatus |
| Highlights: |
- Script Direct
from aimdk.protocol.xxx import xxx_pb2Import, these modules are installed in a virtual environment without any needsys.pathDeal. - Subscriptions
ros2_plugin_proto.msg.RosMsgWrapper;checking in returnserialization_type == "pb"Again.ParseFromString(b"".join(msg.data))Reverse Sequencing, Final UseMessageToJsonOutput. - QoS:
KEEP_LASTDepth 10,BEST_EFFORT。 - Topic name is the result of a transposition of the protobuf type with the ROS2 name
:→_3A,.→_2E)。
Subscribe custom ROS2 messages:audio_capture
Subscriptions/audiohal/audio/capture(AimDK customise ROS2 messages)audio_msgs.msg.AudioCapture, non-ROS2 standard message), print time stamp, number of microphones and reference channels, sample information and length of data.
Four Channel scripts.try/except (KeyboardInterrupt, ExternalShutdownException)Process Ctrl+C, andfinallyMediumdestroy_nodeandrclpy.shutdown()。
aimdk.protocol.*protobuf binding (aimdk-proto(Backloads)
heart_beat、tts_statusIt's used.aimdk.protocol.*_pb2Module provided by SDKaimdk-protoHere's the package. It's been declared inpyproject.tomlReliance. When you build a virtual environment, it's automatically installed, and when you write the code, it's direct.import, no additional configuration is required.
Module path rules:aimdk.protocol.<subdirectories...>.<file-name>_pb2Corresponds to the AimDK protocol.protoThe catalogue structure of documents corresponds to one another, for example:
| Protobuf Type | Import by |
|---|---|
| ProcessHeartbeatChannel | from aimdk.protocol.hds.process import process_heartbeat_channel_pb2 |
| TTSStatus | from aimdk.protocol.interaction import tts_service_pb2 |
If you want to use other messages, just use the same rules to import them.
5.7.3 RPC Examples
Userequests.post(URL, json=payload, timeout=5)Call robot HTTP RPC interface, print formatted after success
- URL rules:
http://<device-ip>:<port>/rpc/<fully-qualified-protobuf-service>/<method>。 - Query Interface Request is an empty object
{};SetAudioVolumeThe request is:
{"audio_volume": int(sys.argv[1]), "is_mute": False, "type": "SPEAKRE_BUILT_IN"}
- Request for abnormal or HTTP status code not 2x(s)
raise_for_status) , output error to stderr and returns exit code 1. - Python version uses the JSON dictionary directly and does not rely on protobuf to generate code; like C++ version, device IP is hard coded and the network does not have to be modified at the same time
URL。
ROS2 Service:AbandonAudioFocus
- Service name
/audio_5Fmsgs/srv/AbandonAudioFocus(AimDK custom service)audio_msgs.srv.AbandonAudioFocus)。 - Process: create client ~ every 2 seconds
wait_for_serviceUntil available fillfocus_requester(pkg_name = "aimdk_examples"、priority = 6、priority_weight = 1)→call_async→spin_until_future_completePrintpkg_nameandfocus_gain。 - Python doesn't need to be a Python, unlike C++.
_ExitEvacuate exit crash, normal.destroy_node+shutdownAll right.
5.7.4 Python Environment Requirements
Dependencies (pyproject.toml, request Python § 3.10:
aimdk-proto(protobuf Python of the AimDK protocol, supplied with SDK environment)protobuf>=6.31,<7♪ Can't be less than ♪aimdk-protoVersion for Generating Code)requests>=2.34.2
rclpy、sensor_msgs、audio_msgs、ros2_plugin_protoWaiting for ROS2 packages not in this dependency, but from the system ROS2/AimDK environment (virtual environment)--system-site-packagesCreates, reuses the system package.
Virtual environment of each chip..venv-x86、.venv-rk3588) has been constructed with SDK, is ready for direct use and does not need to be self-installed.
5.7.5 Package the Runtime Environment
bash tools/package_python_env.sh -c rk3588
# Default output desist/ aimdk_examples_python_env-rk3588.tar.gz, available -o specification
When packing, the source code is copied to the temporary folder, only the virtual environment of the target chip is preserved and renamed..venv(So starting in script).venv/bin/python3And clean it up at the same time.pycache, and delete the invalid script of the path of the shebang to the dead machine.
5.7.6 Run
5.7.6.1 Local
On machines with ROS2 environments, enter the list of examples and run with start-up scripts:
cd examples/native/python/channel/heart_beat
bash start_heart_beat.sh
Example RPC:
cd examples/native/python/rpc/SetAudioVolume
bash start_SetAudioVolume.sh -v 50
Activate script:
- Load ROS2 Environment: Priority
/agibot/software/v0/entry/env/env.sh, second/opt/ros/jazzy、/opt/ros/humble; - For example for AimDK messages, extra
sourceCorrespondinglocal_setup.bash:heart_beat、tts_statusLoadros2_plugin_proto,audio_capture、AbandonAudioFocusLoadaudio_msgs; - Priority Use
python/.venv/bin/python3, return to system if not foundpython3; - Run
.pyScript, and handle SIGINT/SIGTERM exits elegantly (at most 30 seconds).
start_SetAudioVolume.shYes.-v, --volume <volume>Other scripts only support-h。
5.7.6.2 Deploy to the Device
- Pack it against the chip's operating environment. Got it.
aimdk_examples_python_env-<chip>.tar.gz; - Copy to device and depress:
tar -xzf aimdk_examples_python_env-rk3588.tar.gzGot it.python/Contents; - Enter
python/channel/<name>orpython/rpc/<name>, Runstart_<name>.sh。