Lập trình Controller đầu tiên trong Webots bằng Python
Trong hướng dẫn trước, bạn đã nắm được cách thiết lập cơ bản và thao tác với giao diện mô phỏng. Bước tiếp theo, sau khi có sẵn một mô hình 3D, chúng ta cần một đoạn mã để xử lý tín hiệu cảm biến và ra lệnh cho các động cơ hoạt động. Đoạn mã này trong Webots được gọi là controller. Ghi chú này sẽ tiếp nối chuỗi bài viết, tóm tắt quy trình cơ bản để khởi tạo một controller bằng Python: từ việc tìm tên thiết bị phần cứng, cấu hình bước thời gian (time step), cho đến đọc tín hiệu khoảng cách và điều khiển bánh xe.
Tạo file Controller mới
Để bắt đầu lập trình, bạn cần tạo một file mã nguồn liên kết trực tiếp với thế giới mô phỏng hiện tại.
- Trên thanh menu của Webots, chọn File -> New-> New Robot Controller...
- Chọn ngôn ngữ là Python (đây là ngôn ngữ rất phổ biến và dễ đọc, rất phù hợp để bắt đầu).
- Đặt tên cho controller (ví dụ:
my_first_controller). - Webots sẽ tạo một thư mục chứa script Python và tự động mở nó trong Text Editor bên phải màn hình.
Lưu ý quan trọng: Sau khi tạo xong, bạn phải liên kết bộ não này với thân xác robot. Hãy mở Scene Tree ở bên trái, tìm đến node robot của bạn (ví dụ node E-puck hoặc Robot), mở rộng cấu trúc, tìm đến trường controller và chọn đúng tên file script mà bạn vừa tạo. Sau đó bạn chọn lại nút Edit bên cạnh để hiển thị nội dung chương trình ở góc bên phải.

Cấu trúc của một chương trình điều khiển bằng python
Bất kỳ controller nào trong Webots cũng bắt đầu bằng một cấu trúc cốt lõi: khởi tạo thực thể robot và tạo một vòng lặp vô hạn chạy theo TIME_STEP (bước thời gian mô phỏng).
from controller import Robot
# Khởi tạo API Robot
robot = Robot()
# Lấy bước thời gian mặc định của thế giới mô phỏng (tính bằng ms)
timestep = int(robot.getBasicTimeStep())
# Vòng lặp mô phỏng chính
while robot.step(timestep) != -1:
# Mọi logic đọc cảm biến và điều khiển động cơ nằm ở đây
passHàm robot.step(timestep) làm nhiệm vụ đồng bộ code của bạn với môi trường vật lý. Mỗi lần vòng lặp chạy, thời gian mô phỏng sẽ tiến tới đúng một lượng bằng timestep mili-giây.
Điều khiển Động cơ (Motor)
Để di chuyển, bạn cần lấy quyền điều khiển các khớp quay (RotationalMotor). Trong Webots, động cơ có thể được điều khiển theo 3 chế độ: vị trí, vận tốc hoặc lực. Để xe có thể chạy tự do tiến lên phía trước, bạn cần cấu hình động cơ quay liên tục bằng cách đặt mục tiêu vị trí là vô cực, sau đó điều khiển bằng vận tốc.
from controller import Robot
# Khởi tạo API Robot
robot = Robot()
# Lấy bước thời gian mặc định của thế giới mô phỏng (tính bằng ms)
timestep = int(robot.getBasicTimeStep())
# Khởi tạo kết nối với phần cứng bằng tên định danh
left_motor = robot.getDevice('left wheel motor')
right_motor = robot.getDevice('right wheel motor')
# Cấu hình chế độ quay liên tục (không giới hạn góc quay)
left_motor.setPosition(float('inf'))
right_motor.setPosition(float('inf'))
# Đặt tốc độ ban đầu bằng 0
left_motor.setVelocity(0.0)
right_motor.setVelocity(0.0)
# Trong vòng lặp chính:
while robot.step(timestep) != -1:
# Cho robot chạy thẳng với tốc độ 3.14 radian/s
left_motor.setVelocity(3.14)
right_motor.setVelocity(3.14)Ghi chú 1: Vận tốc trong Webots được đo bằng đơn vị góc là radian/giây chứ không phải số vòng quay (RPM). Hãy cẩn thận kiểm tra tài liệu của robot vì mỗi động cơ sẽ có một giới hạn tốc độ tối đa khác nhau.
Ghi chú 2: Mỗi động cơ và cảm biến trong robot sẽ được đặt tên riêng, ví dụ trong code phía trên, động cơ phía trái là left wheel motor, nó sẽ được truyền làm tham số trong hàm robot.getDevice(), bạn cần tìm đúng tên động cơ hoặc cảm biến được khởi tạo để có thể sử dụng.
Làm sao để biết tên các động cơ và cảm biến?
Khi viết code, bạn không thể gọi chung chung là "bánh xe trái" hay "cảm biến trước". Mỗi thiết bị trên mô hình robot đều có một cái tên định danh (name) chính xác được khai báo trong mô hình 3D.
Để tìm tên thiết bị, bạn có hai cách:
- Duyệt qua Scene Tree: Bấm vào node robot của bạn, mở rộng phần
children(hoặc các node bộ phận nhưturret,wheel). Tìm các node có loại làMotor,DistanceSensor,Camera. Bấm vào chúng và nhìn vào trườngnameở bên dưới. Đó chính là chuỗi ký tự bạn phải dùng trong code. - Sử dụng tài liệu (Documentation): Webots cung cấp tài liệu cực kỳ chi tiết tại Trang chủ Documentation (opens in a new tab) và đặc biệt là bảng tra cứu Nodes and API Functions (opens in a new tab). Đối với các robot tích hợp sẵn như E-puck, bạn chỉ cần click chuột phải vào robot, chọn Help, một trang web sẽ mở ra liệt kê đầy đủ tên của mọi thiết bị (ví dụ bánh trái của e-puck thường tên là
left wheel motor). Để hiểu rõ hơn về cách viết code Python trong Webots, bạn có thể tham khảo Hướng dẫn sử dụng Python API (opens in a new tab).
Ví dụ, robot e-puck sẽ có 1 trang mô tả tại đây (opens in a new tab), trong trang sẽ có hình robot và danh mục các động cơ & cảm biến kèm tên của chúng như trong hình.

Đọc tín hiệu Cảm biến (Sensor)
Robot mù không thể tương tác với môi trường. Ta cần bật các cảm biến lên. Giả sử bạn có một cảm biến khoảng cách dùng hồng ngoại tên là ps0.
Nguyên tắc bắt buộc khi làm việc với bất kỳ cảm biến nào trong Webots là bạn phải enable (kích hoạt) nó trước, đồng thời khai báo tần số quét (thường chính bằng timestep).
from controller import Robot
# Khởi tạo API Robot
robot = Robot()
# Lấy bước thời gian mặc định của thế giới mô phỏng (tính bằng ms)
timestep = int(robot.getBasicTimeStep())
# Lấy liên kết tới cảm biến
front_sensor = robot.getDevice('ps0')
# Bật cảm biến với chu kỳ cập nhật bằng timestep
front_sensor.enable(timestep)
# Khởi tạo kết nối với phần cứng bằng tên định danh
left_motor = robot.getDevice('left wheel motor')
right_motor = robot.getDevice('right wheel motor')
# Cấu hình chế độ quay liên tục (không giới hạn góc quay)
left_motor.setPosition(float('inf'))
right_motor.setPosition(float('inf'))
# Đặt tốc độ ban đầu bằng 0
left_motor.setVelocity(0.0)
right_motor.setVelocity(0.0)
# Trong vòng lặp chính:
while robot.step(timestep) != -1:
# Cho robot chạy thẳng với tốc độ 3.14 radian/s
left_motor.setVelocity(3.14)
right_motor.setVelocity(3.14)
# Đọc giá trị trả về
sensor_value = front_sensor.getValue()
# In ra console để debug
print(f"Giá trị cảm biến trước: {sensor_value}")Bây giờ bạn đã có đầy đủ hai mảnh ghép: thu thập dữ liệu (đọc cảm biến) và thực thi (điều khiển động cơ). Tùy thuộc vào giá trị sensor_value, bạn có thể viết các hàm if/else để thay đổi vận tốc của left_motor và right_motor sao cho robot tự động rẽ trái, rẽ phải khi sắp đụng tường.
Đó là cách cơ bản nhất để thổi hồn vào phần cứng trong Webots.