引言
在这篇文章中,我们将使用Python和Pygame库来实现一个简单但有趣的自动扫地机器人模拟系统。这个系统模拟了扫地机器人如何在房间中自主移动、探测并收集垃圾的过程。
系统设计
1. 核心组件
系统主要包含三个核心类:
CleaningRobot
:扫地机器人类Debris
:垃圾类SimulationSystem
:模拟系统类
2. 机器人功能
2.1 自动寻路
机器人具有以下关键功能:
def detect_debris(self, debris_list):
# 在雷达范围内检测最近的垃圾
nearest_debris = None
min_distance = float('inf')
for debris in debris_list:
distance = math.sqrt((self.x - debris.x)**2 + (self.y - debris.y)**2)
if distance <= self.radar_range and distance < min_distance:
min_distance = distance
nearest_debris = debris
return nearest_debris
2.2 移动控制
机器人的移动逻辑如下:
def move_to_target(self):
if self.target is None:
# 没有目标时随机游走
self.wander_timer += 1
if self.wander_timer >= 60:
self.direction = random.randint(0, 360)
self.wander_timer = 0
else:
# 计算并调整到目标的角度
target_angle = math.degrees(math.atan2(
self.target.y - self.y,
self.target.x - self.x
))
3. 系统功能
3.1 垃圾生成
def generate_debris(self, count):
for _ in range(count):
x = random.randint(0, self.width)
y = random.randint(0, self.height)
self.debris_list.append(Debris(x, y))
3.2 状态更新
def update(self):
# 更新机器人状态
nearest_debris = self.robot.detect_debris(self.debris_list)
self.robot.target = nearest_debris
self.robot.move_to_target()
# 检查垃圾收集
for debris in self.debris_list[:]:
distance = math.sqrt((self.robot.x - debris.x)**2 +
(self.robot.y - debris.y)**2)
if distance < (self.robot.size + debris.size) / 2:
self.debris_list.remove(debris)
self.robot.collected_count += 1
视觉效果
系统使用Pygame进行可视化展示:
- 蓝色方块:表示扫地机器人
- 绿色线条:表示机器人朝向
- 灰色圆圈:表示雷达探测范围
- 红色圆圈:表示垃圾
- 左上角计数器:显示已收集的垃圾数量
运行效果
运行后,你将看到:
- 机器人自动在地图上巡航
- 当发现垃圾时,自动追踪并收集
- 没有目标时,随机游走探索地图
- 垃圾被收集后会自动补充新的垃圾
如何运行
- 首先安装必要的库:
pip install pygame
- 将完整代码保存为Python文件并运行
可能的改进方向
- 添加障碍物系统
- 实现更复杂的寻路算法
- 添加充电站功能
- 优化探测算法
- 添加多机器人协同功能
完整代码
import pygame
import random
import math
class CleaningRobot:
def __init__(self, x, y, size=20):
self.x = x
self.y = y
self.size = size
self.radar_range = 100
self.speed = 2
self.direction = 0
self.target = None
self.wander_timer = 0
self.collected_count = 0
def detect_debris(self, debris_list):
# 在雷达范围内检测最近的垃圾
nearest_debris = None
min_distance = float('inf')
for debris in debris_list:
distance = math.sqrt((self.x - debris.x)**2 + (self.y - debris.y)**2)
if distance <= self.radar_range and distance < min_distance:
min_distance = distance
nearest_debris = debris
return nearest_debris
def move_to_target(self):
if self.target is None:
# 没有目标时随机游走
self.wander_timer += 1
if self.wander_timer >= 60: # 每60帧改变一次方向
self.direction = random.randint(0, 360)
self.wander_timer = 0
else:
# 计算到目标的角度
target_angle = math.degrees(math.atan2(
self.target.y - self.y,
self.target.x - self.x
))
# 调整方向
angle_diff = (target_angle - self.direction) % 360
if angle_diff > 180:
angle_diff -= 360
self.direction += min(2, max(-2, angle_diff)) # 限制转向速度
# 移动
self.x += math.cos(math.radians(self.direction)) * self.speed
self.y += math.sin(math.radians(self.direction)) * self.speed
# 确保机器人不会离开屏幕
self.x = max(0, min(self.x, 800))
self.y = max(0, min(self.y, 600))
class Debris:
def __init__(self, x, y, size=10):
self.x = x
self.y = y
self.size = size
class SimulationSystem:
def __init__(self, width=800, height=600):
pygame.init()
self.width = width
self.height = height
self.screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("扫地机器人模拟系统")
# 初始化机器人和垃圾
self.robot = CleaningRobot(width//2, height//2)
self.debris_list = []
self.generate_debris(10) # 生成10个垃圾
self.font = pygame.font.Font(None, 36)
def generate_debris(self, count):
for _ in range(count):
x = random.randint(0, self.width)
y = random.randint(0, self.height)
self.debris_list.append(Debris(x, y))
def update(self):
# 更新机器人状态
nearest_debris = self.robot.detect_debris(self.debris_list)
self.robot.target = nearest_debris
self.robot.move_to_target()
# 检查是否收集到垃圾
for debris in self.debris_list[:]: # 使用切片创建副本以便安全删除
distance = math.sqrt((self.robot.x - debris.x)**2 +
(self.robot.y - debris.y)**2)
if distance < (self.robot.size + debris.size) / 2:
self.debris_list.remove(debris)
self.robot.collected_count += 1
# 如果垃圾太少,生成新的
if len(self.debris_list) < 5:
self.generate_debris(5)
def run(self):
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 更新游戏状态
self.update()
# 绘制
self.screen.fill((255, 255, 255))
# 绘制机器人
pygame.draw.rect(self.screen, (0, 0, 255),
(self.robot.x - self.robot.size//2,
self.robot.y - self.robot.size//2,
self.robot.size, self.robot.size))
# 绘制机器人朝向
end_x = self.robot.x + math.cos(math.radians(self.robot.direction)) * 20
end_y = self.robot.y + math.sin(math.radians(self.robot.direction)) * 20
pygame.draw.line(self.screen, (0, 255, 0),
(self.robot.x, self.robot.y),
(end_x, end_y), 2)
# 绘制雷达范围
pygame.draw.circle(self.screen, (200, 200, 200),
(int(self.robot.x), int(self.robot.y)),
self.robot.radar_range, 1)
# 绘制垃圾
for debris in self.debris_list:
pygame.draw.circle(self.screen, (255, 0, 0),
(int(debris.x), int(debris.y)),
debris.size)
# 显示收集的垃圾数量
text = self.font.render(f"已收集: {self.robot.collected_count}",
True, (0, 0, 0))
self.screen.blit(text, (10, 10))
pygame.display.flip()
clock.tick(60)
pygame.quit()
if __name__ == "__main__":
simulation = SimulationSystem()
simulation.run()
结语
这个简单的模拟系统展示了如何使用Python实现基本的机器人控制逻辑。通过这个项目,我们可以理解扫地机器人的基本工作原理,并为进一步开发更复杂的机器人系统打下基础。