Skip to content

RFUnivese 技术文档

说明

本文档主要披露RFUniverse的技术细节,以及我们想做的到底是什么。前期主要的开发人员是@haoyuan和@wenqiang,如果有问题可以与我们取得联系。

友情链接:(有些网站可能需要挂梯子会加速,仅@RobotFlow中的用户才可以访问代码) RFUniverse Unity端代码 RFUniverse Python端代码 RFUniverse Demo网站 RFUniverse 论文 ML-Agents

目录

RFUniverse

我们想要在RFUniverse中打造一个可以面向家用场景任务的仿真平台,希望它可以支持多种多样的物体仿真。我们这里对于物体的分类并非从语义分类,而是从属性分类,如刚体(杯子、手机、钥匙)、关节体(抽屉、门、箱子)、流体、柔性体、软体等。而Unity提供了这样一个平台,得以使仿真这些属性的物体成为了可能。为了与主流的AI算法相适应,我们在此基础上加入了与Python端进行通信的功能,更加丰富了RFUniverse的生态。

验证环境配置成功

Rigidbody和GameObject篇

  1. 在Unity里面,先把com.robotflow.rfuniverse这个包给导入
  2. 在Unity中找到Assets/Scenes/Demos/PoseTrackerDemo,打开这个scene
  3. 在python端,找到pyrfuniverse/demos/pose_tracker_demo_env/main.py这个脚本
  4. 在pyrfuniverse/demos/pose_tracker_demo_env路径下,在命令行中运行命令

python main.py
5. 运行后,如果在命令行中没有报错,应该会有如下输出,同时程序处于阻塞状态

pybullet build time: May 27 2021 15:50:10
Side channel id in use:
534c891e-810f-11ea-a9d0-822485860400
00c188e2-138b-46f2-afd8-2caab6797864
557cf89f-5555-4dbb-9f5a-67faafe83d46
6. 在Unity端点击运行。 7. 回到在命令行中,应该会持续输出如下内容

{0: {'name': 'Cube', 'position': [-1.3739991188049316, 0.7099998593330383, -6.417701244354248], 'rotation': [-0.00011106694000773132, -7.0520136432605796e-06, -8.0937119491864e-05], 'velocity': [0.0, 0.0, 0.0], 'angular_vel': [0.0, 0.0, 0.0]}, 1: {'name': 'Sphere', 'position': [0.902999997138977, 0.7099999785423279, -6.706999778747559], 'rotation': [-5.826257894173581e-17, 0.0, 0.0], 'velocity': [0.0, 0.0, 0.0], 'angular_vel': [0.0, 0.0, 0.0]}}
{0: {'name': 'Cube', 'position': [-1.3739991188049316, 0.7099998593330383, -6.417701244354248], 'rotation': [-0.00011106694000773132, -7.0520136432605796e-06, -8.0937119491864e-05], 'velocity': [0.0, 0.0, 0.0], 'angular_vel': [0.0, 0.0, 0.0]}, 1: {'name': 'Sphere', 'position': [0.902999997138977, 0.7099999785423279, -6.706999778747559], 'rotation': [-5.826257894173581e-17, 0.0, 0.0], 'velocity': [0.0, 0.0, 0.0], 'angular_vel': [0.0, 0.0, 0.0]}}

如果以上现象均成立,则环境已经配通。

Articulation篇

  1. 从github上更新pyrfuniverse的代码
  2. FrankaRoboticsDemo.unitypackage这个包导入,并在Unity Editor中打开Assets/Scenes/Demos/FrankaRoboticsDemo.unity这个scene。
  3. 进入pyrfuniverse/demos/franka_robotics_env这个文件夹
  4. 打开conda环境,运行脚本

python vis_franka_robotics_env.py
5. 在Unity中运行,应该可以看到场景中的机械臂在规则地进行往复运动。 6. 你也可以修改python代码,将46行注释,47行解注释,再运行,即可看到机械臂的末端在转圈。

简单唠叨几句这个Demo的工作流程,希望能够有助于开发者尽快熟悉RFUniverse的工作方式。这个demo算是比较接近我们在科研中所搭的环境了,如果再加入一些其他的物体来进行交互,再设计一个任务让机器人来完成,就可以当作论文里的实验之一了。场景中的机械臂是放到ArticulationManager下的,也就是它的每一个关节的信息都可以被传到python端,同时它的每一个关节都可以收到Python端代码的控制。

  1. 我们从Python端代码说起,首先你可能会注意到Python代码vis_franka_robotics_env.py里有env.step()函数,这个函数就是我们希望在这次update中,机械臂的末端相对于当前位置移动多少距离。
  2. 相对移动距离这个参数传进env中,env会先从Unity端获取到机械臂末端当前位置在哪,从而计算本次update后机械臂的目标位置。
  3. 有了目标位置后,需要根据这个位置,运用反向运动学(Inverse Kinematics)计算出到达这个目标位置时机械臂各个关节的角度。
  4. 接下来,Python代码会将这个角度传到Unity端,Unity端(或者说ArticulationManager)接收到这一串数据后,分别控制机械臂的每一个关节,运动到它的目标位置,从而完成这一次update。
  5. 由于我在封装的时候限制了,每一次update中机械臂的末端在XYZ三个方向上最多移动5cm,所以各个关节的角度变化也不会特别大,从而我们可以认为这一次update过后,机械臂就达到了目标位置,同时也保证了在Unity中运行时候的稳定性。

Unity端

代码链接

由于模型文件过于庞大,我们没有向Github中上传任何资源文件(.obj,.png,.fbx等),所以有的scene打开后会发现资源文件丢失的情况,我们后续会给到使用者一个第三方下载渠道(Google Drive或百度网盘)来下载所有的模型和资源文件。

目前的Unity端还非常依赖于ML-Agents这个代码库中的通信部分,这个通信部份主要是依据grpc这个通信基础而来的。grpc的一个很明显特征就是.proto文件,这个文件是用来定义传输数据的类型的。除此之外,ML-Agents中的其他部分基本都用不到。所有与ML-Agents有关的代码全都在rfuniverse/com.robotflow.rfuniverse这个插件中,可以在Unity里导入。

然后重点说一下rfuniverse/RFUniverse这个文件夹。这里是Unity的工程文件,里面包含Assets、Packages、ProjectSettings、UserSettings文件夹。在Assets文件夹中,又有一个RFUniverse文件夹,这个文件夹里全都是我们自己写的核心代码,包含Editor文件夹和Scripts文件夹。Editor文件夹中只是一些与修改Unity Editor相关的代码,可以先忽略;在Scripts文件夹中,则是与仿真运行有关的代码了。下面重点介绍一下这个部分。

Agent

这个文件夹中的脚本都是Python与Unity进行通信的直接桥梁,它里面所有脚本的风格都是类似的,定义一些Manager,定义FixedDeltaTime,定义一些GameObject以及FixedUpdate函数等等。本文件夹下的脚本与Unty的Scene一一对应,每一个Scene中会有一个名为Communicator的GameObject用来挂该脚本。

Attributes

这个文件夹中的所有脚本都是会被挂到物体上的,如果是刚体就挂RigidAttr.cs,关节体则挂ArticulationAttr.cs,以此类推。这些脚本主要是为物体提供一个统一的接口,保证编程时的通用性。

Controllers

这里的所有脚本都是单独针对关节体控制的。ControllerBase.cs提供了基本的接口,是一个基类;AgentController.cs和NonAgentObjectController.cs继承自ControllerBase,分别针对像机器人、机械臂、机械手这种主动运动的物体,和抽屉、门、箱子这种被动运动的物体。这部分代码不是MonoBehavior的子类,所以不会挂在物体上。

Heuristics

这里的脚本是为了Debug时写的一些脚本,先不用管。

Manager

Manager脚本是RFUniverse中最重要的一个部分之一。在我们的设计中,不同属性的物体(刚体、关节体、固定的GameObject、柔性体、软体等)是受不同Manager管理的。它在工作过程中,每一次update时,会先接受Python端传来的指令,去对自己所管理的某些物体做一些操作(如改变position、euler_angles等),如果没有指令传来则跳过这一步;然后去调用所控制物体的Attribute脚本中的方法,获取到相应的信息(如position、euler_angles、velocity等),然后把所有信息写在一起,发回Python。所以Manager这个类是对物体的中控,只有被Manager管理的物体才能和Python端发生交互,以及把信息传回Python端进行处理。

Utils

这个文件夹中的脚本是一些工具函数。

总的来说,Unity端的代码遵循了面向对象编程的思想,在前期设计的时候我尽可能做到了接口的统一、风格的统一和代码的易维护性。Unity端所做的事情可以简单概括为以下几点:

  1. 定义了场景中的物体都有哪些,哪些是可控的,哪些是不可控的。
  2. 接收来自Python端的指令,解析指令并执行。
  3. 执行仿真,正常地去Update。
  4. 从场景中可控的物体中获取到相对应的信息,并发回Python端。

Python端

目前的版本在Python-Unity通信上大量依赖于ML-Agents中的mlagents-envs这个Python包。 相比于mlagents-envs,我们添加的功能代码主要在envsrfuniverse_channels文件夹中。

Python端修改进展

  1. 固定各个Manager(Python端中称为channel)的uuid

ArticulationManager               63d7c283-f43a-4336-8aef-916ea91b1d9f
GameObjectManager                   09bfcf57-9120-43dc-99f8-abeeec59df0f
RigidbodyManager                    2d1916c4-4c96-4dff-a341-426976c91192
CameraManager                       d9985808-0d7d-4c77-9f59-4cdbefa1b7b1
ObiClothManager                   557cf89f-5555-4dbb-9f5a-67faafe83d46
ObiClothWithGraspingManager       0a121c78-63c6-4f4f-8c71-186a6951d928
ObiSoftbodyManager                 00c188e2-138b-46f2-afd8-2caab6797864
HumanDressingManager           28c03571-e7fa-494a-9bf7-bfa15ee729ab
LightManager                    d281db7b-e963-4d74-b960-ab3e138b2867
AssetManager                     d587efc8-9eb7-11ec-802a-18c04d443e7d
2. 所有驱动物体的消息,移除头部声明类型的string,并将index(以后将改为id)提到MethodName前。 * 对于头部声明类型的string,目前已全部删除。 * 对于无需提供index的方法,则不进行其他改动。 * 有一个特例是CameraChannel里的GetImages方法。这个方法不是传的index,而是传的rendering_parameters,它是一个数组,包含三个值,分别是index、图片宽和图片高。对于这种特殊情况目前我没有进行额外修改,等后面再讨论如何统一。

现存问题

  1. Python端step()函数的问题
  2. 一次step时,同一个manager只能执行一次发来的消息。如果一个step中有某个manager发来了两条消息,则可能有问题。
  3. 场景中的Attr,向Manager去注册自己。
  4. 代码中的uuid可以统一化,从而不在python端代码显式地放出来。
  5. 导入模型时必须要通过AssetBundle的方式。
  6. 是否可以有一个工具,用户通过GUI的方式可以直接生成AssetBundle。
  7. 如果上面的功能难以实现,我们就需要提供一个初具规模的AssetBundle文件/文件库,用户在使用前将这些文件下载到本地,即可使用。
  8. rfuniverse_channel的扩展性问题
  9. 如果用户想要使用的物体属性,我们这里没有支持,怎么办。

更多可验证环境

在运行前请更新一下pyrfuniverse在dev分支下的代码。然后将三个unitypackage导入Unity,再把RoboTube.zip放到pyrfuniverse/pyrfuniverse/assets/文件夹下并解压。

下面的python脚本都在pyrfuniverse/tests文件夹中。

  1. Scenes/Env/UR5Drawer.unity

python test_ur5_drawer_env.py
2. Scenes/Env/UR5Box.unity

python test_ur5_box_env.py
3. Scenes/Env/RoboTube/DrawerClosing.unity

python test_drawer_closing_env.py
4. Scenes/Env/RoboTube/WaterPouringEasy.unity

python test_water_pouring_env.py

前面四个场景试完之后可以试一下下面这个文件夹中的场景。 Scenes/Env/RCareWorld/

后续开发进程

目前我们确定目标和方案:

  • 目标:用户在不安装Unity的条件下就可以玩转RFUniverse
  • 方案:提供两个Unity可执行文件:
  • 第一个为可编辑的场景。
    • 用户可以直接通过键鼠与环境进行交互,自行搭建环境。
    • 支持导入和导出json配置文件,该文件描述了场景中物体的位置信息。
    • 支持键鼠的交互使Camera的位姿改变。
  • 第二个为与Python端可互通的场景
    • 该场景既支持代码导入物体,也支持json配置文件直接生成场景。
    • 支持键鼠的交互使Camera的位姿改变。

就我个人看来,仿真环境的关键就是两件事:仿真本身性能如何、对外来模型的支持如何。前者决定了仿真环境的可用性,后者决定了仿真环境的扩展性。前者是Unity本身决定的,我们能做的也只有调整某些参数使其达到速度和精度的平衡;而后者是我们能把握的。

对于我们工程项目中已有的prefab,我们都可以内置到GUI里面供用户选择。而对于用户想要自定义的模型或定制prefab,我们暂时不提供无Unity Editor的解决方案(因为我觉得写起来会非常麻烦,这个功能可以放到Todo里面,等到开源了之后再慢慢添加)。

对于用户制作的AssetBundle,我希望第一个场景也可以支持拖动导入,但是这个缩略图可以没有,只显示名字即可。

下面是我回顾之前一段时间RFUniverse的开发过程中,我觉得比较需要的搭建场景所需GUI功能。我目前的想法是先按照这里的开发进程来进行,然后本周末组会上我会跟大家详细介绍一下我们这段时间的进展,也向大家征求一些意见。等下面这些功能以及大家的需求开发完毕(更确切地说,必要的、合乎实际的需求开发完毕)之后,我们把之前的场景都适配到现在的框架下测试一遍,第一版开源就算是完成了。后面的文档、教程以及更多的功能接口可以继续慢慢做。

开发功能:

以下功能都需要在json配置文件中支持记录和复原。

物体创建篇

  • 创建基础几何模型(Cube、Sphere、Capsule、Cylinder、Quad)
  • 创建Prefab中的物体
  • 根据AssetBundle文件创建物体

Transform篇

  • 物体的旋转(Rotation)
  • 物体的平移(Position)
  • 物体的缩放(Scale)
  • 物体的父子关系

物体属性篇

  • 物体的颜色材质可调
  • Collider的添加(VHACD及各种Collider)
  • Rigidbody的mass调整
  • Rigidbody的useGravity调整
  • ArticulationBody的JointType调整
  • ArticulationBody的LowerLimit、UpperLimit调整(仅JointType为Prismatic或Revolute时可调)
  • ArticulationBody的Stiffness调整(仅JointType为Prismatic或Revolute时可调)
  • ArticulationBody的Damping调整(仅JointType为Prismatic或Revolute时可调)
  • Collider的调整
  • Collider的Physics Material参数调整

UI篇

  • 物体旁的transform参数显示
  • 调整transform时的整数吸附
  • 物体transfrom参数可输入
  • 物体的Collider显示
  • 对Rigidbody、ArticulationBody的可调参数的显示和调整
  • 对ArticulationBody的点击可选中其某一部分
  • ArticulationBody的转轴取值范围显示