Cyberbotics 机器人课程/中级编程练习
在上一章中,您学习了如何使用 C 编程语言详细地操作 e-puck 设备。现在您具备了开始本章关于机器人行为的技术背景。将使用不同的技术来编程 e-puck 的行为。值得注意的是,您将看到您的机器人拥有记忆。
编程自动机 [中级]
[edit | edit source]在本练习中,您将把 初级编程练习 中的 FSM 转换成 C 编程语言。首先,将提供一个简单的示例,即 简单行为:有限状态机 练习的新版本。然后,您将创建自己的 FSM。它将是 更好的碰撞避免算法 练习的新版本。
打开世界文件
[edit | edit source]打开以下世界文件
.../worlds/intermediate_finite_state_machine.wbt
您应该看到与 简单行为:有限状态机 部分相同的环境。
FSM 的示例
[edit | edit source]根据图 传感器到执行器循环.png,您的程序主循环应始终按照以下顺序执行其指令
- 获取传感器值
- 根据预期行为处理这些值
- 向执行器发送命令
在我们的例子中,机器人的行为部分是使用 FSM 建模的。
[Q.1] 在给定的 C 编程代码中,找出这 3 个点的位置。解释在每个点中执行了什么操作。
[Q.2] 描述 FSM 是如何实现的,即当前状态是如何建模的,使用了哪种控制结构,状态中执行了哪些指令,从一个状态切换到另一个状态的条件是什么等等。
创建你自己的 FSM
[edit | edit source][P.1] 使用 FSM 实现墙体跟随算法。(提示:开始设计自动机的结构,然后找到触发转换的方式,最后根据经验设置参数。)
*割草机* [中级]
[edit | edit source]在本可选练习中,您将发现机器人技术的另一个主题:穷尽式探索,即您的 e-puck 将在形状未知的表面上移动,并且必须经过每个地方。清洁机器人或自动割草机是这种运动的典型应用。有不同的方法可以处理这个主题。本练习介绍了其中两种:随机行走和“扫描”行走。
随机行走
[edit | edit source]打开以下世界文件
.../worlds/intermediate_lawn_mower.wbt
您应该看到一个带有白色树篱的草坪。目前,机器人的控制器与上一个练习的控制器相同,即一个简单的 FSM,它允许您的 e-puck 在遇到墙壁时返回。在本节中,您将创建一个随机行走。
当您的 e-puck 遇到墙壁时,它必须旋转并朝另一个方向移动,如下图所示。下图描绘了随机行走可能的自动机。
为了生成 0 到 X 之间的随机整数,导入标准库 (#include <stdlib.h>) 和时间库 (#include <time.h>),并编写以下两条指令
// The utility of this line is to have at every simulation a different
// series of random number
srand(time(0));
// change X by the maximal bound (in the double format)
int random_value = X * rand() / (RAND_MAX+1);
[Q.1] 使用 BotStudio 无法实现随机行走的哪一部分?
[P.1] 实现图中给出的自动机:随机行走。对于停止条件,您可以使用定时器或使用编码器的条件。(提示:您可以合并“左转”状态和“随机左转”状态。右边的部分也是如此。)
[Q.2] 一般来说,随机游走算法在表面覆盖方面是否有效?(提示:e-puck 会经过每个点吗?是否有 e-puck 花费更多时间的地方?)
另一种执行全面覆盖的解决方案是“扫描”区域,如图所示。首先,执行水平扫描,然后,当机器人没有更多前进的可能性时,执行垂直扫描。相应的自动机在下一张图中显示。这个自动机是你迄今为止见过的最大的自动机。
[P.2] 实现图中给出的自动机:“扫描式行走”。(提示:你可以利用此自动机的对称性来简化实现。)
[Q.3] 一般来说,扫描式行走算法在表面覆盖方面是否有效?(提示:你能找到另一种房间拓扑结构,以便找到 e-puck 永远不会经过的地方吗?是否有 e-puck 花费更多时间的地方?)
现在,你知道程序如何使用 FSM 来创建机器人行为。FSM 可以用数学方式形式化。此外,这个概念背后有一个理论:自动机理论。FSM 只是这个理论的一部分。你可以在那里找到其他类型的自动机。例如,概率自动机在其转换上具有概率。因此,一个状态和固定的传感器值可能具有不同的下一个状态。有关此主题的更多信息,你可以参考
这是一个良好的起点。在文献中,你会找到几本相关的书籍。
到目前为止,你已经学会了使用有限状态自动机来编程机器人行为。接下来的三个练习将向你解释一个完全不同的处理此主题的方法:基于行为的机器人,由教授 Rodney Brooks[1] 在 1986 年的论文[2] 中提出。
基于行为的机器人是一种创建机器人行为(编程机器人控制器)的方法。其想法是将复杂的行为分成多个更小的行为模块。这些模块是独立的且半自主的。它们有其特定的作用。它们共同工作,无需同步。这些模块的典型示例可能是:“向前走”、“保持直立”、“有障碍物就停止”、“沿着墙壁走”、“寻找食物”、“快乐”或“帮助社区”。你可以观察到这些例子是按层次结构排列的。在层次结构的较低层,将有反射模块(如“保持直立”)。在层次结构的较高层,将有机器人的目标(如“找到食物”)。反射模块可以影响其层次结构上的上级。实际上,如果你绊倒了,保持站立是最重要的:来自你脚部感觉的命令会支配你思考的能力。
模块的外部结构在图中显示。模块直接从传感器或另一个模块接收输入值。这些值可以被另一个模块抑制。类似地,输出值被直接定向到执行器或另一个模块。最后,模块可能具有重置功能。
有多种方法可以实现这些模块。我们决定使用 C 函数来模拟它们。实际上,函数接收参数作为输入并返回输出值。为了简化代码,这些值中的一些存储在全局变量中,以便于模块之间的通信。
在本练习中,你将实际观察到基于行为的机器人,它有两个模块:避障模块和循墙模块。首先,你将独立观察这些模块。然后,你将把它们混合在一起。
本练习与接下来的两个练习密切相关。
打开以下世界文件
.../worlds/intermediate_oam.wbt
你应该观察到一个被障碍物点缀的环境。不要犹豫,移动它们或重叠它们。
给定的机器人控制器实际上只使用避障模块 (OAM)。该模块是一个反射模块。它会一直运行。它接收 IR 传感器值作为输入。如果在 e-puck 前方检测到障碍物,OAM 将计算其自身的加速度估计,以避免碰撞。它只能使机器人自转(左速度 = - 右速度)。最后,OAM 更新side变量以记住墙壁的位置。此信息将有助于其他模块。
[P.1] 在虚拟 e-puck 和实际 e-puck 上运行模拟。
[Q.1] 描述 e-puck 的行为。它遇到墙壁时的反应是什么?在它前方没有障碍物时,它的轨迹是什么?
[Q.2] OAM 产生电机速度差,但机器人向前移动。为什么?
[Q.3] 在 OAM 函数中,如何计算电机速度差(delta变量)?
第二个模块(称为循墙模块 (WFM))根据side变量创建恒定的电机速度差。它的作用是吸引 e-puck 靠近墙壁。如果只有这个模块,机器人会撞到墙壁。幸运的是,如果 OAM 模块也被启用,它会产生排斥力。这两个模块的组合会产生更强大的行为:机器人将能够沿着墙壁走。在生物学中,这种现象被称为涌现。
图描述了这两个模块之间的交互。水平方向上,图表的划分类似于 传感器到执行器循环.png 中的划分,它就是感知到行动的循环。垂直方向上,模块被层次结构层级划分。最底层是反射层级。来自 OAM 到 WFM 的黑色箭头表示sidevariable。
[P.2] 在主函数的主循环中,取消注释wfm()函数调用,并编译您的程序。在虚拟机和真实的 e-puck 上运行仿真。观察机器人的行为。尝试移动 e-puck 所“链接”的障碍物。
[Q.5] 比较图和给定的控制器代码。 (提示:黑色箭头是如何实现的?传感器值是如何发送到模块的?)
[Q.6] 解释wb_differential_wheels_set_speed(...)函数调用中每个求和项的用途。
*[P.3]* 在仿真中,尝试通过更改宏变量(查看使用 #define 语句定义的变量)来获得尽可能平滑的 e-puck 轨迹。带有两个箭头(绿色和红色)的图形显示了与蛇形轨迹相比的平滑轨迹。请注意,平滑轨迹在很大程度上取决于环境,即,如果您获得了平滑轨迹,并且更改了障碍物宽度,您的机器人可能会出现蛇形轨迹。
创建一条线跟随模块 [中级]
[edit | edit source]在上一节练习中,您观察了两个模块之间的交互。在本节练习中,您将同样看到一些其他模块及其交互。本节练习的目的是观察三个模块如何生成一个强大的线跟随控制器。最后,您将创建自己的模块。
打开世界文件
[edit | edit source]打开以下世界文件
.../worlds/intermediate_lfm.wbt
e-puck 准备好在起跑线上绕环形轨道转弯。
用于墙跟随的三个模块
[edit | edit source]本节练习的机器人控制器使用三个模块
- 线跟随模块 (LFM):首先,该模块接收线性相机值(相机最后一行)。借助find_middle(...)函数,它找到机器人前方黑线的中点。然后,它计算出自身对电机速度的理解。与 OAM 类似,此函数只创建电机速度差。这是一个高级模块。它的输入值可以被抑制。
- 线进入模块 (LEM):此模块也观察线性相机值。它会注意到机器人的视野中是否有线。
- 线离开模块 (LLM):此模块与 LEM 协同工作。它会注意到机器人的视野中是否没有线。
LEM 和 LLM 的用途在 e-puck 进入或离开线时显现。通过使用这些模块,这两个事件得以掌控。在本节练习中,这两个模块用于在没有线可跟随时抑制 LFM。这使得机器人能够直线前进。在下一节练习中,我们将使用这两个事件来实现更有用的目的。
这些模块之间的交互在示意图中有所体现。
[P.1] 在虚拟 e-puck 和实际 e-puck 上运行模拟。
[Q.1] 比较图和给定的控制器代码。暂时不要看 UTM。 (提示:LFM 抑制器的作用是什么?LEM 和 LFM 在代码中是如何关联的?为什么图中它们之间没有链接?等等)
[P.2] 修改给定的代码,以便在 e-puck 检测到线时打开 8 个 LED,并在没有检测到线时关闭它们。
您自己的模块
[edit | edit source][P.3] 实现一个新的模块(称为utm()),当机器人前方不再有线时,该模块可以让 e-puck 进行 U 形转弯。当 WFM 被抑制时,此模块将起作用,反之亦然。在此模块中,机器人应该只产生电机速度差。
多个模块的混合 [中级]
[edit | edit source]在之前的两个练习中,您观察了 5 个不同的模块。现在,您将组合它们以获得更复杂的行为。
打开世界文件
[edit | edit source]打开以下世界文件
.../worlds/intermediate_behavior_based.wbt
您应该观察图中显示的世界。地面上绘制了一条线。它呈“C”形。一些障碍物散落在这条线上。
多个模块的组合
[edit | edit source]本节练习的目标是获得以下行为:e-puck 沿着这条线行走,但如果它检测到障碍物,它必须绕过障碍物,直到再次找到这条线。
给定的机器人控制器包含所有先前的模块,但它们之间没有链接。该示意图显示了一种可能的链接方式。该示意图中最重要的点是观察从一个模块到另一个模块的交互
- OAM:它是唯一一个反射模块。如果 OAM 检测到障碍物,它必须抑制 LFM 以避免其影响。OAM 还必须告知 WFM 墙的位置。
- LEM:它的作用是在检测到黑线时解除对 LFM 的抑制。此外,它必须告知 WFM 它必须停止跟随墙壁。
- LLM:如果丢失黑线,它必须抑制 LFM。
[P.1] 实现模块之间的交互,以获得上面描述的行为。参考示意图以了解交互方式。 (提示:您需要修改的代码片段以 TODO 注释标记。)
[Q.1] 与基于有限状态机的机器人相比,基于行为的机器人的优势是什么?劣势是什么?可以将这两种技术结合起来使用吗?举例说明。
- ↑ 参见 罗德尼·布鲁克斯 获取更多信息。
- ↑ Brooks, R. A. "用于移动机器人的鲁棒分层控制系统", IEEE 机器人与自动化杂志,第 2 卷,第 1 期,1986 年 3 月,第 14-23 页; 也是 MIT AI 备忘录 864,1985 年 9 月。