强化学习仿真器Raisim的安装,配置,与初步使用

写在前面 – 最近入坑了强化学习,看了一些基础理论后觉得需要实操一下,于是便研究了一下Raisim这个仿真器。这个仿真器使用的人较少,网上资料也不多,所以在这里记录一下,以便后续查阅。不过说实话,新入强化学习的坑还是建议从OpenAI的gym(gymnasium)看起,毕竟资料多,而且也有很多成熟的算法可以直接使用。不像Raisim是一个单纯的仿真器,gym是一个完整的强化学习框架,可以直接使用,以及配合”stable baseline3”使用可以很快速的将demo跑起来。不过Raisim的优点也很明显,就是仿真速度快,而且可以直接使用C++进行编程,并利用OpenMP并行加速。所以在一些对速度要求较高的场景下,Raisim还是很有优势的。

本文主要介绍了Raisim仿真器的安装,配置,并简要介绍API,以及如何使用Raisim仿真器来进行强化学习仿真环境的搭建。本文主要参考了Raisim官方文档,以及Raisim的github仓库中的一些例子。部分内容使用AI辅助生成。

Raisim简介和安装

Raisim是由ETH Zurich的Robotics and Perception Group开发的一个开源的跨平台物理仿真器,主要用于机器人的仿真。该仿真器的主要特点是仿真速度快,而且可以直接使用C++进行编程,并利用OpenMP并行加速。该仿真器使用CPU进行仿真,官方地址为:https://raisim.com/

该仿真器的安装较为简单,基本上只需要下载源码,然后编译即可。该仿真器在分发的时候直接分发的二进制文件,因此编译的过程基本就是在编译demo,以及一些测试用例。安装过程遵循官方文档即可,所需依赖包括eigen和cmake,Windows平台使用vs2022编译实测通过,但由于gym对Windows的支持不太好,因此建议使用Linux平台进行开发,这里最终选择了WSL2下的Ubuntu22.04开发。在官方的安装教程中提到了需要设置"WORKSPACE""LOCAL_INSTALL"环境变量,但是实际测试发现这些环境变量不需要设置,直接安装即可。Linux平台执行make install命令后会将raisim的头文件和库文件,以及cmake文件安装到/usr/local文件夹下,这样后续使用就无需使用--CMAKE_PREFIX_PATH指定路径了。

Raisim目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Name
----
cmake # cmake文件
DEVELOPERS_ONLY
docs # 文档
examples # 例子
raisim # raisim库二进制文件和头文件
raisimGymTorch # raisimGymTorch库和实例,用于和gym,以及pytorch配合使用
raisimMatlab
raisimPy # raisim的python接口
raisimUnity # 基于unity3D的仿真器
raisimUnityOpengl # 基于unity3D的仿真器,使用opengl渲染(linux下使用)
rsc # 资源文件,主要是例子里的各种模型文件
thirdParty # 第三方库,包括了Eigen和pybind11(共raisimGymTorch使用)
CMakeLists.txt
COPYING
LICENSE.md
package.xml
README.md

Raisim激活

激活部分建议参阅官方文档的激活章节https://raisim.com/sections/License.html, 由于raisim使用了Google Doc来填写申请,因此可能需要一些神奇工具才能打开网页。注意申请学术账户可以使用自己的google账户来申请,但是后续需要填写学校邮箱,激活码将发给学校邮箱内。学术账户最多可以申请10个,应该够用了。

将通过电子邮件收到的激活密钥重命名为 activation.raisim。将该文件保存在 <YOUR-HOME-DIR>/.raisim/ 中。在 Linux 和 Mac 中,这是/home/<YOUR-USERNAME>/.raisim/。在 Windows 中,这是 C/Users/<YOUR-USERNAME>/.raisim/(您可能不使用 C 作为主目录)。

Raisim的Visualizers

Raisim目前包含3个Visualizers,分别是raisimUnity,RaisimUnreal,和RaisimOgre。

  • 如果你只在Linux上工作,并且你想自定义可视化工具 - RaisimOgre。
  • 如果您想要一个适用于所有操作系统的简单解决方案 - RaisimUnity。
  • 如果你只有一个集成的GPU,并且你在Linux上工作 - RaisimUnityOpenGL。
  • 如果您想要最通用的解决方案,如果您想为出版物提供良好的图形,或者如果您在强化学习项目中使用视觉数据 – RaisimUnreal。

本文测试后认为raisimUnity效果最好,因此本文主要介绍raisimUnity的使用。RaisimUnity安装在raisimUnity文件夹下,可以直接打开使用。

在仿真器运行后(后续讲解如何使用Raisim::Server类建立服务端)点击连接就可以查看仿真了,默认端口号是8080,支持连接到远程仿真器。仿真时可以使用键盘QWEASD按钮和鼠标控制视角。下面总结一下仿真过程中会遇到的一些问题。

Visualizers遇到的坑

  • 首先遇到的坑是模型资源加载失败,这个问题有时候会出现有时候又不会出现,坑了我很久,尝试过修改模型里的资源文件为绝对路径等方法,但是都没有解决。最后发现在RaisimUnity中可以指定模型路径,只需要在这里面添加模型的文件夹就可以解决这个问题了。 该问题在访问远程仿真器时必然会出现,因此需要注意。

  • 网络防火墙问题,如果你的电脑上有防火墙,那么需要将raisimUnity添加到防火墙的白名单中,否则会导致无法连接到远程仿真器,在Windows上列入白名单后仍可能会出现问题,建议重启或者关闭防火墙后使用。

  • wslg问题,如果使用的是wsl运行仿真器,那么请不要尝试在wslg中运行RaisimUnity,wslg的图形对3D类应用程序支持欠佳(包括ros的rviz也是)(关闭wslg的缩放会缓解该问题,wslg目前尚不支持vulkan API, 对OpenGL支持还行),会导致RaisimUnity无法正常运行。建议还是在Windows上运行Visualizers,将wsl视为远端服务器。

Raisim的API

Raisim的API文档可以在https://raisim.com/查看,这里简单介绍一下Raisim的API。

World类

World类是Raisim仿真器的核心类,所有的仿真都是在World类中进行的。所有在同一个World对象下的物体支持碰撞检查。World类可以使用XML文件来初始化,也可以使用代码来初始化。World类也可以使用MJCF(MuJoCo格式)来初始化,但是实际测试效果不好,不建议使用。 可以将Objects类等注册到World类中来仿真物体的运动和设置摩擦力,弹性形变等属性。

World类中使用integrate()方法来完成一个时间片的更新。

integrate the world It is equivalent to call integrate1(); integrate2();.
integrate1() performs 1) deletion contacts from previous time step 2) collision detection 3) register contacts to each body 4) calls “preContactSolverUpdate1()” of each object.
integrate2() performs 1) calls “preContactSolverUpdate2()” of each body 2) run collision solver 3) calls “integrate” method of each object.

Object类

有三种可用的类型。

  • DYNAMICS:可以有速度,质量有限(如待仿真的机器人)。
  • KINEMATIC:可以有速度,有无限的质量(例如,传送带)。
  • STATIC:不能有速度,有无限的质量(例如,墙壁)。
    这些物体可以指定为SingleBodyObject或者ArticulatedSystem。前者表示一个单一的物体如球,立方体等,而后者是一个带有铰接的系统,可以从URDF文件读取。可以进行逆向运动学解算或者使用PD控制器控制,具体请参阅API手册。

材质系统

在RaiSim中,所有材料属性都与材料对相关联。目前,RaiSim中使用了五种材料属性。

  • Coefficient of friction ($\mu\ge 0$): This defines how much friction is applied between the two materials.
  • Coefficient of restitution ($c_r\ge 0$): How bouncy the material pair is.
  • Restitution Threshold ($r_{th}\ge 0$): If the impact velocity is smaller than this number, objects do not bounce off.
  • Coefficient of static friction ($\mu_{s}\ge \mu$): If specified, it defines how much friction is applied when the relative velocity between the contact points is very small. By default, it is the same as the coefficient of friction.
  • Velocity threshold for static friction ($v_s \ge 0$): Must be specified if the coefficient of static friction is specified. If the relative velocity is bigger than this value, than static friction is not used. Otherwise, the effective coefficient of friction is interpolated between the two coefficients.

Server类

使用Raisim::Server类可以创立服务器供Visualizers监听。使用inline explicit RaisimServer(World *world)方法将World类绑定到server上,之后使用inline explicit RaisimServer(World*world)方法即可开始监听。注意Server与Visualizers的通信和实际仿真过程发生在不同的线程上,因此需要一些锁来进行线程同步

例如在更新World的过程中使用Server类的lockVisualizationServerMutex(),unlockVisualizationServerMutex()来加锁防止在更新World时读取数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//节选自 examples/server/balls.cpp
for (int i = 0;; i++) {
RS_TIMED_LOOP(int(world.getTimeStep()*1e6))
server.lockVisualizationServerMutex(); //加锁
if (i % interval == 0 && j < numBalls) {
auto* ball = world.addSphere(0.1, 1.0);
ball->setPosition(0, -2, 0.8);
ball->setVelocity(0, 10, 0, 0, 0, 0);
ball->setAppearance("red");
j++;
}
server.applyInteractionForce(); //更新交互力,这句话不能删除,否则会出问题
world.integrate(); //更新World
server.unlockVisualizationServerMutex();
}

或者使用integrateWorldThreadSafe()方法来更新World,该方法会自动加锁。

1
2
3
4
5
6
7
8
9
10
11
12
//节选自 examples/server/meshes.cpp
while (1) {
RS_TIMED_LOOP(int(world.getTimeStep()*1e6))
server.integrateWorldThreadSafe();
//相当于执行如下代码
/*
server.lockVisualizationServerMutex();
server.applyInteractionForce();
world.integrate();
server.unlockVisualizationServerMutex();
*/
}

结语

本文初步介绍了Raisim的安装,配置,以及API,以及如何使用Raisim仿真器来进行强化学习仿真环境的搭建。Raisim的API文档可以在https://raisim.com/查看,本文简单介绍一下Raisim的API,本文还介绍了raisimUnity的使用。在下一篇文章中,将介绍如何使用RaisimGymTorch配合stable_baseline3, gymnasium(Gym), Pytorch等来搭建强化学习仿真环境。


EOF