Skip to main content
🚩 学如逆水行舟,不进则退。 —— 《华北舵狗王》

**2024年6月1日 星期三 我正式开始了学习RL **


公告: 20250302:更新V1.1版本代码,详情查看,附录更新日志,优化了代码结构,增加了Taitan包含上肢的机器人,Tinker样机目前可以在群主获取DIY材料信息 原文及文中涉及资源均在百度云中可下载: 链接: https://pan.baidu.com/s/16SiaTsPg5DgqVBoS_1M1gw 提取码: d43h
外链资料与其他课程: (1)Torch部署模型的教程:在Nvidia Jetson nano上面安装部署torch (2)如果想了解人形机器人从传统控制到RL的技术请阅读:10天借助Tinker学习人形机器人运动控制
**大家好我是华北舵狗王,**实际在博士期间最早课题是强化学习方向,但由于当时导师和实验室并没有相关资源最后还是选择了数据融合方向,但实际也完整的学习莫凡Python强化学习方向的相关课程,并且最终实现了基于DQN驱动2D仿真中无人机完成自动避障和探索的任务,因此有过对马尔科夫过程、Q-Learning和后续深度强化学习基本知识的理解。 在后续某科研项目中涉及到了需要让智能体学习一个策略实现对步态模式、控制参数基于算力和环境、地形复杂度实现自演化的要求,因此最后还是采用了Q学习+RBF网络拟合的方式实现对连续环境特征输入,映射到输出离散动作组指令的RL模型,算是再次捡起了强化学习的相关内容,下面是近期针对强化学习开展学习的记录,里面并不涉及强化学习算法、模型网络设计等基础神经网络和RL知识,更多是从工程层面实现快速上手应用Isacc仿真环境并实现Sim2Sim迁移的过程,可以快速了解采用强化学习这种控制方法实现系统设计的基础流程,本教程与开源项目参考了很多开源项目,这也是目前学习强化学习的最大好处有越来越多的教程。 为了更好的学习强化学习,整个教程从3D模型构建、URDF导出、ROS校验、isacc训练和Mujoco迁移完成了整个流程的记录,并且采用了Tinymal四足机器人模型为例进行测试,完整的给出了一个全新的机器人系统如何从建模到训练场,让大家快速从不了解Isacc Gym到可以完成Mujoco下的Sim2Sim迁移,具体的内容如下表所示
注:此处原飞书文档包含一个嵌入表格,已省略,详情请查看原文档。
通过学习整个教程,可以快速完成对Isacc Gym的使用并且可以用自己的机器人模型进行测试,当然很多更深层次的细节和RL知识需要更深入的学习,但是起码了解了RL的基本流程并且可以针对很多开源项目进行学习,随着Isacc Lab和Sim的推出,Gym不再做更新维护,未来强化学习的工具链会更加丰富,具身智能系统的开发会变得更加的方便, 当然这也完成了对Tinymal项目整个框架中缺失部分的填充,对于Tinymal相关资料可以关注https://tinymal.cn/: media media media media media
本项目最终实物迁移效果,基本与isacc仿真一致(目前机器人重量较小,因此迁移起来比较容易),另外也将RL算法迁移到小尺寸人形机器人实现了基本的步态控制,本项目基于OmniRobLab机器人开发环境进行验证,采用OmniRobCtrl运动控制软件包进行算法开发,在Tinymal四足机器人与Tinker双足机器人平台上均完成了验证: 20240828-122013.mp4(提取码:d43h) Tinymal四足机器人 bc049b14b193ed8810b80555443b0997.mp4(提取码:d43h) Tinker双足人形机器人 项目软件包: (1)四足机器人步态训练代码: LocomotionWithNP3O-masterV5.zip LocomotionWithNP3O-masterV5.zip(提取码:d43h) (2)Isaccgym倒立摆训练代码: IsaacGymEnvs-main.zip(提取码:d43h) 在训练直接我们推荐可以采用如下的训练平台,该计算平台非常小可以满足移动办公与巡逻的需求,同时也可以布置在机器人上完成模型推理: media 项目 地址 显示屏 https://detail.tmall.com/item.htm?_u=i1klsj89a319&id=770322924802&pisk=g6SU_lmH-kEFvPXV1ixr7v-E15xpc3PbZgOWETXkdBA3ypZo4TWDFJF8pNJlN1e8pH6ka_566097J7nP_66cRe15RQvks1XIAQZpz_WfM_i7vw9o416Jr_sPe0JlE_epNJU1p9KJqSNjao6dpir7prseKADGBKRkKPTn8lWQCSNbcuznI3PUG6O0AwaM3KxkKUYnjRJWFpvlZUXgjCpJEXvoxRyweCmnrexkjdvvUpvlZDcGILvWEvYkZAXMUCAkqDvuQOA9UfsF9_hXne2PaQ9pqJ46JIXH_0mqHp8nD93S40P6deAcf_okCGJe8IXCAsaysdj1bETsFRKGHN1HQnrEMp7G3HvP2-0yaUSpbC54m0pO-6SMzGw-HIjdIiKM5o2VIGCCpGWSEuv1GCXdx3r0HH-HthJOV5nHaNblAeK-t7RRbOjhzg5Swd081g3Zq48HBdRbQR5An7BqpNFOZ43JSEvwGJLoy4LhzdRbQRu-yeeyQIwpk&spm=a1z09.2.0.0.62e42e8d9VSxez&sku_properties=21433%3A8504807 计算训练单元(i9-13900H/4070 8G/32G+4T ) https://item.taobao.com/item.htm?spm=a1z09.2.0.0.62e42e8d9VSxez&id=779228235738&_u=i1klsj891da7&pisk=gv1UsGGHKWFF8Q7VfsArQ2REflApiQrbq_tWrabkRHx3eeNoaa7DPyE8JO8lVGU8JB_k4gS6XbT7puhPbM_cdps5d3YkjGbIO3NpUg7fDgG799ToaG_JEg1Pyb8lrgUpVye1JwdJZoZj4S_dJsP7J-1erCmGWEgHqR9nL57Q5oZbG7ynSQrUcMt0OCNMuEAk-LvnsP8WPeYlqLAMIhLJrDYotPzwyhcnEpAksFYvzeYlqXmgsU8SqUxH-cxMJhxkZQjlSP8WzIjd2mTDKzSyVeduK7vMmwxZZjuv8p0PSYGSNFLHLLTDbFT1_eJecdFpkt1hfafC9dFZsQQ13gWlmlMBxt8VbK6U0XSVvUbyrMPxuhfFz1JdCSmwWObCE6IEzbYdOs9yDdzowLOGGKXcY4UASBYl2KC7DXKhrZCAhIPEDeWGuCSzN0Liel1-QbDyKFLwcPzNDZqRu2BTXgD-edvD7napEYHJKT8wcPzZeYpLzF-bJKC.. 建议搭建可以首先按1.1完成软件环境的安装然后采用最新版本的代码运行执行对步态进行训练,在有一定的实践基础后依据教程进行逐步尝试

阶段1 学习IsaccGymEnv 倒立摆例子

本教程一开始首先还是基于IsaccGym提供的相关例程,安装相关软件与依赖环境,并且开始对基础倒立摆与相关的例程进行学习,对于传统控制学习来说倒立摆是最典型的例子,其从自动控制系统建模和控制都是传统控制课程首选的代表,对于RL学习也一样,下面为修改后的gym例子:
media 在IsaccGymEnvs中提供了非常多的RL例子包括倒立摆、机械臂控制和火柴人,可以快速了解并且直观的学习Isacc仿真环境、Pytorch下的算法开发,下图介绍了Gym训练框架完整的软件架构,包括了环境建立、场景建立、Step更新,前后处理**,基本上我们在更新软件中主要还是围绕后处理初始化等部分进行软件修改:** media

1.1 安装与配置软件开发环境:

参考资料:Anaconda安装时默认python版本改成其他版本的两种方式_python_脚本之家 下面给出对IsaccGym下的整体配置环境,首先需要保证Conda安装完毕,然后需要配置如下的软件环境.bashrc,其中后三个需要修改envs为后面建立虚拟空间的名称,否则在运行中会保存:
之后建立虚拟空间,安装相关软件包:
最后下载软件包,安装isaccgym: isaacgym1.zip(提取码:d43h) alias a1=“conda activate OmniRobCtrl”
最后,为了快速的激活conda空间,原始命令为conda activate OmniRobCtrl,则可以修改.bashrc增加如下的指令快速激活虚拟空间:
注意:Cuda与torch和libtorch(下注配置主要针对运行出错的同学,配置成功可直接跳過) 查看显卡驱动情况和支持的最高CUDA版本,为保证Python和C++版本产生的网络模型一致,最好安装相同的pytorch和lib和Cuda,如果出现其他问题请参考如下的流程:
media
两个版本不一致: 通常,driver api的版本能向下兼容runtime api的版本,即 nvidia-smi 显示的版本大于nvcc —version 的版本通常不会出现大问题。 其实,只要上去Pytorch官网瞄瞄,细心的你应该能够发现在命令中指定CUDA版本时,用的是 cudatoolkit,而 nvcc —version 显示的版本就是通过CUDA Toolkit Installer在安装时决定的,因此,我们应该选择与 nvcc —version 对应的CUDA版本匹配的Pytorch
conda create -n OmniRobCtrl python=3.8.10升级CUDA 12.1+pytorch 2.3: media (1)安装CUDA12.1
修改bashrc:
增加软连接,将安装版本对应到系统搜索的目录:
再次查看与Python脚本一致: media (2)安装cudnn版本。注意,这里按照官方即可 https://developer.nvidia.com/rdp/cudnn-archive#a-collapse805-111 从官网下载执行文件解压,查看软连接后是否存在如下文件夹,没有在usr/local下新建cuda文件夹 media 采用指令吧全部下载文件复制进去:
(3)安装libtorch media 下载后,修改C++文件的cmakelist:
如果替换cuda后cmake出现nvcc查找版本:
则需要采用新cuda文件bin中的nvcc进行替换:
遇到gcc版本问题:
media
sh: 1: cicc: not found错误
python训练找不到nccl:
Linking CUDA executable cmTC_0dd9b错误: /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_0dd9b.dir/link.txt —verbose=1 "" CMakeFiles/cmTC_0dd9b.dir/main.cu.o -o cmTC_0dd9b Error running link command: No such file or directory
cmake过程报错:
但是实际上错误不在Could NOT find CUDA (missing: CUDA_NVCC_EXECUTABLE) (found version “12.1”) 上,如果采用更高版本的cmake(3.25),就会出现更准确的错误信息如下:
在cmakelist中添加set(CMAKE_CUDA_COMPILER “/usr/local/你的cuda版本/bin/nvcc”)

1.2 运行测试(安装正常,跳转这里):

启动train训练脚本,开始对模型进行训练:
通过加载模型,load per-train载入预训练结果:

通过运行例程,首先可以了解train脚本的参数输入: train.py 文件描述
  • device_typethe type of device used for simulation. cuda or cpu.
  • device_idID of the device used for simulation. eg 0 for a single GPU workstation.
  • rl_deviceFull name:id string of the device that the RL framework is using.
headless - True/False depending on whether you want the simulation to run the simulation with a viewer.
  • physics_enginewhich physics engine to use. Must be "physx" or "flex".
  • enva dictionary with environment-specific parameters. Can include anything in here you want depending on the specific parameters, but key ones which you must provide are:
  • numEnvsnumber of environments being simulated in parallel
  • numObservationssize of the observation vector used for each environment.
  • numActionssize of the actions vector.
同时,了解基本的RL框架包括环境参数和强化学习参数: 训练环境包括了环境数量,输入输出维度定义等参数,参数配置env文件yaml为:
强化学习目前一般采用PPO训练方法,其参数yaml为:
同时了解了对于一个新RL工程如何建议并注册在Task参数中,新建任务在:
新任务建立后,同时需要在task目录下新增learning和task对应名称后缀的yaml文件! 了解了项目框架下机器人模型一般放置在asset目录下:
对于一个RL项目整体框架代码流程如下:
原始项目中通过reset_buf标志位来判断哪个环境复位,复位条件一般为到达复位摔倒状态或者满足这次回合训练次数:
因此在post后处理时会实时检测那个reset_buf为1,则对对应环境复位:
另外是一些常规的配置: (1)设置最大训练步骤在PPO.yaml中:
(2)设置训练环境参数如个数、控制范围等,在env的yaml中:

1.3 在项目的学习中了解到Gym API和tensor相关用法:

refresh_dof_state_tensor 此函数将使用物理引擎的最新值填充张量。从这个张量创建的所有视图或切片都将自动更新
举例在倒立摆例子中读取观测:

1.3.1 squeeze()方法语法

其中,参数a是需要操作的数组,axis是要删除的维度。若不指定axis参数,则squeeze()方法会删除所有长度为1的维度,主要功能时降维排列: media

1.3.2 torch.where()常规用法

torch.where(condition, x, y) 根据条件,也就是condiction,返回从x或y中选择的元素的张量(这里会创建一个新的张量,新张量的元素就是从x或y中选的,形状要符合x和y的广播条件)。 Parameters解释如下: 1、condition (bool型张量) :当condition为真,返回x的值,否则返回y的值 2、x (张量或标量):当condition=True时选x的值 2、y (张量或标量):当condition=False时选y的值
media API说明: (API介绍在isaacgym/docs/api/python/gym_py.html这个文件中,用浏览器打开这个文件查看即可。) 1) isaacgym.gymapi.Gym.acquire_actor_root_state_tensor() 检索Actor root states缓冲区,包含位置[0:3], 旋转[3:7], 线速度[7:10], 角速度[10:13] isaacgym.gymapi.Gym.refresh_actor_root_state_tensor() 更新actor root state缓冲区 2) saacgym.gymapi.Gym.acquire_dof_state_tensor() 检索DoF state缓冲区2阿,维度为(num_dofs,2), 每一个dof state包含位置和速度 isaacgym.gymapi.Gym.refresh_dof_state_tensor() 更新DOF state缓冲区 3) isaacgym.gymapi.Gym.acquire_net_contact_force_tensor() 检索net contact forces缓冲区,维度为(num_net_contactes,3), 每个接触力状态包含x,y,z轴的一个值。 isaacgym.gymapi.Gym.refresh_net_contact_force_tensor() 更新net contact forces缓冲区 4) isaacgym.gymapi.Gym.acquire_rigid_body_state_tensor() 检索rigid body states缓冲区,维度为(num_rigid_bodies,13), 每个刚体的状态包含位置[0:3], 旋转[3:7], 线速度[7:10], 角速度[10:13] isaacgym.gymapi.Gym.refresh_rigid_body_state_tensor() 更新rigid body state缓冲区 5) saacgym.gymapi.Gym.acquire_force_sensor_tensor() 检索force sensors缓冲区,维度为(num_force_sensor, 6),每个力传感器状态包含3维力,3维力矩。 isaacgym.gymapi.Gym.refresh_force_sensor_tensor 更新force sensors缓冲区 media 访问张量的内容,可以使用:
强化学习模型复位,在计算奖励时候进行判断采用where进行赋值
在判断某个环境满足为1条件时进行复位:
倒立摆增加控制指令:
在奖励增加新的变量需要定义接口变量类型:
参考isaac gym的例程franka_ cube_ik_osc.py其中,涉及使用函数:
以上带有DOMAIN_SIM一类参数函数是部分查找函数的集合,所以有更多不同名称的调用方法,具体见handbook。 获取index后即可切片读取信息:

阶段2 修改倒立摆例子并学习IsaccGymEnv其他项目

2.1 尝试修改例程

Gym自带的倒立摆例子中只实现了保证倒立摆的竖直并且要求小车动作Action指令最优化,通过训练很快智能体就可以实现对倒立摆的平衡,但在传统控制课程中除了对倒立摆姿态的平衡外还需要对小车位置进行控制,因此需要对RL例子进行修改: media 如上图为典型的一阶小车倒立摆carpole的动力学模型,通过控制小车左右的速度或者扭矩实现对倒立摆姿态的控制,其观测包括了小车的位置、速度,倒立摆的角度和角速度,控制输入为小车的速度或者直线电机的力矩,则控制任务为设计一个最优控制器让倒立摆保持竖直,上述例子在IsaccGym中为原始的carpole例子,其可以训练倒立摆完成竖直和启摆过程。在完成对原始例子的学习后可以进一步进行修改尝试,例如进一步完成对在小车竖直情况下对小车位置的控制,则首先依据之前的内容增加相应的任务carpole_cmd,并在task进行注册,复制修改相应的yaml文件: media 在我们提供的例子里,控制任务增加了新的期望指令,因此需要再观测中增加对应的期望位置的观察维度,并修改对应的观察获取程序:
为了满足控制指令的需求,项目中增加新的控制维度:
media 在代码中,增加小车位置的奖励:
需要注意的是compute_cartpole_reward中增加新接口输入需要再type处注释位置增加对应的类型 在每次复位时重新设定期望位置:
运行脚本,进行训练:
media

2.2 学习Gym可视化和API接口

原始的仿真中并没有期望位置因此非常容易从可视化中(在可视化界面按键v可以停止渲染加速训练过程,按键空格可以暂停)看到倒立摆竖直,但在增加期望位置后我们无法判断小车是否达到了期望位置,因此需要通过可视化的方式在各训练空间中增加一个标志物。由于在建立环境的时候实在gym统一的一个大世界新建了很多小的虚拟环境,因此大家是有一个统一的世界坐标系,通过交互UI可以看到不同虚拟环境的中心原点: media 在creat_env中可以看到可以设置环境空间尺寸和数量来实现批量世界的建立:
由于所有模型都是在同一的世界坐标系下,但是通过定义不同的张量可以确定传感器数据是在root还是dof下:
因此绘制期望位置时候首先需要获取各虚拟空间在世界坐标系下的原点位置,然后再加上相对原点的偏差进行绘制就行:
get_env_origin即获取虚拟空间位置的gym接口,draw_sphere调用了gym绘制接口:

2.3 在该阶段进一步学习torch的函数调用方法:

2.3.1 torch中的clamp方法

clamp用于对tensor按照指定范围进行裁剪,tensor.clamp(min, max)将会将tensor中小于min的取为min,大于max的取为max,而在min和max区间内的保留。
从网络action输出转换Joint控制输入的扭矩:
采用torch空间绘制多个内容:

2.3.2 torch.ones:

返回一个填充了标量值1的张量,shape 与 input 相同 torch.ones_like(input)相当于torch.ones(input)

2.3.3 torch.sum(a, dim=0)求和:


阶段3 学习优秀的开源项目

通过学习GymEnv下的例子,可以基本了解到torch和gym的常规接口,在其例子中还有很多五指手、机械臂抓取和作业的例程,都可以详细学习一下如何通过gym接口获取观察并设计奖励函数: media media 对于腿足式机器人目前主要采用的是RSL实验室开源的LeggedGym强化学习软件包,其针对四足、人形机器人构建了一个统一的训练框架,面向机器人训练需要的地形构建、RD域随机化以及腿足强化奖励、课程设计提供了很多可以参考的例子: media media 目前基于该项目已经实现了非常多真实四足机器人的训练与迁移与云深处、宇树、星动等公司都参与该系统进行开发,目前网上也有非常多的开源项目围绕该基础环境进行二次开发,下面推进几个典型的开源项目:
注:此处原飞书文档包含一个嵌入表格,已省略,详情请查看原文档。

3.1 LocomotionWithNP3O项目学习

通过学习leggedgym例子其基本的内容和一些基本的软件接口如下: 首先是训练环境配置,/configs/tinymal_constraint_him.py,由于自建环境一般继承了LeggedRobotCfg 作为基础类,因此很多其中重名的函数和参数将会覆盖,没有的参数将采用LeggedRobotCfg 原始配置:
注:此处原飞书文档包含一个嵌入表格,已省略,详情请查看原文档。
(1)定义环境数量和观测
(2)依据URDF定义关节角度默认关节角度,一般情况下网络输出会与其进行叠加:
(3)控制随机指令范围:
(4)关节PD控制参数,可以独立定义各关节joint名称对应的PD系数:
(5)域随机化设置,用于迁移:
(6)训练网络部分,可以设置重新载入网络二次训练resume部分:
以四足机器人项目为例这边项目,进行训练:
media

3.2 学习必要torch的函数调用方法:

force sensors are used to indicate contacts with the ground plane on the humanoids’ feet.
sensors_per_env: 每个环境中的传感器数量。 self.num_envs: 环境的总数量。 具体代码解释
  1. sensors_per_env = 2
这行代码定义了每个环境中的传感器数量为2。
  1. self.vec_sensor_tensor = gymtorch.wrap_tensor(sensor_tensor).view(self.num_envs, sensors_per_env * 6)
这行代码可以分为几个步骤来解释: gymtorch.wrap_tensor(sensor_tensor): sensor_tensor是一个原始的传感器数据张量。 gymtorch.wrap_tensor是一个将原始张量包装为PyTorch张量的函数。这是为了兼容OpenAI Gym和PyTorch,以便可以使用PyTorch的操作来处理这些数据。 .view(self.num_envs, sensors_per_env * 6): .view()方法重新调整张量的形状。 self.num_envs是环境的总数量。 sensors_per_env 6表示每个环境中的传感器数据有2 6 = 12个数据点。 这里的6通常表示每个传感器的数据维度,例如:3个轴上的力和3个轴上的力矩(通常在传感器中会测量这些数据)。 通过这个方法,原始的传感器数据张量被重新调整为一个形状为(self.num_envs, sensors_per_env * 6)的张量。这意味着每个环境都有一个包含12个数据点的行,共有self.num_envs行。 建立足端接触传感器:
在建立环境时候新建多个对象:
检索ID号:

阶段4 尝试移植自己的机器人模型

在熟悉了四足机器人和人形开源项目后要完整的上手isacc gym需要走过一个完整的流程,即从模型建模、导出、移植、训练到最终的迁移部署,这样才能保证对RL的整个流程进行全盘的理解,当然在这个阶段遇到的问题也是最多的,基本的流程如下图所示: media

4.1 SW建模和导出(关键技术):

首先采用三维建模工具完成机器人模型的建模,采用SW安装URDF导出插件,完成对模型的坐标系定义,为了降低算法移植的难度,我们采取的是参考开源项目中go2的坐标系命名和定义规则,这样在后续导入isacc中会更加简单,通过ros完成对机器人模型的查看:
media 通过在代码中打印相关名称dof name可以了解到其在isacc中的顺序,这关系到后续控制指令顺序、反馈角度q顺序以及xml文件中执行器顺序:
依据上述名称完成在SW增加轴、点、坐标系辅助定义,需要注意的是在建立装配体时,Y轴是向上的,这里可以看下最终模型的阴影来确定机器人组装的是否朝上: media 进一步依据关节定义和腿号依次定义 点-基准轴-坐标系,命名方式点P_,轴A_,坐标系C_,同时注意到装配体状态下关节状态在导出时候即URDF的零位 media 另外,设置每个坐标系时为了避免导出时候出现模型反转,建议都按右手坐标系的方向去定义,不依据机械的变化改变,如下面所示的双足模型导出如下: media 这依据网络教程完成对URDF的导出,注意在导出后会出现整个模型的原点original_global,此时需要手工重新选定其定义在机器人质心,否则会导致最终的模型存在坐标系偏差: media 设置模型材质,如果类似电机简化质量的Step文件可以主动增加一个圆柱体设置相应材质保证质量接近,但是要在后续URDF配置时选择该质量配重 media 在导出URDF中最后需要注意的就是转动惯量的配置,首先需要对各组件设置好其对应的材质,之后通过选中各组件查看质量属性的方式得到参数。 注意转动惯量非对角线上的值要取相反数(正的变负,负的变正)同时在替换URDF文件参数时所有Link都需要替换不能只替换好像比较重的否则会造成isacc训练奖励爆炸 media 在URDF export界面时打开工具-评估-质量属性检查可以自动按之前配置的组合选择link,最终坐标值选择该link的起始坐标,上述参数手动填入到导出的URDF中,对模型进行检测**(可选)**:
media 使用Rviz查看urdf是否正确(无法显示模型不影响后续导出):
media media 通过拖动条查看关节旋转方向,并在URDF中进行修改,为了满足isacc使用还需要对如下几个内容进行修改: (1)修改URDF中STL文件目录为相对目录../meshes:
(2)修改foot等fix关节保证能被检测为刚体,否则isacc运行无法检测到foot_names名称(适用于四足机器人、点接触机器人):
(3)修正碰撞体简化mesh文件,采用正方体,圆柱体简化碰撞,特别是点接触足端采用球体碰撞 总之对于RL来说URDF导出是否正确非常关键,具体导出惯量等问题可以参考: URDF导出惯量不正确,正确导出方法: 检查你的link是否是装配体,是的话,可以利用SolidWorks自己的质量工具得到惯性量,然后自己填到URDF里面。检查你的link是否是装配体,是的话,可以利用SolidWorks自己的质量工具得到惯性量,然后自己填到urdf里面。 操作流程:选中你的link部件后,选择 工具–》评估–》质量属性,就可以得到惯性量了。要注意坐标和单位,urdf中用的是千克平方米,而质量属性中默认显示的是克平方毫米,而1克每平方毫米=1e-9千克每平方。不过你可以通过设置“质量属性”中的选项来选定单位: media 首先,在Solidworks左上角的工具栏中选择**“评估”→“质量属性”,即可打开“质量属性”属性框,之后在URDF导出工具中在Link界面选择对应的结构体名称,在质量属性中进行重算:** media 备注在采用真实惯量后训练难度会有变化,需要设置更合适的训练方案: media URDF模型需要满足如下的设计需求: media

4.2 Rviz下对导出模型的惯量进行检查:

首先,复制URDF⽂件⾄ROS的urdf_tutorial的⽂件夹中: (1)*.urdf⽂件⾄/opt/ros/XX/share/urdf_tutorial/urdf/中 (2)与urdf关联的mesh⽂件放到/opt/ros/XX/share/urdf_tutorial/meshes/中
media 开启惯量显⽰(对ROS 版本有要求):在rviz左侧的菜单树中点选RobotModel-Mass Properties-Inertia,机器⼈模 型中出现红⾊⽅块,即为等效惯量显⽰。 可以点选菜单树中的TF选定去掉,不显⽰坐标轴。 可以在RobotModel-Links中点选不同的link,以显⽰特定的link :
media

4.3 将机器人模型部署在leggedgym框架进行训练:

在导出URDF后就可以开始替换isacc中代码了,首先还是依据legged gym框架完成对新环境与任务的注册,在train脚本中引用对应新的环境和训练类: media 修改配置文件asset中相关内容:
3D文件模型显示出现错误需要设置:
另外依据机器人模型修改PD参数,默认角度,随机化参数,控制指令范围等,之后进行测试和debug: conda activate OmniRobCtrl 启动:
在仿真界面按键V可以暂停和启动仿真 headless=:设置为headless=True可禁用模拟绘制(—headless) 重复训练config文件: resume = True resume_path = ”目录” 输出的刚体信息,仿真画面出现则模型导入成功:
media 则依据机器人尺寸对奖励函数进行调整尝试训练,进一步可以针对性进行奖励函数和约束函数的优化。

4.4 训练奖励优化与学习:

(1)常用回合结束判断,可以通过机器人机体速度、姿态判断是否摔倒,并进行环境复位:
(2)常用随机控制指令,在环境复位中随机设置控制指令,可以增加摆动高度、机体姿态、机体高度、步态模式等新的控制指令,当然需要再观测中同步更新:
(3)RD域随机化处理,对机器人进行扰动和随机误差建模干扰,提高网络的鲁棒性:
(4)主动推动机器人,通过向机体设置速度进行模拟外力推动:
(5)机器人默认控制中主要设置为角度控制,在训练脚本command有专用模式会增加航向控制,即构建了一个P控制器结合航向角误差计算输入网络的转向速度指令:
(6)关节控制模式: 在配置文件中可以设置关节控制模式和参数:
当然也可以通过独立命名的方式设置对应关节的PD参数:

4.5 训练模型保存:

在完成强化学习训练后,需要对模型进行测试,在simple_play文件中可以设置对应网络加载:
设置默认的启动任务:
为了后续使用需要将之前训练中保存的参数载入网络中,并进一步将整个网络模型进行保存:
当然也可以裁剪后采用torch.jit保存和加载模型:
保存jit模型时会对网络保存的内容进行处理,如下只保存了actor部分的网络:
在测试网络时可以增加遥控器或者随机指令的方式来进行移动测试:
另外也可以独立设置关节角度并打印相关观测进行接口校验:
训练网络验证结果如下6000回合在4060 GPU上训练40分钟 media

4.6 增加地形训练课程:

通过修改参数实现增加地形进行训练:
media media 在play中需要修改不同难度地形terrain.py文件中修改,play时设置,训练时注释这句话
最后在sim2sim时增加terrain参数:
media media

4.7 学习必要torch的函数调用方法:

4.7.1 Python获取数据的顺序:

我们假设有一个数组名叫 array 那么可以用array[0:3]访问前三个元素 可以用左开右闭来理解

4.7.2 使用wandb进行数据记录,新建project工程后可以查看到对应的API:

media
则在每次启动时选择已有账户并复制API(不会显示),回车后启动训练则会将过程中的log数据上传。 登录网站:wandb.ai 注册用户,训练时候需要保证能联网,则数据可以上传,通过刷新网络了解最新的训练结果: media media

4.8 启发式训练方法+训练方案探讨

4.8.1 训练问题

在重新导出URDF模型后出现原始训练方法无法实现机器人获取持续奖励,最大问题是机器人不抬腿迈步,在之前SW直接导出的模型中由于其惯量和质量小,因此机器人可以很快发现移动迈腿会获取到更多奖励,但重新导出训练中却出现平台、甚至reward出现回落: media 同样修正奖励发现几个问题: (1)tracking_sigma值过小(0.15)会导致机器人获取一段奖励后出现reward快速跌落机器人在空中不断复位; (2)tracking_sigma值过大(0.25)则会导致机器人不会迈腿,只会站在原地并获取奖励,最终造成如上图所示的平台

4.8.2 解决思路

(1)首先想到的是采用简单粗暴的方式,直接增大线速度与角速度奖励,但并不能保证很好启发踏步(失败): media (2)优化训练方法,采用课程的方式,在平台处机器人已经学会站立,则是否可以在训练回合保存的网络处作为预训练模型,重新设计课程和奖励在该网络参数基础上将tracking_sigma调小让其可以探索出踏步并继续训练(失败 media (3)增加更多启发式的课程和奖励设置,目前驱动摆动的主要是速度奖励和对腾空高度的惩罚,前者如果机器人不移动则无法获取到,因此并不能主动引导机器人产生踏步行为,后者只设置了腿与期望高度重合时的奖励或惩罚,因此如果腿就不摆动,则此时产生的奖励不变,因此也很难产生启发式的奖励,因此需要增加类似相序或参考摆动轨迹、关节运动的奖励:

阶段5 迁移部署对网络进行测试

在完成在isacc下训练后需要进行迁移,模型迁移最核心的是在控制器端搭建运行神经网络的框架并将其所需要的反馈数据送入到网络中,这里参考Human-Gym中通过mujoco仿真器实现sim2sim的迁移,当然面向实物迁移还需搭建C++下的迁移软件,因此这里可以形成如下几种典型的迁移框架: media (1)采用mujoco python/C++仿真框架: 网络输入输出嵌入到mujoco仿真接口中,直接读取和驱动仿真,偏向于半实物迁移; (2)采用mujoco C++仿真,通过LCM或ROS接口实现迁移 异步运行mujoco仿真,通过LCM和C++ pytorch接口独立运行网络,实现多线程并行,偏向与实物迁移;

5.1 URDF转mujoco XMl文件

下面介绍面向半实物迁移的方法,首先完成URDF向xml文件的转换,参考Mujoco教程1:安装与urdf转xml 在urdf中添加以下段,同时mesh需要指定到机器人目录,字段嵌入到robot下:
转换模型,cd进入mujoco bin可执行文件夹下: 第一项是urdf路径,第二项是期望xml所在路径./compile /path/to/model.urdf /path/to/model.xml media
可在asset标签和worldbody标签中添加一些背景材料和光源,需要改造下原始xml文件,增加浮动基座,并改成xml嵌套。

5.2修改xml文件:

采用Aloha下的xml环境构建形式,通过sence、world和机器人实现快速的替换和二次开发,对导出的机器人模型进行修改:
(1)world.xml:
(2)scene.xml :
(3)dependencies.xml:
输入一下指令打开仿真界面,要求输入xml路径,对模型进行测试,可以通过render下的UI查看机器人惯量是否正确:
media media 通过删除机器人模型中浮动基座可以实现机器人模型悬空测试关节控制:

5.3增加电机执行器:

最后在world文件中依据关节增加控制器,可以采用motor,也可以独立设置速度和位置控制器,需要注意的是机器人模型和执行器模型命名顺序需要一致,并且保证与isacc中打印名字的顺序一致joint:
通过运行xml文件,确认关节角度顺序: media media 最后,在机器人模型中绑定site名称,在world中增加对应的关节位置、速度和扭矩传感器、IMU传感器:
最后,sim2sim
从仿真器中读取观察数据并依据网络定义输入,需要注意的是关节角度输入采用的是实际反馈-默认角度:
最后依据网络结构输入为obs[45],和obs_lis[10*45],需要将其压入一个1维度的数组,但是由于我们存储的网络包括了Teacher部分,因此中间还有其他不可观测的状态,需要人为赋值:
media 最终,网络进行输出:
通过,在线工具,查看导出模型的结构https://netron.app/: media 对于Human-gym其导出的是JIT模型,目前还有问题,导出模型需要运行play文件:
  • Please note: Before initiating the sim-to-sim process, ensure that you run **play.py** to export a JIT policy.
  • Mujoco-based Sim2Sim Deployment: Utilize Mujoco for executing simulation-to-simulation (sim2sim) deployments with the command below:
需要再play中导出为JIT模型:
网络部署与迁移结果: media media

5.4仿真迁移:

要实现实物迁移首先需要构建C++下的网络部署框架,采用pytorch或openvino或TVM等神经网络部署框架搭建程序:

5.4.1 LCM消息中间件

通过LCM库完成在跨平台间的数据接口封装和发送,在完成LCM安装后定义lcm消息:
通过,指令生成头文件并包含在项目中: media
面向实物迁移需要搭建C++版本的底层,通过LCM或共享内存的方式操作机器人底层SDK接口,具体可以参考原始开源项目:

5.4.2 迁移测试软件基本框架

在sim2sim.py中构建了一个基于Python接口的仿真迁移案例,为了面向实物样机部署需要构建C++版本的网络部署代码,因此需要采用Mujoco获取仿真数据,单独运行一个网络推理程序,二者采用LCM进行数据交互,由于机器人端程序启动后往往不会重启,因此其设置为LCM服务器,这里我们采用sim2sim的函数进行改造,增加LCM程序: media
上面的代码为修改后的仿真接口,其为RL网络部署提供了一个基于LCM接口的通用框架,发送LCM_OBS:
接收LCM_ACTION:
迁移测试结果如下: media media

5.4.3 Libpytroch迁移

最直接的迁移方式是直接采用pt模型和libpytorch(版本与训练脚本一致),构建C++下的部署代码通过LCM获取观测发送输出,在sim2sim_lcm中提供了一个libpytorch的部署代码,首先需要完成LCM库的编译,并提供cuda等其他依赖: (1)Cuda GPU版本 采用JIT方式导出模型后,载入:
(2)CPU版本 在载入模型时会判断是否有cuda:
(3) LCM通讯版本 通过LCM可以构建标准的通讯接口,因此采用Python下Mujoco仿真接口通过LCM代替传输obs和action,单独开发C++的程序满足后续在样机部署的需求,测试首先启动仿真:
然后再sim2sim_lcm中build文件夹中运行,订阅观测并计算网络输出
(4)UDP通讯版本 LCM底层也是采用UDP通讯,但是由于在嵌入式编译中需要进行交叉编译如面向JetsonNano等ARM核心的处理器,因此也可以直接采用UDP的方式实现通讯,测试首先启动仿真:
然后再sim2sim_lcm中build文件夹中运行,订阅观测并计算网络输出

5.4.3.1 LLVM安装(用于编译TVM)

5.4.3.2 TVM安装

安装TVM Python API

5.4.3.3 ONNX安装

5.4.3.4 PyTorch转ONNX

向ONNX导出器torch.onx.dynamo_export() 提供模型的实例及其输入,导出器将返回torch.onnx的实例,再使用torch.onnx.ONNXProgram.save()保存xx.onnx模型。 安装依赖
示例:
dynamo_export 函数将生成一个 onnx实例onnx_programonnx_program.save将实例保存为onnx格式。

5.4.3.5 ONNX可视化

打开 https://netron.app/ 打开生成的onnx文件,如下图所示,看到MLP每层结构: media

5.4.3.6 ONNX转TVM

安装依赖
ONNX转TVM示例如下: 加载转换后的onnx模型—>加载图像—>Relay 编译模型—>在 TVM 上执行

5.5 实物样机迁移

在完成仿真迁移验证和接口开发后,可以直接套用LCM库或UDP包进行测试与快速迁移。样机迁移最重要的首先是按照网络定义确定好输入数据的单位和坐标极性,关节的零点位置与坐标系定义,依据URDF目前的Obs观察定义如下。对于关节角度首先其角速度与角度转向一致,可以通过Rviz查看URDF,另外需要明确鸡头方向和腿号顺序:
项目 定义 示意图 关节零位 四足机器人关节以全竖直和水平状态为0位置,但由于Tinymal本身小腿是异构因此0位以足端位置竖直为参考 media 腿号顺序 依据URDF定义模型腿号顺序为FL FR RL RR其对应数组04与输入obs中的q顺序一致 侧展定义 从机器人后端看,侧展满足右手定义为+时顺时针偏差 media 大腿定义 前后腿对称,从左侧看大腿为+,向内收腿 media 小腿定义 前后腿对称,从左侧看小腿为+,抬腿 media IMU定义 采用RPY对应01,为Rad,满足右手定义 俯仰+低头,横滚-右倾,航向+逆时针,角速度与其一致 CMD定义 0为VX 1为VY 2为Ryaw 标准单位

5.5.1 UDP部署测试:

为了实现快速的RL控制这里推荐在完成学习后优先采用UDP进行部署测试,验证模型具有基本功能后,再实现在边端模型的转换和部署,通过UDP直接将指令发送到机器人端,因此系统连线如下图所示(目前采用的是4060的训练显卡,1024个环境下每次迭代时间在1.1s左右,后续也将推出专用RL套件帮助配置好硬件,实现到手即练习,到手即部署): media 在机器人端我们安装了路由器使用时将RL训练服务器连接到路由器并保证与Odroid控制器网络联调。 在机器人控制程序启动后,在RL服务器端启动udp_publish读取机器人端的状态反馈发送网络推理结果驱动机器人进行步态机动,由于需要保证网络按训练时的设置进行推理,在RL训练脚本中默认的仿真时间为5ms:
在训练时网络推理的次数由下面的参数确认decimation :
因此网络迭代推理的时间为decimation *dt =20ms也就是50Hz,因此在软件中机器人端建立了服务器,并设置结构体如下:
其中线程以50Hz将trigger设置为1并发送状态反馈,推理测代码为客户端在接收到数据后进行推理计算并反馈action指令从而实现50Hz的推理,当然里面是存在通讯延时等问题,也可以验证网络的泛化能力。另外,為了加快部署可以單獨採購一個JetsonNano運行上述軟件,並通過UDP的方式實現數據傳輸,JetsonNano的環境配置如下:
本教程参考了https://blog.csdn.net/qq_41451125/article/details/116262611这个帖子。
  1. 安装miniconda, 在linux版本里面选择Miniconda3 Linux-aarch64 64-bit版本,创建虚拟环境(python=3.6)。直接创建可能提示当前渠道找不到python3.6*,这时可以修改channel
conda config —add channels conda-forge
  1. 下载jetson nano对应的torch版本 https://forums.developer.nvidia.com/t/pytorch-for-jetson/72048 (应该是1.10版本),在新创建的环境下,用pip安装。
  2. 进入python,import torch看看是否会出错。可能会报“非法指令(核心已转储)”的错误,将 export OPENBLAS_CORETYPE=ARMV8 添加到~/.bashrc中的环境变量即可。
  3. 在新环境下安装cmake。
conda install -c anaconda cmake
  1. 修改cmakelist.txt文件,修改CUDA和torch库地址,添加cuBLAS库地址。
media
  1. 编译sim2sim_lcm文件夹下面的内容,注意编译前需要修改文件中的model_jitt.pt位置,并且运行./udp_publisher。
  2. 设置SSH及VNC远程连接。具体可参考这篇帖子:https://blog.csdn.net/yangyu0515/article/details/133922022#:~:text=%E7%82%B9%E5%87%BBadd%EF%BC%8C%E5%9C%A8%E6%96%B0,add%E7%A1%AE%E8%AE%A4%E6%B7%BB%E5%8A%A0%E3%80%82

5.5.2 LCM部署测试:

通过UDP发送由于需要主动触发同时由于UDP的通讯机制会导致丢包等问题,因此推荐采用LCM的方式来实现。在确定上述坐标系和obs定义后,首先需要参考仿真迁移C++版本在机器人控制软件中增加LCM接口和对应步态,并调整参数,比较推荐的是通过位置闭环或传统控制实现机器人站立之后通过步态切换的方式进入单独步态采用LCM的输入作为控制输出,LCM的结构体记得如下:
(1)LCM交叉编译 为了实现在嵌入式主控的部署,对于ARM内核如JetsonNano需要完成在嵌入式端对软件进行交叉编译,这也相比UDP直接通讯来说比较麻烦的一个问题:
采用工具链进行交叉编译:

(2)测试验证 在C++代码部分主要完成obs坐标系对应与输出角度的映射,需要依据机器人自身坐标系定义对角度进行交换,另外在输出时网络传输的是action输出需要进一步乘以action_scale并加上default_joint才是最终的关节期望角度值。 将服务器网线接入路由器,设置主控IP端口为10000,启动机器人步态控制软件,在站立后再启动网络udp_publish之后,按键X进入RL模式机器人采用网络数据进行步态控制: media 最终,模型迁移效果如下,后续可以将网络模型固化在程序中实现更好的实时性控制: 飞书20240828-121626.mp4(提取码:d43h)

5.5.3 TVM部署测试:

在模型测试无误后我们期望能够实现的是机器人完全脱离服务器独立进行运行,这样我们才能去户外进行更多的测试。通过TVM将模型进行转换采用CPU进行计算,最终测试在Odroid上模型推理需要2ms可以滿足實時性需求,最後總結幾點遷移中的關鍵問題: (1)保證穩定的網絡推理調用周期; (2)保證底層的實時性; (3)保證於仿真一致的參數設置; 采用TVM可以完成模型在OdroidC4和嵌入式处理器上的部署,通过CPU进行计算,同时可以完成快速的模型切换,这里我们提供一个测试脚本,首先完成模型转换工具的安装:
之后可以将jit模型采用如下脚本进行转换:
得到arm和x86架构下的TVM模型,最后将上述模型拷贝到机器人文件下Model文件夹,通过状态机进行调用,下面给出C++下的TVM模型调用方法(下下列程序与UDP版本的代码逻辑一致):

阶段6 面向人形机器人RL的介绍

通过上面的教程我们可以将训练框架转向人形机器人平台,这里给出了一个示例后续我们将推出人形机器人专用的教程从MPC开始介绍如何控制人形机器人并最终采用上述RL框架进行部署。 这里采用的是Tinker桌面级开源双足机器人平台为例,Tinker是我设计模仿迪士尼的一个小型机器人,其基本模拟了迪士尼的机器人结构,后续将作为一个开源项目发布在HuggingFace上让所有人都可以测试和部署RL,这边给出一个基础的例子,感兴趣的同学可以自行修改,同时我们也将适配国内外主流的人形机器人框架如星动的PPO,AMP或则跑跳越障和动作模仿的框架,建立一个人形机器人开发者社区,目前Tinker整机组装成本在1.5W以内是一个非常适合快速上手学习的强化学习开发平台: media media media 首先还是导出URDF,并通过rviz审查坐标系定义与角度,主要是增加关节上下限以及角速度和最大扭矩,Tinker的URDF和XML文件如下: tinker.zip(提取码:d43h)
media media 确认关节顺序和限制后,修改训练程序,新建新的配置脚本,依次修改: (1)观测与动作:
(2)修改原始文件中四足自由度配置,采用2个足端feet_names与URDF中的link名称一致,这样才可以安装足端传感器:
另外,由于腿数量减少还需要再训练脚本中修改相关涉及到腿数量变化的张量初始化部分,最后就是reward中相关关节索引的部分,以hip_pos为例其约束了侧展在移动中不要偏差太大因此需要修改为:

阶段7 总结与遗留的问题

通过上述教程,采用自己的机器人模型走过RL过程,增加了对RL全盘技术的了解,里面有很多细节的问题还没有考虑,但是基本掌握了RL的流程,下一步需要深度学习神经网络、PPO、Isacc、TVM等工具链,并且完成面向实物的部署验证,对于本阶段主要的问题如下: (1)URDF模型导出如何保障是准确的惯量 (2)网络模型改变需要调整迁移部署的结构 (3)增加不同和更复杂的课程设计,地形设计 (4)在训练和推理中增加更多的可视化功能,方便调试 上述教程更多是自己一个学习的过程,也有很多B站同学反馈不完善不合理,但是我觉得相比很多其他动辄上一两百的课程,只是拿出别人论文或者CSDN的帖子介绍一遍把官方源码运行一遍的教程,本文确实能帮助大家走过从传统控制向RL迁移最难的一个环节。 另外,欢迎关注后续即将推出的人形机器人相关课程!

附录8

20250302 V1.1版本软件更新与说明:

全面更新了代码逻辑,将Tinymal、Tinker、Taitan几个不同类型的机器人进行了集成,并可以在头文件中进行快速的配置,更新版本代码如下: LocomotionWithNP3O-masteroldx0301.zip(提取码:d43h) 在新版本中代码更新首先在global_config.py中设置机器人的训练对象与训练好在play文件采用的模型pt文件。
(1)版本新增机器人Taitan Taita采用了Tinker的下肢构型设计,增加了3自由度上肢和1自由度腰部,其更加满足完整人形机器人的自由度和构型配置,后续可以进一步部署模仿学习AMP、动作重映射等不同的算法,满足舞蹈和拟人动作的开发需求: media media 同时,配套其对应的mujoco下的推理部署脚本sim2sim_taitan.py:
media media (2)Tinker软件支持行走与站立的独立训练: 目前代码中新增的站立和行走的2策略方案: media 使用时将stand或tort对应的配置文件覆盖原始配置,同时训练奖励函数文件也设置,后续版本中进一步更新一键切换的逻辑: media 训练演示,下一版本Tinker将更新支持点足和轮足模式的训练: media 如果遇到问题可以微信联系反馈:694373466 If you encounter any problems, please contact us on WeChat at 694373466