N2 SDK开发指南
一、关于N2
(一)部件名称
N2 整机分为上半身和下半身,具备18个自由度。单臂拥有4个自由度,包括:
-
肩关节pitch -
肩关节roll -
上臂关节yaw -
手肘关节pitch
单腿拥有5个自由度,包括:
-
胯关节yaw -
髋关节roll -
髋关节pitch -
膝关节pitch -
踝关节pitch
拥有多个关节电机自由度,使得N2机器人能够实现精确的运动和姿态控制。
| 类型 | N2 |
|---|---|
| 总自由度 | 18 |
| 单腿自由度 | 5 |
| 手臂自由度 | 4 |
| 部件说明 |
1.机器人规格介绍
![]() | ![]() | ![]() |
|---|


| 参数 | N2 | N2-教育版 |
|---|---|---|
| 高宽厚(站立) | 1140mm*491.38mm*280mm | |
| 带电池重量 | 约33.5kg | |
| 总自由度 | 18~20 | |
| 单腿自由度 | 5 | |
| 单手臂自由度 | 4 | |
| 算力模块 | / | Jetson Orin Nano Super |
| 关节最大扭矩 | 150N.m | |
| 手臂最大负载 | 5kg | |
| 小腿&大腿长度 | 约0.76M | |
| 手臂臂展 | 约0.4M | |
| 关节编码器 | 双编码器 | |
| 散热系统 | 局部风冷散热 | |
| 供电方式 | 锂电池 | |
| 基础算力 | 6Tops | 6+67Tops |
| 感知传感器 | 深度相机 | |
| 4麦克风阵列 | 选配 | |
| 5w扬声器 | 选配 | |
| 高算力模组 | / | NVIDIA Jetson Orin |
| 智能电池(快拆) | 52V/7Ah | |
| 充电器 | 54.6V5A | |
| 遥控手柄 | 有 | |
| 续航时间 | 约2h | |
| 二次开发 | / | 有 |
2.电气接口

| 类型 | 数量 |
|---|---|
| 以太网 | 1 |
| USB | 2 |
| HDMI | 1 |
其中HDMI接口接到的是 运控板(RK3588S) 上面,如果用户购买的是教育版本,目前只能通过ssh访问 二开 算力 板(NVIDIA jetson orin nano super)
3.板卡信息及用户名IP
| 类型 | 型号 | 用户 | IP | 密码 | 算力 | 频率 | 内存 |
|---|---|---|---|---|---|---|---|
| 运控板 | 鲁班猫 RK3588S | noetix | 192.168.55.102 | n | 6Tops | 2.4GHz | 4+32GB |
| 二开算力板 | NVIDIA Jetson orin nano super | 192.168.55.101 | n2 | 67Tops | 1.7GHz | 8+128GB |
二开算力板仅教育版本的N2特有
在机器人运动控制程序运行的过程中,请 务必不要通过 连接机器人的运控板(RK3588S) ,否则会占用 EtherCAT 带宽,导致机器人运动控制程序中断,机器人会立刻瘫软在地上,容易造成损失。
如需进行 SSH 连接,请务必先让机器人 趴在地面 ,或 悬挂在保护架上 进入失能状态。连接过程中,请确保机器人周围没有放置物品,并且人与机器人保持安全距离,以避免意外动作造成碰撞。
若未按照上述要求进行 SSH 连接而导致损失,本公司概不负责!!!
(二)操作指南
建议您在日常演示,尤其是二次开发中,全程使用保护支架悬挂N2,以更好的保护N2设备
1.快速开始
原厂运控功能暂不支持上下楼梯,请在平坦开阔处操作E1机器人,同时请远离人群,避免摔倒伤人、损坏机器哦
机器人原厂运控的各种模式
| 模式 | 功能 | 备注(以下按键以澳加狮手柄为例) |
|---|---|---|
失能模式 | 机器人全身关节松软 | 在任何情况下按 + 号 都会进入失能模式(急停) |
使能模式 | 机器人全身关节阻尼 | 失能模式下按 + 号 进入使能模式 |
准备模式 | 机器人四肢稍弯曲,进入运动前准备 | 在使能模式下按 LB & "-"进入准备模式 |
走路模式 | 机器人可以自主站立并且可以走路 | 在准备/跑步模式下按 LB & X 进入走路模式,此模式不要让机器人双脚离地,否则机器人会乱踢伤人 |
跑步模式 | 机器人可以自主栅篱并且可以跑步 | 在走路模式下按 LB & Y 进入跑步模式,此模式不要让机器人双脚离地,否则机器人会乱踢伤人 |
舞蹈模式 | 机器人进入舞蹈准备模式 | 在走路模式下按 LB & A 进入舞蹈模式,此模式不要让机器人双脚离地,否则机器人会乱踢伤人 |
示教模式 | 机器人进入示教模式,记录手部动作 | 在走路模式下按 RB & Y 进入示教模式,此模式不要让机器人双脚离地,否则机器人会乱踢伤人 |
使用流程图

黑色往左的箭头为正常关机流程
黑色往右的箭头为正常使用流程
红色箭头代表紧急情况下的急停操作,在其他任何模式下按急停(+号)都会进入失能模式,使用的时候注意,避免误触
使用流程
将机器人从包装箱中取出,推荐将机器人吊在架子上启动,或者也可以让机器人躺/趴在地上启动
安装电池
安装电池: 按住机器人左侧银色的卡扣按钮(按到底),同时将电池往里推送进去 (取下电池同理)
注意事项:放电池时注意电池方向,按钮在上指示灯在下
安装手柄接收器
将手柄USB接收器 插入机器人背后任意一个USB接口,确保不虚接不松动。
启动机器
电池插入机器人背部后,先短按电池上的开机按钮,等指示灯亮起之后,长按按钮,此时会有流水灯的效果,听到“滴”一声,机器人各部位指示灯亮起,标识开机。
配对手柄
如果手柄和接收器第一次配对时候,需要在机器人开机状态并已经插上手柄接收器后,长按手柄上面的home按键,直至指示灯常亮,此时松手,指示灯快速闪烁进入配对模式。当手柄震动后,并且下面三个指示灯常亮后代表配对成功
已经配对过之后,后续可以直接点按home按键可直接记忆配对
以下操作以澳加狮手柄举例
进入行走模式
机器人开机后,等待10秒左右会自动进入使能模式(阻尼模式)
待机器人进入使能模式后,使机器人站直于地面,按 LB 和 - 让机器人进入准备模式
观察机器人是否出现双腿微屈的情况
,出现后 按 LB 和 X
进入走路模式,如果未出现双腿弯曲,重复上一步
注意:机器人不能走高于5cm的楼梯或者障碍,不能走大于25度的斜坡(有倒地风险)
后续操作请看下面按键功能图表
关机流程
使用完后,此时需要扶住机器人按 LB 和 -让机器人回到准备模式,此时机器失去自主站立的能力,需要人扶住。
将机器人吊起或者放平躺(趴)后,按 + 号键,让机器人进入失能模式
然后长按电机开关,关机后取下电池即可。
遥控器按键功能图表
- 基础功能

| 键位 | 前置条件 | 功能 | 备注 |
|---|---|---|---|
+ | 使能/失能模式 | 使能和失能 | |
LB & - | 使能模式 | 准备模式 | 此时不能自主平衡需人工保持站立 |
LB & X | 准备模式 | 走路模式 | 推摇杆可以保持平衡 |
LB & Y | 走路模式 | 跑步模式 | 请预留足够的空间和停止提前量 |
LB & B | 走路模式 | 倒地动作 | 倒地之后自动进入准备模式 |
左摇杆 | 走路/跑步模式 | 前进和后退 | |
右摇杆 | 走路/跑步模式 | 左右转向 | |
A | 走路模式 | 握手 | |
B | 走路模式 | 挥手 | |
Y | 走路模式 | 欢呼 |
澳加狮手柄的“+”按键是控制机器人使能/失能,也可以用于在紧急状态下急停机器人
在机器人正常运行状态下,注意不要按下或误触“+”键,否则机器人会立刻失能倒地,避免造成损失
- 示教功能
示教功能允许用户通过手动摆动机器人双臂来记录动作。系统实时采集各关节角度和持续时间,并将生成的运动轨迹(.bin 文件)保存到 RK3588S 运控板 SDK 的 data 目录。后续可通过手柄按键或 DDS 客户端触发回放,让机器人精确复现记录的动作轨迹。
简而言之:用户可以零代码DIV机器人的动态手部姿势

| 键位 | 前置条件 | 功能 | 备注 |
|---|---|---|---|
RB & Y | 走路模式 | 进入示教状态 | |
RB & B | 示教状态 | 结束示教 | |
RB & X | 结束示教 | 保存示教 | 接下来按 [A, B, X, Y]保存到对应的按键上 |
RB & LB & [A, B, X, Y] | 走路模式 | 播放对应按键下保存的示教动作 | 播放完后切记先切换回走路模式后,在播放其他示教动作或者切换其他模式 |
使用舞蹈功能请遵循以下几点:
- 请按照备注要求预留足够大的活动空间,路面一定平整不打滑
- 电池电量在2格电及以上
- 跳舞过程中不要用力牵着机器人,不要让机器人收到外部力量干扰
- 部分舞蹈可以中途在接近站立时切走路模式打断 但不要在跳舞中弯腰动作时切到走路模式
PS: 请避免在光滑地面和高低不平地面使用,使用舞蹈时应有足够的施展空间运行动作。因操作环境和操作失误导致的机器人损坏,不在保修范围内。
若您收到机器人后需要测试英歌舞,首次测试需人保护,牵绳(仅做保护不向吊装绳施加额外的力),另外留出足够大的演示空间,以便您清楚了解大致使用空间后再进行后续演示,若第一次测试即出现问题,请及时联系客服人员
- 舞蹈功能(目前仅限澳加狮手柄)
| 键位 | 前置条件 | 功能 | 备注 |
|---|---|---|---|
LB & A | 走路模式 | 进入舞蹈模式 | 请预留 6 * 6(米)的空间 |
X | 舞蹈模式 | 播放长版本英歌舞 | 请预留 6 * 6(米)的空间 |
Y | 舞蹈模式 | 播放短版本英歌舞 | 请预留 6 * 6(米)的空间 |
LT & Y | 走路模式 | 播放广播体操 | 请预留 6 * 6(米)的空间 |
- 大幅度高难动作
使用以下功能请务必注意以下7点:
- 按照功能要求在开阔地带使用,地面平坦没有坡度且粗糙不打滑,附近没有杂物
- 使用时不能离机器太远,会导致机器人断连,导致失制!!!
- 表演时在功能要求范围大小内尤其是动作结束落点要远离人群,尤其是妇女儿童
- 如果机器人表演失败,请立刻按手柄上的
+按键 让机器人失能 - 电池 指示灯 在 4 格
- 半小时内不能连续使用两次
- 机器人的手部必须是出厂原装塑胶球手
如没有按照以上要求使用,造成任何损失与我司无关
| 键位 | 前置条件 | 功能 | 备注 |
|---|---|---|---|
LT & X | 走路模式 | 垫步侧手翻(机器人正面朝向) | 需要机器人正前方为轴,左右90度半圆区域十米开阔的开阔地带 |

二、关节电机顺序
N2机器人关节电机状态数据由SDK接口获取,获取到的顺序固定,如下:
| 序号 | 名称 | 关节 | 扭矩 |
|---|---|---|---|
| 0 | arm_l1_joint | 左臂肩pitch关节 | 27N.m |
| 1 | arm_l2_joint | 左臂肩roll关节 | 27N.m |
| 2 | arm_l3_joint | 左臂大臂yaw关节 | 27N.m |
| 3 | arm_l4_joint | 左臂肘pitch关节 | 27N.m |
| 4 | leg_l1_joint | 左腿髋yaw关节 | 90N.m |
| 5 | leg_l2_joint | 左腿髋roll关节 | 90N.m |
| 6 | leg_l3_joint | 左腿大腿pitch关节 | 150N.m |
| 7 | leg_l4_joint | 左腿膝关节pitch关节(连杆) | 150N.m |
| 8 | leg_l5_joint | 左腿小腿pitch踝关节(连杆) | 70N.m |
| 9 | arm_r1_joint | 右臂肩pitch关节 | 27N.m |
| 10 | arm_r2_joint | 右臂肩roll关节 | 27N.m |
| 11 | arm_r3_joint | 右臂大臂yaw关节 | 27N.m |
| 12 | arm_r4_joint | 右臂肘pitch关节 | 27N.m |
| 13 | leg_r1_joint | 右腿髋yaw关节 | 90N.m |
| 14 | leg_r2_joint | 右腿髋roll关节 | 90N.m |
| 15 | leg_r3_joint | 右腿大腿pitch关节 | 150N.m |
| 16 | leg_r4_joint | 右腿膝关节pitch关节(连杆) | 150N.m |
| 17 | leg_r5_joint | 右腿小腿pitch踝关节(连杆) | 70N.m |
三、遥控器按键数据映射
自研遥控器。button[]和按键映射表如下:
| 键位描述 | Button index |
|---|---|
| KEY1 食指按键扳机上 | 1 |
| KEY2 食指按键扳机下 | 2 |
| KEY5,拇指按键,上左 | 5 |
| KEY6,拇指按键,上右 | 6 |
| KEY7,拇指按键,下左 | 7 |
| KEY8,拇指按键,下右 | 8 |
| KEY9,侧按键,左上S1 | 9 |
| KEY10,侧按键,左下S2 | 10 |
| KEY11 ,侧按键,右上F2 | 11 |
| KEY12 ,侧按键,右下F1 | 12 |
澳加狮手柄。button[]和按键映射表如下:
| 键位描述 | Button index |
|---|---|
| 右肩键 | 1 |
| 左肩键 | 2 |
| X | 5 |
| Y | 6 |
| B | 7 |
| A | 8 |
| + | 9 |
| - | 10 |
| 无 | 11 |
| 左遥感按下 | 12 |
手柄摇杆数据范围
| 最小值 | 最大值 |
|---|---|
| -1 | 1 |
四、N2的URDF文件

请登录到客户服务平台后下载
五、DDS接口开发
(一)SDK概述
本 SDK 采用C/S架构,并基于 DDS消息中间件 实现通信。在隔离机制下,使 N2 机器人的 二次开发算力板(NVIDIA Jetson Orin Nano Super) 作为客户端与机器人上的 运控板 作为服务器之间能够高效、安全地交互。dds使用的是CYCLONEDDS 0.11.0。
(二)SDK开发流程
使用此SDK开发可以分为大致以下几步:
-
初始化DDS
-
通过DDS发布消息让机器人切换为DDS控制模式
-
设置回调,订阅机器人状态等信息
-
用户算法控制
-
通过DDS发布命令控制
以上1 2 3 5 在例程文件中已经做好了,用户仅需参考例程接口代码或者只完成第4步即可
功能简介
用户可使用 SDK 实现以下功能:
-
应用开发:基于原厂控制算法,快速实现机器人自动化应用,或与大模型集成,打造定制化智能行为。例如:-
配合摄像头算法程序与原厂运控结合,实现自主行进
-
配合语音交互,实现语音控制机器人
-
接入大模型,根据输入动态生成并执行机器人原厂控制动作
-
-
运控开发:通过 DDS 接口:-
获取电机状态与 IMU 传感器数据
-
下发电机控制指令,并以500Hz的频率进行闭环控制。
-
支持完全用户重新定制运控模型
-
两种控制方式
-
highcontrol-
用户只需要给方向、速度、动作编号。
-
底层由厂家的运控算法接管。
-
适合快速上手、做行为级控制。
-
-
lowcontrol-
用户要自己生成每个电机的
pos、vel、tau、kp、kd。 -
控制自由度高,但需要较强的运动控制算法。
-
用户可以自己搭建控制算法模型。
-
前置条件
SDK运行在Linux系统上,SDK不依赖ROS,用户基于机器人上的控制器开发不需要安装其他库,机器人二开算力板上出厂默认没有环境,需要安装:
-
fmt -
eigen3 -
onnxruntime -
drake -
glog -
spdlog -
python3 -
pybind11
详细请看N2 SDK环境部署流程
(三)参考例程
1.应用开发
开发者可在 highcontroller.cpp 中的 HighController::process 函数内进行扩展,最后调用set_axes下发控制命令,控制指令下发详细流程代码可以参考set_axes函数。
基本例程
执行此例程后机器人会根据cmd的x和action参数一边执行欢呼动作一边自主向前。
| 参数 | 范围 | 功能 | 备注 |
|---|---|---|---|
| cmd.x | [-1, 1] | 前进后退 | > 0 前进 |
| cmd.y | 无意义 | 无意义 | 无意义 |
| cmd.yaw | [-1, 1] | 左右转向 | > 0 左转 |
| 参数名称 | 定义原型 | 示例值 | 说明(括号内对应按键) |
|---|---|---|---|
| ControlCmd | | WALK | 走路模式(LB & X) |
SWING | 出厂预设动作挥手(B) | ||
SHAKE | 出厂预设动作握手(A) | ||
CHEER | 出厂预设动作欢呼(Y) | ||
RUN | 跑步模式(LB & Y) | ||
DANCE | 跳舞模式
通过设置 shortd 变量 为 1
或者 longd 变量 为 1
来播放长短版本英歌舞 | ||
START | 使能/失能(急停) | ||
SWITCH | 准备模式(LB & -) | ||
STARTTEACH | 开始示教(RB & Y) | ||
SAVETEACH | 保存示教(RB & B and RB & X) ps: 目前下发SAVETEACH,会先发送ENDTEACH在发送SAVETEACH,相等于将两个步骤简化为了一个 保存文件根据参数 file_index,具体可以参考HighController::set_axes接口 | ||
ENDTEACH | 结束示教(RB & B) | ||
PLAYTEACH | 播放示教 (RB & LB & file_index)根据 file_index播放对应文件示教动作 | ||
DEFAULT | 空模式 |
void HighController::process() {
static int keyflag[14];
joydata remote_data;
static char key_updown[14], key_inuse[14];
Command cmd;
auto now = Clock::now();
long starttimestamp =
std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch())
.count();
remote_data = remotedriver.getremotedata();
for (int i = 0; i < 14; i++) {
if (remote_data.button[i] == 0) {
key_updown[i] = 0;
key_inuse[i] = 0;
} else if (remote_data.button[i] == 1) {
key_updown[i] = 1;
}
}
ControlCmd action = ControlCmd::DEFAULT;
cmd.x = 0.0;
cmd.y = 0;
cmd.yaw = 0.0;
if (key_updown[Key2] == 0 && key_updown[Key5] == 1 &&
(key_inuse[Key5] == 0)) {
action = ControlCmd::STARTTEACH;
key_inuse[Key5] = 1;
} else if ((key_updown[Key6] == 1) && key_updown[Key2] == 0 &&
(key_inuse[Key6] == 0)) {
action = ControlCmd::SWING;
key_inuse[Key6] = 1;
} else if ((key_updown[Key7] == 1) && key_updown[Key2] == 0 &&
(key_inuse[Key7] == 0)) {
action = ControlCmd::SHAKE;
key_inuse[Key7] = 1;
} else if ((key_updown[Key8] == 1) && key_updown[Key2] == 0 &&
(key_inuse[Key8] == 0)) {
action = ControlCmd::CHEER;
key_inuse[Key8] = 1;
}
else if ((key_updown[Key9] == 1) && (key_inuse[Key9] == 0)) {
key_inuse[Key9] = 1;
action = ControlCmd::START;
} else if (key_updown[Key10] == 1 && (key_inuse[Key10] == 0)) {
action = ControlCmd::SWITCH;
key_inuse[Key10] = 1;
printf("SWITCH \n");
} else if (key_updown[Key2] == 1 && key_updown[Key5] == 1 &&
(key_inuse[Key5] == 0)) {
action = ControlCmd::WALK;
key_inuse[Key5] = 1;
printf("WALK \n");
} else if (key_updown[Key2] == 1 && key_updown[Key6] == 1 &&
(key_inuse[Key6] == 0)) {
action = ControlCmd::SAVETEACH;
key_inuse[Key6] = 1;
fileindex++;
printf("SAVETEACH \n");
} else if (key_updown[Key2] == 1 && key_updown[Key7] == 1 &&
(key_inuse[Key7] == 0)) {
action = ControlCmd::ENDTEACH;
key_inuse[Key7] = 1;
printf("ENDTEACH \n");
} else if (key_updown[Key2] == 1 && key_updown[Key8] == 1 &&
(key_inuse[Key8] == 0)) {
action = ControlCmd::PLAYTEACH;
key_inuse[Key8] = 1;
fileindex = 1;
printf("PLAYTEACH \n");
}
set_axes(cmd.x, cmd.yaw, (int)action, fileindex);
}
例程功能
将手柄接收器插到客户端的主机上
-
LB & - 下发SWITCH指令,让机器人进入准备模式(弯腿)
-
LB & X 下发WALK指令, 让机器人进入走路模式
-
X 下发 STARTTECH指令,让机器人进入示教模式
-
RB & Y 下发SAVETECH指令,机器人保存刚才录制的动作,根据变量file_index自增命名
-
LB & A 下发PLAYTECH指令,将file_index变量置1,所以一直只会播放一个保存的示教动作
保存下来的示教文件,会存放到机器人sdk中的data文件夹内,会在file_index上添加10个偏移量
例如,file_index=1,则对应保存下来的示教文件名称为demo_pos11.bin
process()_ 函数是周期循环执行的,如果在其中持续下发
action = ControlCmd::CHEER; 等动作或者切换模式的命令的话
机器人会在 欢呼动作尚未完成时不断收到新的 CHEER 指令,导致动作被反复打断,表现为机器人“卡住、无反应”。
正确做法
CHEER
属于 一次性触发指令(事件),应 只发送一次;后续循环发送
DEFAULT(空指令),避免重复触发。
示例代码(修正后)
if (is_first) {
action = ControlCmd::CHEER; // 只触发一次
is_first = false;
} else {
action = ControlCmd::DEFAULT;
}
效果
- 收到 CHEER → 触发并完整执行欢呼动作
- 后续 **DEFAULT → 不再打断动作
- 机器人行为正常、可预期
一句话总结:动作类指令要“边沿触发”,不能在控制循环里持续下发。
此例程仅为将控制机器人代码和参数封装好为可读性和理解性较强的代码,方便用户理解和二次开发,如果想要了解原理和流程请具体参考 HighController::set_axes
void HighController::set_axes(double ver, double hor, int action,
uint16_t index) {
RobotMotorCmd::MotorCmdArray cmdarray;
cmdarray.motorcmds().resize(18);
for (int i = 0; i < 18; i++) {
auto &cmd = cmdarray.motorcmds()[i];
cmd.pos() = 0;
cmd.vel() = 0;
cmd.tau() = 0;
cmd.kp() = 0;
cmd.kd() = 0;
cmd.motor_id() = 0;
}
auto now = Clock::now();
long long timestamp =
std::chrono::duration_cast<std::chrono::microseconds>(
now.time_since_epoch())
.count();
int diff = timestamp - statetimestamp;
cmdarray.timestamp() = timestamp;
cmdarray.controlcmd().axes()[0] = hor;
cmdarray.controlcmd().axes()[1] = ver;
cmdarray.controlcmd().action() = action;
if (action == 9 || action == 11) { // action = SAVETEACH or action = PLAYTEACH
cmdarray.controlcmd().data() = index;
}
if (action == 5) {
if (longd == 1)
cmdarray.controlcmd().data() = 0; // long dance
else if (shortd == 1)
cmdarray.controlcmd().data() = 1; // short dance
}
motor_cmd_buffer_.SetData(cmdarray);
}
2.运控开发
在 DDS 接口版本的 SDK 运行过程中,系统内部会启动两个核心线程:
process_thread_
负责执行用户自定义的控制算法逻辑。
-
从单值缓冲区中获取最新的传感器与状态数据;
-
执行用户算法逻辑;
-
需要用户将电机控制指令结果写入
motor_cmd_buffer_中。 -
send_thread_
负责将用户生成的控制指令通过 DDS 接口自动下发给机器人。 该线程会周期性读取单值缓冲区中的最新控制指令,并通过 DDS 通道发送至目标端。
SDK 使用单值缓冲区Signal-Vel Buffer (以下都简称为缓冲区)在不同线程之间传递数据,实现线程安全与实时性保障。
用户主要与以下四个缓冲区交互:
| 缓冲区名称 | 数据类型 | 方向 | 说明 |
|---|---|---|---|
| motorstate_buffer | std::shared_ptr<const std::array<MotorState, 18>> | 输出 | 存放机器人当前电机状态数据 |
| imubuffer | std::shared_ptr<const NingImuData> | 输出 | 存放 IMU 数据 |
| joybuffer | std::shared_ptr<const JoyData> | 输出 | 存放遥控器输入指令 |
| motorcmd_buffer | std::shared_ptr<const std::array<MotorCmd, 18>> | 输入 | 用户控制算法生成的电机控制指令数组 |
缓冲区(DataBuffer 类)通过 SetData 和 GetData 接口来与之交互数据。
common.h核心类型简介
| 名称 | 类型 | 描述 |
|---|---|---|
| ControlModel | 枚举类 | 用于设定当前控制模式为原厂模式还是用户模式 |
| NingImuData | 结构体 | IMU数据 |
| MotorCmd | 结构体 | 电机控制指令相关结构体 |
| MotorState | 结构体 | 电机状态数据结构体 |
| Proprioception | 结构体 | 机器人座标系下各项数据 |
| JointState | 结构体 | 关节当前位置 |
| joydata | 结构体 | 遥控器数据 |
DDSWrapperDDS通信类核心接口简介
切换DDS控制模式
publishModeData用户客户端程序发送机器人控制信号,将机器人控制模式切换为DDS上位控制模式
示例代码
RobotSetMode::SetMode cmode;
cmode.mode(1);
ddswrapper.publishModeData(cmode);
DDS订阅机器人状态数据
subscribeRobotStatus 接口用于在 DDSWrapper 中注册用户自定义的机器人状态数据回调函数。该回调函数接收的数据类型为 RobotStatus::StatusData,其中包含 IMU 数据、手柄按键数据以及电机状态数据数组。注册完成后,DDSWrapper 将持续订阅机器人状态主题(Topic),在接收到新数据时自动触发用户注册的回调函数进行处理,实现状态数据的实时接收与响应,无需用户手动轮询。
示例代码
ddswrapper.subscribeRobotStatus(
[](const RobotStatus::StatusData &ddsdata) {
std::array<MotorState, 18> data;
joydata remote_data;
NingImuData imudata;
int i = 0;
for (const auto &state :
ddsdata.motorstatearray().motorstates()) {
data[i].pos = state.pos();
data[i].vel = state.vel();
data[i].tau = state.tau();
data[i].motor_id = state.motor_id();
data[i].error = state.error();
data[i].temperature = state.temperature();
i++;
}
for (int i = 0; i < 4; i++) {
imudata.ori[i] = ddsdata.imudata().ori()[i];
}
for (int i = 0; i < 3; i++) {
imudata.angular_vel[i] =
ddsdata.imudata().angular_vel()[i];
imudata.linear_acc[i] =
ddsdata.imudata().linear_acc()[i];
}
for (int i = 0; i < 9; i++) {
imudata.ori_cov[i] = ddsdata.imudata().ori_cov()[i];
imudata.angular_vel_cov[i] =
ddsdata.imudata().angular_vel_cov()[i];
imudata.linear_acc_cov[i] =
ddsdata.imudata().linear_acc_cov()[i];
}
memcpy(remote_data.button, &ddsdata.joydata().button(),
sizeof(remote_data.button));
memcpy(remote_data.axes, &ddsdata.joydata().axes(),
sizeof(remote_data.axes));
LowController::Instance()->set_robotstatusdata(
data, imudata, remote_data);
});
示例代码中,将获取到的电机,imu,手柄数据,直接通过set_robotstatusdata存放到了rb当中。
void LowController::set_robotstatusdata(const std::array<MotorState, 18> &data,
NingImuData &imudata,
joydata &joy_data) {
motor_state_buffer_.SetData(data);
imu_buffer_.SetData(imudata);
joy_buffer_.SetData(joy_data);
}
通过DDS发布机器人关节电机控制指令
publishMotorCmdData 建议运行在send_thread_ 线程当中,通过DDS发布所有的机器人关节电机控制数据,一般用户只需关注将电机控制命令数据通过 motor_cmd_buffer_.setData() 写入到 motor_cmd_buffer_ rb当中即可。
示例代码
void LowController::send_thread_func() {
while (1) {
const std::shared_ptr<const std::array<MotorCmd, 18>> mc =
motor_cmd_buffer_.GetData();
if (mc) {
RobotMotorCmd::MotorCmdArray cmdarray;
cmdarray.motorcmds().resize(18);
for (int i = 0; i < 18; i++) {
auto &cmd = cmdarray.motorcmds()[i];
cmd.pos() = mc->at(i).pos;
cmd.vel() = mc->at(i).vel;
cmd.tau() = mc->at(i).tau;
cmd.kp() = mc->at(i).kp;
cmd.kd() = mc->at(i).kd;
cmd.motor_id() = mc->at(i).motor_id;
}
auto now = Clock::now();
long long timestamp = std::chrono::duration_cast<
std::chrono::microseconds>(
now.time_since_epoch())
.count();
cmdarray.timestamp() = timestamp;
ddswrapper.publishMotorCmdData(cmdarray);
}
std::this_thread::sleep_for(std::chrono::microseconds(2000));
}
}
(四)SDK API详解
此章节内容冗长,大部分信息客户无需关注,需要时查阅,可直接看[快速开发]章节,
1.config文件夹
hwconfig.yaml
用于配置硬件外设等相关参数
| 对象名 | 默认值 | 备注 |
|---|---|---|
| net_card | eth0 | 根据不同版本整机,可进入系统,查询网口名后更改。 |
| remote_port | /dev/input/js0 | /dev/input/js0为澳加狮游戏手柄作为控制器使用,若使用noetix定制手柄,请更改为/dev/remote |
| 其余 | 默认值不变 | 其余对象客户无需关注 |
ning_user.yaml
用于配置用户模型控制的相关参数,如需强化学习模型训练支持,另行联系。
| 对象名 | 子对象名 | 备注 |
|---|---|---|
| init_state | default_joint_angle | 包括各关节的默认启动角度offset。 |
| control | stiffness | 关节刚度,kp |
| damping | 关节阻尼,kd | |
| stiffnessRun | 关节运动时刚度,kp | |
| dampingRun | 关节运动时阻尼,kd | |
| action_scale | 强化学习训练模型参数,默认不做更改 | |
| decimation | 强化学习训练模型参数,默认不做更改 | |
| cycle_time | 强化学习训练模型参数,默认不做更改 | |
| normalization | clip_scales | 强化学习训练模型参数,默认不做更改 |
| obs_scales | 强化学习训练模型参数,默认不做更改 | |
| size | actions_size | 强化学习训练模型参数,默认不做更改 |
| observations_size | 强化学习训练模型参数,默认不做更改 | |
| actions_size_Run | 强化学习训练模型参数,默认不做更改 | |
| observations_size_Run | 强化学习训练模型参数,默认不做更改 | |
| stack_size | 强化学习训练模型参数,默认不做更改 | |
| axis_mappings | scalez | 强化学习训练模型参数,默认不做更改 |
| scalex | 强化学习训练模型参数,默认不做更改 | |
| scaley | 强化学习训练模型参数,默认不做更改 |
dds.xml
dds配置文件
dds_locl.xml
dds配置文件
2.include文件夹
yaml-cpp
yaml文件读取配置库,客户无需关注。
dds
dds文件读取配置库,客户无需关注
ddsc
dds文件读取配置库,客户无需关注
ddscxx
dds文件读取配置库,客户无需关注
idl
dds数据格式文件
org
dds文件读取配置库,客户无需关注
common.h
| 名称 | 类型 | 备注 |
|---|---|---|
| ControlMode | 枚举类 | 当前控制模式为默认或客户自定义控制 |
| ControlCfg | 结构体 | 与yaml文件关联,控制相关配置项 |
| InitState | 结构体 | 关节初始位置 |
| ObsScales | 结构体 | 观测系数 |
| JointState | 结构体 | 关节当前位置 |
| Proprioception | 结构体 | 机器人坐标系下各项数据 |
| Command | 结构体 | 三轴指令 |
| MotorState | 结构体 | 电机状态 |
| MotorCmd | 结构体 | 电机控制指令 |
| NingImuData | 结构体 | IMU数据 |
| joydata | 结构体 | 手柄数据 |
| sleep_ms | 宏定义 | 延时ms级Controllerbase |
| sleep_us | 宏定义 | 延时us级 |
| get_time_us | 宏定义 | 获取当前us时间 |
common.h中各项参数定义详解
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| ControlMode | | ||
| DEFAULT | 原厂控制模式 | ||
| LOWMODE | lowcontrol模式 | ||
| HIGHMODE | highcontrol模式 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| ControlCfg | | stiffness | |
| damping | |||
| actionScale | |||
| decimation | |||
| user_torque_limit | |||
| user_power_limit | |||
| cycle_time | |||
| bf_cycle_time |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| InitState | | 每个关节电机的初始位置 | |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| JointState | | 每个关节电机的当前位置 | |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| ObsScales | | linVel | |
| angVel | |||
| dofPos | |||
| dofVel | |||
| quat | |||
| heightMeasurements |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| Proprioception | | jointPos | |
| jointVel | |||
| baseAngVel | |||
| baseEulerXyz | |||
| projectedGravity |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| Command | | x | |
| y | |||
| yaw |
| 参数名称 | 定义原型 | 示例值 | 说明(括号内对应按键) |
|---|---|---|---|
| ControlCmd | | WALK | 走路模式(LB & X) |
SWING | 出厂预设动作挥手(B) | ||
SHAKE | 出厂预设动作握手(A) | ||
CHEER | 出厂预设动作欢呼(Y) | ||
RUN | 跑步模式(LB & Y) | ||
DANCE | 跳舞模式
通过设置 shortd 变量 为 1
或者 longd 变量 为 1
来播放长短版本英歌舞 | ||
START | 使能模式((失能模式下)+) | ||
SWITCH | 准备模式(LB & -) | ||
STARTTEACH | 开始示教(RB & Y) | ||
SAVETEACH | 保存示教(RB & B and RB & X) ps: 目前下发SAVETEACH,会先发送ENDTEACH在发送SAVETEACH,相等于将两个步骤简化为了一个 保存文件根据参数ID,具体可以参考 HighController::set_axes接口 | ||
ENDTEACH | 结束示教(RB & B) | ||
PLAYTEACH | 播放示教 (RB & LB & file_index)根据 file_index播放对应文件示教动作 | ||
DEFAULT | 失能模式((使能模式下)+) |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| MotorState | | pos | 电机位置 |
| vel | 电机转速 | ||
| tau | 电机扭矩 | ||
| motor_id | 电机ID | ||
| error | 电机错误码:
| ||
| temperature |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| MotorCmd | | pos | 电机位置 |
| vel | 电机转速 | ||
| tau | 电机扭矩 | ||
| kp | pid参数 | ||
| kd | pid参数 | ||
| motor_id | 电机ID |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| NingImuData | | ori | |
| ori_cov | |||
| angular_vel | |||
| angular_vel_cov | |||
| linear_acc | |||
| linear_acc_cov |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| joydata | | axes | 遥控器遥感线性数值 |
| button | 遥控器按键按下映射数值 |
RotationTools.h
函数模版:
| 函数名 | 返回类型 | 备注 |
|---|---|---|
| getRotationMatrixFromZyxEulerAngles | 任意类型3*3矩阵 | 从欧拉角获得旋转矩阵 |
| square | 任意类型实数 | 平方运算 |
| quatToZyx | 任意类型3*1矩阵 | 四元数转换zyx方向矩阵 |
| quatToXyz | 任意类型3*1矩阵 | 四元数转换xyz方向矩阵 |
RotatioTools接口详解
| 函数名 | getRotationMatrixFromZyxEulerAngles |
|---|---|
| 函数原型 | Eigen::Matrix<SCALAR_T, 3, 3> getRotationMatrixFromZyxEulerAngles(const Eigen::Matrix<SCALAR_T, 3, 1>& eulerAngles) |
| 功能概述 | 从欧拉角获得旋转矩阵 |
| 参数 |
|
| 返回值 | Eigen::Matrix<SCALAR_T, 3, 3> 从欧拉角旋转后的矩阵 |
| 备注 |
| 函数名 | square |
|---|---|
| 函数原型 | T square(T a) |
| 功能概述 | 平方运算 |
| 参数 |
|
| 返回值 | Eigen::Matrix<SCALAR_T, 3, 3> 从欧拉角旋转后任意类型的矩阵 |
| 备注 |
| 函数名 | quatToZyx |
|---|---|
| 函数原型 | Eigen::Matrix<SCALAR_T, 3, 1> quatToXyz(const Eigen::Quaternion<SCALAR_T>& q) |
| 功能概述 | 四元数转换zyx方向矩阵 |
| 参数 |
|
| 返回值 | Eigen::Matrix<SCALAR_T, 3, 1> 任意类型3*1矩阵 |
| 备注 |
| 函数名 | quatToXyz |
|---|---|
| 函数原型 | Eigen::Matrix<SCALAR_T, 3, 1> quatToXyz(const Eigen::Quaternion<SCALAR_T>& q) |
| 功能概述 | 四元数转换xyz方向矩阵 |
| 参数 |
|
| 返回值 | Eigen::Matrix<SCALAR_T, 3, 1> 任意类型3*1矩阵 |
| 备注 |
Types.h
定义的数据类型
DDSWrapper.h
| 类名 | 类函数名 | 备注 |
|---|---|---|
| DDSWrapper | DDSWrapper | 构造函数 |
| publishMotorCmdData | 发布电机控制指令数据 | |
| publishModeData | 发布模式切换数据 | |
| subscribeRobotStatus | 订阅机器人状态数据 |
其他私有函数客户无需关注
| 函数名 | publishMotorCmdData |
|---|---|
| 函数原型 | void publishMotorCmdData(const RobotMotorCmd::MotorCmdArray &state) |
| 功能概述 | 通过DDS发布电机控制指令数据 |
| 参数 | - state : 电机控制指令数据 |
| 返回值 | 无 |
| 备注 |
| 函数名 | publishModeData |
|---|---|
| 函数原型 | void publishModeData(const RobotSetMode::SetMode &data) |
| 功能概述 | 通过DDS发布模式切换指令 |
| 参数 | - data 切换模式数据 |
| 返回值 | 无 |
| 备注 |
| 函数名 | subscribeRobotStatus |
|---|---|
| 函数原型 | void subscribeRobotStatus(RobotStatusCallback callback); |
| 功能概述 | 通过DDS订阅机器人imu,遥控器,电机数据 |
| 参数 | - callback 回调数据处理函数 定义如下
|
| 返回值 | 无 |
| 备注 |
highcontroller.h
| 名称 | 类型 | 备注 |
|---|---|---|
| WorkMode | 枚举类 | 机器人状态模式(详细信息同type.h) |
| RobotCfg | 结构体 | 机器人相关配置项,包含其余结构体(详细信息同common.h) |
| DataBuffer | 类 | 定义的rb模板类,用于缓存数据 |
| motorstate_buffer | 变量 | 电机状态rb |
| joy_buffer_ | 变量 | 手柄数据rb |
| imu_buffer_ | 变量 | imu数据rb |
| HighController | 类 | highcontrol模式控制器 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| WorkMode | | STAND | 准备模式,电机上电使能,到0位 |
| LIE | |||
| USERWALK | 用户控制模式走路 | ||
| DEFAULT | 原厂控制模式 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| RobotCfg | | ControlCfg | 同common.h ControlCfg |
| InitState | 同common.h InitState | ||
| ObsScales | 同common.h ObsScales | ||
| encoder_nomalize | |||
| clipActions | |||
| clipObs | |||
| initState | |||
| obsScales | |||
| controlCfg | |||
| loophz | |||
| cycletimeerrorThreshold | |||
| ThreadPriority |
DataBuffer类接口介绍
| 函数名 | SetData |
|---|---|
| 函数原型 | void SetData(const T &newData) |
| 功能概述 | 往缓冲区写入数据 |
| 参数 |
|
| 返回值 | 无 |
| 备注 |
| 函数名 | Clear |
|---|---|
| 函数原型 | void Clear() |
| 功能概述 | 清楚缓冲区里面的数据 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | SetData |
|---|---|
| 函数原型 | std::shared_ptr<const T> GetData() |
| 功能概述 | 从缓冲区获取数据 |
| 参数 | 无 |
| 返回值 | 数据(模板) |
| 备注 |
HighController类详解
| 名称 | 类型 | 备注 |
|---|---|---|
| public | public | public |
| Instance | 方法 | HighController采用单例设计模式 |
| instance | HithController * | 单例指针 |
| init | 方法 | 初始化 |
| process | 方法 | 控制函数,用户的应用开发代码可以在这个函数内扩展 |
| protected | protected | protected |
| onnxdatainit | 方法 | 初始化onnx |
| getmodelparam | 方法 | 获取模型参数 |
| updateStateEstimation | 方法 | 更新状态,包括关节角度,IMU数据等 |
| get_joint_state | 方法 | 获取电机状态 |
| set_axes | 方法 | 将控制存放到rb中模板函数 |
| get_jsdata | 方法 | 获取手柄数据 |
| get_imu_data | 方法 | 获取IMU数据 |
| send_thread_func | 方法 | 通过DDSWrapper类发布DDS数据模板函数 |
| process_thread_func | 方法 | |
| set_imudata | 方法 | 设置IMU数据 |
| set_joydata | 方法 | 设置手柄数据 |
| set_robotstatusdata | 方法 | 设置机器人状态数据 |
| private | private | private |
| count | int64_t | |
| ddswrapper | DDSWrapper | DDSWrapper类控制DDS订阅和发布 |
| baseLinVel_ | vector3_t | higlcontrol模式下客户无需关注 |
| basePosition_ | vector3_t | higlcontrol模式下客户无需关注 |
| lastActions_ | vector_t | higlcontrol模式下客户无需关注 |
| defaultJointAngles_ | vector_t | higlcontrol模式下客户无需关注 |
| walkdefaultJointAngles_ | vector_t | higlcontrol模式下客户无需关注 |
| actuatedDofNum_ | int | higlcontrol模式下客户无需关注 |
| isfirstRecObs_ | bool* | higlcontrol模式下客户无需关注 |
| actionsSize_ | int | higlcontrol模式下客户无需关注 |
| motionSize | int | higlcontrol模式下客户无需关注 |
| observationSize_ | int | higlcontrol模式下客户无需关注 |
| stackSize_ | int | higlcontrol模式下客户无需关注 |
| scalez | float | higlcontrol模式下客户无需关注 |
| scalex | float | higlcontrol模式下客户无需关注 |
| scaley | float | higlcontrol模式下客户无需关注 |
| command_ | vector_t | higlcontrol模式下客户无需关注 |
| loopcount_ | int64_t | higlcontrol模式下客户无需关注 |
| imu_data_ | NingImuData | higlcontrol模式下客户无需关注 |
| remote_data_ | joydata | higlcontrol模式下客户无需关注 |
| motorstate_ | std::array<MotorState, 18> | higlcontrol模式下客户无需关注 |
| statequeue | std::queue<std::array<MotorState, 18>> | higlcontrol模式下客户无需关注 |
| cmdqueue | std::queue<RobotMotorCmd::MotorCmdArray> | higlcontrol模式下客户无需关注 |
| mode_ | WorkMode | higlcontrol模式下客户无需关注 |
| isChangeMode_ | bool | higlcontrol模式下客户无需关注 |
| startcontrol | bool | higlcontrol模式下客户无需关注 |
| initfinish | int | higlcontrol模式下客户无需关注 |
| model_type | int | higlcontrol模式下客户无需关注 |
| statetimestamp | long long | higlcontrol模式下客户无需关注 |
| state_mutex | std::mutex | higlcontrol模式下客户无需关注 |
| usermotorcmd | std::array<MotorCmd, 18> | higlcontrol模式下客户无需关注 |
| motor_cmd_buffer_ | DataBuffer<RobotMotorCmd::MotorCmdArray> | higlcontrol模式下客户无需关注 |
| send_thread_ | std::thread | higlcontrol模式下客户无需关注 |
| process_thread_ | std::thread | higlcontrol模式下客户无需关注 |
HighController部分函数接口介绍
| 函数名 | process |
|---|---|
| 函数原型 | void process() |
| 功能概述 | 控制模板方法,用户可参考此方法进行二开 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | init |
|---|---|
| 函数原型 | bool init(ControlMode mode) |
| 功能概述 | 系统初始化 |
| 参数 |
|
| 返回值 | true:初始化成功;false:初始化失败 |
| 备注 | DEFAULT:运行原厂运控模式;LOWMODE:运行用户开发模式,SDK不进行运动控制。HIGHMODE:控制原厂策略 |
| 函数名 | onnxdatainit |
|---|---|
| 函数原型 | void onnxdatainit() |
| 功能概述 | 初始化onnx数据 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | getmodelparam |
|---|---|
| 函数原型 | bool getmodelparam() |
| 功能概述 | 从yaml文件中获取模型参数 |
| 参数 | 无 |
| 返回值 | true:读取yaml文件成功;false:读取yaml文件失败 |
| 备注 |
| 函数名 | updatestateestimation |
|---|---|
| 函数原型 | bool updatestateestimation() |
| 功能概述 | 更新状态,包括关节角度,IMU数据等从yaml文件中获取模型参数 |
| 参数 | 无 |
| 返回值 | true:读取yaml文件成功;false:读取yaml文件失败 |
| 备注 |
| 函数名 | get_joint_state |
|---|---|
| 函数原型 | const std::array<MontorState, 18> get_joint_state() |
| 功能概述 | 获取关节数据 |
| 参数 | 无 |
| 返回值 | const std::array<MontorState, 18> 电机状态结构体数组 |
| 备注 |
| 函数名 | set_axes |
|---|---|
| 函数原型 | void set_axes(double ver, double hor, int action); |
| 功能概述 | 下发机器人位置控制指令 |
| 参数 |
|
| 返回值 | 无 |
| 备注 |
| 函数名 | get_jsdata |
|---|---|
| 函数原型 | const joydata get_jsdata(); |
| 功能概述 | 获取遥控器数据 |
| 参数 | 无 |
| 返回值 | joydata 遥控器数据结构体 |
| 备注 |
| 函数名 | get_imu_data |
|---|---|
| 函数原型 | const NingImuData get_imu_data() |
| 功能概述 | 获取IMU数据 |
| 参数 | 无 |
| 返回值 | NingImuData IMU结构体数据 |
| 备注 |
| 函数名 | set_robotstatusdata |
|---|---|
| 函数原型 | void set_robotstatusdata(std::array<MotorState,18> motorstate_data,NingImuData imudata,joydata joy_data); |
| 功能概述 | 设置机器人状态数据 |
| 参数 |
|
| 返回值 | 无 |
| 备注 |
lowcontroller.h
| 名称 | 类型 | 备注 |
|---|---|---|
| WorkMode | 枚举类 | 机器人状态模式(详细信息同type.h) |
| RobotCfg | 结构体 | 机器人相关配置项,包含其余结构体(详细信息同common.h) |
| DataBuffer | 类 | 定义的rb模板类,用于缓存数据 |
| motor_state_buffer_ | 变量 | 电机状态rb |
| joy_buffer_ | 变量 | 手柄数据rb |
| imu_buffer_ | 变量 | imu数据rb |
| LowController | 类 | highcontrol模式控制器 |
LowController类详解
| 名称 | 类型 | 备注 |
|---|---|---|
| public | public | public |
| Instance | 方法 | HighController采用单例设计模式 |
| instance | HithController | 单例指针 |
| StaticCallback() | 方法 | 静态回调函数 |
| init | 方法 | 初始化 |
| loadModel | 方法 | 读取模型 |
| handleWalkMode | 方法 | 行走模式控制 |
| setparameter | 方法 | 设置xyz整机控制参数 |
| handleStandMode | 方法 | 站立模式控制 |
| handleDefautMode | 方法 | 默认模式控制 |
| handleLieMode | 方法 | 使能模式控制 |
| process | 方法 | 控制函数,用户的应用开发代码可以在这个函数内扩展 |
| protected | protected | protected |
| set_robotstatusdata | 方法 | 设置机器人状态数据 |
| computeActions | 方法 | 计算最终动作 |
| computeObservation | 方法 | 计算观测系数 |
| onnxdatainit | 方法 | 初始化onnx |
| getmodelparam | 方法 | 获取模型参数 |
| updateStateEstimation | 方法 | 更新状态,包括关节角度,IMU数据等 |
| get_joint_state | 方法 | 获取电机状态 |
| set_joint | 方法 | 设置电机命令 |
| send_thread_func | 方法 | 通过DDSWrapper类发布DDS数据模板函数 |
| process_thread_func | 方法 | |
| private | private | private |
| jointNames | std::vector<std::string> | 电机名称 |
| memoryInfo | Ort::MemoryInfo | 内存信息 |
| onnxEnvPrt_ | shared_ptr<Ort::Env> | |
| policyFilePath_ | std::string | 策略文件路径 |
| modelname | std::string | 模型路径 |
| robotconfig | RobotCfg | |
| policySessionPtr | std::unique_ptr<Ort::Session> | |
| estSessionPtr | std::unique_ptr<Ort::Session> | |
| policyInputNames_ | std::vector<const char *> | |
| policyOutputNames_ | std::vector<const char *> | |
| estInputNames_ | std::vector<const char *> | |
| estOutputNames_ | std::vector<const char *> | |
| policyInputNodeNameAllocatedStrings | std::vector<Ort::AllocatedStringPtr> | |
| policyOutputNodeNameAllocatedStrings | std::vector<Ort::AllocatedStringPtr> | |
| estInputNodeNameAllocatedStrings | std::vector<Ort::AllocatedStringPtr> | |
| estOutputNodeNameAllocatedStrings | std::vector<Ort::AllocatedStringPtr> | |
| policyInputShapes_ | std::vector<std::vector<int64_t>> | |
| policyOutputShapes_ | std::vector<std::vector<int64_t>> | |
| estInputShapes_ | std::vector<std::vector<int64_t>> | |
| estOutputShapes_ | std::vector<std::vector<int64_t>> | |
| count | int64_t | |
| ddswrapper | DDSWrapper | DDSWrapper类控制DDS订阅和发布 |
| baseLinVel_ | vector3_t | |
| basePosition_ | vector3_t | |
| lastActions_ | vector_t | |
| defaultJointAngles_ | vector_t | |
| walkdefaultJointAngles_ | vector_t | |
| actuatedDofNum_ | int | |
| isfirstRecObs_ | bool | |
| actionsSize_ | int | |
| motionSize | int | |
| observationSize_ | int | |
| stackSize_ | int | |
| scalez | float | |
| scalex | float | |
| scaley | float | |
| actions_ | std::vector<tensor_element_t> | |
| policyObservations_ | std::vector<tensor_element_t> | |
| estObservations_ | std::vector<tensor_element_t> | |
| proprioHistoryBuffer_ | Eigen::Matrix<tensor_element_t, Eigen::Dynamic, 1> | |
| isfirstCompAct_ | bool | 标识是否为首次动作计算 |
| command_ | vector_t | |
| propri_ | Proprioception | |
| phase_ | double | |
| loopcount_ | int64_t | |
| imu_data_ | NingImuData | |
| remote_data_ | joydata | |
| remote_data | joydata | |
| imu_data | NingImuData | |
| motorstate_ | std::array<MotorState, 18> | |
| statequeue | std::queue<std::array<MotorState, 18>> | |
| cmdqueue | std::queue<RobotMotorCmd::MotorCmdArray> | |
| standPercent | double | |
| standDuration | scalar_t | |
| lieJointAngles | vector_t | |
| lieJointState | JointState | |
| standJointStatie_ | JointState | |
| mode_ | WorkMode | |
| isChangeMode_ | bool | |
| startcontrol | bool | |
| initfinish | int | |
| model_type | int | |
| statetimestamp | long long | |
| state_mutex | std::mutex | |
| usermotorcmd | std::array<MotorCmd, 18> | |
| lieJointAngles_ | vector_t | |
| standJointAngles_ | vector_t | |
| motor_cmd_buffer_ | DataBuffer<RobotMotorCmd::MotorCmdArray> | |
| send_thread_ | std::thread | |
| new_state_arrived | int | |
| process_thread_ | std::thread |
LowController部分函数接口介绍(部分同名接口详见HighController)
| 函数名 | loadModel |
|---|---|
| 函数原型 | bool loadModel(std::string modelpath) |
| 功能概述 | 加载自有模型 |
| 参数 |
|
| 返回值 | true:加载成功;false:加载失败 |
| 备注 |
| 函数名 | handleWalkMode |
|---|---|
| 函数原型 | bool handleWalkMode() |
| 功能概述 | 行走模式控制 |
| 参数 | 无 |
| 返回值 | true:行走模式切换成功;false:行走模式切换失败 |
| 备注 |
| 函数名 | setparameter |
|---|---|
| 函数原型 | void setparameter(Command &cmd,bool* isfirst) |
| 功能概述 | 设置xyz整机控制参数 |
| 参数 |
|
| 返回值 | 无 |
| 备注 |
| 函数名 | set_joint |
|---|---|
| 函数原型 | void set_joint(std::array<MotorCmd, 18> motorcmd) |
| 功能概述 | 设置关节数据 |
| 参数 |
|
| 返回值 | 无 |
| 备注 |
| 函数名 | handleStandMode |
|---|---|
| 函数原型 | void handleStandMode() |
| 功能概述 | 站立模式控制 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | handleDefautMode |
|---|---|
| 函数原型 | void handleDefautMode() |
| 功能概述 | 默认模式控制 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | handleLieMode |
|---|---|
| 函数原型 | void handleLieMode() |
| 功能概述 | 初始模式控制(全身关节使能) |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | computeActions |
|---|---|
| 函数原型 | void computeActions() |
| 功能概述 | 计算最终的动作 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | computeObservation |
|---|---|
| 函数原型 | void computeObservation() |
| 功能概述 | 计算观测系数 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | set_robotstatusdata |
|---|---|
| 函数原型 | void set_robotstatusdata(std::array<MotorState,18> motorstate_data,NingImuData imudata,joydata joy_data); |
| 功能概述 | 设置机器人状态数据 |
| 参数 |
|
| 返回值 | 无 |
| 备注 |
3.lib文件夹
aarch64
aarch64 arm架构下的静态库,客户无需关注
x86_64
x86_64架构下的静态库,客户无需关注
4.policy文件夹
策略文件,里面有一个出厂默认的原地踏步策略,无需对lowcontroller.cpp进行修改,直接运行lowcontrol直接加载,使用手柄进入到walk模式后,机器人会一直原地踏步,摇杆控制其前后左右移动。
(五)获取SDK
https://github.com/Noetix-Robotics/noetix_sdk_n2
(六)快速开发
前期准备
N2的出厂 运控板(RK3588S) 上默认搭载的sdk不支持dds,用户需在售后平台上下载支持dds接口的sdk,部署到N2机器人的运控板上
更换机器人sdk教程如下:
编译环境准备
N2教育板出厂Nano上默认是没有配置过开发环境的,需要用户自己安装部署
部署流程: SDK 编译环境部署流程
首先用户需要获取dds客户端SDK,放到机器人的二开算力板上(Nvidia jetson orin nano super)。
下面以接网线的通过ssh的方式举例
git clone https://github.com/Noetix-Robotics/noetix_sdk_n2
scp noetix_sdk_n2 noetix@192.168.55.101:Downloads
ssh noetix@192.168.55.101 # 密码:n2
cd Downloads/Noetix-Robotics
确认一下dds的IP配置是否正确,配置文件在目录下config/dds.xml
<?xml version="1.0" encoding="UTF-8"?>
<CycloneDDS>
<!-- 指定网卡(示例:使用eth0,请替换为实际网卡名) -->
<Domain id="any">
<General>
<NetworkInterfaceAddress>192.168.55.101</NetworkInterfaceAddress>
<Transport>udp</Transport>
<AllowMulticast>false</AllowMulticast>
</General>
<Discovery>
<ParticipantIndex>0</ParticipantIndex>
<Peers>
<Peer address="192.168.55.102"/>
</Peers>
</Discovery>
<!-- 启用共享内存优化(本机通信)
<SharedMemory>
<Enable>true</Enable>
<LogLevel>WARNING</LogLevel>
</SharedMemory> -->
<!-- 调优内部缓冲区
<Internal>
<SocketBufferSize>65536</SocketBufferSize>
<ReceiveBufferSize>65536</ReceiveBufferSize>
</Internal>-->
<!-- 针对机器人控制的传输优化
<Tracing>
<Verbosity>WARNING</Verbosity>
<OutputFile>/tmp/cyclonedds_trace.log</OutputFile>
</Tracing>-->
</Domain>
<!-- 为特定Topic配置QoS(示例)
<Topic name="Motor_Cmd_Topic">
<Reliability>RELIABLE</Reliability>
<Deadline>20ms</Deadline>
<History>
<Kind>KEEP_LAST</Kind>
<Depth>10</Depth>
</History>
</Topic>-->
</CycloneDDS>
其中最上面的IP为本机IP,也就是二开算力板的IP,下面的IP为机器人运控板的IP,一般用户收到的机器人都是默认配置好的,如果用户对二开算力板的IP或者机器人运控板的IP进行改动,则需要修改此配置文件
编辑代码
用户需要进行应用开发,则根据 highcontroller.cpp所提供的示例代码进行修改即可
运控开发根据 lowcontroller.cpp 所提供的示例代码修改即可
编译代码
在项目目录下,提供了一键编译的脚本 build_release.sh ,用户修改完代码直接运行此脚本即可,编译成果效果大致如下:
root@hirres-WUJIE14-PRO:/workspace/noetix/n2_sdk/dds_client_demo_relaese/dds_demo_release_onnx# ./build_release.sh
this is x86_64
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done (0.5s)
-- Generating done (0.0s)
-- Build files have been written to: /workspace/noetix/n2_sdk/dds_client_demo_relaese/dds_demo_release_onnx/build
[ 25%] Building CXX object CMakeFiles/lowcontrol.dir/lowcontroller.cpp.o
[ 50%] Building CXX object CMakeFiles/highcontrol.dir/highcontroller.cpp.o
[ 75%] Linking CXX executable /workspace/noetix/n2_sdk/dds_client_demo_relaese/dds_demo_release_onnx/highcontrol
[ 75%] Built target highcontrol
[100%] Linking CXX executable /workspace/noetix/n2_sdk/dds_client_demo_relaese/dds_demo_release_onnx/lowcontrol
[100%] Built target lowcontrol
编译成功后会在项目目录下生成两个可执行文件:
-
lowcontrol: 运控开发可执行文件 -
highcontrol:应用开发可执行文件
执行程序
根据用户需求使用root权限执行编译上面执行好的编译文件即可。
sudo ./lowcontrol # or sudo ./highcontrol
在highcontrol模式下注意:
-
执行DDS客户端后,遥控器上的操作摇杆将会失灵,其他模式控制按键仍然有效,紧急情况可按澳加狮手柄上的“+”号按键,急停机器人
-
不启动DDS客户端,控制器手柄摇杆有效
-
DDS客户端断开之后,机器人自动回到遥控器控制模式
DDS客户端Demo断开连接后,机器人会恢复到进入DDS模式前的模式状态,使用时需要格外注意
六、底层控制开发
后续运控板(RK3588S)逐渐对用户封闭,通过DDS也可以开发底层运控,不推荐使用此SDK
(一)SDK概述
SDK 直接运行在机器人运控板(RK3588S)上,通过实时获取 IMU 数据和电机状态,并下发电机控制指令来实现运动控制,提供了低速端(即关节端)的5个控制参数接口: pos, vel, kp, kd, tau。驱动器端会将最终的关节目标力转化成期望电流,并以500Hz的频率进行闭环控制。同时为开发者提供 C++ 接口。
SDK 功能简介
SDK 主要功能包括:
-
提供接口获取 电机状态、IMU 状态 以及 遥控器数据
-
提供接口下发 电机控制指令:pos, vel, kp, kd, tau
-
内置多种示例工程,包括:
- C++ 二次开发 Demo
前置条件
SDK运行在Linux上,SDK不依赖ROS,用户基于机器人上的控制器开发不需要安装其他库,如果在用户自己的PC上运行,需要安装:
-
fmt -
eigen3 -
onnxruntime -
drake -
glog -
spdlog -
python3 -
pybind11
(二)底层运控参考例程
底层运动开发例程实现了将机器人呢从任意初始关节位置,复位至零位,并且可以用户在一定频率下,打印角度等数据
common.h 核心类型简介
| 名称 | 类型 | 描述 |
|---|---|---|
| ControlModel | 枚举类 | 用于设定当前控制模式为原厂模式还是用户模式 |
| NingImuData | 结构体 | IMU数据 |
| MotorCmd | 结构体 | 电机控制指令相关结构体 |
| MotorState | 结构体 | 电机状态数据结构体 |
| Proprioception | 结构体 | 机器人座标系下各项数据 |
| JointState | 结构体 | 关节当前位置 |
| joydata | 结构体 | 遥控器数据 |
例程的主程序定义在noetix_sdk_release/src/usercontroller.cpp中。
controllerbase核心API简介
系统初始化
init进行系统初始化,可以通过设置ControlMode枚举类型来设置是原厂控制模式和用户控制模式
示例代码
ret = usercontroller.init(mode: ControlMode::USERMODE);
加载运控模型
loadModel函数用于加载运控模型,仅支持加载ONNX模型
示例代码
usercontroller.loadModel(path+"/policy");
注册回调函数
在Controllerbase类当中可以两个可以注册回调函数的接口:
-
用户可以在使用
setcallback注册数据处理函数,使用set_joint函数下发控制命令 -
setpycallback注册python回调函数,功能同上
示例代码
controllerbase.setcallback(StaticCallback);
电机控制指令发送函数
set_joint用于发送电机控制指令
MotorCmd motorcmd;
for (int j = 0; j < 18; j++)
{
motorcmd.kd=0.1;
motorcmd.pos=0;
motorcmd.kp=0;
motorcmd.motor_id = j;
motorcmd.vel =0;
motorcmd.tau = 0;
controllerbase.set_joint(motorcmd);
}
获取各关节电机状态
get_joint_state用于获取所有关节电机状态,关节电机顺序固定详看[关节电机顺序]
示例代码
std::array<MotorState,18> joint_state = controllerbase.get_joint_state();
获取IMU数据
get_imu_data 用于获取imu数据
示例代码
NingImuData imudata;
quaternion_t quat;
vector3_t angularVel, linearAccel;
imudata = controllerbase.get_imu_data();
for (size_t i = 0; i < 4; ++i)
{
quat.coeffs()(i) = imudata.ori[i];
}
for (size_t i = 0; i < 3; ++i)
{
angularVel(i) = imudata.angular_vel[i];
linearAccel(i) = imudata.linear_acc[i];
}
获取遥控器数据
get_jsdata获取遥控器数据,遥控器按键数据映射详细请看[遥控器按键数据映射]
示例代码
joydata remote_data;
remote_data = controllerbase.get_jsdata();
(三)SDK API详细说明
此章节内容冗长,大部分信息客户无需关注,需要时查阅,可直接看[快速开发]章节,

1.config文件夹
hwconfig.yaml
用于配置硬件外设等相关参数
| 对象名 | 默认值 | 备注 |
|---|---|---|
| net_card | eth0 | 根据不同版本整机,可进入系统,查询网口名后更改。 |
| remote_port | /dev/input/js0 | /dev/input/js0为澳加狮游戏手柄作为控制器使用,若使用noetix定制手柄,请更改为/dev/remote |
| 其余 | 默认值不变 | 其余对象客户无需关注 |
ning_ac.yaml
用于配置默认模型控制的相关参数
| 对象名 | 默认值 | 备注 |
|---|---|---|
| 其余 | 默认值不变 | 其余对象客户无需关注 |
ning_user.yaml
用于配置用户模型控制的相关参数,如需强化学习模型训练支持,另行联系。
| 对象名 | 子对象名 | 备注 |
|---|---|---|
| init_state | default_joint_angle | 包括各关节的默认启动角度offset。 |
| control | stiffness | 关节刚度,kp |
| damping | 关节阻尼,kd | |
| stiffnessRun | 关节运动时刚度,kp | |
| dampingRun | 关节运动时阻尼,kd | |
| action_scale | 强化学习训练模型参数,默认不做更改 | |
| decimation | 强化学习训练模型参数,默认不做更改 | |
| cycle_time | 强化学习训练模型参数,默认不做更改 | |
| normalization | clip_scales | 强化学习训练模型参数,默认不做更改 |
| obs_scales | 强化学习训练模型参数,默认不做更改 | |
| size | actions_size | 强化学习训练模型参数,默认不做更改 |
| observations_size | 强化学习训练模型参数,默认不做更改 | |
| actions_size_Run | 强化学习训练模型参数,默认不做更改 | |
| observations_size_Run | 强化学习训练模型参数,默认不做更改 | |
| stack_size | 强化学习训练模型参数,默认不做更改 | |
| axis_mappings | scalez | 强化学习训练模型参数,默认不做更改 |
| scalex | 强化学习训练模型参数,默认不做更改 | |
| scaley | 强化学习训练模型参数,默认不做更改 |
2.include文件夹
yaml-cpp
yaml文件读取配置库,客户无需关注。
common.h
| 名称 | 类型 | 备注 |
|---|---|---|
| ControlMode | 枚举类 | 当前控制模式为默认或客户自定义控制 |
| ControlCfg | 结构体 | 与yaml文件关联,控制相关配置项 |
| InitState | 结构体 | 关节初始位置 |
| ObsScales | 结构体 | 观测系数 |
| JointState | 结构体 | 关节当前位置 |
| Proprioception | 结构体 | 机器人坐标系下各项数据 |
| Command | 结构体 | 三轴指令 |
| MotorState | 结构体 | 电机状态 |
| MotorCmd | 结构体 | 电机控制指令 |
| NingImuData | 结构体 | IMU数据 |
| joydata | 结构体 | 手柄数据 |
| sleep_ms | 宏定义 | 延时ms级Controllerbase |
| sleep_us | 宏定义 | 延时us级 |
| get_time_us | 宏定义 | 获取当前us时间 |
common.h中各项参数定义详解
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| ControlMode | | USERMODE | 用户控制模式 |
| DEFAULT | 原厂控制模式 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| ControlCfg | | stiffness | |
| damping | |||
| actionScale | |||
| decimation | |||
| user_torque_limit | |||
| user_power_limit | |||
| cycle_time | |||
| bf_cycle_time |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| InitState | | 每个关节电机的初始位置 | |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| JointState | | 每个关节电机的当前位置 | |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| ObsScales | | linVel | |
| angVel | |||
| dofPos | |||
| dofVel | |||
| quat | |||
| heightMeasurements |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| Proprioception | | jointPos | |
| jointVel | |||
| baseAngVel | |||
| baseEulerXyz | |||
| projectedGravity |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| Command | | x | |
| y | |||
| yaw |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| MotorState | | pos | 电机位置 |
| vel | 电机转速 | ||
| tau | 电机扭矩 | ||
| motor_id | 电机ID | ||
| error | 电机错误码:
| ||
| temperature |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| MotorCmd | | pos | 电机位置 |
| vel | 电机转速 | ||
| tau | 电机扭矩 | ||
| kp | pid参数 | ||
| kd | pid参数 | ||
| motor_id | 电机ID |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| NingImuData | | ori | |
| ori_cov | |||
| angular_vel | |||
| angular_vel_cov | |||
| linear_acc | |||
| linear_acc_cov |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| joydata | | axes | 遥控器遥感线性数值 |
| button | 遥控器按键按下映射数值 |
controllerbase.h
Controllerbase类:基础控制类
| 类名 | 类函数名 | 备注 |
|---|---|---|
| Controllerbase | init | 系统初始化 |
| loadModel | 加载自有模型 | |
| get_joint_state | 获取关节数据 | |
| set_joint | 设置关节数据 | |
| get_jsdata | 获取遥控器数据 | |
| get_imu_data | 获取IMU数据 | |
| start | 机器人启动进入standby状态 | |
| setcallback | 注册客户自有模型处理函数 | |
| setpycallback | 注册python回调函数 |
Controllerbase 接口详解
| 函数名 | init |
|---|---|
| 函数原型 | bool init(ControlMode mode) |
| 功能概述 | 系统初始化 |
| 参数 | - mode:当前控制模式为默认或用户控制 |
| 返回值 | true:初始化成功;false:初始化失败 |
| 备注 | DEFAULT:运行原厂运控模式;USERMODE:运行用户开发模式,SDK不进行运动控制。 |
| 函数名 | loadModel |
|---|---|
| 函数原型 | bool loadModel(std::string modelname, std::string modelpath, std::string type) bool loadModel(std::string modelname, std::string modelpath) |
| 功能概述 | 加载自有模型 |
| 参数 |
|
| 返回值 | true:加载成功;false:加载失败 |
| 备注 |
| 函数名 | get_joint_state |
|---|---|
| 函数原型 | const std::array<MontorState, 18> get_joint_state() |
| 功能概述 | 获取关节数据 |
| 参数 | 无 |
| 返回值 | const std::array<MontorState, 18> 电机状态结构体数组 |
| 备注 |
| 函数名 | set_joint |
|---|---|
| 函数原型 | void set_joint(Motor motorcmd) |
| 功能概述 | 设置关节数据 |
| 参数 | - motorcmd 电机命令结构体 |
| 返回值 | 无 |
| 备注 |
| 函数名 | get_jsdata |
|---|---|
| 函数原型 | const joydata get_jsdata(); |
| 功能概述 | 获取遥控器数据 |
| 参数 | 无 |
| 返回值 | joydata 遥控器数据结构体 |
| 备注 |
| 函数名 | get_imu_data |
|---|---|
| 函数原型 | const NingImuData get_imu_data() |
| 功能概述 | 获取IMU数据 |
| 参数 | 无 |
| 返回值 | NingImuData IMU结构体数据 |
| 备注 |
| 函数名 | start |
|---|---|
| 函数原型 | void start() |
| 功能概述 | 机器人启动进入standby状态 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | setcallback |
|---|---|
| 函数原型 | void setcallback(ExternFuntionType cb) |
| 功能概述 | 注册客户自有模型处理函数,可以在进行数据的前后处理,调用set_joint下发控制命令 |
| 参数 | - cb : 用户的自有模型处理回调函数 |
| 返回值 | 无 |
| 备注 |
| 函数名 | setpycallback |
|---|---|
| 函数原型 | void setpycallback(py::function callback) |
| 功能概述 | 注册python回调函数 |
| 参数 | - callback : python回调函数 |
| 返回值 | 无 |
| 备注 |
RotationTools.h
函数模版:
| 函数名 | 返回类型 | 备注 |
|---|---|---|
| getRotationMatrixFromZyxEulerAngles | 任意类型3*3矩阵 | 从欧拉角获得旋转矩阵 |
| square | 任意类型实数 | 平方运算 |
| quatToZyx | 任意类型3*1矩阵 | 四元数转换zyx方向矩阵 |
| quatToXyz | 任意类型3*1矩阵 | 四元数转换xyz方向矩阵 |
RotatioTools接口详解
| 函数名 | getRotationMatrixFromZyxEulerAngles |
|---|---|
| 函数原型 | Eigen::Matrix<SCALAR_T, 3, 3> getRotationMatrixFromZyxEulerAngles(const Eigen::Matrix<SCALAR_T, 3, 1>& eulerAngles) |
| 功能概述 | 从欧拉角获得旋转矩阵 |
| 参数 |
|
| 返回值 | Eigen::Matrix<SCALAR_T, 3, 3> 从欧拉角旋转后的矩阵 |
| 备注 |
| 函数名 | square |
|---|---|
| 函数原型 | T square(T a) |
| 功能概述 | 平方运算 |
| 参数 |
|
| 返回值 | Eigen::Matrix<SCALAR_T, 3, 3> 从欧拉角旋转后任意类型的矩阵 |
| 备注 |
| 函数名 | quatToZyx |
|---|---|
| 函数原型 | Eigen::Matrix<SCALAR_T, 3, 1> quatToXyz(const Eigen::Quaternion<SCALAR_T>& q) |
| 功能概述 | 四元数转换zyx方向矩阵 |
| 参数 |
|
| 返回值 | Eigen::Matrix<SCALAR_T, 3, 1> 任意类型3*1矩阵 |
| 备注 |
| 函数名 | quatToXyz |
|---|---|
| 函数原型 | Eigen::Matrix<SCALAR_T, 3, 1> quatToXyz(const Eigen::Quaternion<SCALAR_T>& q) |
| 功能概述 | 四元数转换xyz方向矩阵 |
| 参数 |
|
| 返回值 | Eigen::Matrix<SCALAR_T, 3, 1> 任意类型3*1矩阵 |
| 备注 |
Types.h
using创建类型别名 usercontroller.h
| 名称 | 类型 | 备注 |
|---|---|---|
| WorkMode | 枚举类 | 当前机器人控制状态,默认态,客户定义行走态,初始态,站立态等 |
| RobotCfg | 结构体 | 机器人相关配置项,包含其余结构体 |
| ControlCfg | 结构体 | 与yaml文件关联,控制相关配置项,包含于RobotCfg |
| InitState | 结构体 | 关节初始位置,包含于RobotCfg |
| ObsScales | 结构体 | 包含于RobotCfg |
| UserController | 类 | 客户控制类 |
| init | 类函数 | 系统初始化 |
| loadModel | 类函数 | 加载自有模型 |
| loadrknnmodel | 类函数 | 加载rknn模型 |
| handleWalkMode | 类函数 | 行走模式控制 |
| setparameter | 类函数 | 设置xyz整机控制参数 |
| handleStandMode | 类函数 | 站立模式控制 |
| handleDefautMode | 类函数 | 默认模式控制 |
| handleLieMode | 类函数 | 初始模式控制(全身关节使能) |
| process | 类函数 | 主控制进程 |
| computeActions | 类函数 | 计算最终的动作 |
| computeActionsrknn | 类函数 | rknn中计算最终的动作 |
| computeObservation | 类函数 | 计算观测系数 |
| onnxdatainit | 类函数 | 初始化onnx数据 |
| getmodelparam | 类函数 | 从yaml文件中获取模型参数 |
| updateStateEstimation | 类函数 | 更新状态,包括关节角度,IMU数据等 |
type.h定义参数详解
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| WorkMode | | STAND | 准备模式,电机上电使能,到0位 |
| LIE | |||
| USERWALK | 用户控制模式走路 | ||
| DEFAULT | 原厂控制模式 |
| 参数名称 | 定义原型 | 示例值 | 说明 |
|---|---|---|---|
| RobotCfg | | ControlCfg | 同common.h ControlCfg |
| InitState | 同common.h InitState | ||
| ObsScales | 同common.h ObsScales | ||
| encoder_nomalize | |||
| clipActions | |||
| clipObs | |||
| initState | |||
| obsScales | |||
| controlCfg | |||
| loophz | |||
| cycletimeerrorThreshold | |||
| ThreadPriority |
usercontroller.h接口详解
| 函数名 | init |
|---|---|
| 函数原型 | bool init(ControlMode mode) |
| 功能概述 | 系统初始化 |
| 参数 |
|
| 返回值 | true:初始化成功;false:初始化失败 |
| 备注 |
| 函数名 | loadModel |
|---|---|
| 函数原型 | bool loadModel(std::string modelpath) |
| 功能概述 | 加载自有模型 |
| 参数 |
|
| 返回值 | true:加载成功;false:加载失败 |
| 备注 |
| 函数名 | loadrknnmodel |
|---|---|
| 函数原型 | bool loadrknnmodel(std::string modle_path); |
| 功能概述 | 加载rknn模型 |
| 参数 |
|
| 返回值 | true:加载成功;false:加载失败 |
| 备注 |
| 函数名 | handleWalkMode |
|---|---|
| 函数原型 | bool handleWalkMode() |
| 功能概述 | 行走模式控制 |
| 参数 | 无 |
| 返回值 | true:行走模式切换成功;false:行走模式切换失败 |
| 备注 |
| 函数名 | setparameter |
|---|---|
| 函数原型 | void setparameter(Command &cmd,bool* isfirst) |
| 功能概述 | 设置xyz整机控制参数 |
| 参数 |
|
| 返回值 | 无 |
| 备注 |
| 函数名 | handleStandMode |
|---|---|
| 函数原型 | void handleStandMode() |
| 功能概述 | 站立模式控制 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | handleDefautMode |
|---|---|
| 函数原型 | void handleDefautMode() |
| 功能概述 | 默认模式控制 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | handleLieMode |
|---|---|
| 函数原型 | void handleLieMode() |
| 功能概述 | 初始模式控制(全身关节使能) |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | process |
|---|---|
| 函数原型 | void process() |
| 功能概述 | 主控制进程 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | computeActions |
|---|---|
| 函数原型 | void computeActions() |
| 功能概述 | 计算最终的动作 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | computeActionssrknn |
|---|---|
| 函数原型 | void computeActionsrknn() |
| 功能概述 | rknn中计算最终的动作 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | computeObservation |
|---|---|
| 函数原型 | void computeObservation() |
| 功能概述 | 计算观测系数 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | onnxdatainit |
|---|---|
| 函数原型 | void onnxdatainit() |
| 功能概述 | 初始化onnx数据 |
| 参数 | 无 |
| 返回值 | 无 |
| 备注 |
| 函数名 | getmodelparam |
|---|---|
| 函数原型 | bool getmodelparam() |
| 功能概述 | 从yaml文件中获取模型参数 |
| 参数 | 无 |
| 返回值 | true:读取yaml文件成功;false:读取yaml文件失败 |
| 备注 |
| 函数名 | updatestateestimation |
|---|---|
| 函数原型 | bool updatestateestimation() |
| 功能概述 | 更新状态,包括关节角度,IMU数据等从yaml文件中获取模型参数 |
| 参数 | 无 |
| 返回值 | true:读取yaml文件成功;false:读取yaml文件失败 |
| 备注 |
3.lib文件夹
aarch64
aarch64 arm架构下的静态库,客户无需关注
x86_64
x86_64架构下的静态库,客户无需关注
4.policy文件夹
x86架构下onnx模型文件以及arm架构下rknn模型文件,客户无需关注
5.data文件夹
存放示教动作保存的bin文件
6.src文件夹
controller_example.cpp
默认测试主函数
usercontroller.cpp
客户开源代码
(四)获取SDK
SDK在机器人的运控板RK3588S)中home/noetix/work/noetix_sdk_release路径下
(五)快速开发
进入SDK目录
SDK 的目录位于机器人运控板的家目录(/home/noetix/)下的 work文件夹中,其中用户需要关注下面两个文件:
-
noetix_sdk_release(SDK 文件夹) -
startup.sh(自启动脚本)。
自启动脚本会在机器人主控每次上电开机后自动执行,用户可以根据需要修改脚本内容来决定机器人启动后运行的程序,大致内容如下:
#!/bin/bash
sleep 5
sudo -s << EOF
echo "#################"
cd /home/noetix/work/noetix_sdk_release # 用户可以修这行和下面这行两行代码,决定启动那个sdk
./noetix_joint_controller
EOF
wait
我们可以通过vscode的Remote SSH插件远程进入SDK目录,或者直接通过SSH连接使用vim编辑代码文件
编辑代码
出厂的N2机器人在程序当中默认使用的是原厂运控模式,用户想要二次开发需要切换到用户控制模式上,则需要在程序历程入口noetix_sdk_release/src/controler_example.cpp当中解除掉 //#define usermode的注释
#define usermode //解除此行注释
然后,客户按照想要实现的功能编辑构造代码文件。
编译代码
机器人运控板卡是出厂默认是有编译环境的,直接在noetix_sdk_release目录下运行脚本文件build_release.sh编译SDK代码
./build_release.sh
编译成功效果如下:
noetix@noetix:~/work/noetix_sdk_release$ ./build_release.sh
this is arm64
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- environment user : noetix
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found PythonInterp: /usr/bin/python3 (found suitable version "3.8.10", minimum required is "3.7")
-- Found PythonLibs: /usr/lib/aarch64-linux-gnu/libpython3.8.so
-- Performing Test HAS_FLTO
-- Performing Test HAS_FLTO - Success
-- Found pybind11: /home/noetix/.local/lib/python3.8/site-packages/pybind11/include (found version "2.13.6")
-- Found Python3: /usr/bin/python3.8 (found version "3.8.10") found components: Interpreter Development Development.Module Development.Embed
LIB_DIR:/home/noetix/work/noetix_sdk_release/lib/aarch64
-- Configuring done (4.6s)
-- Generating done (0.0s)
CMake Warning:
Manually-specified variables were not used by the project:
RK3588
-- Build files have been written to: /home/noetix/work/noetix_sdk_release/build
[ 33%] Building CXX object CMakeFiles/noetix_joint_controller.dir/src/controller_example.cpp.o
[ 66%] Building CXX object CMakeFiles/noetix_joint_controller.dir/src/usercontroller.cpp.o
[100%] Linking CXX executable /home/noetix/work/noetix_sdk_release/noetix_joint_controller
[100%] Built target noetix_joint_controller
如果用户想要在自己的电脑上编译代码,需要安装环境,详细看 N2 SDK部署流程
执行代码
在noetix_sdk_release目录使用root权限执行编译出来的可执行文件:noetix_joint_controller
sudo ./noetix_joint_controller
运行效果如下:
noetix@noetix:~/work/noetix_sdk_release$ sudo ./noetix_joint_controller
cur path is /home/noetix/work/noetix_sdk_release
noetix_sdk ver: 1.5.7
network interface:
eth0
[EtherCAT] Initializing EtherCAT
[EtherCAT] Attempting to start EtherCAT, try 1 of 3.
[EtherCAT Init] Initialization on device eth0 succeeded.
[EtherCAT Init] 4 slaves found and configured.
[EtherCAT Init] Mapped slaves.
[SLAVE 1]
IN 110 bytes, 880 bits
OUT 88 bytes, 704 bits
dora_2
[SLAVE 2]
IN 110 bytes, 880 bits
OUT 88 bytes, 704 bits
dora_2
[SLAVE 3]
IN 110 bytes, 880 bits
OUT 88 bytes, 704 bits
dora_2
[SLAVE 4]
IN 80 bytes, 640 bits
OUT 8 bytes, 64 bits
imu_rc
[EtherCAT Init] segments : 1 : 682 0 0 0
[EtherCAT Init] Requesting operational state for all slaves...
[EtherCAT Init] Calculated workcounter 12
[EtherCAT Init] Operational state reached for all slaves.
[EtherCAT] EtherCAT successfully initialized on attempt 1
hardware init success
Cycle time exceeded error threshold by: 1.75766e+09s, cycle time: 1.75766e+09s, threshold: 0.002s
sdk version : 2.1.0 (967d001cc8@2024-08-07T19:28:19) driver version : 0.9.8
model input num: 1,output num: 1
input info: index = 0 ,name= policy_input,n_dims=2,dims=[1, 195],n_elems=195,size=390,w_stride=0,size_with_stride=390,fmt=UNDEFINED,type=FP16, qnt_type=AFFINE,zp=0,scale=1.000000
output info: index = 0 ,name= policy_output,n_dims=2,dims=[1, 10],n_elems=10,size=20,w_stride=0,size_with_stride=20,fmt=UNDEFINED,type=FP16, qnt_type=AFFINE,zp=0,scale=1.000000
Load walk rknn model successfully !!!
sdk version : 2.1.0 (967d001cc8@2024-08-07T19:28:19) driver version : 0.9.8
model input num: 1,output num: 1
input info: index = 0 ,name= policy_input,n_dims=2,dims=[1, 315],n_elems=315,size=630,w_stride=0,size_with_stride=630,fmt=UNDEFINED,type=FP16, qnt_type=AFFINE,zp=0,scale=1.000000
output info: index = 0 ,name= policy_output,n_dims=2,dims=[1, 18],n_elems=18,size=36,w_stride=0,size_with_stride=36,fmt=UNDEFINED,type=FP16, qnt_type=AFFINE,zp=0,scale=1.000000
Load run rknn model successfully !!!
sdk version : 2.1.0 (967d001cc8@2024-08-07T19:28:19) driver version : 0.9.8
model input num: 1,output num: 1
input info: index = 0 ,name= policy_input,n_dims=2,dims=[1, 310],n_elems=310,size=620,w_stride=0,size_with_stride=620,fmt=UNDEFINED,type=FP16, qnt_type=AFFINE,zp=0,scale=1.000000
output info: index = 0 ,name= policy_output,n_dims=2,dims=[1, 18],n_elems=18,size=36,w_stride=0,size_with_stride=36,fmt=UNDEFINED,type=FP16, qnt_type=AFFINE,zp=0,scale=1.000000
Load ygdance rknn model successfully !!!
loadModel ret 1
Start Control
七、强化学习运动控制
训练框架后续完善,目前购买后可以联系技术支持获得
八、更多例程
Intel D435i 相机例程请参考
https://github.com/IntelRealSense/librealsense
九、调试说明
后续完善
十、常见问题
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架构:
./highcontrol: 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


