完善流量控制前馈、稳态判定与阀门标定流程

- 前馈冻结改用可配置的 3 秒流量绝对误差滑窗,修复采样抖动造成的重复解冻,并保留下游扰动后的自动更新
- 支持非单调阀特性反解、最小可测面积以下直接全关,以及闭阀端精细扫点与辨识开关
- 调整双压力判稳、最长等待时间、在线入口全开收尾和闭环四联图
- 更新配置、README、阀模型及离线测试,归档本轮实验数据与诊断产物
This commit is contained in:
2026-09-02 16:14:42 +08:00
parent 5888b4ccce
commit cfeedcf887
80 changed files with 40473 additions and 171 deletions
+61 -9
View File
@@ -13,8 +13,9 @@ class PerformanceReporter:
"""逐周期观测流量,判定稳态并输出控制性能报告。
稳态判定采用两个条件同时满足(AND):
1. 滑窗均值落在目标流量 ±band_pct% 误差带内;
2. 滑窗标准差低于 std_pct% 目标流量阈值。
1. 流量滑窗均值落在目标流量 ±band_pct% 误差带内;
2. 阀前、阀后压力的窗口样本均位于各自窗口均值
±pressure_band_kpa 范围内。
报告只在首次判定稳态时输出一次。
"""
@@ -25,7 +26,7 @@ class PerformanceReporter:
window_s,
sample_period_s,
band_pct,
std_pct,
pressure_band_kpa,
flow_range_min_slm,
flow_range_max_slm,
initial_flow_slm=None,
@@ -35,7 +36,7 @@ class PerformanceReporter:
self.window_s = float(window_s)
self.sample_period_s = float(sample_period_s)
self.band_pct = float(band_pct)
self.std_pct = float(std_pct)
self.pressure_band_kpa = float(pressure_band_kpa)
self.flow_range_min_slm = float(flow_range_min_slm)
self.flow_range_max_slm = float(flow_range_max_slm)
self.initial_flow_slm = (
@@ -48,10 +49,15 @@ class PerformanceReporter:
self.steady_mean = None
self.steady_std = None
self.steady_error_slm = None
self.steady_pressure_before_mean = None
self.steady_pressure_after_mean = None
self.steady_pressure_before_max_deviation = None
self.steady_pressure_after_max_deviation = None
self._first_timestamp = None
self._peak_flow_slm = None
self._min_flow_slm = None
self._window = deque() # 元素为 (elapsed_s, flow_slm)
# 元素为 (elapsed_s, flow_slm, pressure_before_kpa, pressure_after_kpa)
self._window = deque()
self._reached = False
def observe(self, result):
@@ -62,7 +68,16 @@ class PerformanceReporter:
return
flow = float(result.measured_flow_slm)
if not math.isfinite(flow):
pressure_before = result.pressure_before_kpa
pressure_after = result.pressure_kpa
if pressure_before is None or pressure_after is None:
return
pressure_before = float(pressure_before)
pressure_after = float(pressure_after)
if not all(
math.isfinite(value)
for value in (flow, pressure_before, pressure_after)
):
return
target = float(result.target_flow_slm)
if target <= 0.0:
@@ -80,7 +95,9 @@ class PerformanceReporter:
if self._min_flow_slm is None or flow < self._min_flow_slm:
self._min_flow_slm = flow
self._window.append((elapsed_s, flow))
self._window.append(
(elapsed_s, flow, pressure_before, pressure_after)
)
cutoff = elapsed_s - self.window_s
while self._window and self._window[0][0] < cutoff:
self._window.popleft()
@@ -95,17 +112,38 @@ class PerformanceReporter:
return
flows = [item[1] for item in self._window]
pressures_before = [item[2] for item in self._window]
pressures_after = [item[3] for item in self._window]
mean = statistics.mean(flows)
std = statistics.pstdev(flows)
pressure_before_mean = statistics.mean(pressures_before)
pressure_after_mean = statistics.mean(pressures_after)
pressure_before_max_deviation = max(
abs(value - pressure_before_mean) for value in pressures_before
)
pressure_after_max_deviation = max(
abs(value - pressure_after_mean) for value in pressures_after
)
band = self.band_pct / 100.0 * target
std_threshold = self.std_pct / 100.0 * target
if abs(mean - target) <= band and std <= std_threshold:
pressure_stable = (
pressure_before_max_deviation <= self.pressure_band_kpa
and pressure_after_max_deviation <= self.pressure_band_kpa
)
if abs(mean - target) <= band and pressure_stable:
self._reached = True
self.settling_time_s = elapsed_s
self.steady_mean = mean
self.steady_std = std
self.steady_error_slm = target - mean
self.steady_pressure_before_mean = pressure_before_mean
self.steady_pressure_after_mean = pressure_after_mean
self.steady_pressure_before_max_deviation = (
pressure_before_max_deviation
)
self.steady_pressure_after_max_deviation = (
pressure_after_max_deviation
)
self._report()
def finalize(self):
@@ -125,6 +163,10 @@ class PerformanceReporter:
self.steady_mean = None
self.steady_std = None
self.steady_error_slm = None
self.steady_pressure_before_mean = None
self.steady_pressure_after_mean = None
self.steady_pressure_before_max_deviation = None
self.steady_pressure_after_max_deviation = None
self._first_timestamp = None
self._peak_flow_slm = None
self._min_flow_slm = None
@@ -171,6 +213,16 @@ class PerformanceReporter:
f"调节时间(至稳态): {self.settling_time_s:.3f} s",
f"稳态流量(窗口均值): {self.steady_mean:.3f} SLM",
f"稳态标准差(窗口): {self.steady_std:.3f} SLM",
(
"阀前压力(窗口均值/最大偏差): "
f"{self.steady_pressure_before_mean:.3f} kPa / "
f"±{self.steady_pressure_before_max_deviation:.3f} kPa"
),
(
"阀后压力(窗口均值/最大偏差): "
f"{self.steady_pressure_after_mean:.3f} kPa / "
f"±{self.steady_pressure_after_max_deviation:.3f} kPa"
),
(
f"稳态误差: {self.steady_error_slm:+.3f} SLM "
f"(目标 - 稳态均值)"