跳到主要内容

N2 SDK开发指南

一、关于N2

(一)部件名称

N2 整机分为上半身和下半身,具备18个自由度。单臂拥有4个自由度,包括:

  • 肩关节pitch

  • 肩关节roll

  • 上臂关节yaw

  • 手肘关节pitch

单腿拥有5个自由度,包括:

  • 胯关节yaw

  • 髋关节roll

  • 髋关节pitch

  • 膝关节pitch

  • 踝关节pitch

拥有多个关节电机自由度,使得N2机器人能够实现精确的运动和姿态控制。

类型N2
总自由度18
单腿自由度5
手臂自由度4
部件说明

1.机器人规格介绍

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

2.电气接口

类型数量
以太网1
USB2
HDMI1

其中HDMI接口接到的是 运控板(RK3588S) 上面,如果用户购买的是教育版本,目前只能通过ssh访问 二开 算力 板(NVIDIA jetson orin nano super)

3.板卡信息及用户名IP

类型型号用户IP密码算力频率内存
运控板鲁班猫 RK3588Snoetix192.168.55.102n6Tops2.4GHz4+32GB
二开算力板NVIDIA Jetson orin nano super192.168.55.101n267Tops1.7GHz8+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 和 -让机器人回到准备模式,此时机器失去自主站立的能力,需要人扶住。

将机器人吊起或者放平躺(趴)后,按 + 号键,让机器人进入失能模式

然后长按电机开关,关机后取下电池即可。

遥控器按键功能图表

  1. 基础功能

键位前置条件功能备注
+使能/失能模式使能和失能
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点:

  1. 按照功能要求在开阔地带使用,地面平坦没有坡度且粗糙不打滑,附近没有杂物
  2. 使用时不能离机器太远,会导致机器人断连,导致失制!!!
  3. 表演时在功能要求范围大小内尤其是动作结束落点要远离人群,尤其是妇女儿童
  4. 如果机器人表演失败,请立刻按手柄上的+按键 让机器人失能
  5. 电池 指示灯 在 4 格
  6. 半小时内不能连续使用两次
  7. 机器人的手部必须是出厂原装塑胶球手

如没有按照以上要求使用,造成任何损失与我司无关

键位前置条件功能备注
LT & X
走路模式
垫步侧手翻(机器人正面朝向需要机器人正前方为轴,左右90度半圆区域十米开阔的开阔地带


二、关节电机顺序

N2机器人关节电机状态数据由SDK接口获取,获取到的顺序固定,如下:

序号名称关节扭矩
0arm_l1_joint左臂肩pitch关节27N.m
1arm_l2_joint左臂肩roll关节27N.m
2arm_l3_joint左臂大臂yaw关节27N.m
3arm_l4_joint左臂肘pitch关节27N.m
4leg_l1_joint左腿髋yaw关节90N.m
5leg_l2_joint左腿髋roll关节90N.m
6leg_l3_joint左腿大腿pitch关节150N.m
7leg_l4_joint左腿膝关节pitch关节(连杆)150N.m
8leg_l5_joint左腿小腿pitch踝关节(连杆)70N.m
9arm_r1_joint右臂肩pitch关节27N.m
10arm_r2_joint右臂肩roll关节27N.m
11arm_r3_joint右臂大臂yaw关节27N.m
12arm_r4_joint右臂肘pitch关节27N.m
13leg_r1_joint右腿髋yaw关节90N.m
14leg_r2_joint右腿髋roll关节90N.m
15leg_r3_joint右腿大腿pitch关节150N.m
16leg_r4_joint右腿膝关节pitch关节(连杆)150N.m
17leg_r5_joint右腿小腿pitch踝关节(连杆)70N.m

三、遥控器按键数据映射

自研遥控器。button[]和按键映射表如下:

键位描述Button index
KEY1 食指按键扳机上1
KEY2 食指按键扳机下2
KEY5,拇指按键,上左5
KEY6,拇指按键,上右6
KEY7,拇指按键,下左7
KEY8,拇指按键,下右8
KEY9,侧按键,左上S19
KEY10,侧按键,左下S210
KEY11 ,侧按键,右上F211
KEY12 ,侧按键,右下F112

澳加狮手柄。button[]和按键映射表如下:

键位描述Button index
右肩键1
左肩键2
X5
Y6
B7
A8
+9
-10
11
左遥感按下12

手柄摇杆数据范围

最小值最大值
-11

四、N2的URDF文件

请登录到客户服务平台后下载


五、DDS接口开发

(一)SDK概述

本 SDK 采用C/S架构,并基于 DDS消息中间件 实现通信。在隔离机制下,使 N2 机器人的 二次开发算力板(NVIDIA Jetson Orin Nano Super) 作为客户端与机器人上的 运控板 作为服务器之间能够高效、安全地交互。dds使用的是CYCLONEDDS 0.11.0

(二)SDK开发流程

使用此SDK开发可以分为大致以下几步:

  1. 初始化DDS

  2. 通过DDS发布消息让机器人切换为DDS控制模式

  3. 设置回调,订阅机器人状态等信息

  4. 用户算法控制

  5. 通过DDS发布命令控制

以上1 2 3 5 在例程文件中已经做好了,用户仅需参考例程接口代码或者只完成第4步即可

功能简介

用户可使用 SDK 实现以下功能:

  • 应用开发:基于原厂控制算法,快速实现机器人自动化应用,或与大模型集成,打造定制化智能行为。例如:

    • 配合摄像头算法程序与原厂运控结合,实现自主行进

    • 配合语音交互,实现语音控制机器人

    • 接入大模型,根据输入动态生成并执行机器人原厂控制动作

  • 运控开发:通过 DDS 接口:

    • 获取电机状态与 IMU 传感器数据

    • 下发电机控制指令,并以500Hz的频率进行闭环控制。

    • 支持完全用户重新定制运控模型

两种控制方式

  1. highcontrol

    • 用户只需要给方向、速度、动作编号。

    • 底层由厂家的运控算法接管。

    • 适合快速上手、做行为级控制。

  2. lowcontrol

    • 用户要自己生成每个电机的 posveltaukpkd

    • 控制自由度高,但需要较强的运动控制算法。

    • 用户可以自己搭建控制算法模型。

前置条件

SDK运行在Linux系统上,SDK不依赖ROS,用户基于机器人上的控制器开发不需要安装其他库,机器人二开算力板上出厂默认没有环境,需要安装:

  • fmt

  • eigen3

  • onnxruntime

  • drake

  • glog

  • spdlog

  • python3

  • pybind11

详细请看N2 SDK环境部署流程

(三)参考例程


1.应用开发

开发者可在 highcontroller.cpp 中的 HighController::process 函数内进行扩展,最后调用set_axes下发控制命令,控制指令下发详细流程代码可以参考set_axes函数。

基本例程

执行此例程后机器人会根据cmdxaction参数一边执行欢呼动作一边自主向前。

参数范围功能备注
cmd.x[-1, 1]前进后退> 0 前进
cmd.y无意义无意义无意义
cmd.yaw[-1, 1]左右转向> 0 左转
参数名称定义原型示例值说明(括号内对应按键)
ControlCmd
enum class ControlCmd : uint8_t {
WALK,
SWING,
SHAKE,
CHEER,
RUN,
DANCE,
START,
SWITCH,
STARTTEACH,
SAVETEACH,
ENDTEACH,
PLAYTEACH,
DEFAULT
};
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_bufferstd::shared_ptr<const std::array<MotorState, 18>>输出存放机器人当前电机状态数据
imubufferstd::shared_ptr<const NingImuData>输出存放 IMU 数据
joybufferstd::shared_ptr<const JoyData>输出存放遥控器输入指令
motorcmd_bufferstd::shared_ptr<const std::array<MotorCmd, 18>>输入用户控制算法生成的电机控制指令数组

缓冲区(DataBuffer 类)通过 SetDataGetData 接口来与之交互数据。

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_cardeth0根据不同版本整机,可进入系统,查询网口名后更改。
remote_port/dev/input/js0/dev/input/js0为澳加狮游戏手柄作为控制器使用,若使用noetix定制手柄,请更改为/dev/remote
其余默认值不变其余对象客户无需关注

ning_user.yaml

用于配置用户模型控制的相关参数,如需强化学习模型训练支持,另行联系。

对象名子对象名备注
init_statedefault_joint_angle包括各关节的默认启动角度offset。
controlstiffness关节刚度,kp
damping关节阻尼,kd
stiffnessRun关节运动时刚度,kp
dampingRun关节运动时阻尼,kd
action_scale强化学习训练模型参数,默认不做更改
decimation强化学习训练模型参数,默认不做更改
cycle_time强化学习训练模型参数,默认不做更改
normalizationclip_scales强化学习训练模型参数,默认不做更改
obs_scales强化学习训练模型参数,默认不做更改
sizeactions_size强化学习训练模型参数,默认不做更改
observations_size强化学习训练模型参数,默认不做更改
actions_size_Run强化学习训练模型参数,默认不做更改
observations_size_Run强化学习训练模型参数,默认不做更改
stack_size强化学习训练模型参数,默认不做更改
axis_mappingsscalez强化学习训练模型参数,默认不做更改
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
enum class ControlMode : uint8_t { LOWMODE, HIGHMODE, DEFAULT };
DEFAULT原厂控制模式
LOWMODElowcontrol模式
HIGHMODEhighcontrol模式
参数名称定义原型示例值说明
ControlCfg
struct ControlCfg {
std::map&#x3C;std::string, float> stiffness;
std::map&#x3C;std::string, float> damping;
float actionScale;
int decimation;
float user_torque_limit;
float user_power_limit;
float cycle_time;
float bf_cycle_time;
};
stiffness
damping
actionScale
decimation
user_torque_limit
user_power_limit
cycle_time
bf_cycle_time
参数名称定义原型示例值说明
InitState
struct InitState {
// default joint angles
scalar_t arm_l1_joint;
scalar_t arm_l2_joint;
scalar_t arm_l3_joint;
scalar_t arm_l4_joint;
scalar_t leg_l1_joint;
....(总共18个)
};
每个关节电机的初始位置
参数名称定义原型示例值说明
JointState
struct JointState {
double arm_l1_joint;
double arm_l2_joint;
double arm_l3_joint;
double arm_l4_joint;
double leg_l1_joint;
....(总共18个)
};
每个关节电机的当前位置
参数名称定义原型示例值说明
ObsScales
struct ObsScales {
scalar_t linVel;
scalar_t angVel;
scalar_t dofPos;
scalar_t dofVel;
scalar_t quat;
scalar_t heightMeasurements;
};
linVel
angVel
dofPos
dofVel
quat
heightMeasurements
参数名称定义原型示例值说明
Proprioception
struct Proprioception {
vector_t jointPos;
vector_t jointVel;
vector3_t baseAngVel;
vector3_t baseEulerXyz;
vector3_t projectedGravity;
};
jointPos
jointVel
baseAngVel
baseEulerXyz
projectedGravity
参数名称定义原型示例值说明
Command
struct Command {
std::atomic&#x3C;double> x;
std::atomic&#x3C;double> y;
std::atomic&#x3C;double> yaw;
};
x
y
yaw
参数名称定义原型示例值说明(括号内对应按键)
ControlCmd
enum class ControlCmd : uint8_t {
WALK,
SWING,
SHAKE,
CHEER,
RUN,
DANCE,
START,
SWITCH,
STARTTEACH,
SAVETEACH,
ENDTEACH,
PLAYTEACH,
DEFAULT
};
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
struct MotorState {
double pos;
double vel;
double tau;
uint16_t motor_id;
uint8_t error;
int temperature;
};
pos电机位置
vel电机转速
tau电机扭矩
motor_id电机ID
error

电机错误码:

  • 02H:电机过流
  • 03H:电机电压过低
  • 04H:电机编码器错误
  • 06H:电机刹车电压过高
  • 07H:DRV驱动错误
  • 08H:超压
  • 09H:欠压
  • 0AH:过流
  • 0BH:MOS过温
  • 0CH:电机线圈过温
  • 0DH:通讯丢失
  • 0EH:过载
temperature
参数名称定义原型示例值说明
MotorCmd
struct MotorCmd {
double pos;
double vel;
double tau;
double kp;
double kd;
uint16_t motor_id;
};
pos电机位置
vel电机转速
tau电机扭矩
kppid参数
kdpid参数
motor_id电机ID
参数名称定义原型示例值说明
NingImuData
struct NingImuData {
double ori[4];
double ori_cov[9];
double angular_vel[3];
double angular_vel_cov[9];
double linear_acc[3];
double linear_acc_cov[9];
};
ori
ori_cov
angular_vel
angular_vel_cov
linear_acc
linear_acc_cov
参数名称定义原型示例值说明
joydata
struct joydata {
double axes[2]; // horz,vert;
int button[14];
};
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)
功能概述从欧拉角获得旋转矩阵
参数
  • eulerAngles 任意类型3*1矩阵
返回值Eigen::Matrix<SCALAR_T, 3, 3> 从欧拉角旋转后的矩阵
备注
函数名square
函数原型T square(T a)
功能概述平方运算
参数
  • a 任意实数
返回值Eigen::Matrix<SCALAR_T, 3, 3> 从欧拉角旋转后任意类型的矩阵
备注
函数名quatToZyx
函数原型Eigen::Matrix<SCALAR_T, 3, 1> quatToXyz(const Eigen::Quaternion<SCALAR_T>& q)
功能概述四元数转换zyx方向矩阵
参数
  • q 四元数对象的常量引用
返回值Eigen::Matrix<SCALAR_T, 3, 1> 任意类型3*1矩阵
备注
函数名quatToXyz
函数原型Eigen::Matrix<SCALAR_T, 3, 1> quatToXyz(const Eigen::Quaternion<SCALAR_T>& q)
功能概述四元数转换xyz方向矩阵
参数
  • q 四元数对象的常量引用
返回值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 回调数据处理函数 定义如下

using RobotStatusCallback = std::function<void(const RobotStatus::StatusData &)>;
返回值
备注

highcontroller.h

名称类型备注
WorkMode枚举类机器人状态模式(详细信息同type.h)
RobotCfg结构体机器人相关配置项,包含其余结构体(详细信息同common.h)
DataBuffer定义的rb模板类,用于缓存数据
motorstate_buffer变量电机状态rb
joy_buffer_变量手柄数据rb
imu_buffer_变量imu数据rb
HighControllerhighcontrol模式控制器
参数名称定义原型示例值说明
WorkMode
enum class WorkMode : uint8_t {
STAND,
LIE,
USERWALK,
DEFAULT
};
STAND准备模式,电机上电使能,到0位
LIE
USERWALK用户控制模式走路
DEFAULT原厂控制模式
参数名称定义原型示例值说明
RobotCfg
struct RobotCfg {
struct ControlCfg {
...
};

struct InitState {

...
};

struct ObsScales {

...
};

bool encoder_nomalize;
scalar_t clipActions;
scalar_t clipObs;
InitState initState;
ObsScales obsScales;
ControlCfg controlCfg;
int loophz;
double cycletimeerrorThreshold;
int ThreadPriority;
};

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)
功能概述往缓冲区写入数据
参数
  • newData 数据(模板)
返回值
备注
函数名Clear
函数原型void Clear()
功能概述清楚缓冲区里面的数据
参数
返回值
备注
函数名SetData
函数原型std::shared_ptr<const T> GetData()
功能概述从缓冲区获取数据
参数
返回值数据(模板)
备注

HighController类详解

名称类型备注
publicpublicpublic
Instance方法HighController采用单例设计模式
instanceHithController *单例指针
init方法初始化
process方法控制函数,用户的应用开发代码可以在这个函数内扩展
protectedprotectedprotected
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方法设置机器人状态数据
privateprivateprivate
countint64_t
ddswrapperDDSWrapperDDSWrapper类控制DDS订阅和发布
baseLinVel_vector3_thiglcontrol模式下客户无需关注
basePosition_vector3_thiglcontrol模式下客户无需关注
lastActions_vector_thiglcontrol模式下客户无需关注
defaultJointAngles_vector_thiglcontrol模式下客户无需关注
walkdefaultJointAngles_vector_thiglcontrol模式下客户无需关注
actuatedDofNum_inthiglcontrol模式下客户无需关注
isfirstRecObs_bool*higlcontrol模式下客户无需关注
actionsSize_inthiglcontrol模式下客户无需关注
motionSizeinthiglcontrol模式下客户无需关注
observationSize_inthiglcontrol模式下客户无需关注
stackSize_inthiglcontrol模式下客户无需关注
scalezfloathiglcontrol模式下客户无需关注
scalexfloathiglcontrol模式下客户无需关注
scaleyfloathiglcontrol模式下客户无需关注
command_vector_thiglcontrol模式下客户无需关注
loopcount_int64_thiglcontrol模式下客户无需关注
imu_data_NingImuDatahiglcontrol模式下客户无需关注
remote_data_joydatahiglcontrol模式下客户无需关注
motorstate_std::array<MotorState, 18>higlcontrol模式下客户无需关注
statequeuestd::queue<std::array<MotorState, 18>>higlcontrol模式下客户无需关注
cmdqueuestd::queue<RobotMotorCmd::MotorCmdArray>higlcontrol模式下客户无需关注
mode_WorkModehiglcontrol模式下客户无需关注
isChangeMode_boolhiglcontrol模式下客户无需关注
startcontrolboolhiglcontrol模式下客户无需关注
initfinishinthiglcontrol模式下客户无需关注
model_typeinthiglcontrol模式下客户无需关注
statetimestamplong longhiglcontrol模式下客户无需关注
state_mutexstd::mutexhiglcontrol模式下客户无需关注
usermotorcmdstd::array<MotorCmd, 18>higlcontrol模式下客户无需关注
motor_cmd_buffer_DataBuffer<RobotMotorCmd::MotorCmdArray>higlcontrol模式下客户无需关注
send_thread_std::threadhiglcontrol模式下客户无需关注
process_thread_std::threadhiglcontrol模式下客户无需关注

HighController部分函数接口介绍

函数名process
函数原型void process()
功能概述控制模板方法,用户可参考此方法进行二开
参数
返回值
备注
函数名init
函数原型bool init(ControlMode mode)
功能概述系统初始化
参数
  • 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);
功能概述下发机器人位置控制指令
参数
  • ver: 机器人前后移动 >0 前进
  • hor 机器人左右转向 >0 左转
  • action 机器人行为(1:打招呼 2:握手 3:喝彩)
返回值
备注
函数名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);
功能概述设置机器人状态数据
参数
  • motorstate_data:电机状态数据
  • imudata:imu数据
  • joy_data:遥控器数据
返回值
备注

lowcontroller.h

名称类型备注
WorkMode枚举类机器人状态模式(详细信息同type.h)
RobotCfg结构体机器人相关配置项,包含其余结构体(详细信息同common.h)
DataBuffer定义的rb模板类,用于缓存数据
motor_state_buffer_变量电机状态rb
joy_buffer_变量手柄数据rb
imu_buffer_变量imu数据rb
LowControllerhighcontrol模式控制器

LowController类详解

名称类型备注
publicpublicpublic
Instance方法HighController采用单例设计模式
instanceHithController单例指针
StaticCallback()方法静态回调函数
init方法初始化
loadModel方法读取模型
handleWalkMode方法行走模式控制
setparameter方法设置xyz整机控制参数
handleStandMode方法站立模式控制
handleDefautMode方法默认模式控制
handleLieMode方法使能模式控制
process方法控制函数,用户的应用开发代码可以在这个函数内扩展
protectedprotectedprotected
set_robotstatusdata方法设置机器人状态数据
computeActions方法计算最终动作
computeObservation方法计算观测系数
onnxdatainit方法初始化onnx
getmodelparam方法获取模型参数
updateStateEstimation方法更新状态,包括关节角度,IMU数据等
get_joint_state方法获取电机状态
set_joint方法设置电机命令
send_thread_func方法通过DDSWrapper类发布DDS数据模板函数
process_thread_func方法
privateprivateprivate
jointNamesstd::vector<std::string>电机名称
memoryInfoOrt::MemoryInfo内存信息
onnxEnvPrt_shared_ptr<Ort::Env>
policyFilePath_std::string策略文件路径
modelnamestd::string模型路径
robotconfigRobotCfg
policySessionPtrstd::unique_ptr<Ort::Session>
estSessionPtrstd::unique_ptr<Ort::Session>
policyInputNames_std::vector<const char *>
policyOutputNames_std::vector<const char *>
estInputNames_std::vector<const char *>
estOutputNames_std::vector<const char *>
policyInputNodeNameAllocatedStringsstd::vector<Ort::AllocatedStringPtr>
policyOutputNodeNameAllocatedStringsstd::vector<Ort::AllocatedStringPtr>
estInputNodeNameAllocatedStringsstd::vector<Ort::AllocatedStringPtr>
estOutputNodeNameAllocatedStringsstd::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>>
countint64_t
ddswrapperDDSWrapperDDSWrapper类控制DDS订阅和发布
baseLinVel_vector3_t
basePosition_vector3_t
lastActions_vector_t
defaultJointAngles_vector_t
walkdefaultJointAngles_vector_t
actuatedDofNum_int
isfirstRecObs_bool
actionsSize_int
motionSizeint
observationSize_int
stackSize_int
scalezfloat
scalexfloat
scaleyfloat
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_datajoydata
imu_dataNingImuData
motorstate_std::array<MotorState, 18>
statequeuestd::queue<std::array<MotorState, 18>>
cmdqueuestd::queue<RobotMotorCmd::MotorCmdArray>
standPercentdouble
standDurationscalar_t
lieJointAnglesvector_t
lieJointStateJointState
standJointStatie_JointState
mode_WorkMode
isChangeMode_bool
startcontrolbool
initfinishint
model_typeint
statetimestamplong long
state_mutexstd::mutex
usermotorcmdstd::array<MotorCmd, 18>
lieJointAngles_vector_t
standJointAngles_vector_t
motor_cmd_buffer_DataBuffer<RobotMotorCmd::MotorCmdArray>
send_thread_std::thread
new_state_arrivedint
process_thread_std::thread

LowController部分函数接口介绍(部分同名接口详见HighController)

函数名loadModel
函数原型bool loadModel(std::string modelpath)
功能概述加载自有模型
参数
  • modelpath: 模型路径(程序所在的当前绝对路径)
返回值true:加载成功;false:加载失败
备注
函数名handleWalkMode
函数原型bool handleWalkMode()
功能概述行走模式控制
参数
返回值true:行走模式切换成功;false:行走模式切换失败
备注
函数名setparameter
函数原型void setparameter(Command &cmd,bool* isfirst)
功能概述设置xyz整机控制参数
参数
  • cmd:设置指令
  • isfirst: 是否是第一次设置
返回值
备注
函数名set_joint
函数原型void set_joint(std::array<MotorCmd, 18> motorcmd)
功能概述设置关节数据
参数
  • 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);
功能概述设置机器人状态数据
参数
  • motorstate_data:电机状态数据
  • imudata:imu数据
  • 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 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_cardeth0根据不同版本整机,可进入系统,查询网口名后更改。
remote_port/dev/input/js0/dev/input/js0为澳加狮游戏手柄作为控制器使用,若使用noetix定制手柄,请更改为/dev/remote
其余默认值不变其余对象客户无需关注

ning_ac.yaml

用于配置默认模型控制的相关参数

对象名默认值备注
其余默认值不变其余对象客户无需关注

ning_user.yaml

用于配置用户模型控制的相关参数,如需强化学习模型训练支持,另行联系。

对象名子对象名备注
init_statedefault_joint_angle包括各关节的默认启动角度offset。
controlstiffness关节刚度,kp
damping关节阻尼,kd
stiffnessRun关节运动时刚度,kp
dampingRun关节运动时阻尼,kd
action_scale强化学习训练模型参数,默认不做更改
decimation强化学习训练模型参数,默认不做更改
cycle_time强化学习训练模型参数,默认不做更改
normalizationclip_scales强化学习训练模型参数,默认不做更改
obs_scales强化学习训练模型参数,默认不做更改
sizeactions_size强化学习训练模型参数,默认不做更改
observations_size强化学习训练模型参数,默认不做更改
actions_size_Run强化学习训练模型参数,默认不做更改
observations_size_Run强化学习训练模型参数,默认不做更改
stack_size强化学习训练模型参数,默认不做更改
axis_mappingsscalez强化学习训练模型参数,默认不做更改
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
enum class ControlMode : uint8_t { USERMODE, DEFAULT };
USERMODE用户控制模式
DEFAULT原厂控制模式
参数名称定义原型示例值说明
ControlCfg
struct ControlCfg {
std::map&#x3C;std::string, float> stiffness;
std::map&#x3C;std::string, float> damping;
float actionScale;
int decimation;
float user_torque_limit;
float user_power_limit;
float cycle_time;
float bf_cycle_time;
};
stiffness
damping
actionScale
decimation
user_torque_limit
user_power_limit
cycle_time
bf_cycle_time
参数名称定义原型示例值说明
InitState
struct InitState {
// default joint angles
scalar_t arm_l1_joint;
scalar_t arm_l2_joint;
scalar_t arm_l3_joint;
scalar_t arm_l4_joint;
scalar_t leg_l1_joint;
....(总共18个)
};
每个关节电机的初始位置
参数名称定义原型示例值说明
JointState
struct JointState {
double arm_l1_joint;
double arm_l2_joint;
double arm_l3_joint;
double arm_l4_joint;
double leg_l1_joint;
....(总共18个)
};
每个关节电机的当前位置
参数名称定义原型示例值说明
ObsScales
struct ObsScales {
scalar_t linVel;
scalar_t angVel;
scalar_t dofPos;
scalar_t dofVel;
scalar_t quat;
scalar_t heightMeasurements;
};
linVel
angVel
dofPos
dofVel
quat
heightMeasurements
参数名称定义原型示例值说明
Proprioception
struct Proprioception {
vector_t jointPos;
vector_t jointVel;
vector3_t baseAngVel;
vector3_t baseEulerXyz;
vector3_t projectedGravity;
};
jointPos
jointVel
baseAngVel
baseEulerXyz
projectedGravity
参数名称定义原型示例值说明
Command
struct Command {
std::atomic&#x3C;double> x;
std::atomic&#x3C;double> y;
std::atomic&#x3C;double> yaw;
};
x
y
yaw
参数名称定义原型示例值说明
MotorState
struct MotorState {
double pos;
double vel;
double tau;
uint16_t motor_id;
uint8_t error;
int temperature;
};
pos电机位置
vel电机转速
tau电机扭矩
motor_id电机ID
error

电机错误码:

  • 02H:电机过流
  • 03H:电机电压过低
  • 04H:电机编码器错误
  • 06H:电机刹车电压过高
  • 07H:DRV驱动错误
  • 08H:超压
  • 09H:欠压
  • 0AH:过流
  • 0BH:MOS过温
  • 0CH:电机线圈过温
  • 0DH:通讯丢失
  • 0EH:过载
temperature
参数名称定义原型示例值说明
MotorCmd
struct MotorCmd {
double pos;
double vel;
double tau;
double kp;
double kd;
uint16_t motor_id;
};
pos电机位置
vel电机转速
tau电机扭矩
kppid参数
kdpid参数
motor_id电机ID
参数名称定义原型示例值说明
NingImuData
struct NingImuData {
double ori[4];
double ori_cov[9];
double angular_vel[3];
double angular_vel_cov[9];
double linear_acc[3];
double linear_acc_cov[9];
};
ori
ori_cov
angular_vel
angular_vel_cov
linear_acc
linear_acc_cov
参数名称定义原型示例值说明
joydata
struct joydata {
double axes[2]; // horz,vert;
int button[14];
};
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)

功能概述加载自有模型
参数
  • modelname : 模型名称(对应config/ning_ac.yaml中的字段walk、run等) - modelpath: 模型路径(程序所在的当前绝对路径) - type : 模型类型
返回值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)
功能概述从欧拉角获得旋转矩阵
参数
  • eulerAngles 任意类型3*1矩阵
返回值Eigen::Matrix<SCALAR_T, 3, 3> 从欧拉角旋转后的矩阵
备注
函数名square
函数原型T square(T a)
功能概述平方运算
参数
  • a 任意实数
返回值Eigen::Matrix<SCALAR_T, 3, 3> 从欧拉角旋转后任意类型的矩阵
备注
函数名quatToZyx
函数原型Eigen::Matrix<SCALAR_T, 3, 1> quatToXyz(const Eigen::Quaternion<SCALAR_T>& q)
功能概述四元数转换zyx方向矩阵
参数
  • q 四元数对象的常量引用
返回值Eigen::Matrix<SCALAR_T, 3, 1> 任意类型3*1矩阵
备注
函数名quatToXyz
函数原型Eigen::Matrix<SCALAR_T, 3, 1> quatToXyz(const Eigen::Quaternion<SCALAR_T>& q)
功能概述四元数转换xyz方向矩阵
参数
  • q 四元数对象的常量引用
返回值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
enum class WorkMode : uint8_t {
STAND,
LIE,
USERWALK,
DEFAULT
};
STAND准备模式,电机上电使能,到0位
LIE
USERWALK用户控制模式走路
DEFAULT原厂控制模式
参数名称定义原型示例值说明
RobotCfg
struct RobotCfg {
struct ControlCfg {
...
};

struct InitState {

...
};

struct ObsScales {

...
};
bool encoder_nomalize;
scalar_t clipActions;
scalar_t clipObs;
InitState initState;
ObsScales obsScales;
ControlCfg controlCfg;
int loophz;
double cycletimeerrorThreshold;
int ThreadPriority;
};

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)
功能概述系统初始化
参数
  • mode:当前控制模式为默认或客户自定义控制
返回值true:初始化成功;false:初始化失败
备注
函数名loadModel
函数原型bool loadModel(std::string modelpath)
功能概述加载自有模型
参数
  • modelpath: 模型路径
返回值true:加载成功;false:加载失败
备注
函数名loadrknnmodel
函数原型bool loadrknnmodel(std::string modle_path);
功能概述加载rknn模型
参数
  • modelpath: 模型路径
返回值true:加载成功;false:加载失败
备注
函数名handleWalkMode
函数原型bool handleWalkMode()
功能概述行走模式控制
参数
返回值true:行走模式切换成功;false:行走模式切换失败
备注
函数名setparameter
函数原型void setparameter(Command &cmd,bool* isfirst)
功能概述设置xyz整机控制参数
参数
  • cmd:设置指令
  • isfirst: 是否是第一次设置
返回值
备注
函数名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

我们可以通过vscodeRemote 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