跳到內容
中文(繁體)

通訊

你的程式透過每台機器人都有的兩個裝置與比賽溝通:

  • 發射器(emitter)會傳送訊息給比賽。它不需要啟用。
  • 接收器(receiver)會接收來自比賽的訊息。請像感測器一樣啟用它。

以下每一節都是一個適用於入門機器人的完整程式。所有訊息都列在訊息參考中。

要靠字母受害者或認知目標得分,機器人必須:

  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)會把它移回最後一個檢查點,並扣 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% 的出口加成。

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)

接下來,在牆上的標記中學習如何分辨各種標記。