การสื่อสาร
โปรแกรมของคุณสื่อสารกับเกมผ่านอุปกรณ์สองชิ้นที่หุ่นยนต์ทุกตัวมี:
- ตัวส่ง (emitter) ส่งข้อความไปยังเกม ไม่จำเป็นต้องเปิดใช้งาน
- ตัวรับ (receiver) รับข้อความจากเกม ให้เปิดใช้งานเหมือนเซนเซอร์
แต่ละหัวข้อด้านล่างเป็นโปรแกรมที่สมบูรณ์สำหรับหุ่นยนต์เริ่มต้น ข้อความทั้งหมดอยู่ในข้อมูลอ้างอิงข้อความ
การทำคะแนนจากสัญลักษณ์บนผนัง
หัวข้อที่มีชื่อว่า “การทำคะแนนจากสัญลักษณ์บนผนัง”ในการทำคะแนนจากผู้ประสบภัยแบบตัวอักษร (letter victim) หรือเป้าหมายเชิงรับรู้ (cognitive target) หุ่นยนต์ต้อง:
- หยุดนิ่งนานกว่า 1 วินาที ใกล้กับสัญลักษณ์ Erebus จะไม่รับการรายงานหากหุ่นยนต์เคลื่อนที่ภายใน 1 วินาทีที่ผ่านมา
- ส่งตำแหน่งและชนิดของสัญลักษณ์: X และ Z เป็นเซนติเมตร และชนิดเป็นตัวอักษรหนึ่งตัว
| สัญลักษณ์บนผนัง | ชนิด |
|---|---|
| ผู้ประสบภัยแบบตัวอักษร Φ (บาดเจ็บ) | H |
| ผู้ประสบภัยแบบตัวอักษร Ψ (อาการคงที่) | S |
| ผู้ประสบภัยแบบตัวอักษร Ω (ไม่บาดเจ็บ) | U |
| เป้าหมายเชิงรับรู้ ผลรวม 0 (ก๊าซไวไฟ) | F |
| เป้าหมายเชิงรับรู้ ผลรวม 1 (สารพิษ) | P |
| เป้าหมายเชิงรับรู้ ผลรวม 2 (สารกัดกร่อน) | C |
| เป้าหมายเชิงรับรู้ ผลรวม 3 (สารเปอร์ออกไซด์อินทรีย์) | O |
ชนิดยังคงเป็นตัวอักษร แม้ว่าตั้งแต่ปี 2026 ผู้ประสบภัยจะแสดงเป็นสัญลักษณ์แทนแล้ว ส่วน GPS ให้ค่าเป็นเมตร จึงต้องคูณด้วย 100
from controller import Robotimport 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 isprint("Reported")#include <iostream>#include <cmath>#include <cstring>#include <webots/Robot.hpp>#include <webots/Emitter.hpp>#include <webots/GPS.hpp>#include <webots/Motor.hpp>
using namespace webots;
Robot *robot;Emitter *emitter;GPS *gps;Motor *leftWheel, *rightWheel;int timeStep;
void wait(double seconds) { double start = robot->getTime(); while (robot->step(timeStep) != -1) { if (robot->getTime() - start >= seconds) break; }}
void report(char 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 int position[2] = {(int)(gps->getValues()[0] * 100), (int)(gps->getValues()[2] * 100)}; char message[9]; memcpy(message, position, sizeof(position)); message[8] = tokenType; emitter->send(message, sizeof(message)); robot->step(timeStep);}
int main() { robot = new Robot(); timeStep = (int)robot->getBasicTimeStep();
emitter = robot->getEmitter("emitter"); // Always on the robot. It does not need to be enabled. gps = robot->getGPS("gps"); gps->enable(timeStep); leftWheel = robot->getMotor("left wheel motor"); rightWheel = robot->getMotor("right wheel motor"); leftWheel->setPosition(INFINITY); rightWheel->setPosition(INFINITY);
report('H'); // Reports a harmed victim (Φ) where the robot is std::cout << "Reported" << std::endl;
delete robot; return 0;}หุ่นยนต์ต้องอยู่ฝั่งเดียวกันของผนังกับสัญลักษณ์ และทั้งหุ่นยนต์และตำแหน่งที่คุณส่งต้องอยู่ใกล้สัญลักษณ์ กติกากำหนดไว้ไม่เกินครึ่งช่อง จึงควรให้อยู่ในระยะนั้น ส่วน Erebus v26.1 ตรวจสอบที่ระยะ 9 ซม.
รันโปรแกรมนี้ที่จุดเริ่มต้นของ world1.wbt: ที่นั่นไม่มีสัญลักษณ์ ประวัติของหน้าต่างควบคุมจึงแสดง Misidentification of Victim -5 การรายงานผิด รวมถึงการรายงานของปลอม จะเสีย 5 คะแนน และสัญลักษณ์แต่ละอันได้คะแนนเพียงครั้งเดียว

การไม่มีความคืบหน้า
หัวข้อที่มีชื่อว่า “การไม่มีความคืบหน้า”เมื่อหุ่นยนต์ติดอยู่ การไม่มีความคืบหน้า (lack of progress) จะย้ายหุ่นยนต์กลับไปยังจุดตรวจล่าสุดและเสีย 5 คะแนน ซึ่งจะเกิดขึ้นโดยอัตโนมัติเมื่อหุ่นยนต์ไม่เคลื่อนที่ 20 วินาที และโปรแกรมของคุณก็เรียกเองได้โดยส่ง L ทุกครั้งที่เกิดขึ้น เกมจะส่ง L ให้หุ่นยนต์ เพื่อให้โปรแกรมของคุณรู้ว่าตำแหน่งเปลี่ยนไปแล้ว
from controller import Robotimport struct
robot = Robot()timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")receiver = robot.getDevice("receiver")receiver.enable(timeStep) # The receiver must be enabled
askedAt = Nonewhile 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()#include <iostream>#include <webots/Robot.hpp>#include <webots/Emitter.hpp>#include <webots/Receiver.hpp>
using namespace webots;using namespace std;
int main() { Robot *robot = new Robot(); int timeStep = (int)robot->getBasicTimeStep();
Emitter *emitter = robot->getEmitter("emitter"); Receiver *receiver = robot->getReceiver("receiver"); receiver->enable(timeStep); // The receiver must be enabled
bool asked = false; while (robot->step(timeStep) != -1) { // Call a lack of progress once, after 2 seconds if (!asked && robot->getTime() > 2) { char message = 'L'; emitter->send(&message, 1); asked = true; }
// Listen for messages from the game while (receiver->getQueueLength() > 0) { const char *data = (const char *)receiver->getData(); if (receiver->getDataSize() == 1 && data[0] == 'L') cout << "Lack of progress! The robot is back at the last checkpoint." << endl; receiver->nextPacket(); } }
delete robot; return 0;}ตัวรับอาจได้รับข้อความหลายแบบ จึงควรตรวจสอบความยาวของแต่ละข้อความก่อนอ่าน เหมือนในตัวอย่าง
ข้อมูลของเกม
หัวข้อที่มีชื่อว่า “ข้อมูลของเกม”ส่ง G เพื่อรับคะแนนและเวลาที่เหลือ เกมจะตอบกลับด้วยข้อความขนาด 16 ไบต์: ตัวอักษร G คะแนน เวลาเกมที่เหลือ และเวลาจริงที่เหลือ เป็นวินาที
from controller import Robotimport struct
robot = Robot()timeStep = int(robot.getBasicTimeStep())
emitter = robot.getDevice("emitter")receiver = robot.getDevice("receiver")receiver.enable(timeStep)
lastAsked = 0while 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()#include <iostream>#include <cstring>#include <webots/Robot.hpp>#include <webots/Emitter.hpp>#include <webots/Receiver.hpp>
using namespace webots;using namespace std;
int main() { Robot *robot = new Robot(); int timeStep = (int)robot->getBasicTimeStep();
Emitter *emitter = robot->getEmitter("emitter"); Receiver *receiver = robot->getReceiver("receiver"); receiver->enable(timeStep);
double lastAsked = 0; while (robot->step(timeStep) != -1) { // Ask for the game information once a second if (robot->getTime() - lastAsked > 1) { char message = 'G'; emitter->send(&message, 1); lastAsked = robot->getTime(); }
while (receiver->getQueueLength() > 0) { const char *data = (const char *)receiver->getData(); if (receiver->getDataSize() == 16 && data[0] == 'G') { // The game information is 16 bytes long float score; int timeLeft, realTimeLeft; memcpy(&score, data + 4, 4); memcpy(&timeLeft, data + 8, 4); memcpy(&realTimeLeft, data + 12, 4); cout << "Score: " << score << " Time left: " << timeLeft << " s Real time left: " << realTimeLeft << " s" << endl; } receiver->nextPacket(); } }
delete robot; return 0;}เวลาของเกมเดินเร็วขึ้นในหนองน้ำ และเกมจะจบเมื่อเวลาอย่างใดอย่างหนึ่งหมด ใช้ทั้งสองค่าเพื่อตัดสินใจว่าควรเริ่มกลับไปยังจุดเริ่มต้นเมื่อใด
การจบเกม
หัวข้อที่มีชื่อว่า “การจบเกม”ส่ง E เพื่อจบเกม หากหุ่นยนต์อยู่บนช่องเริ่มต้นและได้ระบุสัญลักษณ์บนผนังไปแล้วอย่างน้อยหนึ่งอัน จะได้รับโบนัสออกจากสนาม (exit bonus) 10%
from controller import Robotimport 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)#include <iostream>#include <webots/Robot.hpp>#include <webots/Emitter.hpp>
using namespace webots;
int main() { Robot *robot = new Robot(); int timeStep = (int)robot->getBasicTimeStep(); Emitter *emitter = robot->getEmitter("emitter");
robot->step(timeStep); std::cout << "Ending the game" << std::endl; // 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. char message = 'E'; emitter->send(&message, 1); robot->step(timeStep);
delete robot; return 0;}ขั้นต่อไป เรียนรู้การแยกแยะสัญลักษณ์ในสัญลักษณ์บนผนัง
