observable connect
This commit is contained in:
parent
24b88da023
commit
b1d10fe3b1
|
@ -1 +1,4 @@
|
||||||
## modbus
|
## Работа с роботом
|
||||||
|
|
||||||
|
### Тестовое окружение
|
||||||
|
* `poetry run python main.py --mode test`
|
|
@ -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
|
44
gui/init.py
44
gui/init.py
|
@ -5,6 +5,9 @@ from PyQt5.QtGui import QColor, QPalette
|
||||||
from gui.robot import ChangeRobot
|
from gui.robot import ChangeRobot
|
||||||
from gui.status import Status
|
from gui.status import Status
|
||||||
from gui.imitator import Imitator
|
from gui.imitator import Imitator
|
||||||
|
from gui.visualize import Visualize
|
||||||
|
from gui.observable import Observable
|
||||||
|
from logger import logger
|
||||||
|
|
||||||
|
|
||||||
class RightPanel(QWidget):
|
class RightPanel(QWidget):
|
||||||
|
@ -12,7 +15,6 @@ class RightPanel(QWidget):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
for panel in panels:
|
for panel in panels:
|
||||||
# panel.setFixedHeight(200)
|
|
||||||
layout.addWidget(panel)
|
layout.addWidget(panel)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
self.initUI()
|
self.initUI()
|
||||||
|
@ -25,8 +27,11 @@ class RightPanel(QWidget):
|
||||||
|
|
||||||
|
|
||||||
class MainPanel(QWidget):
|
class MainPanel(QWidget):
|
||||||
def __init__(self):
|
def __init__(self, panels):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
for panel in panels:
|
||||||
|
layout.addWidget(panel)
|
||||||
self.initUI()
|
self.initUI()
|
||||||
|
|
||||||
def initUI(self):
|
def initUI(self):
|
||||||
|
@ -40,20 +45,33 @@ class MainContentComponent(QWidget):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
self.observable = Observable(kwargs.get("get_status"))
|
||||||
|
self.observable.value_changed.connect(self.handle_value_change)
|
||||||
|
|
||||||
robotArgs = kwargs.get("robotPanel", {})
|
robotArgs = kwargs.get("robotPanel", {})
|
||||||
robotPanel = ChangeRobot(**robotArgs)
|
self.robotPanel = ChangeRobot(**robotArgs)
|
||||||
|
|
||||||
statusArgs = kwargs.get("statusPanel", {})
|
statusArgs = kwargs.get("statusPanel", {})
|
||||||
statusPanel = Status(**statusArgs)
|
self.statusPanel = Status(**statusArgs)
|
||||||
|
|
||||||
imitatorArgs = kwargs.get("imitatorPanel", {})
|
imitatorArgs = kwargs.get("imitatorPanel", {})
|
||||||
imitatorPanel = Imitator(**imitatorArgs)
|
self.imitatorPanel = Imitator(**imitatorArgs)
|
||||||
|
|
||||||
self.rightPanel = RightPanel(
|
self.rightPanel = RightPanel(
|
||||||
panels=[
|
panels=[
|
||||||
statusPanel,
|
self.statusPanel,
|
||||||
robotPanel,
|
self.robotPanel,
|
||||||
imitatorPanel
|
self.imitatorPanel,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
visArgs = kwargs.get("visPanel", {})
|
||||||
|
self.visPanel = Visualize(**visArgs)
|
||||||
|
self.mainPanel = MainPanel(
|
||||||
|
panels=[
|
||||||
|
self.visPanel,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
self.mainPanel = MainPanel()
|
|
||||||
|
|
||||||
layout = QHBoxLayout()
|
layout = QHBoxLayout()
|
||||||
layout.addWidget(self.mainPanel)
|
layout.addWidget(self.mainPanel)
|
||||||
|
@ -74,6 +92,14 @@ class MainContentComponent(QWidget):
|
||||||
self.rightPanel.setFixedWidth(rightPanelWidth)
|
self.rightPanel.setFixedWidth(rightPanelWidth)
|
||||||
super().resizeEvent(event)
|
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__":
|
if __name__ == "__main__":
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
|
|
@ -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)
|
|
@ -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)
|
||||||
|
|
|
@ -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")
|
24
main.py
24
main.py
|
@ -1,17 +1,20 @@
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
import argparse
|
||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
from robot.client_socket import SocketRobotArm
|
from robot.client_socket import SocketRobotArm
|
||||||
from gui.init import MainContentComponent
|
from gui.init import MainContentComponent
|
||||||
|
from logger import logger
|
||||||
|
|
||||||
|
|
||||||
class MyApp:
|
class MyApp:
|
||||||
with open("./robots.json", "r") as file:
|
with open("./robots.json", "r") as file:
|
||||||
robots = json.load(file)
|
robots = json.load(file)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, mode):
|
||||||
|
self.mode = mode
|
||||||
self.startRobot()
|
self.startRobot()
|
||||||
self.startGui()
|
self.startGui()
|
||||||
|
|
||||||
|
@ -27,6 +30,7 @@ class MyApp:
|
||||||
def startGui(self):
|
def startGui(self):
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
mainWindow = MainContentComponent(
|
mainWindow = MainContentComponent(
|
||||||
|
get_status=self.get_status,
|
||||||
robotPanel={
|
robotPanel={
|
||||||
"robots": self.robots,
|
"robots": self.robots,
|
||||||
"updateRobot": self.updateRobot,
|
"updateRobot": self.updateRobot,
|
||||||
|
@ -41,6 +45,9 @@ class MyApp:
|
||||||
"command_count": self.robot_app.get_command_count,
|
"command_count": self.robot_app.get_command_count,
|
||||||
"updateData": self.robot_app.upd_model,
|
"updateData": self.robot_app.upd_model,
|
||||||
},
|
},
|
||||||
|
visPanel={
|
||||||
|
"get_pybullet_image": self.robot_app.get_pybullet_image,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
mainWindow.setWindowTitle("ROBOT GUI")
|
mainWindow.setWindowTitle("ROBOT GUI")
|
||||||
mainWindow.show()
|
mainWindow.show()
|
||||||
|
@ -53,7 +60,8 @@ class MyApp:
|
||||||
def updateRobot(self, robot):
|
def updateRobot(self, robot):
|
||||||
if robot in self.robots:
|
if robot in self.robots:
|
||||||
selected_robot = robot
|
selected_robot = robot
|
||||||
selected_robot = {"name": "test", "host": "127.0.0.1", "slave_id": 11}
|
if self.mode == "test":
|
||||||
|
selected_robot = {"name": "test", "host": "127.0.0.1", "slave_id": 11}
|
||||||
|
|
||||||
if self.robot_app.status == "connected":
|
if self.robot_app.status == "connected":
|
||||||
self.robot_app.close()
|
self.robot_app.close()
|
||||||
|
@ -65,4 +73,14 @@ class MyApp:
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
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)
|
||||||
|
|
|
@ -61,6 +61,23 @@ class SocketRobotArm:
|
||||||
useFixedBase=True,
|
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):
|
def close(self):
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
self.socket = None
|
self.socket = None
|
||||||
|
|
Loading…
Reference in New Issue