入门机器人强化学习的一些坑:模拟环境篇

入门机器人强化学习的一些坑:模拟环境篇

2021.10.20 更新:好消息,DeepMind把Mujoco买了准备开源!Github: deepmind/mujoco。虽然好像花了些时间做了无用功,搞了一个Pybullet的环境,但是过程学到了不少东西,也算是经验吧哈哈。不行了,我感觉还是Mujoco香,坐等开源公告!

2021.01.13 更正:经朋友提醒,moveit!是有提供Python API的,只要熟悉了ROS的通讯框架,用它来planning不会很难。不过,由于Gazebo离不开ROS和GUI,所以效率还是一般。从易用性来说还是比pybullet和mujoco-py麻烦不少。

另外再推荐一个看似发展前景还不错的模拟器:Webots,这个模拟器也是老牌了,不过更新比Gazebo做的好很多。自带IDE,不依赖于ROS,主要支持Python编程语言。物体模型有官方给的脚本对urdf进行转换。效率目测应该是pybullet这个水准,甚至更快。主要缺点是目前用户少,社区比较小。这可能是跟其对技术支持进行收费有关系。

源 Webots: robot simulatoraidudezzz/deepbotsWebots: robot simulator
强化学习框架 aidudezzz/deepbots


2020.11.24 基于Pybullet移植的OpenAI Robotics Multigoal环境第一版完成了。

花了5天,果然功力有所提高了。以后会接着补充更多机器人模型和任务,目前就只有原版的四个任务啦:Reach, Puch, Pick and Place, Slide。另外,由于MJDF文件无法直接使用,我用的是Kuka iiwa 14的模型+Robotiq85的手指。

Github指路:IanYangChina/pybullet_multigoal_gym

简单运用展示,跟原版是不是一模一样!

import pybullet_multigoal_gym as pmg

env = pmg.make('KukaPickAndPlaceRenderSparseEnv-v0')
obs = env.reset()
t = 0
while True:
    t += 1
    action = env.action_space.sample()
    obs, reward, done, info = env.step(action)
    if done:
        env.reset()

2020.11.22 关于Pybullet Gym的补充

着手对Pybullet Gym进行重构之后,发现这套代码底层一些难搞的地方还是挺多的。另外,这个包已经被纳入Pybullet中了。安装Pybullet即可用到Pybullet Gym的东西。首先Pybullet Gym的环境没有机器手任务,比如抓取类的。另外,Pybullet读取MJDF文件的功能有缺陷,可能是没有更新,一些MJDF的标签无法读取。所以,到头来我想移植OpenAI Gym的机器手环境还是要重新写URDF文件。个人感觉MJDF是比URDF强大的,没用过的同学倒是不用管这事了,直接URDF入手即可。MJDF可以设置的内容比较多,而用URDF的话,后期在Python代码里需要设置的东西就变多了。比如Mujoco提供Motion capture功能,内置了IK计算和控制,用户完全不用管怎么计算和设置手臂joint motor,但Pybullet需要自己调用IK和设置joint的控制信号。这点对于不需要IK的大部分OpenAI Gym任务来说倒是没什么,但是像我要做机器手抓取这样的用户来说,Mujoco的Mocap模块简直是不要太香!于是打算在Pybullet上写个类似Mocap的模块了(秃。

也回想起来之前觉得Pybullet慢的原因了。Pybullet的运行架构是Server-Client式的,通讯比Mujoco稍慢些,另外在重置模拟环境状态的时候,Pybullet需要把所有环境里的物体都重新加载,Mujoco我印象中不用这么麻烦,底层是直接重新设置模拟器时间和物体状态就行了。


概述

我经过一年多的学习、编程和实验,对目前面向机器人强化学习的模拟环境有一些个人认为比较值得记录的经验。这篇文章将作为自己对这些经验的总结分析,以及希望对社区有所帮助。以后应该会继续写自己在研究过程中涉及较多的关于机器人强化学习其他方面的类似文章,比如ROS编程、抓取、视觉方面的小方向等等,更新时间不定。接下来我们进入本文正题。

在机器人强化学习领域所面临的各种问题里面,收集训练数据的成本过于高昂是每个人都要迟早都要面对的。毕竟不像游戏领域,我们需要的不仅仅是在一个虚拟的世界里面取得成功,机器人始终是要在现实世界里工作的。然而对于需要大量训练数据支持的深度强化学习算法,价格高昂的机器人设备、缓慢的环境交互过程、以及强化学习算法在探索过程中损坏设备、环境甚至伤害到人类的高风险,使得在现实机器人上直接采集大量训练数据这件事变得不切实际。于是一个可靠和方便使用的模拟环境在这个领域里成了刚需。

以此为起点,为了使得在模拟环境里训练的强化学习算法能够在现实环境里工作,即所谓“填充模拟到现实的鸿沟(fill up the sim-to-real gap)”,进而出现了模拟现实迁移(Sim2Real Transfer)这个近几年十分热门的研究领域。但这是后话,不在这篇文章的讨论范围了。

在过去的一年多时间里,我不同程度地接触了五个在学术研究中出现最多的面向机器人强化学习的模拟环境,包括OpenAI Gym、Deepmind control suite、PyRep/RL Bench、Pybullet Gym、Gazebo。这五个环境有各自的优缺点,我想主要从API易用性、个性化难度、运行效率、社区资源四个维度对它们进行总结和比较。选择这四个角度,是因为个人认为它们是我所在的领域里人们在选择模拟环境时候最关心的。另外,这四个角度常常互相牵连,分析起来并不是绝对各自独立的。

API易用性主要关系到编程效率
个性化难度主要关系到用户能多方便的针对各自面对的问题进行模拟环境搭建
运行效率主要关系到训练效率
社区资源主要影响了用户在编程和仿真过程中遇到问题的时候能多快地找到解决方案

在开始细节分析之前,先给出各个环境的主观总体评分,总分5分,如下。首先,这个评分是主观性的,根据我个人经验的,所以有一定的bias。第二,这个评分面向针对机器人强化学习任务的,不考虑其他。想了解这些分数背后的原因?请接着看。

OpenAI Gym:4
Dm Control Suite:3
Pybullet Gym:4.5
PyRep/RL Bench:4
Gazebo:1

OpenAI Gym & Deepmind control suiteMujoco

对强化学习有所了解的同学应该对OpenAI Gym不会陌生,这是一个为强化学习而生的模拟环境包。它包括了Atari游戏、连续控制环境、文本游戏、以及不少依赖其代码结构的第三方模拟环境(比如后面要谈到的Pybullet Gym)。其面对连续控制任务的模拟环境是建立在Mujoco物理引擎(C++)和Mujoco-py这个Python包上的,包括了如locomotion、manipulation等常见的机器人控制任务。Deepmind control suite跟OpenAI Gym从各个方面都非常相似,所以我放到这里一起讲。另外,Mujoco这个物理引擎是需要付费使用的,而且不便宜,虽然学生可以申请到一年的免费Licence,但也就一年而已。

API易用性:从强化学习应用的角度来看,这方面OpenAI Gym和DM control都做得很不错。首先,它们都是基于Python的,这很重要。一方面Python的可读性和易上手性自不必说,另一方面也因为绝大多数强化学习算法的实验都依赖于于PyTorch和Tensorflow。其次,用它们来写一段环境交互代码的思路完美贴合主流强化学习算法的思维方式,即主要以观察、行动、回报构成的循环。如果用户已经搭建好了模拟环境(做机器人的需要自己搭建模拟环境应该不是什么少见的事情),那写训练代码就很方便了。当然实际情况是我们还需要一堆其他的东西,比如对policy进行update、记录和可视化训练数据、保存和读取神经网络模型等等。但这都不是模拟环境代码包需要考虑的。可以看看下面这段从官网摘来的小脚本。

---"OpenAI Gym"---
# http://gym.openai.com/
import gym
env = gym.make("CartPole-v1")
observation = env.reset()
for _ in range(1000):
  env.render()
  action = env.action_space.sample() # your agent here (this takes random actions)
  observation, reward, done, info = env.step(action)

  if done:
    observation = env.reset()
env.close()

---"DM control"---
# https://github.com/deepmind/dm_control/tree/master/dm_control/suite
from dm_control import suite
import numpy as np

# Load one task:
env = suite.load(domain_name="cartpole", task_name="swingup")

# Step through an episode and print out reward, discount and observation.
action_spec = env.action_spec()
time_step = env.reset()
while not time_step.last():
  action = np.random.uniform(action_spec.minimum,
                             action_spec.maximum,
                             size=action_spec.shape)
  time_step = env.step(action)
  print(time_step.reward, time_step.discount, time_step.observation)

个性化难度:这是一个比较Advanced的角度了,因为对模拟环境进行个性化意味着我们需要深入掌握模拟环境源代码的架构和运行逻辑。深入程度会因不同任务需求而异,对大部分用户来说主要是构建一个新的物理模型。而我由于需要做Hierarchical Goal-conditioned RL,不得不对OpenAI Gym的机器人抓取(Fetch robotics)环境做彻底地个性化,仅保留继承于Gym的原始类。由于我训练任务所需的功能不存在,所以这个过程不仅涉及到搭建新的物理模型,还需要重新编写环境的Python源码。我需要全面地理解其代码架构,主要指的是代码包的结构、各个类和函数之间的继承和调用关系。

从重新搭建物理模型的角度来说,用户需要熟悉Mujoco的建模方式。不同与机器人社区建模界的老大哥urdf和sdf,Mujoco有自己的XML编程规则,其文件一般被缩写为MJDF。对于我这种当初对老大哥也不熟悉的人来说,倒是没多大差别了。不过,由于MJDF相对来说是比较新的,其主要应用也就我们这里提到的两个模拟环境,我们比较难在社区里找到现成的物理模型文件(找到了也未必能work)。据我所知,目前常见的机器人厂商也没有提供官方的MJDF机器人模型文件。不过MJDF和老大哥们差别也没那么大,对熟悉老大哥的同学而言,学习MJDF应该不难。只不过,我觉得Mujoco的官方XML文档写得有些乱,查阅起来可能会比较费劲。

对于构成物理模型交互的Python源码,我认为Gym的架构比Dm control的架构更有条理,因此也更好理解和修改。这里是指对于比较有编程经验的人而言,如果是编程小白,不管是对哪个模拟环境的源码进行重构都是很难的事情。Gym的架构比较有条理,主要体现在源码中针对不同类型任务的代码、不同机器人模型的代码被分配在不同的文件夹里,并且各自有一个文件夹储存MJDF模型。另外,各个环境类代码被根据它们之间的继承关系储存于不同的层级。并且,一些通用的函数必须通过严格的规则来进行继承和个性化。当然,最后一点虽然降低了底层机制出现bug的几率,也增加了个性化的难度,比如我想把它改成适用于Hierarchical RL的时候就得另辟蹊径去打破原有的规则。这几个方面,个人认为Dm control都做得不如Gym。至少,我看不惯Dm control源码里把MJDF文件和环境python代码丢一起,又把模型mesh文件另外放这种编程习惯;测试文件和真正work的东西也分类不清晰(强迫症爆发)。

最后一点,由于Mujoco是C/C++写的,所以二者都需要一个Python桥梁,这也是做个性化的时候会经常需要查阅的代码(一般不会做改动)。Gym的桥梁代码就是mujoco-py,是一个独立于Gym本身的开源包,Dm则是自己写的,这两者相比之下,mujoco-py不管在源码可读性和Documentation方面做得都比Dm完善。更别提Dm把这玩意放模拟环境包里和环境本身混杂起来了。

运行效率:训练的快慢有多重要想必也不用多说了,而由于Mujoco本身就是针对强化学习训练的,所以在运行效率方面优化得比较不错,在这篇文章提到的各个环境里应该是排第一的。Gym和Dm两者在这个方面的区别也不大,因为运行效率很大程度上决定于物理引擎本身的代码设计。当然,也跟环境交互代码有关系,但因为从最底层开始就是面向长时间RL训练的,所以这方面优化二者都做得很好。

社区资源:一个用户和开发者活跃交流和分享资源的社区对于开源软件而言,基本上就跟我们需要氧气一样。Python之所以能发展到现在这个程度,社区的贡献有多大不言而喻。在这方面我比较倾向于Gym,从各自的Github主页也可以看到,Gym收到过1000+的issues、800+个pull request、拥有5000+用户、261个代码贡献者、以及22.7k颗星,而Dm则仅有100+issues、17个pull request、少到系统不显示的用户、18个代码贡献者、以及2.1k颗星。所以也可以想象应用Gym做机器人RL的人更多,benchmark什么的更多。

从物理模型的方面来看,二者是相同的,都依赖于Mujoco的社区。而这个社区相比老大哥模型urdf和sdf来说就弱很多了。也许是因为其本身是付费软件,开源的模型文件少只有少,能找到的也都比较粗糙,各机器人厂商也没有提供MJDF文件的。很多物理模型都需要用户从零搭建,这对新人、甚至许多非新人而言,可以说是很不友好了。好在MJDF和老大哥的区别也不是特别大,熟悉老大哥的同学可以稍微省电力气。但是到头来,我们开源(白嫖)党,共享资源才是我们的力量根基啊!

Pybullet Gym

Bullet在机器人强化学习领域也是一个比较出名的物理引擎,而Pybullet则是基于Bullet引擎的面向Python用户的机器人模拟环境,目前已经开发到了第三个官方版本。前面提到的Mujoco也提供了用户使用Bullet来作为底层物理引擎的选项,而Pybullet也提供给用户直接使用MJDF模型的功能。再进一步,Pybullet Gym则是在Pybullet之上构建的,对OpenAI Gym各种机器人强化学习任务的移植。(Bullet现在背后是谷歌)。

API易用性:由于Pybullet本体并不是纯粹面向强化学习而开发的模拟环境,所以这个模拟环境其本身并没有特别适合强化学习训练的一套API。我猜测这可能就是为什么后来基于Mujoco的OpenAI Gym会在强化学习领域先火起来的原因之一。然而,由于Mujoco是付费的,所以也就进而在18年初又有了基于Pybullet的对Gym的移植项目,尽管这个项目现在还不是很热门,代码贡献者也不多。但是由于Pybullet Gym继承了OpenAI Gym的环境交互逻辑,提供了前面提到的完美贴合强化学习训练的编程API,又集合了Pybullet开源免费的特点并且通吃URDF、SDF和MJDF三大类模型文件,所以个人比较看好这个模拟环境在未来的发展。

个性化难度:我其实近期才对Pybullet Gym进行了比较深入的探索,因为之前用一年的免费Mujoco苟了一篇文章出来。所以在个性化难度方面的理解可能会不太准确,不过给我第一印象是和OpenAI Gym差不多,甚至更方便,因为模型文件支持更广。同样是从两个方面讲,构建模型和源码重构。

构建模型问题真的不大了,毕竟背后的Pybullet通吃领域内三大类物理模型文件。基本上常见的机器人厂商都会给出URDF和/或者SDF文件。

对于源码重构,我虽然还没实操重构(刚准备做),但从源码结构来看,至少比Dm control好。这可能是因为它是OpenAI Gym的移植版本,所以作者也继承了Gym那种比较清晰的源码结构,甚至单看文件夹命名的时候二者基本一致。这其实也是我看好它的原因之一,我在阅读源码的过程中看到了作者比较严谨和有责任心的编程习惯(白嫖党直呼内行)。因此,由于对OpenAI Gym做过重构,所以我不太觉得在比较相似的Pybullet Gym上会花我很多时间去做同样的事情。

运行效率:我稍微跑了一下基本的环境交互代码,感觉和OpenAI Gym的速度差不多,虽然直觉跟我说Bullet会慢一点。暂时还不知道哪来的直觉,隐隐约约好像是因为以前跑过Bullet然后有点慢,可能新版本做了优化之类的。

社区资源:如果是说Pybullet这个引擎,用户量已经不小了,在学术论文上也是常客。虽然由于Pybullet SDK本身不太好入手,而且更偏向于机器人控制任务,所以比OpenAI Gym少一些。而对于Pybullet Gym来说目前就更少了。但是背后可是开源老大哥谷歌在维护的物理引擎,虽然不是谷歌官方对OpenAI Gym/Mujoco的开源移植,可我还是觉得前途无限。另外,今年ICLR以Mujoco非开源软件有违科研开放原则为由拒稿了一篇基于Mujoco的benchmark文章,也在Reddit和Twitter上领域的小伙伴们的讨论。我没仔细去看大家的观点是怎么样的,但是科研社区对一个开源物理环境的需求体现得很到位了。虽然目前用户不多社区不活跃是我扣分的原因,但也因为开源和代码风格等其他方面都不弱于OpenAI Gym,我主观地给了它最高分。

PyRep / RL Bench

这个环境是帝国理工的博士生Stephen带头基于V-Rep开发的,他们组的研究侧重于我开篇提到过的Sim2Real Transfer。V-Rep(现在改名叫CoppeliaSim了)是一个相比Pybullet和Mujoco而言,更加传统的机器人仿真软件。始于2010年,其开发初衷根本就和强化学习无关,而是与后面要提到的Gazebo类似,侧重于现实机器人、特别是工业机器人应用。PyRep是基于V-Rep开发的面向机器人学习(不限于强化学习)的模拟环境,而RL Bench则是针对Benchmarking而开发的一个任务集合。一年前还没有RL Bench的时候我就尝试了PyRep,那时候也是刚开始摸索,然后它当时给我的印象是效率低而且源码重构很难。经过一年的迭代,它已经进步了很多,在某些方面提供了不少便利性,甚至有官方视频tutorial教用户怎么构建新的任务环境。尽管还是有点不尽人意,但开发者很努力而且做得很好。此外,这个环境是提供给学生免费License的。

API易用性:这方面,由于开发者知道大家都很吃Gym那套面向RL的编程范式,所以它做得跟Gym很像,表面上用起来基本没差别。所以简单应用,比如仅作为benchmark而不对环境进行修改的话,很直观了。

个性化难度:从物理建模的角度来说,V-Rep支持urdf这些老大哥文件,所以首先机器人模型的资源不是问题。其次,它本身就提供了一个用于物理建模的图形交互界面,用户可以直观地在图形界面上修改物理模型,而不用像前面几个环境一样只能写底层XML代码。另外,PyRep和RL Bench都分别提供了详细的机器人以及任务建模教程,因为用户自己的模型得兼容PyRep和RL Bench源码处理模型的方式。

重构源码这事,我觉得比前面的难。主要是因为V-Rep的很多用户脚本是用Lua写的,这是我个人觉得在我的领域里属于比较难学的小众语言,而不像C++这种随处可见而且我又学过的。查阅底层模拟环境这事会比较吃力。当然,如果不需要重构源码,那么这个环境还是挺方便使用的。

运行效率:它的效率要低于前面三个环境。主要是因为它跑headless模式(无图形界面)需要xvfb之类的虚拟渲染buffer来支持,也就是说它并不是真正的headless,模拟环境的图形界面还是会被渲染出来,只是用户没看到而已。前面几个环境都是提供一个render()函数,当用户需要渲染图形界面的时候就调用它,而PyRep是反过来的,它默认渲染图形界面。这也是因为V-Rep本身就不是为了长时间跑实验而设计的。另外,可能是我没过于深究,感觉Linux的虚拟渲染buffer软件挺难正常工作。

社区资源:V-Rep的社区还是挺活跃的,但是由于PyRep和RL Bench比较新,刚起步没多久,另外大多数人都已经被Mujoco和Bullet先入为主了,所以社区资源相对比较匮乏。但由于它最初是为工业机器人应用而生的,所以物理模型文件对于用户来说依然不是什么问题。而API方面,PyRep的接口做得也很不错,开发者们目前也还活跃着(PhD没毕业呢)。所以即使一些问题没有现存的解决方案,也不会很难取得开发者的support,毕竟学生还是有很多时间会坐在电脑前敲敲打打的。

Gazebo

这个环境是真的老大哥了,老大哥中的老大哥,但是真的太老了。它是面向工业机器人应用的,自身与强化学习没有瓜葛,和V-Rep属于同类。我相信很多做机器人的同学都会被导师推荐去用这个环境,或者自己在网上很容易就搜出来它。但是相比前面几个,它真的太不适合做强化学习训练了。

API易用性:对不起,没有Python API,只有ROS topic。只能通过ROS与它进行通讯,对机器人进行控制。而且,没有内置的IK和motion planning功能,想实现对机器手的Cartesian space控制,你有两个选择:用MOVEIT!或者自己写一个。对了,Gazebo、ROS以及ubuntu版本之间的版本依赖太强,这也很头疼。

2021.01.13 更正:经朋友提醒,moveit!是有提供Python API的,只要熟悉了ROS的通讯框架,用它来planning不会很难。不过,由于Gazebo离不开ROS和GUI,所以效率还是一般。从易用性来说还是比pybullet和mujoco-py麻烦不少。

个性化难度:毕竟是老大哥,开源模型特别多。但是没有一个系统完整的面向RL的SDK。也就是说,要完全自己写。而且,只能通过ROS通讯。用ROS通讯会有一个时间同步的问题。而且要自己写motion planning。我尝试了一个月,熟悉了ROS,但是卡在了mp这里,现在要放弃了。而且回过头看觉得自己有点二,ROS本来就是用来和现实机器人通讯的东西,我为什么要踩这个坑?

运行效率:都已经是仿真环境了,用ROS间接交换数据肯定没有前面那些直接交换数据的快。而且不能跑Headless,虽然可以跟V-Rep一样,选择xvbf之类的东西。

社区资源:模型文件小问题。但是用它来跑RL的案例太少了,也很少在领域内文章上听说过这么用的。

结语

所以,前面的分析,就是我一年来对这几个机器人强化学习领域的常见模拟环境的小结。(自我)感觉我对它们的评分还算公正。

OpenAI Gym:4
Dm Control Suite:3
Pybullet Gym:4.5
PyRep/RL Bench:4
Gazebo:1

我用了一年的Mujoco,如果能搞到License的话我可能会继续留下去,但是没有,License真的太贵了。之前写的环境,等文章发表后就会开源,但应该不会有进一步发展了,也可能会直接跟官方提出Pull request。

有了Pybullet Gym这个移植作品,加上Bullet完全开源、支持老大哥物理模型文件,我已经转战Bullet了。虽然刚刚结束了有点折磨的Gazebo之旅,但其实我并不后悔花了这些时间,因为我学了很多ROS方面的东西,这是迟早要用到的。值得一提的是,基于Mujoco和Bullet的环境都没有内置的ROS接口,而V-Rep和Gazebo都有。我是觉得这没关系,因为大多数时候在模拟环境训练和应用到现实机器人中这两件事是分开进行的。

跟我一样要长时间使用模拟环境但又不太可能拥有Mujoco License的同学,我的建议是看看Pybullet Gym和PyRep/RL Bench,二者各有千秋吧,但我比较喜欢Bullet。

以上。

2020.11.19. 卡迪夫 英国

编辑于 2021-10-20 16:45