实现流量控制前馈 + 增益调度(MFC 结构)
按 plan.md 新增三个交付物,全部默认关闭以保持与纯 PID 的 A/B 兼容: - valve_model.py:阀特性模型 Q_ss = A_eff(x)·P1_abs·F(r),含 ISO 6358 椭圆 F(r)、行程/面积互逆插值、单调性校验、JSON 存取。 - identify_valve.py:从 open_loop.py 扫点 CSV 拟合 A_eff 表并输出 JSON。 - 控制器集成:config/flow_control/main/data_logger 新增阀前压读取 (channel 2)、前馈打底 + PI 修残差、按 P1 增益调度,并记录/绘制前馈项。 新增配置 FEEDFORWARD_ENABLED / GAIN_SCHEDULE_ENABLED 默认 False, VALVE_MODEL_PATH 默认空,未加载模型时行为与原先纯 PID 完全一致。
This commit is contained in:
@@ -23,6 +23,7 @@ from controllers import IncrementalPID
|
||||
from data_logger import FlowRunRecorder
|
||||
from flow_control import FlowControlFault, FlowControlLoop
|
||||
from performance_reporter import PerformanceReporter
|
||||
from valve_model import ValveModel
|
||||
|
||||
|
||||
class ConsoleGate(logging.Filter):
|
||||
@@ -61,7 +62,27 @@ def build_logger():
|
||||
return logger, console_gate
|
||||
|
||||
|
||||
def _load_valve_model(logger):
|
||||
"""按配置加载阀特性模型;配置为空或文件缺失/损坏时返回 None(纯 PID)。"""
|
||||
if not config.VALVE_MODEL_PATH:
|
||||
return None
|
||||
model_path = Path(__file__).resolve().parent / config.VALVE_MODEL_PATH
|
||||
if not model_path.exists():
|
||||
logger.warning("阀特性模型文件不存在:%s,退化为纯 PID", model_path)
|
||||
return None
|
||||
try:
|
||||
return ValveModel.load(
|
||||
str(model_path),
|
||||
config.MOTOR_OPEN_POSITION,
|
||||
config.MOTOR_CLOSED_POSITION,
|
||||
)
|
||||
except (ValueError, OSError) as exc:
|
||||
logger.warning("加载阀特性模型失败(%s):%s,退化为纯 PID", model_path, exc)
|
||||
return None
|
||||
|
||||
|
||||
def build_control_loop(hardware, logger):
|
||||
valve_model = _load_valve_model(logger)
|
||||
pid = IncrementalPID(
|
||||
kp=config.PID_FAR_KP,
|
||||
ki=config.PID_FAR_KI,
|
||||
@@ -77,6 +98,7 @@ def build_control_loop(hardware, logger):
|
||||
period_s=config.CONTROL_PERIOD_S,
|
||||
flow_channel=config.FLOW_INPUT_CHANNEL,
|
||||
pressure_channel=config.PRESSURE_INPUT_CHANNEL,
|
||||
pressure_before_channel=config.PRESSURE_BEFORE_CHANNEL,
|
||||
motor_channel=config.MOTOR_OUTPUT_CHANNEL,
|
||||
motor_open_position=config.MOTOR_OPEN_POSITION,
|
||||
motor_closed_position=config.MOTOR_CLOSED_POSITION,
|
||||
@@ -112,6 +134,15 @@ def build_control_loop(hardware, logger):
|
||||
pid_mode_switch_confirm_cycles=(
|
||||
config.PID_MODE_SWITCH_CONFIRM_CYCLES
|
||||
),
|
||||
valve_model=valve_model,
|
||||
feedforward_enabled=config.FEEDFORWARD_ENABLED,
|
||||
feedforward_correction_band_pct=config.FEEDFORWARD_CORRECTION_BAND_PCT,
|
||||
gain_schedule_enabled=config.GAIN_SCHEDULE_ENABLED,
|
||||
gain_schedule_ref_abs_kpa=config.GAIN_SCHEDULE_REF_ABS_KPA,
|
||||
gain_schedule_floor_abs_kpa=config.GAIN_SCHEDULE_FLOOR_ABS_KPA,
|
||||
gain_schedule_scale_change_threshold=(
|
||||
config.GAIN_SCHEDULE_SCALE_CHANGE_THRESHOLD
|
||||
),
|
||||
logger=logger,
|
||||
)
|
||||
|
||||
@@ -139,12 +170,27 @@ def format_status(result):
|
||||
"--" if result.pressure_kpa is None
|
||||
else f"{result.pressure_kpa:.2f}"
|
||||
)
|
||||
return (
|
||||
f"状态={result.status} 目标={result.target_flow_slm:.2f} SLM "
|
||||
f"实际={flow_text} SLM 压力={pressure_text} kPa "
|
||||
f"开度={result.opening_pct:.2f}% "
|
||||
f"行程={result.motor_position:.1f} dt={result.actual_dt_s:.3f}s"
|
||||
pressure_before_text = (
|
||||
"--" if result.pressure_before_kpa is None
|
||||
else f"{result.pressure_before_kpa:.2f}"
|
||||
)
|
||||
parts = [
|
||||
f"状态={result.status}",
|
||||
f"目标={result.target_flow_slm:.2f} SLM",
|
||||
f"实际={flow_text} SLM",
|
||||
f"压力={pressure_text} kPa",
|
||||
f"阀前压={pressure_before_text} kPa",
|
||||
f"开度={result.opening_pct:.2f}%",
|
||||
]
|
||||
if result.feedforward_pct is not None:
|
||||
parts.append(f"前馈={result.feedforward_pct:.2f}%")
|
||||
if result.correction_pct is not None:
|
||||
parts.append(f"修正={result.correction_pct:+.2f}%")
|
||||
if result.gain_scale is not None and abs(result.gain_scale - 1.0) > 1e-9:
|
||||
parts.append(f"scale={result.gain_scale:.3f}")
|
||||
parts.append(f"行程={result.motor_position:.1f}")
|
||||
parts.append(f"dt={result.actual_dt_s:.3f}s")
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
def run(target_flow_slm):
|
||||
|
||||
Reference in New Issue
Block a user