跳转到内容
中文(简体)

通信

你的程序通过每个机器人都有的两个设备与比赛通信:

  • 发射器(emitter)向比赛发送消息。它不需要启用。
  • 接收器(receiver)接收来自比赛的消息。像传感器一样启用它。

下面每一节都是一个适用于入门机器人的完整程序。所有消息都列在消息参考中。

要为一个字母受害者(Letter victim)或认知目标(Cognitive target)得分,机器人必须:

  1. 在标识附近停止超过 1 秒。如果机器人在最近一秒内移动过,Erebus 会忽略这次报告。
  2. 发送标识的位置和类型:X 和 Z 以厘米为单位,类型用一个字母表示。
墙面标识 类型
字母受害者 Φ(受伤) H
字母受害者 Ψ(稳定) S
字母受害者 Ω(未受伤) U
认知目标,和为 0(易燃气体) F
认知目标,和为 1(毒性物质) P
认知目标,和为 2(腐蚀性物质) C
认知目标,和为 3(有机过氧化物) O

虽然从 2026 年起受害者显示的是符号,但类型仍然是字母。GPS 给出的单位是米,所以要乘以 100。

from controller import Robot
import struct
robot = Robot()
timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter") # Always on the robot. It does not need to be enabled.
gps = robot.getDevice("gps")
gps.enable(timeStep)
leftWheel = robot.getDevice("left wheel motor")
rightWheel = robot.getDevice("right wheel motor")
leftWheel.setPosition(float("inf"))
rightWheel.setPosition(float("inf"))
def wait(seconds):
start = robot.getTime()
while robot.step(timeStep) != -1:
if robot.getTime() - start >= seconds:
break
def report(tokenType):
# 1. Stop for more than 1 second
leftWheel.setVelocity(0)
rightWheel.setVelocity(0)
wait(1.2)
# 2. Send the position in centimeters, and the type as one letter
x, _, z = gps.getValues()
message = struct.pack("i i c", int(x * 100), int(z * 100), tokenType.encode())
emitter.send(message)
robot.step(timeStep)
report("H") # Reports a harmed victim (Φ) where the robot is
print("Reported")

机器人必须和标识位于墙的同一侧,而且机器人和你发送的位置都必须离标识足够近。规则要求的距离最多为半个地块,所以请以此为目标。Erebus v26.1 检查的距离是 9 cm。

在 world1.wbt 的起点运行这个程序:那里没有标识,所以控制窗口的历史记录会显示 Misidentification of Victim -5。错误的报告(包括报告假标识)会扣 5 分,而且每个标识只能得分一次。

一次错误报告和提交地图之后,控制窗口中的历史记录

当机器人被卡住时,缺乏进展(Lack of progress,LoP)会把它移回最后一个检查点,并扣 5 分。机器人 20 秒不动时会自动触发,你的程序也可以通过发送 L 来主动请求。每次发生时,比赛都会向机器人发送 L,让你的程序知道它的位置已经改变。

from controller import Robot
import struct
robot = Robot()
timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")
receiver = robot.getDevice("receiver")
receiver.enable(timeStep) # The receiver must be enabled
askedAt = None
while robot.step(timeStep) != -1:
# Call a lack of progress once, after 2 seconds
if askedAt is None and robot.getTime() > 2:
emitter.send(struct.pack("c", b"L"))
askedAt = robot.getTime()
# Listen for messages from the game
while receiver.getQueueLength() > 0:
data = receiver.getBytes()
if len(data) == 1 and data == b"L":
print("Lack of progress! The robot is back at the last checkpoint.")
receiver.nextPacket()

接收器可能会收到不同的消息,所以像示例中那样,在读取每条消息之前先检查它的长度。

发送 G 来获取得分和剩余时间。比赛会回复一条 16 字节的消息:字母 G、得分、剩余比赛时间和剩余真实时间,时间以秒为单位。

from controller import Robot
import struct
robot = Robot()
timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")
receiver = robot.getDevice("receiver")
receiver.enable(timeStep)
lastAsked = 0
while robot.step(timeStep) != -1:
# Ask for the game information once a second
if robot.getTime() - lastAsked > 1:
emitter.send(struct.pack("c", b"G"))
lastAsked = robot.getTime()
while receiver.getQueueLength() > 0:
data = receiver.getBytes()
if len(data) == 16: # The game information is 16 bytes long
_, score, timeLeft, realTimeLeft = struct.unpack("c f i i", data)
print("Score:", round(score, 2), "Time left:", timeLeft, "s", "Real time left:", realTimeLeft, "s")
receiver.nextPacket()

在沼泽中,比赛时间会流逝得更快,而任意一个时间耗尽时比赛就会结束。同时利用这两个时间来判断什么时候该返回起点。

发送 E 来结束比赛。如果机器人位于起始地块上,并且已经识别出至少一个墙面标识,就能获得 10% 的离场奖励(Exit bonus)。

from controller import Robot
import struct
robot = Robot()
timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")
robot.step(timeStep)
print("Ending the game")
# Ends the game. Send it on the starting tile, after identifying a token, to get the exit bonus.
# The game stops your program right after this message.
emitter.send(struct.pack("c", b"E"))
robot.step(timeStep)

接下来,在墙面标识中学习如何区分各种标识。