From ef58b7e2f569a947b98b6316ca9fe8081333a796 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 6 Feb 2025 13:57:51 +0300 Subject: [PATCH] =?UTF-8?q?dev:=20roboter,=20gui=20=D0=B8=20plotter=20?= =?UTF-8?q?=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D1=8B=20=D0=B2?= =?UTF-8?q?=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- params/plot_structure_params.json | 399 +++++++++++++++++++++++------- src/base/base.py | 6 + src/controller/controller.py | 2 +- src/controller/mediator.py | 4 + src/controller/passport_former.py | 2 +- src/gui/plotter.py | 19 +- src/performance/roboter.py | 71 +++++- 7 files changed, 400 insertions(+), 103 deletions(-) diff --git a/params/plot_structure_params.json b/params/plot_structure_params.json index 2bba5e5..8c04328 100644 --- a/params/plot_structure_params.json +++ b/params/plot_structure_params.json @@ -1,102 +1,325 @@ { -"Electrode Force, N & Welding Current, kA": { - "Settings": { - "zoom": false, - "stages": true, - "performance": true, - "ideals": true, - "mirror ME": false, - "workpiece": false, - "force compensation FE": false, - "force accuracy":true - }, - "Real_signals": [ - { - "name": "Electrode Force, N ME", - "pen": "r" + "Online Path Scanner": { + + "Electrode Force, N & Welding Current, kA": { + "Settings": { + "zoom": false, + "stages": true, + "performance": true, + "ideals": true, + "mirror ME": false, + "workpiece": false, + "force compensation FE": false, + "force accuracy":true + }, + "Real_signals": [ + { + "name": "Electrode Force, N ME", + "pen": "r" + }, + { + "name": "Electrode Force, N FE", + "pen": "w" + } + ], + "Ideal_signals": [ + { + "name": "Force", + "pen": {"color": "g", "width":3} + } + ] }, - { - "name": "Electrode Force, N FE", - "pen": "w" + + + "Electrode Position, mm": { + "Settings": { + "zoom": false, + "stages": true, + "performance": false, + "ideals": true, + "mirror ME": true, + "workpiece": true, + "force compensation FE": true, + "force accuracy":false + }, + "Real_signals": [ + { + "name": "Rotor Position, mm ME", + "pen": {"color": "r", "width":2} + }, + { + "name": "Rotor Position, mm FE", + "pen": {"color": "w", "width":2} + } + ], + "Ideal_signals": [ + { + "name": "Position ME", + "pen": {"color": "g", "width":4} + }, + { + "name": "Position FE", + "pen": {"color": "b", "width":4} + } + ] + }, + + + "Electrode Speed, mm/s": { + "Settings": { + "zoom": false, + "stages": true, + "performance": false, + "ideals": true, + "mirror ME": false, + "workpiece": false, + "force compensation FE": false, + "force accuracy":false + }, + "Real_signals": [ + { + "name": "Rotor Speed, mm/s ME", + "pen": "r", + "zoom": false + }, + { + "name": "Rotor Speed, mm/s FE", + "pen": "w", + "zoom": false + } + ], + "Ideal_signals": [ + { + "name": "Rotor Speed ME", + "pen": {"color": "g", "width":3}, + "zoom": false + }, + { + "name": "Rotor Speed FE", + "pen": {"color": "b", "width":3}, + "zoom": false + } + ] } - ], - "Ideal_signals": [ - { - "name": "Force", - "pen": {"color": "g", "width":3} - } - ] }, - - - "Electrode Position, mm": { - "Settings": { - "zoom": false, - "stages": true, - "performance": false, - "ideals": true, - "mirror ME": true, - "workpiece": true, - "force compensation FE": true, - "force accuracy":false + "Report Editor": { + + "Electrode Force, N & Welding Current, kA": { + "Settings": { + "zoom": false, + "stages": true, + "performance": true, + "ideals": true, + "mirror ME": false, + "workpiece": false, + "force compensation FE": false, + "force accuracy":true + }, + "Real_signals": [ + { + "name": "Electrode Force, N ME", + "pen": "r" + }, + { + "name": "Electrode Force, N FE", + "pen": "w" + } + ], + "Ideal_signals": [ + { + "name": "Force", + "pen": {"color": "g", "width":3} + } + ] }, - "Real_signals": [ - { - "name": "Rotor Position, mm ME", - "pen": {"color": "r", "width":2} + + + "Electrode Position, mm": { + "Settings": { + "zoom": false, + "stages": true, + "performance": false, + "ideals": true, + "mirror ME": true, + "workpiece": true, + "force compensation FE": true, + "force accuracy":false }, - { - "name": "Rotor Position, mm FE", - "pen": {"color": "w", "width":2} - } - ], - "Ideal_signals": [ - { - "name": "Position ME", - "pen": {"color": "g", "width":4} + "Real_signals": [ + { + "name": "Rotor Position, mm ME", + "pen": {"color": "r", "width":2} + }, + { + "name": "Rotor Position, mm FE", + "pen": {"color": "w", "width":2} + } + ], + "Ideal_signals": [ + { + "name": "Position ME", + "pen": {"color": "g", "width":4} + }, + { + "name": "Position FE", + "pen": {"color": "b", "width":4} + } + ] + }, + + + "Electrode Speed, mm/s": { + "Settings": { + "zoom": false, + "stages": true, + "performance": false, + "ideals": true, + "mirror ME": false, + "workpiece": false, + "force compensation FE": false, + "force accuracy":false }, - { - "name": "Position FE", - "pen": {"color": "b", "width":4} - } - ] + "Real_signals": [ + { + "name": "Rotor Speed, mm/s ME", + "pen": "r", + "zoom": false + }, + { + "name": "Rotor Speed, mm/s FE", + "pen": "w", + "zoom": false + } + ], + "Ideal_signals": [ + { + "name": "Rotor Speed ME", + "pen": {"color": "g", "width":3}, + "zoom": false + }, + { + "name": "Rotor Speed FE", + "pen": {"color": "b", "width":3}, + "zoom": false + } + ] + } }, + "Client Trace Watcher":{ - - "Electrode Speed, mm/s": { - "Settings": { - "zoom": false, - "stages": true, - "performance": false, - "ideals": true, - "mirror ME": false, - "workpiece": false, - "force compensation FE": false, - "force accuracy":false + "Client Trace": { + "Settings": { + "zoom": false, + "stages": true + }, + "Real_signals": [ + { + "name": "Electrode Force, N ME", + "pen": "r" + }, + { + "name": "Electrode Position, mm ME", + "pen": "g" + }, + { + "name": "Electrode Speed, mm ME", + "pen": "b" + }, + { + "name": "Cartesian Tool Speed, mm/s ME", + "pen": "w" + } + ], + "Ideal_signals": [] }, - "Real_signals": [ - { - "name": "Rotor Speed, mm/s ME", - "pen": "r", - "zoom": false + + "TCW Trace": { + "Settings": { + "stages": true, + "ideals": true, + "mirror ME": true, + "workpiece": true, + "force compensation FE": true }, - { - "name": "Rotor Speed, mm/s FE", - "pen": "w", - "zoom": false - } - ], - "Ideal_signals": [ - { - "name": "Rotor Speed ME", - "pen": {"color": "g", "width":3}, - "zoom": false + "Real_signals": [], + "Ideal_signals": [ + { + "name": "Force", + "pen": {"color": "r", "width":4} + }, + { + "name": "Position ME", + "pen": {"color": "g", "width":4} + }, + { + "name": "Position FE", + "pen": {"color": "b", "width":4} + }, + { + "name": "Rotor Speed ME", + "pen": {"color": "w", "width":3}, + "zoom": false + }, + { + "name": "Rotor Speed FE", + "pen": {"color": "w", "width":3}, + "zoom": false + } + + ] + }, + + "Combined Trace": { + "Settings": { + "stages": true, + "performance": false, + "ideals": true, + "workpiece": false }, - { - "name": "Rotor Speed FE", - "pen": {"color": "b", "width":3}, - "zoom": false - } - ] + "Real_signals": [ + { + "name": "Electrode Force, N ME", + "pen": "r" + }, + { + "name": "Electrode Position, mm ME", + "pen": "g" + }, + { + "name": "Electrode Speed, mm ME", + "pen": "b" + }, + { + "name": "Cartesian Tool Speed, mm/s ME", + "pen": "w" + } + ], + "Ideal_signals": [ + { + "name": "Force", + "pen": {"color": "r", "width":4} + }, + { + "name": "Position ME", + "pen": {"color": "g", "width":4} + }, + { + "name": "Position FE", + "pen": {"color": "b", "width":4} + }, + { + "name": "Rotor Speed ME", + "pen": {"color": "w", "width":3}, + "zoom": false + }, + { + "name": "Rotor Speed FE", + "pen": {"color": "w", "width":3}, + "zoom": false + } + ] + + } + } } diff --git a/src/base/base.py b/src/base/base.py index 1bce78e..cf8c1c5 100644 --- a/src/base/base.py +++ b/src/base/base.py @@ -106,6 +106,9 @@ class BaseMediator: def prerender(self, data:list[str]) -> None: ... + + def set_mode(self, mode: int) -> None: + ... class BaseDirectoryMonitor: @@ -218,6 +221,9 @@ class BasePlotWidget: def build_raw_trace(self, data:pd.DataFrame) -> None: ... + + def set_mode(self, mode:int) -> None: + ... class BaseController(QObject): diff --git a/src/controller/controller.py b/src/controller/controller.py index 679dc23..669d250 100644 --- a/src/controller/controller.py +++ b/src/controller/controller.py @@ -12,7 +12,7 @@ class Controller(BaseController): signal_status_text = pyqtSignal(str) def set_working_mode(self, mode:int) -> None: - self._file_manager.set_mode(mode) + self._mediator.set_mode(mode) def update_plots(self) -> None: self._file_manager.replot_all() diff --git a/src/controller/mediator.py b/src/controller/mediator.py index dee74b4..a38ac9d 100644 --- a/src/controller/mediator.py +++ b/src/controller/mediator.py @@ -48,6 +48,10 @@ class Mediator(BaseMediator): def prerender(self, data:list[str]) -> None: self._trace_processor.prerender(data) + + def set_mode(self, mode: int) -> None: + self._plot.set_mode(mode) + self._file_manager.set_mode(mode) diff --git a/src/controller/passport_former.py b/src/controller/passport_former.py index 96bd99d..ad3448d 100644 --- a/src/controller/passport_former.py +++ b/src/controller/passport_former.py @@ -31,7 +31,7 @@ class PassportFormer(BasePointPassportFormer): """ try: dataframe, events = data - point_quantity = len(events["Welding"][0]) + point_quantity = len(events["Squeeze"][0]) data_passport = self._form_graphic_passport(dataframe, events, point_quantity) return_data = [data_passport] except Exception as e: diff --git a/src/gui/plotter.py b/src/gui/plotter.py index 2d271c8..89d8371 100644 --- a/src/gui/plotter.py +++ b/src/gui/plotter.py @@ -39,7 +39,8 @@ class PlotWidget(BasePlotWidget): def __init__(self, controller:BaseController): super().__init__(controller=controller) - self._plt_channels = read_json("params/plot_structure_params.json") + self._plt_structures = read_json("params/plot_structure_params.json") + self._plt_channels = None def build(self, data: list[GraphicPassport]) -> None: """ @@ -72,6 +73,18 @@ class PlotWidget(BasePlotWidget): container_widget.setProperty("pyqt_container", pyqt_container) self._mediator.notify(self, [container_widget]) + + def set_mode(self, mode:int) -> None: + match mode: + case 1: + self._plt_channels = self._plt_structures["Online Path Scanner"] + print (1) + case 2: + self._plt_channels = self._plt_structures["Report Editor"] + print (2) + case 3: + self._plt_channels = self._plt_structures["Client Trace Watcher"] + print(3) def _build_raw_plotitem(self, dataframe:pd.DataFrame, @@ -149,7 +162,7 @@ class PlotWidget(BasePlotWidget): def _update_status(self, widgsteps:int, pointsteps:int, cur_widg:int, cur_point:int): if self._datalen: sycle_start = self._datastep/self._datalen*100 + 1 - period1 = 100/self._datalen + period1 = 99/self._datalen else: sycle_start = 1 period1 = 100 @@ -157,7 +170,7 @@ class PlotWidget(BasePlotWidget): period2 = period1/widgsteps if widgsteps != 0 else period1 period3 = period2/pointsteps if pointsteps != 0 else period2 - progress = sycle_start + period2*cur_widg + period3*cur_point + progress = int(sycle_start + period2*cur_widg + period3*cur_point) self._controller.update_progress(progress) diff --git a/src/performance/roboter.py b/src/performance/roboter.py index a22f05c..c7af66f 100644 --- a/src/performance/roboter.py +++ b/src/performance/roboter.py @@ -5,6 +5,7 @@ from dataclasses import dataclass, field import numpy as np import pandas as pd +from loguru import logger from base.base import (BaseKukaDataParser, BaseKukaTextParser, BaseTraceStageDetector, BaseTextStageDetector, @@ -273,9 +274,9 @@ class TraceProcessor(BaseRawTraceProcessor): trace_df = self._unpack_trace(dat_filepath) text_data = self._unpack_text(txt_filepath) events = self._detect_stages(trace_df, text_data) - print (events) + dataframe = self._rename_df_columns(trace_df) - self._mediator.notify(self, [trace_df, events]) + self._mediator.notify(self, [dataframe, events]) def update_settings(self, data:Settings) -> None: self._settings = data @@ -297,7 +298,18 @@ class TraceProcessor(BaseRawTraceProcessor): events = self._form_events(trace_stages, welding_stages) return events return None - + + @staticmethod + def _normalize_events(events:dict[list]) -> dict[list]: + max_len = max([len(item_list[0]) if key != "Oncomming" else len(item_list[0])-1 for key, item_list in events.items() ]) + for key, item_list in events.items(): + list_len = len(item_list[0]) + if list_len < max_len: + logger.warning(f"_normalize_events - Ошибка детекции событий {key}: ожидалось {max_len} событий, получено {list_len}") + for i in range (max_len - list_len): + events[key][0].append(0) + events[key][1].append(1) + return events @staticmethod def _form_events(trace_stages:list, welding_stages:list) -> dict[list]: idx = 0 @@ -327,8 +339,47 @@ class TraceProcessor(BaseRawTraceProcessor): else: events[trace_stages[i]['stage']][0].append(trace_stages[i]['start_time']) events[trace_stages[i]['stage']][1].append(trace_stages[i]['end_time']) - return events + normalized_events = TraceProcessor._normalize_events(events) + return normalized_events + @staticmethod + def _rename_df_columns(dataframe: pd.DataFrame) -> pd.DataFrame: + correct_mapping = { + "time": ["Time", "Timestamp"], + "Tool Coordinate, mm X": ["X_Act"], + "Tool Coordinate, mm Y": ["Y_Act"], + "Tool Coordinate, mm Z": ["Z_Act"], + "Electrode Force, N ME": ["DriveMotorTorq_Act7"], + "Electrode Position, mm ME": ["AxisPos_Act7"], + "Electrode Speed, mm ME": ["AxisVel_Act7"], + "Rotor Position, mm FE": ["DriveMotorPos_Act7"], + "Rotor Speed, mm/s ME": ["DriveMotorVel_Act7"], + "Rotor Current, A ME": ["DriveMotorCurr_Act7"], + "Cartesian Tool Speed, mm/s ME": ["CartVel_Act"], + } + + working_mapping = {key: [item.lower() for item in items] for key, items in correct_mapping.items()} + + try: + new_columns = {} + for col in dataframe.columns: + col_lower = col.lower() + for key, values in working_mapping.items(): + if col_lower in values: + new_columns[col] = key + break + else: + new_columns[col] = col + + dataframe.rename(columns=new_columns, inplace=True) + dataframe = dataframe.loc[:, ~dataframe.columns.duplicated()] + return dataframe + except AttributeError as e: + logger.error(f"_rename_df_columns - AttributeError: Проверьте, что переданный объект является DataFrame. {e}") + return None + except Exception as e: + logger.error(f"_rename_df_columns - Непредвиденная ошибка: {e}") + return None "Перемещение" #FUNCTION/PROCEDURE: SW_RSP030TL01_SN - какое-то перемещение @@ -401,11 +452,11 @@ if __name__ == '__main__': txt_parser.parse(path) print(len(txt_parser._datapacks)) """ - - - - - - + + + + + +