observable connect

This commit is contained in:
Kseninia Mikhaylova 2024-10-25 10:55:03 +03:00
parent 24b88da023
commit b1d10fe3b1
8 changed files with 172 additions and 13 deletions

View File

@ -1 +1,4 @@
## modbus
## Работа с роботом
### Тестовое окружение
* `poetry run python main.py --mode test`

26
app.log Normal file
View File

@ -0,0 +1,26 @@
2024-10-25 09:35:09,819 - logger - INFO - test
2024-10-25 09:35:13,350 - logger - INFO - test
2024-10-25 10:32:36,506 - logger - INFO - not_connected
2024-10-25 10:39:48,747 - logger - INFO - not_connected
2024-10-25 10:42:35,337 - logger - INFO - not_connected
2024-10-25 10:42:36,287 - logger - INFO - not_connected
2024-10-25 10:42:37,541 - logger - INFO - connected
2024-10-25 10:42:38,252 - logger - INFO - connected
2024-10-25 10:42:39,252 - logger - INFO - connected
2024-10-25 10:42:40,253 - logger - INFO - connected
2024-10-25 10:42:41,253 - logger - INFO - connected
2024-10-25 10:42:42,253 - logger - INFO - connected
2024-10-25 10:42:43,252 - logger - INFO - connected
2024-10-25 10:42:44,253 - logger - INFO - connected
2024-10-25 10:42:45,252 - logger - INFO - connected
2024-10-25 10:43:37,355 - logger - INFO - Value changed: not_connected
2024-10-25 10:43:40,252 - logger - INFO - Value changed: connected
2024-10-25 10:43:43,595 - logger - INFO - Value changed: not_connected
2024-10-25 10:53:29,935 - logger - INFO - Value changed: not_connected
2024-10-25 10:53:41,824 - logger - INFO - Value changed: not_connected
2024-10-25 10:53:45,860 - logger - INFO - Value changed: connected
2024-10-25 10:53:50,752 - logger - INFO - Value changed: not_connected
2024-10-25 10:53:52,751 - logger - INFO - Value changed: connected
2024-10-25 10:53:54,993 - logger - INFO - Value changed: not_connected
2024-10-25 10:53:57,014 - logger - INFO - Value changed: connected
2024-10-25 10:54:02,382 - logger - INFO - Value changed: not_connected

View File

@ -5,6 +5,9 @@ from PyQt5.QtGui import QColor, QPalette
from gui.robot import ChangeRobot
from gui.status import Status
from gui.imitator import Imitator
from gui.visualize import Visualize
from gui.observable import Observable
from logger import logger
class RightPanel(QWidget):
@ -12,7 +15,6 @@ class RightPanel(QWidget):
super().__init__()
layout = QVBoxLayout()
for panel in panels:
# panel.setFixedHeight(200)
layout.addWidget(panel)
self.setLayout(layout)
self.initUI()
@ -25,8 +27,11 @@ class RightPanel(QWidget):
class MainPanel(QWidget):
def __init__(self):
def __init__(self, panels):
super().__init__()
layout = QVBoxLayout()
for panel in panels:
layout.addWidget(panel)
self.initUI()
def initUI(self):
@ -40,20 +45,33 @@ class MainContentComponent(QWidget):
def __init__(self, **kwargs):
super().__init__()
self.observable = Observable(kwargs.get("get_status"))
self.observable.value_changed.connect(self.handle_value_change)
robotArgs = kwargs.get("robotPanel", {})
robotPanel = ChangeRobot(**robotArgs)
self.robotPanel = ChangeRobot(**robotArgs)
statusArgs = kwargs.get("statusPanel", {})
statusPanel = Status(**statusArgs)
self.statusPanel = Status(**statusArgs)
imitatorArgs = kwargs.get("imitatorPanel", {})
imitatorPanel = Imitator(**imitatorArgs)
self.imitatorPanel = Imitator(**imitatorArgs)
self.rightPanel = RightPanel(
panels=[
statusPanel,
robotPanel,
imitatorPanel
self.statusPanel,
self.robotPanel,
self.imitatorPanel,
]
)
visArgs = kwargs.get("visPanel", {})
self.visPanel = Visualize(**visArgs)
self.mainPanel = MainPanel(
panels=[
self.visPanel,
]
)
self.mainPanel = MainPanel()
layout = QHBoxLayout()
layout.addWidget(self.mainPanel)
@ -74,6 +92,14 @@ class MainContentComponent(QWidget):
self.rightPanel.setFixedWidth(rightPanelWidth)
super().resizeEvent(event)
def handle_value_change(self, new_value):
logger.info(f"Value changed: {new_value}")
if new_value == "not_connected":
self.imitatorPanel.setDisabled(True)
if new_value == "connected":
self.imitatorPanel.setDisabled(False)
if __name__ == "__main__":
app = QApplication(sys.argv)

22
gui/observable.py Normal file
View File

@ -0,0 +1,22 @@
from PyQt5.QtCore import pyqtSignal, QObject, QTimer
from logger import logger
class Observable(QObject):
value_changed = pyqtSignal(object) # Сигнал с переданным значением
def __init__(self, func, interval=1000):
super().__init__()
self.get_dynamic_value = func
self._value = None
# Таймер для периодической проверки значения
self.timer = QTimer(self)
self.timer.timeout.connect(self.check_function) # Вызываем some_function на каждом таймере
self.timer.start(interval) # Интервал в миллисекундах
def check_function(self):
# Пример функции, которая обновляет значение
new_value = self.get_dynamic_value()
if new_value != self._value:
self._value = new_value
self.value_changed.emit(new_value)

33
gui/visualize.py Normal file
View File

@ -0,0 +1,33 @@
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QSizePolicy
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QTimer
class Visualize(QWidget):
def __init__(self, get_pybullet_image):
super().__init__()
self.get_pybullet_image = get_pybullet_image
# Настройка компоновки
self.layout = QVBoxLayout(self)
self.layout.setContentsMargins(0, 0, 0, 0) # Убираем отступы по краям
self.label = QLabel(self)
self.label.setScaledContents(True) # Масштабирование изображения по размеру QLabel
self.label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # QLabel занимает всю доступную область
self.layout.addWidget(self.label)
# Таймер для обновления изображения
self.timer = QTimer()
self.timer.timeout.connect(self.update_image)
self.timer.start(100) # Обновление каждые 100 мс
def update_image(self):
(rgb, width, height) = self.get_pybullet_image()
# Преобразование RGB-данных в QImage
image = QImage(rgb, width, height, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(image)
# Обновление изображения на QLabel
self.label.setPixmap(pixmap)

14
logger.py Normal file
View File

@ -0,0 +1,14 @@
import sys
import logging
# Настройка логгера
logging.basicConfig(
level=logging.DEBUG, # Уровень логирования
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler("app.log"), # Запись в файл
logging.StreamHandler(sys.stdout), # Вывод в консоль
],
)
logger = logging.getLogger("logger")

22
main.py
View File

@ -1,17 +1,20 @@
import json
import sys
import time
import argparse
from PyQt5.QtWidgets import QApplication
from robot.client_socket import SocketRobotArm
from gui.init import MainContentComponent
from logger import logger
class MyApp:
with open("./robots.json", "r") as file:
robots = json.load(file)
def __init__(self):
def __init__(self, mode):
self.mode = mode
self.startRobot()
self.startGui()
@ -27,6 +30,7 @@ class MyApp:
def startGui(self):
app = QApplication(sys.argv)
mainWindow = MainContentComponent(
get_status=self.get_status,
robotPanel={
"robots": self.robots,
"updateRobot": self.updateRobot,
@ -41,6 +45,9 @@ class MyApp:
"command_count": self.robot_app.get_command_count,
"updateData": self.robot_app.upd_model,
},
visPanel={
"get_pybullet_image": self.robot_app.get_pybullet_image,
},
)
mainWindow.setWindowTitle("ROBOT GUI")
mainWindow.show()
@ -53,6 +60,7 @@ class MyApp:
def updateRobot(self, robot):
if robot in self.robots:
selected_robot = robot
if self.mode == "test":
selected_robot = {"name": "test", "host": "127.0.0.1", "slave_id": 11}
if self.robot_app.status == "connected":
@ -65,4 +73,14 @@ class MyApp:
if __name__ == "__main__":
MyApp()
parser = argparse.ArgumentParser(description="MyApp Command Line Interface")
parser.add_argument(
"--mode",
type=str,
choices=["test", "prod"],
default="prod",
help="Mode of operation",
)
# MyApp()
args = parser.parse_args()
app = MyApp(args.mode)

View File

@ -61,6 +61,23 @@ class SocketRobotArm:
useFixedBase=True,
)
def get_pybullet_image(self):
width, height, rgb, _, _ = p.getCameraImage(
width=320,
height=240,
viewMatrix=p.computeViewMatrix(
cameraEyePosition=[1, 1, 1],
cameraTargetPosition=[0, 0, 0],
cameraUpVector=[0, 0, 1],
),
projectionMatrix=p.computeProjectionMatrixFOV(
fov=60.0, aspect=1.0, nearVal=0.1, farVal=10.0
),
renderer=p.ER_BULLET_HARDWARE_OPENGL,
physicsClientId=self.physics_client,
)
return (rgb, width, height)
def close(self):
self.socket.close()
self.socket = None