gui improvement and blueprint

This commit is contained in:
raiot 2024-10-16 22:53:09 +08:00
parent 53ccf4439c
commit f0096d2c74
4 changed files with 185 additions and 34 deletions

View File

@ -5,6 +5,7 @@ import random
from utils.cv_marker import cap_and_mark
# from utils.stack_exe import Stackbot
import cv2
import sys
pygame.init()
@ -28,6 +29,14 @@ cap.set(6,cv2.VideoWriter.fourcc('M','J','P','G'))
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
# 定义屏幕尺寸
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# 定义按钮尺寸
BUTTON_WIDTH = 200
BUTTON_HEIGHT = 200
class Block:
def __init__(self, x, y, width, height, angle, layer):
self.x = x
@ -62,30 +71,34 @@ class Block:
class Tower:
def __init__(self):
def __init__(self, blueprint, tower_image=None):
self.blocks = []
self.current_layer = 0
self.layer_centroids = [] # 存储每层的重心
self.stability_threshold = 10 # 稳定性阈值(像素)
self.rotation_angle = 15 # 预设每层旋转角度
self.angle_tolerance = 5 # 允许的角度偏移
self.position_tolerance = 10 # 允许的位置偏移
self.layer_centroids = []
self.stability_threshold = 10
self.rotation_angle = 15
self.angle_tolerance = 5
self.position_tolerance = 10
self.sim_to_robot_matrix = np.array([
[1, 0, 0, -300], # 假设的转换矩阵,需要根据实际情况调整
[1, 0, 0, -300],
[0, -1, 0, -200],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
self.robot_to_sim_matrix = np.linalg.inv(self.sim_to_robot_matrix)
# self.stack_bot = Stackbot()
self.is_upper = False
self.blueprint = blueprint
self.center_x, self.center_y = 300, 300 # 定义塔的中心点
self.ideal_positions = self.get_ideal_positions()
self.position_tolerance = 20 # 允许的位置偏差(像素)
self.angle_tolerance = 15 # 允许的角度偏差(度)
self.position_tolerance = 20
self.angle_tolerance = 15
self.tower_image = None
if tower_image:
self.tower_image = pygame.transform.scale(tower_image, (150, 150)) # 调整图片大小
def sim_to_robot_coords(self, x, y, angle):
sim_coords = np.array([x, y, 0, 1])
@ -262,29 +275,15 @@ class Tower:
self.current_layer += 1
def get_ideal_positions(self):
# 定义中心原点
center_x, center_y = 400, 450
# 定义相对坐标和角度
relative_positions = [
[(0, 40, 0), (0, -40, 0)], # 第一层
[(-40, 0, 90), (40, 0, 90)], # 第二层
[(0, 40, 0), (0, -40, 0)], # 第三层
[(-40, 0, 90), (40, 0, 90)], # 第四层
[(0, 40, 0), (0, -40, 0)], # 第五层
# ... 可以继续添加更多层 ...
]
# 转换为绝对坐标
# 将相对坐标转换为绝对坐标
absolute_positions = []
for layer in relative_positions:
for layer in self.blueprint:
layer_positions = []
for rel_x, rel_y, angle in layer:
abs_x = center_x + rel_x
abs_y = center_y + rel_y
abs_x = self.center_x + rel_x
abs_y = self.center_y + rel_y
layer_positions.append((abs_x, abs_y, angle))
absolute_positions.append(layer_positions)
return absolute_positions
def auto_place_block(self):
@ -297,7 +296,7 @@ class Tower:
if best_position:
x, y, angle = best_position
print(f"选择的最佳位置: ({x}, {y}) 角度为 {angle}") # 添加这行来调试
print(f"选择的最佳位置: ({x}, {y}) 角度为 {angle}")
return Block(x, y, 100, 20, angle, self.current_layer)
else:
print("无法找到合适的放置位置")
@ -323,15 +322,27 @@ class Tower:
best_position = None
min_distance = float('inf')
# 获取当前层已放置的木块数量
blocks_in_current_layer = sum(1 for block in self.blocks if block.layer == self.current_layer)
# 获取当前层的理想位置
ideal_positions = self.ideal_positions[self.current_layer]
# 确保我们选择正确的理想位置
if blocks_in_current_layer < len(ideal_positions):
ideal_x, ideal_y, ideal_angle = ideal_positions[blocks_in_current_layer]
else:
print("警告:当前层的所有位置都已被填满")
return None
for x, y, angle in possible_positions:
new_block = Block(x, y, 100, 20, angle, self.current_layer)
if self.has_support(new_block) and not self.check_interference(new_block):
temp_tower = Tower()
temp_tower = Tower(self.blueprint)
temp_tower.blocks = self.blocks.copy()
temp_tower.add_block(new_block)
if temp_tower.check_stability():
ideal_x, ideal_y, ideal_angle = self.ideal_positions[self.current_layer][len(self.blocks) % 2]
distance = np.sqrt((x - ideal_x)**2 + (y - ideal_y)**2) + abs(angle - ideal_angle)
if distance < min_distance:
@ -398,8 +409,146 @@ class Tower:
self.add_block_from_robot(block[0][0], block[0][1], block[1])
def draw_tower_image(self, screen):
if self.tower_image:
image_rect = self.tower_image.get_rect()
image_rect.topright = (SCREEN_WIDTH - 10, 10) # 放置在右上角留出10像素的边距
screen.blit(self.tower_image, image_rect)
def show_tower_selection(screen):
# 加载塔型图片
tower_images = [
pygame.image.load("tower1.png"),
pygame.image.load("tower2.png"),
pygame.image.load("tower3.png")
]
# 调整图片大小
tower_images = [pygame.transform.scale(img, (BUTTON_WIDTH, BUTTON_HEIGHT)) for img in tower_images]
# 计算按钮位置
button_y = (SCREEN_HEIGHT - BUTTON_HEIGHT) // 2
button_x_start = (SCREEN_WIDTH - (BUTTON_WIDTH * 3 + 40)) // 2
# 创建按钮矩形
buttons = [
pygame.Rect(button_x_start + i * (BUTTON_WIDTH + 20), button_y, BUTTON_WIDTH, BUTTON_HEIGHT)
for i in range(3)
]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
for i, button in enumerate(buttons):
if button.collidepoint(mouse_pos):
return i # 返回选择的塔型索引
screen.fill(WHITE)
# 绘制按钮和图片
for i, (button, image) in enumerate(zip(buttons, tower_images)):
screen.blit(image, button.topleft)
pygame.draw.rect(screen, BLACK, button, 2)
# 添加标题
font = pygame.font.Font(None, 36)
title = font.render("选择塔型", True, BLACK)
title_rect = title.get_rect(center=(SCREEN_WIDTH // 2, 50))
screen.blit(title, title_rect)
pygame.display.flip()
def get_tower_blueprint_1():
# 第一种塔型的蓝图(相对坐标)
return [
[(-40, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-35, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-30, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-25, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-20, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-15, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-10, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-5, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(0, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-5, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-10, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-15, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-20, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-25, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-30, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-35, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
[(-40, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
]
def get_tower_blueprint_2():
# 第二种塔型的蓝图(相对坐标)
return [
[(-20, 0, 90), (20, 0, 90)],
[(0, 20, 0), (0, -20, 0)],
]
def get_tower_blueprint_3():
# 第三种塔型的蓝图(相对坐标)
return [
[(-60, -60, 45), (60, -60, 135), (-60, 60, 135), (60, 60, 45)],
[(0, -80, 0), (80, 0, 90), (0, 80, 0), (-80, 0, 90)],
[(-55, -55, 45), (55, -55, 135), (-55, 55, 135), (55, 55, 45)],
[(0, -75, 0), (75, 0, 90), (0, 75, 0), (-75, 0, 90)],
[(-50, -50, 45), (50, -50, 135), (-50, 50, 135), (50, 50, 45)],
[(0, -70, 0), (70, 0, 90), (0, 70, 0), (-70, 0, 90)],
[(-45, -45, 45), (45, -45, 135), (-45, 45, 135), (45, 45, 45)],
[(0, -65, 0), (65, 0, 90), (0, 65, 0), (-65, 0, 90)],
[(-40, -40, 45), (40, -40, 135), (-40, 40, 135), (40, 40, 45)],
[(0, -60, 0), (60, 0, 90), (0, 60, 0), (-60, 0, 90)],
[(-40, 0, 90), (40, 0, 90)],
[(0, 40, 0), (0, -40, 0)],
]
def main():
tower = Tower()
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("积木塔仿真")
# 加载塔型图片
tower_images = [
pygame.image.load("tower1.png"),
pygame.image.load("tower2.png"),
pygame.image.load("tower3.png")
]
# 显示塔型选择界面
selected_tower = show_tower_selection(screen)
# 根据选择的塔型设置相应的蓝图和图片
if selected_tower == 0:
tower_blueprint = get_tower_blueprint_1()
elif selected_tower == 1:
tower_blueprint = get_tower_blueprint_2()
else:
tower_blueprint = get_tower_blueprint_3()
tower = Tower(tower_blueprint, tower_images[selected_tower])
clock = pygame.time.Clock()
current_block = None
@ -469,6 +618,8 @@ def main():
layer_text = font.render(f"Current layer: {tower.current_layer + 1}", True, BLACK)
screen.blit(layer_text, (10, 10))
tower.draw_tower_image(screen)
pygame.display.flip()
clock.tick(60)

BIN
tower1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
tower2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
tower3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB