墙面标识
机器人需要做什么
Section titled “机器人需要做什么”墙面标识(Wall tokens)占了你得分的大部分,而每次错误的报告都会扣 5 分。所以对于你找到的每一个标识,都必须做出判断:
| 它是…… | 怎么做 |
|---|---|
| 字母受害者(Letter victim:Φ、Ψ、Ω) | 报告 H、S 或 U |
| 假受害者(Fake victim:同样的符号,但是立体的) | 不要报告,也不要把它画进地图 |
| 数值之和为 0 到 3 的认知目标(Cognitive target) | 报告 F、P、C 或 O |
| 数值之和为其他值的认知目标 | 它是假标识:不要报告,也不要把它画进地图 |
摄像头看到的画面
Section titled “摄像头看到的画面”入门机器人的摄像头只有 64 × 40 像素。在这个分辨率下,机器人靠近之前,一个标识只占几个像素,所以最好先从远处寻找可能的标识,再靠近去识别它们。记住,报告时机器人必须在距离标识半个地块以内;另外,自定义摄像头可以使用更高的分辨率,但要花费更多预算。

![]()
字母受害者是白色方块上的黑色符号,它们可能被旋转成任意角度,所以你的方法不能依赖于方向。

读取认知目标
Section titled “读取认知目标”认知目标由五个同心的部分组成,所以不需要识别它的形状:只要找到它的圆心和外半径,就可以在每个部分的中间取样颜色。各部分的半径分别是 0.5、1、1.5、2 和 2.5 cm,所以它们的中点分别位于外半径的 0、0.3、0.5、0.7 和 0.9 处。
下面的函数用 Python 和 OpenCV 实现了这一点。要找到圆心和半径,你可以像迷宫导航中那样使用目标的轮廓。
import cv2 as cvimport numpy as np
# Colour of each part in BGR order, as seen by the cameraCOLORS = { 'K': (0, 0, 0), # Black 'R': (0, 0, 255), # Red 'Y': (0, 255, 255), # Yellow 'G': (0, 255, 0), # Green 'B': (255, 0, 0), # Blue}
def nearestColor(bgr): # Returns the name of the colour that is closest to a pixel distances = {name: np.linalg.norm(np.array(color) - bgr) for name, color in COLORS.items()} return min(distances, key=distances.get)
def readRings(image, centerX, centerY, radius): # image is a BGR image, as in the RGB Camera tutorial # Returns the 5 colours from the center outwards, for example ['Y', 'B', 'R', 'K', 'G'] rings = [] for position in [0, 0.3, 0.5, 0.7, 0.9]: x = int(round(centerX + position * radius)) y = int(round(centerY)) rings.append(nearestColor(image[y, x].astype(float))) return rings在实际运行中,机器人可能会从斜着的角度看到目标,这时它看起来像一个椭圆。移动到目标正前方、把看起来不对的颜色当作警示,或者读取多帧画面,都能让结果更可靠。

得到五种颜色之后,要报告的代码就由它们的和决定。五个部分中的每一个都始终计入,即使相邻的颜色相同也是如此。
VALUES = {'K': -2, 'R': -1, 'Y': 0, 'G': 1, 'B': 2}CODES = {0: 'F', 1: 'P', 2: 'C', 3: 'O'}
def targetCode(rings): # rings is the list of the 5 colours of the target # Returns the code to report, or None if the target is fake total = sum(VALUES[color] for color in rings) return CODES.get(total)#include <map>#include <vector>
using namespace std;
// rings has the 5 colours of the target: 'K', 'R', 'Y', 'G' or 'B'// Returns the code to report, or 0 if the target is fakechar targetCode(const vector<char>& rings) { map<char, int> values = {{'K', -2}, {'R', -1}, {'Y', 0}, {'G', 1}, {'B', 2}}; int total = 0; for (char color : rings) total += values[color];
switch (total) { case 0: return 'F'; case 1: return 'P'; case 2: return 'C'; case 3: return 'O'; default: return 0; }}例如,['Y', 'B', 'R', 'K', 'G'] 的和为 0,所以它是 F;而 ['B', 'Y', 'K', 'K', 'K'] 的和为 -4,所以它是假标识。
识别假受害者
Section titled “识别假受害者”假受害者显示的符号与真受害者相同,但字母是立体的。从正面看,仅凭摄像头可能无法区分它们:

规则规定,可以用 Robot Customizer 中提供的某一种传感器检测出这种深度。下面是一些可以尝试的思路:
- 用激光雷达或距离传感器在标识上不同位置测量距离并进行比较,寻找高度差。
- 从斜着的角度观察标识,此时凸起会改变符号的形状。
world3.wbt 和 world4.wbt 这两个世界中包含假受害者,World Editor 也可以把它们添加到你自己的地图中。Erebus 还附带了脚本 scripts/update_maps_with_fakes.py,它会把现有世界中的受害者随机变成假受害者。
报告一个假标识会被算作误判,扣 5 分;而在区域 1 的线性地块上,一个真受害者连同正确类型可以得 15 分,在其他区域还会更多。在决定机器人需要多有把握才进行报告时,请记住这一点。
