教程 2:修改环境(30 分钟)
在本教程中,我们将教你如何在环境中创建简单对象。 第一步将创建一个可与环境交互的球。 我们将涉及与节点相关的几个概念:节点的含义是什么、如何创建节点、节点之间必须如何归属关联等等。 此外,我们还将学习如何设置物理属性。
我们将介绍几种不同类型的节点。 它们的详细定义可以在[参考手册(https://cyberbotics.com/doc/reference/nodes-and-api-functions)中找到。 手边放着[节点关系图(https://cyberbotics.com/doc/reference/node-chart)也有助于理解节点之间的继承关系。
一个新仿真
首先,我们基于教程 1 中创建的仿真来新建一个仿真。
动手实践 #1:确保
my_first_simulation.wbt世界文件已打开,并且仿真处于暂停状态且虚拟时间为 0。 使用File / Save World As...(文件 / 世界另存为……)菜单,将仿真保存为obstacles.wbt。
修改地面
默认的 RectangleArena PROTO 定义了一个固定在静态环境上的简单地面,即没有 [Physics(https://cyberbotics.com/doc/reference/physics)(物理)节点,四周被墙壁环绕。
Webots 对象库中还提供了其他预建的地面。
我们现在将删除 RectangleArena 节点,并添加一个简单的地面,稍后在本教程中我们会手动为它四周添加墙壁。
动手实践 #2:要移除
RectangleArena,可以在 3D 视图或场景树视图中用鼠标左键单击选中它,然后按下键盘上的 del 键。 或者,你也可以在 3D 视图中右键单击它,并在上下文菜单中选择Delete(删除)(你也可以直接在场景树视图中使用上下文菜单)。 选中TexturedBackgroundLight节点并点击Add(添加)按钮。 在打开的对话框中,选择PROTO nodes (Webots Projects) / objects / floors / Floor (Solid)。
新添加的 Floor PROTO 默认尺寸为 10 米 x 10 米,但可以通过修改相应的字段来调整它的大小、位置和纹理。
动手实践 #3:在场景树视图中选中并展开
Floor。 修改size字段并将其设置为{1, 1},将其尺寸调整为 1 米 x 1 米。
Solid 节点
本节介绍 Webots 中最重要的基础节点:[Solid(https://cyberbotics.com/doc/reference/solid)(实体)节点,许多其他节点都派生自它。
[Solid(https://cyberbotics.com/doc/reference/solid) 节点表示一个刚体,即形变可以忽略不计的物体。 刚体上任意两点之间的距离始终保持不变,不受作用于其上的外力的影响。 例如,一张桌子、一个机器人手指指节或一个轮子都是刚体。 软体和铰接物体不是刚体。 例如,一根绳子、一个轮胎、一块海绵或一条铰接式机械臂都不是刚体。 不过,一个铰接实体可以被拆分为若干个刚体。
Webots 的物理引擎仅设计用于模拟刚体。 在设计仿真时,一个重要步骤就是把各种实体拆分为独立的刚体。
要定义一个刚体,你需要创建一个 [Solid(https://cyberbotics.com/doc/reference/solid) 节点。
在该节点内部,你将设置不同的子节点,对应刚体的各项特性。
下图(该图)描绘了一个刚体及其子节点。
[Solid(https://cyberbotics.com/doc/reference/solid) 节点的图形表示由填充其 children(子节点)列表的 [Shape(https://cyberbotics.com/doc/reference/shape)(形状)节点定义。
碰撞边界在其 boundingObject(包围对象)字段中定义。
图形表示和碰撞形状经常相同,但并不必然相同。
最后,physics(物理)字段定义该对象属于动态环境还是静态环境。
所有这些子节点都是可选的,但 physics 字段需要 boundingObject 已被定义。
graph TD
Solid[Solid] -->|physics| Physics[Physics]
Solid -->|boundingObject| Geometry1[Geometry]
Solid -->|children| Shape[Shape]
Shape -->|geometry| Geometry2[Geometry]
class Solid highlightedNode;该图中的 Geometry(几何)框代表任意种类的几何图元。 实际上,它可以被替换为 [Sphere(https://cyberbotics.com/doc/reference/sphere)(球)、[Box(https://cyberbotics.com/doc/reference/box)(盒)、[Cylinder(https://cyberbotics.com/doc/reference/cylinder)(圆柱)等。
创建一个球
我们现在要向仿真中添加一个球。 该球将如此图所示被建模为刚体。 我们将使用 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点来定义球的几何形状。
动手实践 #4:在场景树视图中,选中最后一个节点并按下
Add(添加)按钮。 在对话框中,打开Bases nodes(基础节点)部分并选择 [Solid(https://cyberbotics.com/doc/reference/solid) 节点。 在场景树视图中,展开 [Solid(https://cyberbotics.com/doc/reference/solid) 节点并选中其children字段。 使用Add(添加)按钮向其中添加一个 [Shape(https://cyberbotics.com/doc/reference/shape) 节点。 选中 [Shape(https://cyberbotics.com/doc/reference/shape) 节点的appearance(外观)字段,并使用Add(添加)按钮添加一个PBRAppearance节点。
- 添加一个 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点作为新建 [Shape(https://cyberbotics.com/doc/reference/shape) 节点的
geometry(几何)字段。 - 展开
PBRAppearance节点,将其metalness(金属度)字段改为 0,roughness(粗糙度)字段改为 1。 - 向 [Solid(https://cyberbotics.com/doc/reference/solid) 的
boundingObject字段添加另一个 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点。 - 最后,向 [Solid(https://cyberbotics.com/doc/reference/solid) 的
physics字段添加一个 [Physics(https://cyberbotics.com/doc/reference/physics) 节点。 - 通过修改 [Solid(https://cyberbotics.com/doc/reference/solid) 节点的
translation(平移)字段,把球放到机器人前方(例如{0.2, 0, 0.2})。 - 保存仿真。
- 结果如此图所示。

仿真启动后,球会落到地面上。
你可以通过对球[施加力(the-3d-window.html#applying-a-force-to-a-solid-object-with-physics)来移动它(ctrl + alt + 左键单击 + 拖动)。
启用 View / Optional Rendering / Show Contact Points(视图 / 可选渲染 / 显示接触点)菜单项后,球与地面之间的接触点可以以青色线条显示。
几何节点
为了定义球,我们在两种不同的上下文中使用了 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点:用于图形表示(children)以及用于定义物理边界(boundingObject)。
所有几何节点(例如 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点)都可以用于图形上下文。
但其中只有一部分可以用于物理上下文。
[节点关系图(https://cyberbotics.com/doc/reference/node-chart)指出了每种上下文中支持哪些节点。
接下来我们要减小 [Sphere(https://cyberbotics.com/doc/reference/sphere) 的尺寸,并通过增加用于表示它的三角形数量来提高其图形质量。
动手实践 #5:对于定义球的每个 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点,将其
radius(半径)字段设为0.05,将其subdivision(细分)字段设为2。 参阅[参考手册(https://cyberbotics.com/doc/reference/sphere)以了解subdivision字段的含义。
DEF-USE 机制
DEF-USE 机制允许在一个地方定义节点,并在场景树的其他地方复用该定义。 这有助于避免在世界文件中重复定义相同的节点。 此外,它还允许用户同时修改多个对象。 其工作原理如下:首先给节点添加一个 DEF 字符串标签。 然后可以在其他地方使用 USE 关键字复用该节点的副本。 只有 DEF 节点的字段可以被编辑,USE 的字段继承自 DEF 节点且不能被修改。 该机制依赖于节点在世界文件中的顺序。 DEF 节点应在任何对应的 USE 节点之前定义。
我们先前用来定义球的两个 [Sphere(https://cyberbotics.com/doc/reference/sphere) 定义是冗余的。 现在我们将使用 DEF-USE 机制把这两个 [Sphere(https://cyberbotics.com/doc/reference/sphere) 合并为一个。
动手实践 #6:在场景树视图中选中第一个 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点(即 [Shape(https://cyberbotics.com/doc/reference/shape) 的子节点)。 场景树视图的[字段编辑器(the-scene-tree.html#field-editor)允许你输入 DEF 字符串。
- 在该字段中输入
BALL_GEOMETRY。 - 选中
boundingObject字段(包含第二个 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点),在场景树中右键单击该字段并在弹出的上下文菜单中选择Delete(删除)条目来清空它。 - 然后,选中
boundingObject字段并点击Add(添加)按钮,在对话框中选择USE / BALL_GEOMETRY。 - 结果如此图所示。
现在,修改第一个 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点的 radius 字段也会同时改变它的 boundingObject。
为了方便起见,boundingObject 字段也接受 [Shape(https://cyberbotics.com/doc/reference/shape) 节点(而不是直接使用 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点)。
同样可以在 [Shape(https://cyberbotics.com/doc/reference/shape) 这一层级使用相同的 DEF-USE 机制,如此图所示。
目前,这样做的最大好处是能够同时将这个 [Shape(https://cyberbotics.com/doc/reference/shape) 直接用于图形目的。
后文将会看到,这种机制对于某些传感器非常有用。

graph TD
Solid[Solid] -->|physics| Physics[Physics]
Solid -->|boundingObject| USEBALLGEOMETRY[USE BALL_GEOMETRY]
Solid -->|children| Shape[Shape]
Shape -->|geometry| Sphere[DEF BALL_GEOMETRY Sphere]
USEBALLGEOMETRY -.- Sphere
class Solid highlightedNode;
class USEBALLGEOMETRY,Shape secondaryNode;动手实践 #7:创建一个参数相同的第二个球,但在 DEF-USE 机制中使用 [Shape(https://cyberbotics.com/doc/reference/shape) 节点(而不是直接使用 [Sphere(https://cyberbotics.com/doc/reference/sphere) 节点)。
添加墙壁
为了检验你的进度,请自己动手实现四面墙壁来环绕环境。
这些墙壁必须被静态地定义到环境中。
要理解静态与动态的区别,我们来考虑上面定义的一个物体(球)。
如果 [Physics(https://cyberbotics.com/doc/reference/physics) 节点为 NULL,那么在仿真期间它会静止悬停在半空中(静态情形)。
如果 physics 字段包含一个 [Physics(https://cyberbotics.com/doc/reference/physics) 节点,它会在重力作用下下落(动态情形)。
尽可能在 [Shape(https://cyberbotics.com/doc/reference/shape) 层级而非几何(Geometry)层级使用 DEF-USE 机制。
事实上,在 [Solid(https://cyberbotics.com/doc/reference/solid) 节点的 boundingObject 字段中添加一个中间的 [Shape(https://cyberbotics.com/doc/reference/shape) 节点更方便。
实现墙壁的最佳几何图元是 Box 节点。
所有墙壁只需要定义一个 [Shape(https://cyberbotics.com/doc/reference/shape)。
预期结果如此图所示。
动手实践 #8:添加四面没有物理属性的墙壁,并且只使用一份 [Shape(https://cyberbotics.com/doc/reference/shape) 节点定义。
解答:世界文件
要将你的世界与解答进行对比,请进入你的文件目录,找到在[教程 1(tutorial-1-your-first-simulation-in-webots.html)中创建的名为 "my_first_simulation" 的文件夹,然后进入 "worlds" 文件夹,用文本编辑器打开对应的世界文件。 本解答与其他解答一样位于解答目录中。

效率
刚体的仿真在计算上开销很大。
可以通过减少包围对象(bounding object)的数量、尽量减少它们之间的约束(关于约束的更多信息见后续教程),以及增大 WorldInfo.basicTimeStep 字段来提高仿真速度。
在每一次仿真中,都必须在仿真速度和真实感之间找到一个折衷。
结论
完成本教程后,你能够创建基于刚体的简单环境。 你能够从场景树视图添加节点并修改它们的字段。 你已经熟悉了 [Solid(https://cyberbotics.com/doc/reference/solid)、[Physics(https://cyberbotics.com/doc/reference/physics)、[Shape(https://cyberbotics.com/doc/reference/shape)、[Sphere(https://cyberbotics.com/doc/reference/sphere) 和 [Box(https://cyberbotics.com/doc/reference/box) 节点。 你还学习了 DEF-USE 机制,它能够减少场景树中节点的冗余。