feat: add shared window

This commit is contained in:
2025-06-30 01:33:09 +03:00
parent 8b6bb3e22c
commit 2d85d78def
4 changed files with 316 additions and 118 deletions

View File

@@ -8,16 +8,10 @@ from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from autopilot import Pilot
from visualization import VisualizationManager, SimMode
from enum import Enum
import matplotlib.pyplot as plt
import numpy as np
import os
class SimMode(Enum):
OPERATOR = 1
AUTONOME = 2
class Simulator:
driver: webdriver.Chrome
mode: SimMode
@@ -27,42 +21,32 @@ class Simulator:
angle: float
# Переменные для отслеживания траектории
trajectory_x: list
trajectory_y: list
trajectory_modes: list # Для отслеживания режимов полета
# Менеджер визуализации
viz_manager: VisualizationManager
current_x: float
current_y: float
fig: plt.Figure
ax: plt.Axes
def __init__(self, operatorPilot: Pilot, autonomePilot: Pilot):
def __init__(self, operatorPilot: Pilot, autonomePilot: Pilot, viz_manager: VisualizationManager = None):
self.mode = SimMode.OPERATOR
self.operatorPilot = operatorPilot
self.autonomePilot = autonomePilot
# Инициализация переменных для траектории
self.trajectory_x = []
self.trajectory_y = []
self.trajectory_modes = []
self.current_x = 0.0
self.current_y = 0.0
# Создание окна для карты
plt.ion() # Включаем интерактивный режим
self.fig, self.ax = plt.subplots(figsize=(10, 8))
self.ax.set_title('Global Map - Траектория полета беспилотника')
self.ax.set_xlabel('X координата')
self.ax.set_ylabel('Y координата')
self.ax.grid(True, alpha=0.3)
self.ax.axhline(y=0, color='k', linestyle='-', alpha=0.3)
self.ax.axvline(x=0, color='k', linestyle='-', alpha=0.3)
# Создаем менеджер визуализации
self.viz_manager = viz_manager
# Передаем менеджер визуализации в автопилот, если он поддерживает это
if hasattr(self.autonomePilot, 'viz_manager'):
self.autonomePilot.viz_manager = self.viz_manager
# Создаем папку для изображений, если её нет
os.makedirs('./images', exist_ok=True)
options = webdriver.ChromeOptions()
options.add_experimental_option("detach", True)
# options.add_experimental_option("detach", True)
self.driver = webdriver.Chrome(options)
self.driver.get("https://yandex.ru/maps/43/kazan/?ll=49.103814%2C55.794258&z=14")
sleep(2)
@@ -112,69 +96,12 @@ class Simulator:
# Обновляем текущие координаты
self.current_x += dx
self.current_y += dy
# Добавляем точку в траекторию
self.trajectory_x.append(self.current_x)
self.trajectory_y.append(self.current_y)
self.trajectory_modes.append(self.mode)
def update_map(self):
"""
Обновляет карту траектории полета
"""
self.ax.clear()
self.ax.set_title('Global Map - Траектория полета беспилотника')
self.ax.set_xlabel('X координата')
self.ax.set_ylabel('Y координата')
self.ax.grid(True, alpha=0.3)
self.ax.axhline(y=0, color='k', linestyle='-', alpha=0.3)
self.ax.axvline(x=0, color='k', linestyle='-', alpha=0.3)
if len(self.trajectory_x) > 1:
# Разделяем траекторию по режимам
operator_indices = [i for i, mode in enumerate(self.trajectory_modes) if mode == SimMode.OPERATOR]
autonome_indices = [i for i, mode in enumerate(self.trajectory_modes) if mode == SimMode.AUTONOME]
# Рисуем траекторию оператора (синий цвет)
if len(operator_indices) > 1:
operator_x = [self.trajectory_x[i] for i in operator_indices]
operator_y = [self.trajectory_y[i] for i in operator_indices]
self.ax.plot(operator_x, operator_y, 'b-', linewidth=2, label='Режим оператора')
# Рисуем траекторию автономного режима (красный цвет)
if len(autonome_indices) > 1:
autonome_x = [self.trajectory_x[i] for i in autonome_indices]
autonome_y = [self.trajectory_y[i] for i in autonome_indices]
self.ax.plot(autonome_x, autonome_y, 'r-', linewidth=2, label='Автономный режим')
# Рисуем начальную точку (зеленая)
self.ax.plot(self.trajectory_x[0], self.trajectory_y[0], 'go', markersize=8, label='Начальная точка')
# Рисуем текущую позицию (черная)
self.ax.plot(self.current_x, self.current_y, 'ko', markersize=6, label='Текущая позиция')
# Рисуем целевую точку (0, 0) - желтая
self.ax.plot(0, 0, 'yo', markersize=8, label='Цель (0, 0)')
self.ax.legend()
# Автоматически масштабируем оси
if len(self.trajectory_x) > 0:
margin = 50 # Отступ от краев
x_min, x_max = min(self.trajectory_x), max(self.trajectory_x)
y_min, y_max = min(self.trajectory_y), max(self.trajectory_y)
# Учитываем целевую точку (0, 0)
x_min = min(x_min, 0)
x_max = max(x_max, 0)
y_min = min(y_min, 0)
y_max = max(y_max, 0)
self.ax.set_xlim(x_min - margin, x_max + margin)
self.ax.set_ylim(y_min - margin, y_max + margin)
plt.draw()
plt.pause(0.25) # Небольшая пауза для обновления окна
self.viz_manager.update_global_map(self.current_x, self.current_y, self.mode)
def loop(self):
@@ -184,7 +111,7 @@ class Simulator:
# Добавляем начальную точку в траекторию
self.update_trajectory(0, 0)
sleep(2)
self.viz_manager.update_global_map(self.current_x, self.current_y, self.mode)
for i in range(1000):
dangle = None
@@ -200,15 +127,11 @@ class Simulator:
if dangle is None:
break
# Сдвиг камеры
action = ActionChains(self.driver)
action.move_to_element_with_offset(html, 200, 200)
action.click_and_hold()
print(f" [Simulator] Drone Position: ({self.current_x:.2f}, {self.current_y:.2f})")
print(f" [Simulator] Angle: {self.angle * 180 / math.pi:.1f}°")
self.angle += dangle
dx = math.cos(self.angle) * velocity
dy = math.sin(self.angle) * velocity
@@ -232,17 +155,19 @@ class Simulator:
rotated_im.save(f"./images/{i}.png")
# Обновляем карту каждые несколько итераций для производительности
# Обновляем визуализацию каждые несколько итераций для производительности
if i % 5 == 0:
self.update_map()
self.viz_manager.update_display()
self.viz_manager.pause(0.25)
# Финальное обновление карты
self.update_map()
self.viz_manager.update_display()
print("last position: ", self.driver.current_url)
print(f"Финальная позиция: ({self.current_x:.2f}, {self.current_y:.2f})")
# Показываем карту до закрытия
plt.ioff()
plt.show()
# Показываем карту до закрытия, но не поднимаем на передний план
self.viz_manager.show_final()
print("Симуляция завершена. Окно визуализации остается открытым для анализа.")