本教程将带你熟悉 Webots 的界面和基本概念。你将创建一个包含地板、墙壁、箱子和 e-puck 机器人的仿真环境,并编写控制器让机器人运动。
第一个教程完成后你应该看到的效果
World(世界文件)是一个包含场景中所有对象位置、外观、交互方式、天空颜色、重力、摩擦、物体质量等信息的文件。它定义了仿真的初始状态。不同的对象称为 Nodes(节点),并以层级结构组织在 Scene Tree(场景树)中,因此一个节点可以包含子节点。世界文件以 .wbt
为扩展名,文件格式基于 VRML97 语言,且为人类可读。所有世界文件必须直接存放在名为 worlds
的目录下。
my_first_simulation
,不要用默认的 my_project
。my_first_simulation.wbt
,不要用默认的 empty.wbt
。Webots 会显示刚刚创建的目录和文件列表,这就是 Webots 项目的标准文件结构。点击 Finish(Windows, Linux)或 Done(macOS)按钮关闭此窗口。
恭喜!你已经创建了第一个 Webots 世界。3D 视图中会显示一个带有方格地板的正方形场地。你可以用鼠标左键、右键和滚轮在 3D 视图中移动视角(鼠标操作说明)。
Webots 世界文件中的节点以树状结构(scene tree)组织。主窗口有两个子窗口可查看场景树:3D 视图(窗口中央,显示场景树的三维效果)和 场景树视图(左侧,显示场景树的层级结构)。你可以在场景树视图中修改节点和属性。此时应能看到如下节点:
每个节点都有一些可自定义的属性,称为 Fields。我们来修改这些属性以调整矩形场地:
RectangleArena
节点,展开并显示其属性。
floorTileSize
字段,将其值设置为 0.25 0.25
(原值为 0.5 0.5
)。你会在 3D 视图中立即看到效果。wallHeight
字段,将其值改为 0.05
(原值为 0.1
)。场地的墙会变矮。在场景树视图中,如果某个字段的值与默认值不同,会以不同颜色显示(具体颜色取决于主题)。
现在我们来添加一些物体到场景中。我们将添加几个木箱来丰富仿真环境。
RectangleArena
节点将其关闭并选中。点击场景树顶部的 Add 按钮 。在弹出的对话框中,选择 PROTO nodes (Webots Projects) / objects / factory / containers / WoodenBox (Solid)。此时场地中央会出现一个大箱子。双击该箱子以展开其属性。
size
改为 0.1 0.1 0.1
(原值为 0.6 0.6 0.6
)。translation
改为 0 0 0.05
(原值为 0 0 0.3
)。也可以用 3D 视图中的蓝色箭头调整 translation.z
。WoodenBox
节点的 rotation
字段。如何用平移和旋转手柄移动物体,可参考本节说明。
e-puck 是一款小型差速轮机器人,带有 10 个 LED 和多个传感器(包括 8 个 距离传感器 和一个 摄像头)。本教程只用到它的轮子,其他功能将在后续教程中介绍。
现在我们要将 e-puck 机器人添加到世界中。请确保仿真已暂停且虚拟时间为 0(如不是,请点击
重置按钮)。当你打算保存 Webots 世界时,务必先暂停仿真并重置到初始状态(主工具栏虚拟时间应为 0:00:00:000),否则每次保存时 3D 对象的位置可能会累计误差。因此,修改世界的正确顺序是:暂停、重置、修改并保存。
我们无需从零创建 e-puck,只需导入一个 E-puck
节点即可。这个节点其实是一个 PROTO 节点,和前面用到的 RectangleArena
、WoodenBox
一样。PROTO 机制允许你创建和复用自定义对象。
WoodenBox
节点。点击场景树顶部的 Add 按钮 。在对话框中选择 PROTO nodes (Webots Projects) / robots / gctronic / e-puck / E-puck (Robot)。此时场地中央会出现一台 e-puck 机器人。像移动箱子一样拖动和旋转机器人。保存仿真,并点击 按钮运行仿真。
机器人会自动移动、闪灯并避障,这是因为它有默认的控制器。你可能会注意到 3D 视图左上角弹出一个黑色小窗口,显示 e-puck 机器人摄像头的画面。只有当控制器显式启用摄像头时,这个画面才会显示内容。你可以拖动该窗口移动位置,也可以拖动右下角调整大小,点击右上角"x"关闭。需要时可在 Overlays 菜单的 Camera Devices 子菜单中重新打开。由于本教程暂不需要摄像头画面,可以直接关闭。
现在,仿真运行时我们来体验一下物理效果:
WoodenBox
节点没有质量,被视为固定在地面,无法施加力。要让箱子参与物理仿真,请将 WoodenBox
的 mass
字段设置为非零值(如 0.2kg),这样就可以对箱子施加力了。
仿真可以通过
暂停、 单步、 实时运行或 快速运行。现在我们要修改世界,将物理仿真的步长(时间步长)调小,这样可以提升仿真的精度和稳定性(但会降低最大仿真速度)。
basicTimeStep
字段设置为 16,然后保存仿真。
控制器(controller)是定义机器人行为的程序。Webots 控制器可以用多种编程语言编写:C、C++、Java、Python、MATLAB 等。C、C++ 和 Java 控制器需要编译后才能运行,Python 和 MATLAB 控制器为解释型语言,无需编译即可直接运行。本教程以 C 语言为例,所有代码片段也可用于 C++、Java、Python 和 MATLAB。关于不同语言的控制器设置方法,请参考语言章节。
controller
字段用于指定 Robot
节点当前关联的控制器。注意:同一个控制器可以被多个机器人共用,但每个机器人同一时刻只能使用一个控制器。每个控制器会作为独立的子进程由 Webots 启动,因此它们拥有独立的地址空间,可能运行在不同的 CPU 核心上。
epuck_go_forward
(C++/Java 命名为 EPuckGoForward
),通过菜单 File / New / New Robot Controller...。这将在 my_first_simulation/controllers
目录下创建一个新的 epuck_go_forward
(或 EPuckGoForward
)文件夹。选择“在文本编辑器中打开源文件”。
新建的源文件会在 Webots 的文本编辑器中显示。Python 代码可直接编译,但初始代码没有实际功能。接下来我们将把新建的 epuck_go_forward
(或 EPuckGoForward
)控制器关联到 E-puck
节点。
E-puck
节点的 controller
字段,在底部属性编辑器中点击 Select...,然后在列表中选择 epuck_go_forward
。控制器关联后,保存世界。leftMotor = robot.getDevice('left wheel motor')
),并设置电机目标位置(如 leftMotor.setPosition(10.0)
):
from controller import Robot, Motor
TIME_STEP = 64
# 创建机器人实例
robot = Robot()
# 获取电机设备
leftMotor = robot.getDevice('left wheel motor')
rightMotor = robot.getDevice('right wheel motor')
# 设置电机目标位置
leftMotor.setPosition(10.0)
rightMotor.setPosition(10.0)
while robot.step(TIME_STEP) != -1:
pass
机器人的轮子通常用速度(velocity)而不是位置(position)来控制。要让轮子以速度模式运行,需要将目标位置设为无穷大(float('inf')
),然后设置期望的速度。
from controller import Robot, Motor
TIME_STEP = 64
MAX_SPEED = 6.28
# 创建机器人实例
robot = Robot()
# 获取电机句柄,并将目标位置设为无穷大(速度控制)
leftMotor = robot.getDevice('left wheel motor')
rightMotor = robot.getDevice('right wheel motor')
leftMotor.setPosition(float('inf'))
rightMotor.setPosition(float('inf'))
# 设置电机速度为最大速度的10%
leftMotor.setVelocity(0.1 * MAX_SPEED)
rightMotor.setVelocity(0.1 * MAX_SPEED)
while robot.step(TIME_STEP) != -1:
pass
恭喜你完成了第一个 Webots 仿真项目!你已经学会了:
.wbt
文件中,位于 Webots 项目目录下。controller
字段与 Robot
节点关联。下一步: 在教程 2中,你将学习如何修改环境和添加更多对象到仿真世界中。