dev: разработан новый алгоритм детекции состояний системы в клиентских трейсах
This commit is contained in:
parent
90b6660a15
commit
9be6843307
@ -1,23 +1,29 @@
|
|||||||
{
|
{
|
||||||
"robot_zero_velocity_trashold": [
|
"act_vel_min": [
|
||||||
0.008
|
1800.0
|
||||||
],
|
],
|
||||||
"actuator_zero_velocity_trashold": [
|
"act_vel_close": [
|
||||||
100.0
|
1700.0
|
||||||
],
|
],
|
||||||
"actuator_finishing_velocity": [
|
"act_vel_thresh": [
|
||||||
2000.0
|
10.0
|
||||||
],
|
],
|
||||||
"actuator_finishing_velocity_trashold": [
|
"act_vel_negative": [
|
||||||
200.0
|
200.0
|
||||||
],
|
],
|
||||||
"actuator_current_trashold": [
|
"rob_vel_thresh": [
|
||||||
0.5
|
4.0
|
||||||
],
|
],
|
||||||
"ROI_start": [
|
"act_force_close": [
|
||||||
8.0
|
700.0
|
||||||
],
|
],
|
||||||
"ROI_finish": [
|
"act_force_weld": [
|
||||||
43.0
|
1300.0
|
||||||
|
],
|
||||||
|
"force_increase": [
|
||||||
|
100.0
|
||||||
|
],
|
||||||
|
"force_decrease": [
|
||||||
|
100.0
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -241,13 +241,15 @@ class OperatorSettings(settingsWindow):
|
|||||||
class FilterSettings(settingsWindow):
|
class FilterSettings(settingsWindow):
|
||||||
def __init__(self, path, name, upd_func):
|
def __init__(self, path, name, upd_func):
|
||||||
assosiated_names = {
|
assosiated_names = {
|
||||||
"robot_zero_velocity_trashold" : "Robot zero speed filter +-m/sec",
|
"act_vel_min" : "Minimum for ME speed in Closing mm/sec",
|
||||||
"actuator_zero_velocity_trashold" : "Actuator zero speed filter +-m/sec",
|
"act_vel_close" : "Maximum for ME speed in Squeeze mm/sec",
|
||||||
"actuator_finishing_velocity" : "Actuator finishing speed m/sec",
|
"act_vel_thresh" : "ME zero speed threshold mm/sec",
|
||||||
"actuator_finishing_velocity_trashold" : "Actuator finishing speed filter m/sec",
|
"act_vel_negative" : "ME Relief speed mm/sec",
|
||||||
"actuator_current_trashold": "Actuator force filter N",
|
"rob_vel_thresh": "Robot zero speed threshold mm/sec",
|
||||||
"ROI_start" : "Start time, sec",
|
"act_force_close" : "Maximum ME force in Closing, N",
|
||||||
"ROI_finish" : "End time, sec"
|
"act_force_weld" : "Minimum ME force in Welding, N",
|
||||||
|
"force_increase": "ME force rising speed in Squeeze",
|
||||||
|
"force_decrease":"ME force falling speed in Relief"
|
||||||
}
|
}
|
||||||
super().__init__(path, name, upd_func, assosiated_names)
|
super().__init__(path, name, upd_func, assosiated_names)
|
||||||
self._num_points.setVisible(False)
|
self._num_points.setVisible(False)
|
||||||
|
|||||||
@ -173,63 +173,104 @@ class TraceStageDetector(BaseTraceStageDetector):
|
|||||||
def __init__(self, parent:TraceProcessor = None):
|
def __init__(self, parent:TraceProcessor = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
def detect_stages(self, df: pd.DataFrame) -> list:
|
|
||||||
df = df.sort_index()
|
|
||||||
stage_markers = []
|
|
||||||
timestamps = df['time'].to_list() # времена (в секундах) как список
|
|
||||||
|
|
||||||
for i, time in enumerate(timestamps):
|
|
||||||
mark = self._mark_timestamp(df, i, time)
|
|
||||||
if mark: stage_markers.append(mark)
|
|
||||||
|
|
||||||
# Объединяем подряд идущие одинаковые метки в единые этапы.
|
|
||||||
stages = self._merge_marks_to_stages(stage_markers, timestamps)
|
|
||||||
return stages
|
|
||||||
|
|
||||||
def _mark_timestamp(self, df:pd.DataFrame, index:int, time:float) -> Union[str, None]:
|
def _mark_timestamp(self, df:pd.DataFrame, index:int, time:float) -> Union[str, None]:
|
||||||
# Не интересные значения помечаем как "unknown"
|
# Не интересные значения помечаем как "unknown"
|
||||||
if (time < self._parent._settings.filter["ROI_start"][0] or
|
if (time < self._parent._settings.filter["ROI_start"][0] or
|
||||||
time > self._parent._settings.filter["ROI_finish"][0]):
|
time > self._parent._settings.filter["ROI_finish"][0]):
|
||||||
return "unknown"
|
return "unknown"
|
||||||
|
|
||||||
rob_vel = df.loc[index, "CartVel_Act"]
|
@staticmethod
|
||||||
act_vel = df.loc[index, "DriveMotorVel_Act7"]
|
def is_closing(rob_vel:float,
|
||||||
act_curr = df.loc[index, "DriveMotorCurr_Act7"]
|
act_vel:float,
|
||||||
|
act_force:float,
|
||||||
|
th:dict) -> bool:
|
||||||
|
# act_vel > min, rob_vel ~ 0, act_force ниже порога
|
||||||
|
return act_vel > th['act_vel_min'] and abs(rob_vel) < th['rob_vel_thresh'] and act_force < th['act_force_close']
|
||||||
|
|
||||||
if abs(rob_vel) > self._parent._settings.filter["robot_zero_velocity_trashold"][0]:
|
@staticmethod
|
||||||
return "Oncomming"
|
def is_squeeze(rob_vel:float,
|
||||||
|
act_vel:float,
|
||||||
|
act_force:float,
|
||||||
|
force_rate:float,
|
||||||
|
th:dict) -> bool:
|
||||||
|
# rob_vel ~ 0, act_vel меньше, чем в closing, и резкий рост act_force
|
||||||
|
return abs(rob_vel) < th['rob_vel_thresh'] and act_vel < th['act_vel_close'] and force_rate > th['force_increase']
|
||||||
|
|
||||||
if (abs(act_vel) < self._parent._settings.filter["actuator_zero_velocity_trashold"][0] and
|
@staticmethod
|
||||||
abs(act_curr) > self._parent._settings.filter["actuator_current_trashold"][0]):
|
def is_welding(rob_vel:float,
|
||||||
return "Squeeze&Welding&Relief"
|
act_vel:float,
|
||||||
|
act_force:float,
|
||||||
|
th:dict) -> bool:
|
||||||
|
# обе скорости ≈ 0, act_force выше порога сварки
|
||||||
|
return abs(rob_vel) < th['rob_vel_thresh'] and abs(act_vel) < th['act_vel_thresh'] and act_force > th['act_force_weld']
|
||||||
|
|
||||||
if self._parent._settings.filter["actuator_finishing_velocity_trashold"][0] > abs(abs(act_vel) - self._parent._settings.filter["actuator_finishing_velocity"][0]):
|
@staticmethod
|
||||||
return "Closing"
|
def is_relief(rob_vel:float,
|
||||||
|
act_vel:float,
|
||||||
|
act_force:float,
|
||||||
|
force_rate:float,
|
||||||
|
th:dict) -> bool:
|
||||||
|
# резкое падение act_force, отрицательный act_vel, малые rob_vel
|
||||||
|
return force_rate < -th['force_decrease'] and act_vel < -th['act_vel_negative'] and abs(rob_vel) < th['rob_vel_thresh']
|
||||||
|
|
||||||
|
def detect_stages(self, df:pd.DataFrame):
|
||||||
|
timestamps = df['time'].to_list()
|
||||||
|
n = len(df)
|
||||||
|
th = {key: item[0] for key, item in self._parent._settings.filter.items()}
|
||||||
|
# Вычисляем разностную производную силы
|
||||||
|
act_force = df["DriveMotorTorq_Act7"].values
|
||||||
|
force_diff = np.diff(act_force, prepend=act_force[0])
|
||||||
|
|
||||||
return None
|
states = []
|
||||||
|
current_state = "Oncomming"
|
||||||
def _merge_marks_to_stages(self, stage_markers:list, timestamps:list) -> list:
|
state_start = timestamps[0]
|
||||||
stages = []
|
|
||||||
current_stage = stage_markers[0]
|
# Проходим по всем записям
|
||||||
start_time = timestamps[0]
|
for i in range(n):
|
||||||
|
rob_vel = df.loc[i, "CartVel_Act"]
|
||||||
for i in range(1, len(stage_markers)):
|
act_vel = df.loc[i, "DriveMotorVel_Act7"]
|
||||||
if stage_markers[i] != current_stage:
|
act_force_val = df.loc[i, "DriveMotorTorq_Act7"]
|
||||||
end_time = timestamps[i - 1]
|
force_rate = force_diff[i]
|
||||||
stages.append({
|
|
||||||
"stage": current_stage,
|
if current_state == "Oncomming":
|
||||||
"start_time": start_time,
|
if self.is_closing(rob_vel, act_vel, act_force_val, th):
|
||||||
"end_time": end_time
|
state_end = timestamps[i]
|
||||||
})
|
states.append(("Oncomming", state_start, state_end))
|
||||||
current_stage = stage_markers[i]
|
current_state = "Closing"
|
||||||
start_time = timestamps[i]
|
state_start = timestamps[i]
|
||||||
|
|
||||||
stages.append({
|
elif current_state == "Closing":
|
||||||
"stage": current_stage,
|
if self.is_squeeze(rob_vel, act_vel, act_force_val, force_rate, th):
|
||||||
"start_time": start_time,
|
state_end = timestamps[i]
|
||||||
"end_time": timestamps[-1]
|
states.append(("Closing", state_start, state_end))
|
||||||
})
|
current_state = "Squeeze"
|
||||||
return stages
|
state_start = timestamps[i]
|
||||||
|
|
||||||
|
elif current_state == "Squeeze":
|
||||||
|
if self.is_welding(rob_vel, act_vel, act_force_val, th):
|
||||||
|
state_end = timestamps[i]
|
||||||
|
states.append(("Squeeze", state_start, state_end))
|
||||||
|
current_state = "Welding"
|
||||||
|
state_start = timestamps[i]
|
||||||
|
|
||||||
|
elif current_state == "Welding":
|
||||||
|
if self.is_relief(rob_vel, act_vel, act_force_val, force_rate, th):
|
||||||
|
state_end = timestamps[i]
|
||||||
|
states.append(("Welding", state_start, state_end))
|
||||||
|
current_state = "Relief"
|
||||||
|
state_start = timestamps[i]
|
||||||
|
|
||||||
|
elif current_state == "Relief":
|
||||||
|
# Когда признаки relief отпадают, считаем, что цикл завершён и возвращаемся в Oncomming
|
||||||
|
if not self.is_relief(rob_vel, act_vel, act_force_val, force_rate, th):
|
||||||
|
state_end = timestamps[i]
|
||||||
|
states.append(("Relief", state_start, state_end))
|
||||||
|
current_state = "Oncomming"
|
||||||
|
state_start = timestamps[i]
|
||||||
|
|
||||||
|
# Фиксируем последний сегмент
|
||||||
|
states.append((current_state, state_start, timestamps[-1]))
|
||||||
|
return states
|
||||||
|
|
||||||
|
|
||||||
class TextStageDetector(BaseTextStageDetector):
|
class TextStageDetector(BaseTextStageDetector):
|
||||||
@ -305,8 +346,9 @@ class TraceProcessor(BaseRawTraceProcessor):
|
|||||||
def _detect_stages(self, trace_df:pd.DataFrame, text_data:list) -> dict[list]:
|
def _detect_stages(self, trace_df:pd.DataFrame, text_data:list) -> dict[list]:
|
||||||
if trace_df is not None and text_data is not None:
|
if trace_df is not None and text_data is not None:
|
||||||
trace_stages = self._data_detector.detect_stages(trace_df)
|
trace_stages = self._data_detector.detect_stages(trace_df)
|
||||||
welding_stages = self._text_detector.detect_welding(text_data)
|
#welding_stages = self._text_detector.detect_welding(text_data)
|
||||||
events = self._form_events(trace_stages, welding_stages)
|
#events = self._form_events(trace_stages, welding_stages)
|
||||||
|
events = self.__form_events_2(trace_stages)
|
||||||
return events
|
return events
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -354,6 +396,21 @@ class TraceProcessor(BaseRawTraceProcessor):
|
|||||||
events[trace_stages[i]['stage']][1].append(trace_stages[i]['end_time'])
|
events[trace_stages[i]['stage']][1].append(trace_stages[i]['end_time'])
|
||||||
normalized_events = TraceProcessor._normalize_events(events)
|
normalized_events = TraceProcessor._normalize_events(events)
|
||||||
return normalized_events
|
return normalized_events
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def __form_events_2(trace_stages:list):
|
||||||
|
events = {
|
||||||
|
"Closing":[[],[]],
|
||||||
|
"Squeeze":[[],[]],
|
||||||
|
"Welding":[[],[]],
|
||||||
|
"Relief":[[],[]],
|
||||||
|
"Oncomming":[[],[]]
|
||||||
|
}
|
||||||
|
for stage in trace_stages:
|
||||||
|
name, start_t, end_t = stage
|
||||||
|
events[name][0].append(start_t)
|
||||||
|
events[name][1].append(end_t)
|
||||||
|
return events
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _rename_df_columns(dataframe: pd.DataFrame) -> pd.DataFrame:
|
def _rename_df_columns(dataframe: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
|||||||
@ -86,7 +86,7 @@ DIAEXTENDED
|
|||||||
#BEGINCHANNELHEADER
|
#BEGINCHANNELHEADER
|
||||||
200,DriveMotorPos_Act7
|
200,DriveMotorPos_Act7
|
||||||
201,AxisValAtMMInterface
|
201,AxisValAtMMInterface
|
||||||
202,°
|
202,<EFBFBD>
|
||||||
210,EXPLIZIT
|
210,EXPLIZIT
|
||||||
211,teslaSP_VelTCP_KRCIpo.r64
|
211,teslaSP_VelTCP_KRCIpo.r64
|
||||||
213,BLOCK
|
213,BLOCK
|
||||||
@ -101,7 +101,7 @@ DIAEXTENDED
|
|||||||
#BEGINCHANNELHEADER
|
#BEGINCHANNELHEADER
|
||||||
200,DriveMotorVel_Act7
|
200,DriveMotorVel_Act7
|
||||||
201,AxisValAtMMInterface
|
201,AxisValAtMMInterface
|
||||||
202,°/s
|
202,<EFBFBD>/s
|
||||||
210,EXPLIZIT
|
210,EXPLIZIT
|
||||||
211,teslaSP_VelTCP_KRCIpo.r64
|
211,teslaSP_VelTCP_KRCIpo.r64
|
||||||
213,BLOCK
|
213,BLOCK
|
||||||
@ -124,7 +124,7 @@ DIAEXTENDED
|
|||||||
220,3806
|
220,3806
|
||||||
221,7
|
221,7
|
||||||
240,0
|
240,0
|
||||||
241,1.000000e+00
|
241,1.000000e+03
|
||||||
#ENDCHANNELHEADER
|
#ENDCHANNELHEADER
|
||||||
|
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ DIAEXTENDED
|
|||||||
220,3806
|
220,3806
|
||||||
221,10
|
221,10
|
||||||
240,0
|
240,0
|
||||||
241,1.000000e-03
|
241,1.000000e+00
|
||||||
#ENDCHANNELHEADER
|
#ENDCHANNELHEADER
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user