Bumi 综合使用文档
一、关于Bumi
(一)部件信息
Bumi 整机具备 21 个自由度。单臂拥有 4 个自由度,包括(左手坐标系):
肩关节pitch肩关节roll上臂关节yaw手肘关节pitch
单腿拥有 6 个自由度,包括:
胯关节pitch髋关节roll大腿关节yaw膝关节pitch踝关节pitch踝关节roll
腰关节拥有 1 个自由度,包括:
腰关节yaw
拥有多个关节电机自由度,使得Bumi机器人能够实现精确的运动控制和姿态控制。
详细信息如下:
| 参数 | Bumi | Bumi-教育版 |
|---|---|---|
| 高宽厚(站立) | 98cm35cm20cm | |
| 带电池重量 | 约17kg | |
| 总自由度 | 21 | |
| 单腿自由度 | 6 | |
| 单手臂自由度 | 4 | |
| 腰部自由度 | 1 | |
| 算力模块 | / | NVIDIA Jetson Orin(Nano Super / NX) 【个别型号无算力模块】 |
| 关节通讯方式 | Ethercat & Canfd | |
| 关节最大扭矩 | 70N.m | |
| 小腿&大腿长度 | 约513mm | |
| 手臂臂展 | 约379mm | |
| 供电方式 | 锂电池 | |
| 基础算力 | 6 Tops | 6 + 67 / 117 Tops |
| 相机型号 | DC_V93 | Realsense D435ICB(EDU_Air除外) |
| 感知传感器 | IMU、相机 | |
| 麦克风阵列 | 标配 | |
| 扬声器 | 标配 | |
| 智能电池 | 快拆电池 | |
| 图像传输 | App内有 | 开发中可直接在算力板上访问硬件 |
| 充电器 | 有 | |
| 手机APP | 有 | |
| OTA升级 | 有 | |
| 续航时间 | 2~3H | |
| 二次开发(highcontroller) | 有 | |
| 二次开发(lowcontroller) | / | 有 |
| 部件介绍图 | ![]() | |
(二)外观件尺寸

(三)电气接口
在Bumi背面,提供电气接口如下:

| 序号 | 类型 | 说明 | 数量 |
|---|---|---|---|
| 1 | RJ45 | 交换机 1000 BASE-T | 1 |
| 2 | USB | 运控板/算力板 USB 3.0 | 2 |
| 3 | HDMI | 运控板/算力板 高清显示线 | 1 |
带算力板的Bumi 后背接口为算力板的接口,不带算力板的Bumi,后背接口为运控板的接口
(四)机载计算机
| 类型 | 型号 | 用户 | 密码 | IP | 算力 | 频率 | 内存 |
|---|---|---|---|---|---|---|---|
| 运控板 | 瑞星微 RK3576 | 运控板不对用户开放 | 运控板不对用户开放 | 192.168.55.102 | 6 Tops | 2.4GHz | 8+64GB |
| 二开算力板 | NVIDIA Jetson orin nano super | noetix | bumi | 192.168.55.101 | 67 Tops | 1.7GHz | 8+128GB |
| 二开算力板 | NVIDIA Jetson orin NX | noetix | bumi | 192.168.55.101 | 117 Tops | 2.0GHz | 16+128GB |
运控板(瑞星微 RK3576)不面向用户开放,如果用户私自访问运控板,导致机器人运控程序失控,造成损失与我司无关
(五)相机信息
Bumi-EDU:Realsense D435i
英特尔® 实感™ 深度摄像头 D435i - 产品规格 | 英特尔
Bumi-标准:DC_V93

(六)电池信息
| 参数 | 信息 |
|---|---|
| 品牌 | 深圳格瑞普 |
| 型号 | GRP6752097-13S1P |
| 容量 | 5100mAh |
| 电压 | 48V |
(七)充电器规格参数
| 参数 | 信息 |
|---|---|
| 产品型号 | TA300 Robot |
| 输入 | 100-240V~50/60Hz 4.5A |
| 电池类型 | LiPo/LiFe/LiHV 13S-16S |
| 尺寸 | 1729746mm |
| 产品名称 | Smart charger智能充电器 |
| 输出 | 35-72V ⎓ 7.5A 350W Max |
| 工作模式 | Charge/充电 |
| 重量 | 510g±10g |
二、使用说明
(一)启动设备及注意事项
一、设备取出与放置
- 将 Bumi 从收纳位置取出。
- 将其扶稳,使其坐于地面。
二、电池安装
- 将电池插入 Bumi 后背电池仓。
- 确认电池安装到位(卡扣锁定)。
三、设备开机
- 短按一次电池开关,确认电池指示灯亮起。
- 随后长按电池开关,直至出现流水灯效果。
- 等待机器人完成开机。
四、初始化姿态调整
- 将 Bumi 面朝上平躺于地面,要确地面平坦不打滑,Bumi脚底板无其他异物,且周围无杂物,避免Bumi执行自动起身的时候被周围杂物影响而失败
五、系统初始化说明
- 开机后,Bumi 会自动进入全身使能模式:
- 所有关节将自动运动至零位
- 过程中请勿干预或阻挡关节运动
⚠️ 注意事项
- 开机过程中避免触碰关节,防止夹伤或干扰初始化
- 确保地面平整,避免姿态异常
- 电池未正确安装时禁止开机
(二)Bumi连接方式

连接 Bumi 后,请勿在系统设置中选择‘遗忘设备’,否则会清除蓝牙记录,导致该设备无法再次连接。如误操作,请联系售后。
(三)手机APP连接设备及操作控制
Noetix run App下载:
Android:

iOS:NOETIX Run App - App Store
Noetix run App使用说明: BUMI机器人使用说明
(四)设备关机及电池充电
(五)操作教程视频
1. 安装APP
2. 开机
3. 激活绑定
4. 连接BUMI
- 蓝牙连接
- 蓝牙组网和WIFI连接
连接 Bumi 后,请勿在系统设置中选择‘遗忘设备’,否则会清除蓝牙记录,导致该设备无法再次连接。如误操作,请联系售后。
5. 一键起身
使用Bumi的一键起身功能时 要确地面平坦不打滑,且周围无杂物,避免Bumi执行自动起身的时候被周围杂物影响而失败
6. 移动
7. 基本动作
8. 示教模式
9. 舞蹈模式
10. 图传模式
(无算力板版本Bumi有)
11. 语音交互
12. 一键收纳
在 APP 中执行 一键收纳 前,要确保地面平坦不打滑且周围无杂物。
13. 关机
14. 电池充电
(六)常见问题及设备日常维护
- 设备防水系数不高
请勿在雨雪天气室外或者潮湿的环境中使用
三、Bumi开发指南
SDK介绍
本文档介绍Bumi基于 DDS消息中间件 通信开发,本SDK采用 C/S架构,在隔离机制下,使 Bumi 机器人的 二次开发算力板部署DDS客户端程序 与机器人上作为服务器的 运控板的运控程序 以 500HZ 的频率下发控制命令,并持续获取当前机器人状态。dds采用的是 CYCLONEDDS 0.11.0。
(一)系统架构图

(二)开发接口
DDS C++ Python
(三)获取SDK
https://github.com/Noetix-Robotics/noetix_sdk_bumi
(四)URDF文件
(五)应用开发 Highcontrol
应用开发介绍
Highcontrol 基于原厂运动控制策略进行上层调度开发,在不改变底层控制逻辑的前提下,实现机器人自动化应用的快速构建,并支持与大模型集成,打造定制化智能行为系统。
典型应用包括:
- 结合视觉算法与原厂运控系统,实现自主感知与自主行进
- 结合语音交互模块,实现自然语言控制
- 接入大模型,根据输入动态生成并调用原厂控制动作(具备一定风险,需要严格安全策略)
- 配合外挂感知雷达,实现定位导航巡检系统
简而言之,HighControl 通过对原厂控制能力的高层调度封装,实现对遥控器或 APP 可控行为的自动化与程序化调用,并在此基础上拓展部分自主化与智能化能力。
1. Highcontrol架构图

(1)状态上报机制
当客户端 SDK 与机器人运控程序建立连接后,运控程序会持续向客户端推送机器人实时状态信息,包括:
-
全身电机参数数据(pos 位置、vel 速度、tau 扭矩、kp、kd、temperature 温度、error 错误信息)
-
IMU 状态数据
-
当前工作模式(
workmode,表示当前运行的控制策略) -
澳加狮手柄数据(用于同步人工输入或辅助控制)
-
电池电量及相关系统状态信息
(2)客户端控制指令下发
客户端结合自身应用场景向运控程序发送控制指令,主要包括:
-
(x, y, z) 行进控制数据
仅在特定模式下有效,例如走路模式、握手、打招呼、欢呼、示教模式等。
-
action 指令
与
workmode对应,用于切换或触发机器人当前运行的算法策略。 -
data 附加 DDS 数据
通常在
PLAYTEACH(播放示教模式)下使用,用于指定示教文件索引等附加参数。
(3)运控程序内部处理流程
运控程序接收到客户端指令后:
-
将控制参数传递给内部控制算法
-
算法基于强化学习模型进行策略计算
-
生成电机目标期望值(目标位置、速度或力矩)并发送到电机控制接口
-
将计算结果下发至硬件控制层
(4)硬件执行层
硬件层接收目标控制数据后:
-
执行电机控制指令
-
完成对应的期望动作
在整个流程中,用户仅需下发部分高层控制参数。
具体的运动规划、动态平衡与电机级控制计算均由原厂运控程序中的黑盒算法完成。
因此,在 Highcontrol 模式 下,用户能够调用和自动化的能力范围,原则上不超过 APP 或手柄原本可实现的功能边界,但不开放底层电机级控制权限。
2. Highcontrol运行流程图

(1)初始化阶段(init)
系统启动后完成以下初始化流程:
-
建立客户端与机器人运控程序之间的通信连接
-
注册机器人状态数据接收回调函数
(2)DDS 回调线程持续接收回传状态
运控程序持续向客户端推送机器人状态数据。
回调函数接收到数据后进行封装,并分别存入缓冲区及全局状态变量:
-
motor_state_buffer_:电机状态缓冲区 -
imu_buffer_:IMU 状态缓冲区 -
joy_buffer_:手柄数据缓冲区 -
curmode:当前运控策略模式 -
curbattery:当前电池信息
3. HighController常用接口及参数表
| HighController接口 | ||
|---|---|---|
| 接口名称 | 接口描述 | 返回类型 |
| instance | 获取HighController单例指针 | 对象指针 |
| init | HighController对象初始化 | 无 |
| publish_cmd | 发布DDS控制命令数据 | 无 |
| get_mode | 获取当前机器人策略模式 | int |
| from_dds_get_joydata | 从DDS订阅中获取手柄数据 | 手柄数据结构体 |
| get_imu_data | 从DDS订阅中获取imu数据 | IMU数据结构体 |
| get_joint_state | 从DDS订阅中获取电机数据 | 电机数据结构体数组 |
获取HighController对象单例
| 函数名 | instance |
|---|---|
| 函数原型 | static HighController *Instance() |
| 功能概述 | 获取 HighController单例 |
| 参数 | 无 |
| 返回值 | HighController单例对象指针 |
| 备注 |
C++示例:
HighController *ctrl = HighController::Instance();
Python示例:
ctrl = HighController.instance()
HighController对象初始化
| 函数名 | init |
|---|---|
| 函数原型 | bool init() |
| 功能概述 | HighController对象初始化 |
| 参数 | 无 |
| 返回值 | bool |
| 备注 |
C++示例:
ctrl->init()
Python示例:
ctrl.init()
发布机器人控制指令
| 函数名 | publish_cmd |
|---|---|
| 函数原型 | void publish_cmd(double ver, double hor, ControlCmd action, uint16_t index) |
| 功能概述 | 使用HighController发送dds控制指令 |
| 参数 |
|
| 返回值 | 无 |
| 备注 | 此接口不能连续调用,否则机器人接收指令太快会无法响应,需要在每次指令发送至少添加2ms的延时 |
C++示例:
ctrl->publish_cmd(0, 0, ControlCmd.CHEER, 0);
Python示例:
ctrl.publish_cmd(0, 0, ControlCmd.CHEER, 0)
action参数表示切换机器人到对应模式
| 参数名称 | 定义原型 | 序号 | 示例值 | 说明 |
|---|---|---|---|---|
ControlCmd | | 0 | WALK | 走路模式 |
| 1 | SWING | 出厂预设动作挥手 | ||
| 2 | SHAKE | 出厂预设动作握手 | ||
| 3 | CHEER | 出厂预设动作欢呼 | ||
| 4 | RUN | 预留模式,当前版本不可用 | ||
| 5 | START | 使能/失能 | ||
| 6 | SWITCH | 准备模式 | ||
| 7 | STARTTEACH | 开始示教 | ||
| 8 | SAVETEACH | 保存示教 | ||
| 9 | ENDTEACH | 结束示教(弃用) | ||
| 10 | PLAYTEACH | 播放示教 | ||
| 11 | DANCE | 舞蹈1模式 | ||
| 12 | FALLTOSTAND | 倒地起身 | ||
| 13 | STANDTOFALL | 起身倒地 | ||
| 14 | DANCE1 | 舞蹈2模式 | ||
| 15 | DANCE2 | 舞蹈3模式 | ||
| 16 | TEAR | 预设擦眼泪动作 | ||
| 17 | DEFAULT | 空模式 |
DEFAULT空模式使用目的
整个机器人线程会循环执行process 控制函数是周期循环执行的,如果在其中持续下发
action = ControlCmd::PLAYTEACH; 等示教相关命令的话
机器人会在 示教播放动作未播放完的情况,导致动作被反复打断,表现为机器人“卡住、无反应”。
正确做法
PLAYTEACH 属于 一次性触发指令(事件),应 只发送一次;后续循环发送 DEFAULT(空指令),避免重复触发。
示例代码(修正后)
if (is_first) {
action = ControlCmd::`**`PLAYTEACH`**`; // 只触发一次`
is_first = false;
} else {
action = ControlCmd::DEFAULT;
}
效果
-
收到
PLAYTEACH→ 触发并完整执行示教动作 -
后续
DEFAULT→ 不再打断动作 -
机器人行为正常、可预期
动作类指令要“边沿触发”,不能在控制循环里持续下发。
START 使能/失能
workmode == 30,发送START使机器人进入使能模式
workmode != 30,发送START使机器人立刻进入失能模式
index用于在示教相关模式下指定示教文件索引
ctrl.publish_cmd(0, 0, ControlCmd.STARTTEACH, 0) # 开始示教
sleep(10) # 录制示教动作
ctrl.publish_cmd(0, 0, ControlCmd.SAVETEACH, 1) # 结束并保存示教动作,指定索引为1
sleep(2) # 让运控程序执行完保存流程,防止被下条命令打断
ctrl.publish_cmd(0, 0, ControlCmd.PLAYTEACH, 1) # 播放示教文件1
仅当 action 为以下模式时:
TEAR / PLAYTEACH / WALK / SWING / CHEER / SHAKE / DEFAULT
参数 x 和 yaw 才会生效,用于控制机器人运动;在其他模式下,x 和 yaw 无效。
获取当前机器人策略模式
| 函数名 | get_mode |
|---|---|
| 函数原型 | int get_mode() |
| 功能概述 | 获取DDS机器人当前策略模式 |
| 参数 | 无 |
| 返回值 | int |
| 备注 |
C++示例:
int curmode = ctrl->get_mode();
Python示例:
curmode = ctrl.get_mode()
get_mode 返回数据对应表
| int值 | 说明 |
|---|---|
| 0 | 使能模式 |
| 1 | 准备模式 |
| 2 | 走路模式 |
| 5 | 舞蹈模式 |
| 8 | 出厂预设动作 打招呼 |
| 9 | 出厂预设动作 握手 |
| 10 | 出厂预设动作 欢呼 |
| 11 | 开始示教 |
| 12 | 结束示教 |
| 14 | 保存示教1 |
| 23 | 播放示教 |
| 26 | 保护模式 |
| 27 | 倒地起身 |
| 28 | 起身倒地 |
| 29 | 保存示教2 |
| 30 | 失能模式 |
| 31 | 舞蹈模式1 |
| 32 | 舞蹈模式2 |
| 33 | 擦眼泪动作 |
保存示教
SDK向机器人发送 SAVETEACH 后,机器人会陆续返回 退出示教 保存示教1 保存示教2 三个状态
保护模式
在处于站立控制策略(走路,示教,舞蹈等)下,运控程序会对 IMU 姿态数据进行持续监测。
当检测到姿态偏离站立稳定区间,并超过预设阈值时,系统将立即触发保护机制,强制切换至安全模式。
在保护模式下:
-
全身关节进入失能状态(电机停止主动输出)
-
终止当前运动控制策略
-
阻断进一步动作指令执行
该机制的目的在于:
-
防止机器人在跌倒或失稳过程中持续输出控制力矩
-
避免四肢失控摆动造成二次损伤
-
降低对设备本体及周围环境的潜在损害
该保护逻辑属于底层安全防护机制,具有最高优先级,不受上层控制指令影响。
获取DDS订阅的手柄数据
| 函数名 | from_dds_get_joydata |
|---|---|
| 函数原型 | const joydata from_dds_get_joydata() |
| 功能概述 | 获取DDS手柄输入数据 |
| 参数 | 无 |
| 返回值 | joydata结构体 |
| 备注 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| joydata | | axes | 遥控器遥感线性数值 |
| button | 遥控器按键按下映射数值 1 被按下 0 正常 |
| 手柄摇杆映射 | 映射说明 | 范围 |
|---|---|---|
| axes[0] | 右摇杆左右推动值 | [-1, 1] |
| axes[1] | 左摇杆前后推动值 | [-1, 1] |
带算力板的Bumi 后背接口为算力板接口,运控板无法插入手柄接收器,所以DDS获取不到手柄数据,所以手柄数据需要直接算力板上获取,详细请看 算力板直接获取手柄数据
C++示例:
joydata jsdata = ctrl->from_dds_get_joydata();
for (int i = 0; i < 14; i++)
std::cout << jsdata.button[i] << std::endl;
std::cout << jsdata.axes[0] << std::endl;
std::cout << jsdata.axes[1] << std::endl;
Python示例:
jsdata = ctrl.from_dds_get_joydata()
for i in range(14):
print(jsdata.button[i])
print(jsdata.axes[0])
print(jsdata.axes[1])
获取DDS订阅IMU数据
| 函数名 | get_imu_data |
|---|---|
| 函数原型 | const NingImuData get_imu_data() |
| 功能概述 | 获取imu数据 |
| 参数 | 无 |
| 返回值 | NingImuData结构体 |
| 备注 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| NingImuData | | ori | 姿态四元数 |
| ori_cov | 姿态协方差 | ||
| angular_vel | 角速度 | ||
| angular_vel_cov | 角速度协方差 | ||
| linear_acc | 线加速度 | ||
| linear_acc_cov | 线加速度协方差 |
C++示例:
NingImuData imu_data = ctrl->get_imu_data();
for (int i = 0; i < 4; i++)
std::cout << imu_data.ori[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.ori_cov[i] << std::endl;
for (int i = 0; i < 3; i++)
std::cout << imu_data.angular_vel[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.angular_vel_cov[i] << std::endl;
for (int i = 0; i < 3; i++)
std::cout << imu_data.linear_acc[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.linear_acc_cov[i] << std::endl;
Python示例:
imu_data = ctrl.get_imu_data()
for i in range(4):
print(imu_data.ori[i])
for i in range(9):
print(imu_data.ori_cov[i])
for i in range(3):
print(imu_data.angular_vel[i])
for i in range(9):
print(imu_data.angular_vel_cov[i])
for i in range(3):
print(imu_data.linear_acc[i])
for i in range(9):
print(imu_data.linear_acc_cov[i])
获取DDS订阅的电机信息数据
| 函数名 | get_joint_state |
|---|---|
| 函数原型 | const std::array<MotorState, 21> get_joint_state() |
| 功能概述 | 获取机器人电机状态数据 |
| 参数 | 无 |
| 返回值 | MotorState结构体数组 |
| 备注 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| MotorState | | pos | 电机位置 |
| vel | 电机转速 | ||
| tau | 电机扭矩 | ||
| motor_id | 电机ID | ||
| error | 电机错误码:
| ||
| temperature | 温度 |
C++示例:
std::array<MotorState, 21> joint_state = ctrl->get_joint_state();
for (int i = 0; i < 21; i++) {
std::cout << joint_state[i].pos << std::endl;
std::cout << joint_state[i].vel << std::endl;
std::cout << joint_state[i].tau << std::endl;
std::cout << joint_state[i].motor_id << std::endl;
std::cout << static_cast<int>(joint_state[i].error) << std::endl;
std::cout << joint_state[i].temperature << std::endl;
}
Python示例:
joint_state = ctrl.get_joint_state()
for i in range(21):
print(joint_state[i].pos)
print(joint_state[i].vel)
print(joint_state[i].tau)
print(joint_state[i].motor_id)
print(joint_state[i].error)
print(joint_state[i].temperature)
4. 运控状态切换流程图

注意:使用HighController开发过程中,模式切换请遵循上述流程图以确保合理安全
5. Demo例程介绍
SDK 文件夹中的 example_high.cpp 与 src/test_high.cpp 提供了一个示例 Demo,用于解析澳加狮手柄输入数据,并根据手柄操作生成对应控制指令发送至机器人。
(六)运控开发 LowController
运控开发介绍
LowController 将运控程序中的电机控制接口开放至 SDK,允许用户以 500Hz 的控制频率直接调节底层电机参数。结合强化学习算法部署,可实现对 Bumi 运动能力的深度定制,使其完成多样化的新动作与舞蹈等复杂行为。
注意:仅有EDU版本的Bumi可以开发LowController
1. Bumi训练框架
后续开放
2. LowController架构图

(1)状态数据上报
当客户端 SDK 与机器人运控程序建立连接后,运控程序会持续向客户端推送机器人实时状态信息,包括:
-
全身电机参数数据(pos 位置、vel 速度、tau 扭矩、kp、kd、temperature 温度、error 错误信息)
-
IMU 状态数据
-
澳加狮手柄数据
(2)客户端侧控制计算
客户端结合自身算法(通常为强化学习模型)进行实时策略计算,生成各电机的目标期望值(如目标位置等),并将电机控制指令数组写入缓冲区后下发至运控程序。
(3)运控程序转发机制
运控程序接收到客户端下发的电机指令数组后,不进行高层策略计算,而是直接将控制参数转发至硬件控制层。
(4)硬件执行层
硬件层接收电机目标参数后执行控制指令,驱动电机完成期望动作。
在 LowController 模式下:
-
强化学习模型部署在客户端侧
-
用户可直接参与电机级控制
-
运控程序主要承担通信与安全转发职责
-
控制频率可达
500Hz
该模式具备更高的控制自由度与灵活性,但同时也意味着:
-
对算法稳定性要求更高
-
对实时性与系统安全性的要求更严格
-
若控制策略不稳定,可能直接影响机器人运动安全
3. LowController运行流程图

(1)初始化阶段(init)
系统启动后完成以下初始化步骤:
-
建立客户端与机器人运控程序之间的通信连接
-
注册机器人状态数据接收回调函数
-
创建
send_thread数据发送线程
(2)状态数据回调机制
运控程序持续向客户端推送机器人状态数据。
回调函数接收数据后进行封装,并存入对应缓冲区或全局变量:
-
motor_state_buffer_:电机状态缓冲区 -
imu_buffer_:IMU 状态缓冲区 -
joy_buffer_:手柄数据缓冲区
该阶段仅负责数据接收与缓存,不参与控制策略计算。
(3)send_thread(数据发送线程)
数据发送线程同样以 2ms 周期运行:
-
若
motor_cmd_buffer_不为空 -
读取最新电机控制指令
-
将电机目标数组发送至运控程序
运控程序仅负责数据转发至硬件层,不参与高层控制决策。
(4)架构特征
LowController 模式的核心特征是:
-
客户端直接参与电机级控制
-
强化学习或自定义控制算法运行在客户端
-
运控程序不再负责高层策略计算,仅承担通信与安全转发职责
-
控制频率可达 500Hz
该模式提供更高的控制自由度与算法可塑性,但同时对:
-
实时性
-
算法稳定性
-
线程安全与调度精度
提出更高要求。
4. 关节电机信息
| ID | 名称 | 关节 | 扭矩 | 角度范围 | 弧度范围 | ||
|---|---|---|---|---|---|---|---|
| 0 | arm_l1_joint | 左臂肩关节pitch | 5 N.m | -135 | 135 | -2.36 | 2.36 |
| 1 | arm_l2_joint | 左臂肩关节roll | 5 N.m | -8 | 111 | -0.14 | 1.94 |
| 2 | arm_l3_joint | 左臂关节yaw | 5 N.m | -90 | 90 | -1.57 | 1.57 |
| 3 | arm_l4_joint | 左臂肘关节pitch | 5 N.m | -129 | 0 | -2.26 | 0.00 |
| 4 | leg_l1_joint | 左腿髋关节pitch | 60 N.m | -120 | 120 | -2.09 | 2.09 |
| 5 | leg_l2_joint | 左腿髋关节roll | 60 N.m | -38 | 90 | -0.66 | 1.57 |
| 6 | leg_l3_joint | 左大腿关节yaw | 15 N.m | -145 | 145 | -2.53 | 2.53 |
| 7 | leg_l4_joint | 左腿膝关节pitch | 60 N.m | 0 | 128 | 0.00 | 2.24 |
| 8 | leg_l5_joint | 左腿踝关节pitch | 30 N.m | -55 | 25 | -0.96 | 0.44 |
| 9 | leg_l6_joint | 左腿踝关节roll | 30 N.m | -10 | 10 | -0.17 | 0.17 |
| 10 | arm_r1_joint | 右臂肩关节pitch | 5 N.m | -135 | 135 | -2.36 | 2.36 |
| 11 | arm_r2_joint | 右臂肩关节roll | 5 N.m | -111 | 8 | -1.94 | 0.14 |
| 12 | arm_r3_joint | 右臂关节yaw | 5 N.m | -90 | 90 | -1.57 | 1.57 |
| 13 | arm_r4_joint | 右臂肘关节pitch | 5 N.m | -129 | 0 | -2.26 | 0.00 |
| 14 | leg_r1_joint | 右腿髋关节pitch | 60 N.m | -120 | 120 | -2.09 | 2.09 |
| 15 | leg_r2_joint | 右腿髋关节roll | 60 N.m | -90 | 38 | -1.57 | 0.66 |
| 16 | leg_r3_joint | 右大腿关节yaw | 15 N.m | -145 | 145 | -2.53 | 2.53 |
| 17 | leg_r4_joint | 右腿膝关节pitch | 60 N.m | 0 | 128 | 0.00 | 2.24 |
| 18 | leg_r5_joint | 右腿踝关节pitch | 30 N.m | -55 | 25 | -0.96 | 0.44 |
| 19 | leg_r6_joint | 右腿踝关节roll | 30 N.m | -10 | 10 | -0.17 | 0.17 |
| 20 | waist_1_joint | 腰关节yaw | 27 N.m | -90 | 90 | -1.57 | 1.57 |
MotorCmd.pos 对应 弧度信息
5. 澳加狮手柄数据映射
澳加狮手柄。button[]和按键映射表如下:
| 键位描述 | Button index |
|---|---|
| 右肩键 | 1 |
| 左肩键 | 2 |
| X | 5 |
| Y | 6 |
| B | 7 |
| A | 8 |
| + | 9 |
| - | 10 |
| 无 | 11 |
| 左摇杆按下 | 12 |
| 手柄摇杆映射 | 映射说明 |
|---|---|
| axes[0] | 右摇杆Y方向值 |
| axes[1] | 左摇杆X方向值 |
手柄摇杆数据范围
| 最小值 | 最大值 |
|---|---|
| -1 | 1 |
6. LowController常用接口及使用例程
| LowController接口 | ||
|---|---|---|
| 接口名称 | 接口描述 | 返回类型 |
| instance | 获取LowController单例指针 | 对象指针 |
| init | LowController对象初始化 | 无 |
| set_joint | 将电机控制命令写入缓冲区 | 无 |
| get_mode | 获取当前机器人策略模式 | int |
| from_dds_get_joydata | 从DDS订阅中获取手柄数据 | 手柄数据结构体 |
| get_imu_data | 从DDS订阅中获取imu数据 | IMU数据结构体 |
| get_joint_state | 从DDS订阅中获取电机数据 | 电机数据结构体数组 |
获取LowController对象单例
| 函数名 | instance |
|---|---|
| 函数原型 | static LowController *Instance() |
| 功能概述 | 获取 HighController单例 |
| 参数 | 无 |
| 返回值 | LowController单例对象指针 |
| 备注 |
C++示例:
LowController *ctrl = LowController::Instance();
Python示例:
ctrl = LowController.instance()
LowController对象初始化
| 函数名 | init |
|---|---|
| 函数原型 | bool init() |
| 功能概述 | LowController对象初始化 |
| 参数 | 无 |
| 返回值 | bool |
| 备注 |
C++示例:
ctrl->init()
Python示例:
ctrl.init()
电机控制命令数组存入缓冲区
存入缓冲区后,会由send_thread 线程自动发送
| 函数名 | set_joint |
|---|---|
| 函数原型 | void set_joint(std::array<MotorCmd, 21> motorcmd) |
| 功能概述 | 设置关节数据 |
| 参数 | motorcmd 电机命令结构体 |
| 返回值 | 无 |
| 备注 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| MotorCmd | | pos | 电机位置 |
| vel | 电机转速 | ||
| tau | 电机扭矩 | ||
| kp | pid参数 | ||
| kd | pid参数 | ||
| motor_id | 电机ID |
电机控制命令下发请严格参考 关节电机信息 中的指定参数范围
C++示例:
std::array<MotorCmd, 21> motorcmd;
// 省略算法逻辑 ...
ctrl->set_joint(motorcmd);
Python示例:
cmds = [MotorCmd() for _ in range(21)]
# 省略算法逻辑 ...
ctrl.set_joint(cmds)
根据关节电机名称获取对应关节电机ID
| 函数名 | getJointsIndex |
|---|---|
| 函数原型 | int getJointsIndex(std::string jointname) |
| 功能概述 | 根据关节电机名称获取对应关节电机ID |
| 参数 | jointname: 关节电机名称 |
| 返回值 | int:对应关节电机ID |
| 备注 |
C++示例:
int id = ctrl->getJointsIndex("arm_l1_joint");
Python示例:
id = ctrl.getJointsIndex("arm_l1_joint");
| 函数名 | from_dds_get_joydata |
|---|---|
| 函数原型 | const joydata from_dds_get_joydata() |
| 功能概述 | 获取DDS手柄输入数据 |
| 参数 | 无 |
| 返回值 | joydata结构体 |
| 备注 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| joydata | | axes | 遥控器遥杆线性数值 |
| button | 遥控器按键按下映射数值 1 被按下 0 正常 |
| 手柄摇杆映射 | 映射说明 | 范围 |
|---|---|---|
| axes[0] | 右摇杆左右推动值 | [-1, 1] |
| axes[1] | 左摇杆前后推动值 | [-1, 1] |
带算力板的Bumi 后背接口为算力板接口,运控板无法插入手柄接收器,所以DDS获取不到手柄数据,所以手柄数据需要直接算力板上获取,详细请算力板直接获取手柄数据
C++示例:
joydata jsdata = ctrl->from_dds_get_joydata();
for (int i = 0; i < 14; i++)
std::cout << jsdata.button[i] << std::endl;
std::cout << jsdata.axes[0] << std::endl;
std::cout << jsdata.axes[1] << std::endl;
Python示例:
jsdata = ctrl.from_dds_get_joydata()
for i in range(14):
print(jsdata.button[i])
print(jsdata.axes[0])
print(jsdata.axes[1])
| 函数名 | get_imu_data |
|---|---|
| 函数原型 | const NingImuData get_imu_data() |
| 功能概述 | 获取imu数据 |
| 参数 | 无 |
| 返回值 | NingImuData结构体 |
| 备注 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| NingImuData | | ori | 姿态四元数 |
| ori_cov | 姿态协方差 | ||
| angular_vel | 角速度 | ||
| angular_vel_cov | 角速度协方差 | ||
| linear_acc | 线加速度 | ||
| linear_acc_cov | 线加速度协方差 |
C++示例:
NingImuData imu_data = ctrl->get_imu_data();
for (int i = 0; i < 4; i++)
std::cout << imu_data.ori[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.ori_cov[i] << std::endl;
for (int i = 0; i < 3; i++)
std::cout << imu_data.angular_vel[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.angular_vel_cov[i] << std::endl;
for (int i = 0; i < 3; i++)
std::cout << imu_data.linear_acc[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.linear_acc_cov[i] << std::endl;
Python示例:
imu_data = ctrl.get_imu_data()
for i in range(4):
print(imu_data.ori[i])
for i in range(9):
print(imu_data.ori_cov[i])
for i in range(3):
print(imu_data.angular_vel[i])
for i in range(9):
print(imu_data.angular_vel_cov[i])
for i in range(3):
print(imu_data.linear_acc[i])
for i in range(9):
print(imu_data.linear_acc_cov[i])
| 函数名 | get_joint_state |
|---|---|
| 函数原型 | const std::array<MotorState, 21> get_joint_state() |
| 功能概述 | 获取机器人电机状态数据 |
| 参数 | 无 |
| 返回值 | MotorState结构体数组 |
| 备注 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| MotorState | | pos | 电机位置 |
| vel | 电机转速 | ||
| tau | 电机扭矩 | ||
| motor_id | 电机ID | ||
| error | 电机错误码:
| ||
| temperature | 温度 |
C++示例:
std::array<MotorState, 21> joint_state = ctrl->get_joint_state();
for (int i = 0; i < 21; i++) {
std::cout << joint_state[i].pos << std::endl;
std::cout << joint_state[i].vel << std::endl;
std::cout << joint_state[i].tau << std::endl;
std::cout << joint_state[i].motor_id << std::endl;
std::cout << static_cast<int>(joint_state[i].error) << std::endl;
std::cout << joint_state[i].temperature << std::endl;
}
Python示例:
joint_state = ctrl.get_joint_state()
for i in range(21):
print(joint_state[i].pos)
print(joint_state[i].vel)
print(joint_state[i].tau)
print(joint_state[i].motor_id)
print(joint_state[i].error)
print(joint_state[i].temperature)
获取澳加狮手柄数据(带算力板的Bumi 算力板直接获取)
AoLionDriver类
| AoLionDriver类接口 | |
|---|---|
| init | 初始化 |
| getremotedata | 获取手柄数据 |
| 函数名 | init |
|---|---|
| 函数原型 | bool init(std::string port, int baudrate) |
| 功能概述 | 初始化手柄设备端口 |
| 参数 |
|
| 返回值 | true:初始化成功 falese:初始化失败 |
| 备注 |
| 函数名 | getremotedata |
|---|---|
| 函数原型 | const joydata getremotedata() |
| 功能概述 | 获取手柄数据 |
| 参数 | 无 |
| 返回值 | joydata:手柄数据结构体 |
| 备注 |
使用示例
C++
AoLionDriver aoliondriver;
joydata remote_data;
aoliondriver.init("/dev/input/js0", 115200);
const joydata jdata=aoliondriver.getremotedata();
for (int i = 0; i < 14; i++)
std::cout << jdata.button[i] << std::endl;
std::cout << jdata.axes[0] << std::endl;
std::cout << jdata.axes[1] << std::endl;
Python
al = AoLionDriver()
al.init("/dev/input/js0", 115200)
jdata = al.getremotedata()
for i in range(14):
print(jdata.button[i])
print(jdata.axes[0])
print(jdata.axes[1])
7. Demo例程介绍
examples_cpp/example_low.cpp 和 examples_py/test_low.py中运行了一个Bumi的21个自由度跑步策略(policy/policy.onnx)的sim2real(算法模型实机部署)的代码,根据策略提供了部分强化学习部署接口
| 函数名 | loadModel |
|---|---|
| 函数原型 | bool loadModel(std::string modelpath) |
| 功能概述 | 加载自有模型 |
| 参数 |
|
| 返回值 | true:加载成功;false:加载失败 |
| 备注 |
| 函数名 | onnxdatainit |
|---|---|
| 函数原型 | void onnxdatainit() |
| 功能概述 | 初始化onnx数据 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | getmodelparam |
|---|---|
| 函数原型 | bool getmodelparam() |
| 功能概述 | 从yaml文件中获取模型参数 |
| 参数 | 无 |
| 返回值 | true:读取yaml文件成功;false:读取yaml文件失败 |
| 备注 |
| 函数名 | setparameter |
|---|---|
| 函数原型 | void setparameter(Command &cmd,bool* isfirst) |
| 功能概述 | 设置xyz整机控制参数 |
| 参数 |
|
| 返回值 | 无 |
| 备注 |
| 函数名 | updatestateestimation |
|---|---|
| 函数原型 | bool updatestateestimation() |
| 功能概述 | 更新状态,包括关节角度,IMU数据等从yaml文件中获取模型参数 |
| 参数 | 无 |
| 返回值 | true:读取yaml文件成功;false:读取yaml文件失败 |
| 备注 |
| 函数名 | computeObservation |
|---|---|
| 函数原型 | void computeObservation() |
| 功能概述 | 计算观测系数 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | computeActions |
|---|---|
| 函数原型 | void computeActions() |
| 功能概述 | 计算最终的动作 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
手柄操作流程
| 使用步骤 | |
|---|---|
+ | 全身关节回0位进入阻尼模式 |
LB & - | 四肢微微弯曲,进入策略前准备模式 |
LB & X | 进入策略控制跑步模式 |
(七)相机例程
EDU版本Bumi(BumiEDU_Pro、BumiEDU_MAX、BumiEDU_Tailor)相机硬件直接到算力板上,可以直接访问算力板上硬件接口获取数据
Intel D435i 相机例程请参考: https://github.com/IntelRealSense/librealsense
(八)快速开发
以下所有操作都是在Bumi算力板上进行,算力板本身已经安装好所需编译环境也可以通过docker部署编译环境
外挂开发部署环境请看:SDK编译环境部署流程
有线连接算力板 SSH登录
ssh noetix@192.168.55.101
无线连接算力板 SSH登录(无线IP可通过手机AppWfii连接中查看,算力板使用的运控板的Wifi模块)
ssh -p 2222 noetix@[机器人WIFI-IP]
1. SDK目录结构
.
├── build.sh # 编译脚本
├── CMakeLists.txt
├── config # 模型配置文件 DDS配置文件等
├── examples_cpp # C++ 示例代码
├── examples_py # python 示例代码
├── include # 头文件目录
├── lib # 库文件目录
├── LICENSE
├── policy # 模型策略文件目录
├── README.md
└── src # 源文件目录
2. docker开发环境镜像部署
注意:此镜像包为aarch64架构,仅在aarch64架构电脑上可部署
- 解压压缩包
tar -zxvf noetix_dds.tar.gz
解压出来后,压缩包内会有noetix_dds.tar 开发镜像文件 noetix_dds.yaml 配置部署文件
version: "3.8"
services:
noetix_dds:
image: noetix_dds:arm64
container_name: noetix_dds
network_mode: host
volumes:
- /home/noetix/work:/home/noetix/work:rw # 挂载工作目录
# /home/noetix/work 冒号前这部分要改成用户的工作目录,创建一个/home/noetix/work/路径目录
stdin_open: true
tty: true
- 部署
docker load -i noetix_dds.tar
docker images # 确认noetix_dds arm64 镜像是否存在
mkdir -p /home/noetix/work # 创建工作目录, 用户自行选择
docker compose -f noetix_dds.yaml up -d # 部署
docker ps # 检查 noetix_dds 是否存在
- 进入dock容器
docker exec -it noetix_dds /bin/bash
后续将DDS SDK 放入工作目录即可开始开发
3. 编译SDK
cd noetix_sdk_bumi
./build.sh # 一键编译脚本
编译成功后会在SDK根目录下生成可执行文件 example_low 和 example_high ,并且在build目录下生成highcontrol_py 以及 lowcontrol_py pybind库,供python调用
4. 启动程序
C++
cd noetix_sdk_bumi
sudo ./build/example_high # or sudo ./build/example_low
Python
cd noetix_sdk_bumi
python3 examples_py/test_low.py # python3 examples_py/test_high.py
调试过程中,请全程使用机器人吊架,以免错误程序失控造成损失
(九)常见问题及注意事项
- DDS客户端demo:运行报错(1)
ARM架构:
error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
libssl1.1_1.1.1f-1ubuntu2.16_arm64.deb
sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2.16_arm64.deb
X86架构:
error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
libssl1.1_1.1.1f-1ubuntu2_amd64.deb
sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb
