From 1d065d81d3a14f7f5126348095d6a2d71ea873ec Mon Sep 17 00:00:00 2001 From: louissun Date: Thu, 20 Aug 2026 09:24:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=BE=93=E5=87=BA=E7=A8=B3?= =?UTF-8?q?=E6=80=81=E6=97=B6=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3=E6=B5=81?= =?UTF-8?q?=E9=87=8F=E5=9D=87=E5=80=BC=E5=92=8C=E6=A0=87=E5=87=86=E5=B7=AE?= =?UTF-8?q?=EF=BC=8C=E4=BB=A5=E5=8F=8A=E7=A8=B3=E6=80=81=E8=AF=AF=E5=B7=AE?= =?UTF-8?q?=EF=BC=88=E5=88=A4=E7=A8=B3=E6=88=90=E5=8A=9F=E6=97=B6=E7=9B=AE?= =?UTF-8?q?=E6=A0=87=E6=B5=81=E9=87=8F=E5=87=8F=E5=8E=BB=E5=BD=93=E6=97=B6?= =?UTF-8?q?=E6=B5=81=E9=87=8F=EF=BC=89=E3=80=82=20=E7=9B=AE=E5=89=8D?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E6=98=AF=E3=80=8C=E4=B8=80=E7=9B=B4=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=20+=20=E6=AF=8F=E7=A7=92=E7=8A=B6=E6=80=81=E7=85=A7?= =?UTF-8?q?=E5=B8=B8=E8=BE=93=E5=87=BA=20+=20=E7=A8=B3=E6=80=81=E6=97=B6?= =?UTF-8?q?=E9=A2=9D=E5=A4=96=E5=A4=9A=E6=89=93=E5=8D=B0=E4=B8=80=E6=AC=A1?= =?UTF-8?q?=E6=80=A7=E8=83=BD=E6=8A=A5=E5=91=8A=E3=80=8D=E3=80=82=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=80=E4=B8=AA=E5=8F=AF=E9=80=89=E7=9A=84?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=81=9C=E6=AD=A2=E5=8A=9F=E8=83=BD--config?= =?UTF-8?q?=E5=BC=80=E5=85=B3=EF=BC=8C=E3=80=8C=E8=BE=BE=E5=88=B0=E7=A8=B3?= =?UTF-8?q?=E6=80=81=E5=90=8E=E8=87=AA=E5=8A=A8=E5=81=9C=E6=AD=A2=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E3=80=8D=EF=BC=8C=E8=AE=A9=20reporter=20=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E4=B8=BB=E5=BE=AA=E7=8E=AF=E9=80=80=E5=87=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 2 ++ main.py | 4 ++++ performance_reporter.py | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/config.py b/config.py index b6f7074..bf0bc26 100644 --- a/config.py +++ b/config.py @@ -54,6 +54,8 @@ STEADY_STATE_WINDOW_S = 2.0 # 滑动时间窗口长度 STEADY_STATE_BAND_PCT = 2.0 # 滑窗均值相对目标的允许误差带(±2%) STEADY_STATE_STD_PCT = 2.0 # 滑窗标准差阈值(相对目标百分比) +AUTO_STOP_ON_STEADY = True # 达到稳态后是否自动停止控制(False 则持续控制) + # --------------------------------------------------------------------------- # 阀门执行机构 # --------------------------------------------------------------------------- diff --git a/main.py b/main.py index e0212a6..f9baed6 100644 --- a/main.py +++ b/main.py @@ -189,6 +189,10 @@ def run(target_flow_slm): recorder.record(result) reporter.observe(result) + if config.AUTO_STOP_ON_STEADY and reporter.steady_reached: + logger.info("已达到稳态,自动停止控制") + break + if now >= next_status_time or result.status != "OK": logger.info(format_status(result)) next_status_time = now + config.STATUS_PRINT_PERIOD_S diff --git a/performance_reporter.py b/performance_reporter.py index 4e0f765..3076c85 100644 --- a/performance_reporter.py +++ b/performance_reporter.py @@ -43,6 +43,9 @@ class PerformanceReporter: self.target_flow_slm = None self.settling_time_s = None + self.steady_mean = None + self.steady_std = None + self.steady_error_slm = None self._first_timestamp = None self._peak_flow_slm = None self._min_flow_slm = None @@ -94,6 +97,9 @@ class PerformanceReporter: if abs(mean - target) <= band and std <= std_threshold: self._reached = True self.settling_time_s = elapsed_s + self.steady_mean = mean + self.steady_std = std + self.steady_error_slm = target - mean self._report() def finalize(self): @@ -101,6 +107,11 @@ class PerformanceReporter: if not self._reached and self.target_flow_slm is not None: self._log("info", "本次运行未达到稳态,未生成控制性能报告") + @property + def steady_reached(self): + """是否已判定达到稳态(供主循环决定是否自动停止)。""" + return self._reached + def _report(self): target = self.target_flow_slm initial = self.initial_flow_slm @@ -134,6 +145,12 @@ class PerformanceReporter: f"{self.flow_range_max_slm:.3f} SLM" ), f"调节时间(至稳态): {self.settling_time_s:.3f} s", + f"稳态流量(窗口均值): {self.steady_mean:.3f} SLM", + f"稳态标准差(窗口): {self.steady_std:.3f} SLM", + ( + f"稳态误差: {self.steady_error_slm:+.3f} SLM " + f"(目标 - 稳态均值)" + ), f"初始流量: {initial:.3f} SLM", ( f"超调量: {extremum_text},{direction} "