574 lines
25 KiB
Markdown
574 lines
25 KiB
Markdown
# FbStateMachine 深度分析与修正设计
|
||
|
||
> 对上轮优化方案中 FbStateMachine 设计不完整之处的修正,综合考虑 StatExp 状态函数刷新机制。
|
||
|
||
---
|
||
|
||
## 一、现有反馈状态机完整映射
|
||
|
||
### 1.1 真状态图(7 状态)
|
||
|
||
阅读源码后得出的真实状态图,比上一版的 5 状态更精确:
|
||
|
||
```
|
||
┌──────────────────────────────────────┐
|
||
│ exec_mon_call() 层 │
|
||
│ get_prr()==false → 强制重置 │
|
||
│ alarm 触发 → fun_reset(PRR的FunVars) │
|
||
└──────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ mon_proc() 层 │
|
||
│ │
|
||
│ ┌─────────┐ act_triggered ┌──────────┐ │
|
||
│ │ Idle │ ───────────────► │ Started │ │
|
||
│ │ (空闲) │ │ (动作开始) │ │
|
||
│ │ fun✓ │ │ fun✗ │ │
|
||
│ └─────────┘ └────┬─────┘ │
|
||
│ ▲ │ │
|
||
│ │ ┌───────┼───────┐ │
|
||
│ │ │ │ │ │
|
||
│ │ ▼ ▼ ▼ │
|
||
│ │ ┌────────┐┌──────┐┌──────────┐ │
|
||
│ │ │NotHold ││Done ││Timeout │ │
|
||
│ │ │(不保持) ││(完成) ││(超时) │ │
|
||
│ │ │ fun✓ ││ fun✓ ││ fun✓ │ │
|
||
│ │ └───┬────┘└──┬───┘└────┬─────┘ │
|
||
│ │ │ │ │ │
|
||
│ └──────────────────┴────────┴─────────┘ │
|
||
│ 下次 mon_proc() 自动回到 Idle │
|
||
│ │
|
||
│ ┌──────────────────────────────────────────┐ │
|
||
│ │ InProgress (动作进行中) │ │
|
||
│ │ act_started_=true, 但未触发终端条件 │ │
|
||
│ │ fun✗, 持续更新 mv2/up/dw/mx/mi/time │ │
|
||
│ └──────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
|
||
注释: fun✓ = 本周期设置 is_fun_vars_need_reset_ = true
|
||
fun✗ = 不设置(状态函数持续累加)
|
||
```
|
||
|
||
**关键**:InProgress 不是一个独立的 `return` 分支,而是 "所有终端条件都不满足时,fallthrough 到 return {}"的隐式状态。
|
||
|
||
### 1.2 七个状态详解
|
||
|
||
| 状态 | 触发条件 | act_started_ | 返回 | fun_reset | 变量操作 |
|
||
|------|---------|-------------|------|-----------|---------|
|
||
| **Idle** | act_triggered_=false | false | {} | **true** (via act_start_done else分支) | 无 |
|
||
| **Started** | 首次 act_triggered_=true | false→true | {} | **false** | 快照 sN, 初始化 mx/mi/mv2/up/dw, stime=now, time=0 |
|
||
| **InProgress** | started后, 未达终端 | true | {} | **false** | act_done()更新: time, mx=max, mi=min, mv2+=1, up+=flag, dw+=flag |
|
||
| **Done** | feedback_triggered_=true | true→false | AlarmInfo 或 {} | **true** | etime=now (在act_done内) |
|
||
| **NotHold** | keep_mode && !act_triggered_ | true→false | {} | **true** | 无额外 |
|
||
| **Timeout** | now-start > timeout | true→false | AlarmInfo 或 {} | **true** | 清零 mv2/up/dw (在act_timeout内) |
|
||
| **PRR_False** | get_prr()=false (外层) | →false | (不进入mon_proc) | **false** | act_started_/act_triggered_/feedback_triggered_ 全部重置 |
|
||
|
||
### 1.3 fun_vars 完整生命周期
|
||
|
||
```
|
||
单周期时序:
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 1. AlgBase::exec_mon_call() │
|
||
│ ├── get_cycled()? │
|
||
│ ├── get_prr() → 若false: 重置fb状态, return (不进入mon) │
|
||
│ └── exec_mon() → ExpBase::exec_mon() │
|
||
│ │
|
||
│ 2. ExpBase::exec_mon() │
|
||
│ ├── refresh_exp_vars_mem/ihd() │
|
||
│ │ └── fun_vars_.refresh_fun_vars(false) ← 评估funN │
|
||
│ └── mon_proc() │
|
||
│ │
|
||
│ 3. mon_proc() │
|
||
│ ├── auto_fun_vars_reset() ← 若flag, reset funN │
|
||
│ ├── evaluate expressions (使用当前funN值) │
|
||
│ ├── [反馈状态机判断] │
|
||
│ │ └── 若终端状态: is_fun_vars_need_reset_ = true │
|
||
│ └── return alarm or {} │
|
||
│ │
|
||
│ 4. 回到 exec_mon_call() │
|
||
│ └── if alarm: exp_mpdule_ptr_->fun_reset() ← PRR的funN │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
|
||
关键时序规则:
|
||
- refresh_fun_vars(false) 在 mon_proc() 之前执行
|
||
- auto_fun_vars_reset() 在 mon_proc() 开头执行(用的是上一周期设置的flag)
|
||
- is_fun_vars_need_reset_ 在当前周期设置,下周期生效
|
||
- 报警消息使用的是本周期(reset前)的funN值
|
||
```
|
||
|
||
### 1.4 两套 FunVars 的独立性
|
||
|
||
代码中存在**两套独立的 FunVars 实例**:
|
||
|
||
| 属性 | ExpBase::fun_vars_ | ExpModule::fun_vars_ |
|
||
|------|-------------------|---------------------|
|
||
| 所属 | ExpBase | ExpModule (exp_mpdule_ptr_) |
|
||
| 用途 | 主表达式 (exp_act_, exp_feedback_, exp_result_) 中的状态函数 | PRR 前提表达式 (pre_result) 中的状态函数 |
|
||
| 刷新 | refresh_exp_vars_mem/ihd() 中 refresh_fun_vars(false) | ExpModule::update() 中 refresh_fun_vars(false) |
|
||
| 重置 | mon_proc() 中 auto_fun_vars_reset() | AlgBase::exec_mon_call() 中 alarm 时 fun_reset() |
|
||
| is_exp_alg_=true时 | 由 ExpBase 管理 | **跳过刷新**(共享 ExpBase 的 mm_vars) |
|
||
| 变量命名 | fun0,fun1... | fun0,fun1... (独立index,可能冲突!) |
|
||
|
||
**⚠️ 潜在问题**:当 `is_exp_alg_=true` 时,ExpModule::update() 跳过其 fun_vars 刷新。但两个 FunVars 的 `index` 计数器是独立的——如果 PRR 表达式中也有状态函数(如 `KeepC(tag1,1)`),且 ExpBase::fun_vars_init() 将其加入了 ExpBase::fun_vars_,则两套 FunVars 可能创建同名的 `fun0` 变量指向不同的表达式。幸好 `is_exp_alg_=true` 时 ExpModule 这部分逻辑被跳过。
|
||
|
||
---
|
||
|
||
## 二、上一版 FbStateMachine 设计的缺陷
|
||
|
||
### 缺陷 1:未处理变量快照和更新
|
||
|
||
上一版的 FbStateMachine::update() 设计只做状态转换,但**变量操作(快照/更新)与状态转换不可分割**:
|
||
|
||
- `act_start_done()` 在 Started 状态执行变量快照(6 类变量初始化)
|
||
- `act_done()` 在每个 InProgress 周期更新累积变量(time, mx, mi, mv2, up, dw)
|
||
- `act_timeout()` 在 Timeout 状态清零累积变量
|
||
|
||
这些操作必须和状态转换在同一个事务中完成,否则反馈表达式(引用 mv2_tagN, up_tagN 等)会读到过期值。
|
||
|
||
### 缺陷 2:未考虑 Idle 状态的 fun_vars 重置
|
||
|
||
`act_start_done()` 的 else 分支 `!act_started_ && !act_triggered_` 设置了 `is_fun_vars_need_reset_ = true`。这意味着**每个 Idle 周期**都会标记 fun_vars 需要重置。上一版设计中 Idle→needReset=true 是正确的,但没有考虑这个重置是通过 `act_start_done()` 的副作用实现的。
|
||
|
||
### 缺陷 3:未处理 Timeout 哨兵值
|
||
|
||
`time_out_ == milliseconds(-32768)` 表示无超时限制。此时 `act_timeout()` 不检查时间,而是检查 mv2_tagN 是否接近 DBL_MAX(防溢出)。这是一个特殊分支,上一版未覆盖。
|
||
|
||
### 缺陷 4:未处理 PRR 强制重置
|
||
|
||
当 `get_prr()` 返回 false 时(`ExpBase` 重写版本),反馈状态标志被强制清零:
|
||
```cpp
|
||
this->act_started_ = false;
|
||
this->act_triggered_ = false;
|
||
this->feedback_triggered_ = false;
|
||
```
|
||
但 `is_fun_vars_need_reset_` 不设置。PRR 恢复后,fun_vars 保持之前的状态。FbStateMachine 需要暴露一个 `forceReset()` 方法。
|
||
|
||
### 缺陷 5:未考虑 Done 状态中 CondBound 的特殊逻辑
|
||
|
||
`act_done()` 返回 true 后,mon_proc() 还有后续逻辑:
|
||
- 计算 `exp_result_->evaluate()`
|
||
- CondBound:检测上下限 → 可能报警
|
||
- 非 CondBound:检测布尔值 → 可能报警
|
||
- 有自学习:添加统计样本
|
||
|
||
上一版设计中把这些放在了 FbStateMachine 外部,但没有明确接口。
|
||
|
||
---
|
||
|
||
## 三、修正后的 FbStateMachine 设计
|
||
|
||
### 3.1 接口设计
|
||
|
||
```cpp
|
||
// 状态枚举
|
||
enum class FbState {
|
||
Idle, // 空闲
|
||
Started, // 刚启动(第一个周期,等待下次检查反馈条件)
|
||
InProgress, // 进行中
|
||
Done, // 反馈条件满足,动作完成
|
||
NotHold, // 不保持(keep_mode下触发条件丢失)
|
||
Timeout // 超时
|
||
};
|
||
|
||
// update() 返回结构
|
||
struct FbUpdateResult {
|
||
FbState state;
|
||
bool funVarsNeedReset; // 本周期是否需要标记 fun_vars 重置(下周期生效)
|
||
};
|
||
|
||
class FbStateMachine {
|
||
public:
|
||
// === 配置(替代 reload_config_exp_feedback 中的状态相关部分)===
|
||
void configure(bool keepMode, TimeDur timeout);
|
||
|
||
// === 核心:每个 mon 周期调用一次 ===
|
||
// now: 当前时间
|
||
// vars: 变量管理器引用(用于快照/更新变量)
|
||
// actTriggered: 前提表达式结果 (exp_act_->evaluate())
|
||
FbUpdateResult update(bool actTriggered, TimePoint now, VarManager& vars);
|
||
|
||
// === 条件检查(在 update 返回 InProgress 后调用)===
|
||
// fbCondition: 反馈表达式结果 (exp_feedback_->evaluate())
|
||
// 返回 true 表示反馈条件满足,应转为 Done
|
||
bool checkFeedback(bool fbCondition, TimePoint now, VarManager& vars);
|
||
|
||
// === 外部强制重置(PRR=false 时调用)===
|
||
void forceReset();
|
||
|
||
// === 查询 ===
|
||
bool isActive() const; // Started 或 InProgress
|
||
TimePoint actionStartTime() const;
|
||
bool isKeepMode() const;
|
||
|
||
private:
|
||
bool keep_mode_ = false;
|
||
TimeDur timeout_ = 10min;
|
||
FbState state_ = FbState::Idle;
|
||
TimePoint start_time_;
|
||
int tag_count_ = 0;
|
||
|
||
// 防溢出(替代 act_timeout 中 timeout_ == -32768 分支)
|
||
bool checkOverflowPrevention(VarManager& vars);
|
||
};
|
||
```
|
||
|
||
### 3.2 完整状态转换实现
|
||
|
||
```cpp
|
||
FbUpdateResult FbStateMachine::update(bool actTriggered, TimePoint now,
|
||
VarManager& vars) {
|
||
FbUpdateResult result;
|
||
result.funVarsNeedReset = false;
|
||
|
||
switch (state_) {
|
||
// ── Idle ─────────────────────────────────────────────
|
||
case FbState::Idle:
|
||
if (actTriggered) {
|
||
// → Started:快照变量
|
||
vars.snapshotActionStart(now);
|
||
state_ = FbState::Started;
|
||
start_time_ = now;
|
||
result.state = FbState::Started;
|
||
// funVarsNeedReset = false(保持状态函数连续性)
|
||
} else {
|
||
// 保持 Idle,但标记 fun_vars 重置
|
||
result.state = FbState::Idle;
|
||
result.funVarsNeedReset = true;
|
||
// 原因:无活动事件时,KeepC/RiseEdge 不应累积
|
||
}
|
||
break;
|
||
|
||
// ── Started(仅在首次触发的那个周期)─────────────────
|
||
case FbState::Started:
|
||
// 更新累积变量(第一个周期也需要更新)
|
||
vars.updateActionVars(now);
|
||
|
||
if (!actTriggered && keep_mode_) {
|
||
// 触发条件在第一个周期就丢失 → NotHold
|
||
state_ = FbState::Idle; // 下周期回到 Idle
|
||
result.state = FbState::NotHold;
|
||
result.funVarsNeedReset = true;
|
||
} else if (checkOverflowPrevention(vars)) {
|
||
state_ = FbState::Idle;
|
||
result.state = FbState::Timeout;
|
||
result.funVarsNeedReset = true;
|
||
} else {
|
||
// 正常进入 InProgress
|
||
state_ = FbState::InProgress;
|
||
result.state = FbState::Started; // 返回 Started 让调用方跳过反馈检查
|
||
// funVarsNeedReset = false
|
||
}
|
||
break;
|
||
|
||
// ── InProgress ───────────────────────────────────────
|
||
case FbState::InProgress:
|
||
// 先更新累积变量
|
||
vars.updateActionVars(now);
|
||
|
||
if (!actTriggered && keep_mode_) {
|
||
state_ = FbState::Idle;
|
||
result.state = FbState::NotHold;
|
||
result.funVarsNeedReset = true;
|
||
} else if (checkOverflowPrevention(vars)) {
|
||
state_ = FbState::Idle;
|
||
result.state = FbState::Timeout;
|
||
result.funVarsNeedReset = true;
|
||
} else if (timeout_ != TimeDur(-32768) &&
|
||
(now - start_time_) > timeout_) {
|
||
// 超时
|
||
vars.clearActionAccumulators();
|
||
state_ = FbState::Idle;
|
||
result.state = FbState::Timeout;
|
||
result.funVarsNeedReset = true;
|
||
}
|
||
// 否则保持 InProgress,等待 checkFeedback()
|
||
break;
|
||
|
||
// ── 终端状态(Done/NotHold/Timeout,由 checkFeedback 或上述分支设置)──
|
||
default:
|
||
// 上周期是终端状态,本周期自动回到 Idle
|
||
state_ = FbState::Idle;
|
||
result.state = FbState::Idle;
|
||
result.funVarsNeedReset = true; // 延续 Idle 的 reset 行为
|
||
break;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
bool FbStateMachine::checkFeedback(bool fbCondition, TimePoint now,
|
||
VarManager& vars) {
|
||
if (state_ != FbState::InProgress && state_ != FbState::Started) {
|
||
return false;
|
||
}
|
||
|
||
if (fbCondition) {
|
||
vars.recordActionEnd(now); // etime = now
|
||
state_ = FbState::Idle; // 下周期回到 Idle
|
||
return true; // → Done
|
||
}
|
||
return false;
|
||
}
|
||
|
||
void FbStateMachine::forceReset() {
|
||
state_ = FbState::Idle;
|
||
start_time_ = TimePoint{};
|
||
}
|
||
|
||
bool FbStateMachine::checkOverflowPrevention(VarManager& vars) {
|
||
if (timeout_ != TimeDur(-32768)) return false;
|
||
return vars.isAccumulatorNearOverflow();
|
||
}
|
||
```
|
||
|
||
### 3.3 VarManager 需要新增的方法
|
||
|
||
为配合 FbStateMachine,VarManager 需要新增以下方法:
|
||
|
||
```cpp
|
||
class VarManager {
|
||
public:
|
||
// ... 原有方法 ...
|
||
|
||
// ── 反馈状态机配合 ──
|
||
|
||
// 动作开始时快照(替代 act_start_done 中的变量初始化)
|
||
void snapshotActionStart(TimePoint now);
|
||
// 动作进行中更新累积值(替代 act_done 中前半段的变量更新)
|
||
void updateActionVars(TimePoint now);
|
||
// 动作结束时记录(替代 act_done 中 etime 设置)
|
||
void recordActionEnd(TimePoint now);
|
||
// 超时时清零累积器(替代 act_timeout 中的清零)
|
||
void clearActionAccumulators();
|
||
// 累积值是否接近溢出
|
||
bool isAccumulatorNearOverflow() const;
|
||
};
|
||
```
|
||
|
||
具体实现直接迁移现有代码:
|
||
|
||
```cpp
|
||
void VarManager::snapshotActionStart(TimePoint now) {
|
||
mm_vars_["stime"] = duration_cast<milliseconds>(now.time_since_epoch()).count();
|
||
mm_vars_["time"] = 0;
|
||
for (size_t i = 0; i < tag_count_; i++) {
|
||
std::string idx = std::to_string(i + 1);
|
||
double tag_val = mm_vars_["tag" + idx];
|
||
mm_vars_["s" + idx] = tag_val;
|
||
mm_vars_["mx_tag" + idx] = tag_val;
|
||
mm_vars_["mi_tag" + idx] = tag_val;
|
||
mm_vars_["mv2_tag" + idx] = 0;
|
||
mm_vars_["mv2_p" + idx] = 0;
|
||
double p_val = mm_vars_["p" + idx];
|
||
mm_vars_["up_tag" + idx] = (p_val == 0 && tag_val == 1) ? 1.0 : 0.0;
|
||
mm_vars_["dw_tag" + idx] = (p_val == 1 && tag_val == 0) ? 1.0 : 0.0;
|
||
if (tag_val == 1) mm_vars_["mv2_tag" + idx] = 1;
|
||
if (p_val == 1) mm_vars_["mv2_p" + idx] = 1;
|
||
}
|
||
}
|
||
|
||
void VarManager::updateActionVars(TimePoint now) {
|
||
mm_vars_["time"] = mm_vars_["now"] - mm_vars_["stime"];
|
||
for (size_t i = 0; i < tag_count_; i++) {
|
||
std::string idx = std::to_string(i + 1);
|
||
double tag_val = mm_vars_["tag" + idx];
|
||
double p_val = mm_vars_["p" + idx];
|
||
mm_vars_["mx_tag" + idx] = std::max(tag_val, mm_vars_["mx_tag" + idx]);
|
||
mm_vars_["mi_tag" + idx] = std::min(tag_val, mm_vars_["mi_tag" + idx]);
|
||
if (tag_val == 1) mm_vars_["mv2_tag" + idx] += 1;
|
||
if (p_val == 1) mm_vars_["mv2_p" + idx] += 1;
|
||
mm_vars_["up_tag" + idx] += (p_val == 0 && tag_val == 1) ? 1.0 : 0.0;
|
||
mm_vars_["dw_tag" + idx] += (p_val == 1 && tag_val == 0) ? 1.0 : 0.0;
|
||
}
|
||
}
|
||
|
||
void VarManager::recordActionEnd(TimePoint now) {
|
||
mm_vars_["etime"] = mm_vars_["now"];
|
||
}
|
||
|
||
void VarManager::clearActionAccumulators() {
|
||
for (size_t i = 0; i < tag_count_; i++) {
|
||
std::string idx = std::to_string(i + 1);
|
||
mm_vars_["mv2_tag" + idx] = 0;
|
||
mm_vars_["mv2_p" + idx] = 0;
|
||
mm_vars_["up_tag" + idx] = 0;
|
||
mm_vars_["dw_tag" + idx] = 0;
|
||
}
|
||
}
|
||
|
||
bool VarManager::isAccumulatorNearOverflow() const {
|
||
for (size_t i = 0; i < tag_count_; i++) {
|
||
std::string idx = std::to_string(i + 1);
|
||
if (std::abs(mm_vars_.at("mv2_tag" + idx) - DBL_MAX) < 2.0)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
```
|
||
|
||
### 3.4 mon_proc() 重构后的完整流程
|
||
|
||
```cpp
|
||
// FeedbackAlg (Alg 3/4) 的 doMonProc()
|
||
AlarmInfo FeedbackAlg::doMonProc() {
|
||
// 1. 自动重置 fun_vars(若上周期标记)
|
||
vars_.autoResetFunVars();
|
||
|
||
// 2. 评估前提条件
|
||
double result_value = exp_act_->evaluate();
|
||
|
||
// 3. 如果有上下限的反馈模式(CondBound),先做筛选+统计
|
||
if (hasBoundCheck_ && is_learning_) {
|
||
bool filter_ok = checkFilter();
|
||
if (filter_ok) {
|
||
stat_.addSample(result_value);
|
||
}
|
||
}
|
||
|
||
// 4. 反馈状态机更新(含变量快照/累积更新)
|
||
auto [fbState, needFunReset] = fb_fsm_.update(
|
||
static_cast<bool>(result_value), now_time_, vars_);
|
||
|
||
if (needFunReset) {
|
||
vars_.markFunVarsNeedReset();
|
||
}
|
||
|
||
// 5. 根据状态分发
|
||
switch (fbState) {
|
||
case FbState::Started:
|
||
return {}; // 刚启动,等待下周期
|
||
|
||
case FbState::InProgress: {
|
||
// 检查反馈条件
|
||
bool fbCond = exp_feedback_->evaluate();
|
||
if (fb_fsm_.checkFeedback(fbCond, now_time_, vars_)) {
|
||
// Done! 计算结果并判断报警
|
||
vars_.markFunVarsNeedReset();
|
||
return evaluateResultAndAlarm();
|
||
}
|
||
return {};
|
||
}
|
||
|
||
case FbState::NotHold:
|
||
return {};
|
||
|
||
case FbState::Timeout:
|
||
return buildTimeoutAlarm();
|
||
|
||
case FbState::Done:
|
||
// 由 checkFeedback 内部处理,不应直接到此
|
||
return {};
|
||
|
||
case FbState::Idle:
|
||
return {};
|
||
}
|
||
return {};
|
||
}
|
||
|
||
AlarmInfo FeedbackAlg::evaluateResultAndAlarm() {
|
||
double result = exp_result_->evaluate();
|
||
query_time_range_.set_left(
|
||
query_time_range_.get_right() - milliseconds(int(vars_["time"])));
|
||
|
||
if (hasBoundCheck_) {
|
||
// CondBound: Alg 4
|
||
stat_.addSample(result);
|
||
if (boundChecker_.isOutOfBounds(result)) {
|
||
return buildBoundAlarm(result);
|
||
}
|
||
} else {
|
||
// FeedbackLogic: Alg 3
|
||
if (static_cast<bool>(result)) {
|
||
return buildLogicAlarm();
|
||
}
|
||
}
|
||
return {};
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、修正后的组件与新旧对比
|
||
|
||
### 4.1 修正后的组件清单
|
||
|
||
```
|
||
┌─────────────────┐
|
||
│ VarManager │ 变量存储、pv历史移位、hold变量
|
||
│ │ 【新增】snapshotActionStart/updateActionVars/
|
||
│ │ recordActionEnd/clearActionAccumulators
|
||
│ │ autoResetFunVars/markFunVarsNeedReset
|
||
├─────────────────┤
|
||
│ BoundChecker │ 上下限比较、检测模式、哨兵值处理
|
||
├─────────────────┤
|
||
│ FbStateMachine │ 反馈状态转换【完整7状态】
|
||
│ │ 含变量快照/更新调度、防溢出、keep模式
|
||
├─────────────────┤
|
||
│ StatCollector │ DAA::STA 统计学习、DB2 持久化
|
||
├─────────────────┤
|
||
│ FunVarsManager │ 【新增】统一管理两套 FunVars 的刷新与重置
|
||
└─────────────────┘
|
||
```
|
||
|
||
### 4.2 FunVarsManager(新增组件)
|
||
|
||
为避免 ExpBase::fun_vars_ 和 ExpModule::fun_vars_ 的混乱,引入统一管理:
|
||
|
||
```cpp
|
||
class FunVarsManager {
|
||
public:
|
||
// 注册主表达式的状态函数(替代 ExpBase::fun_vars_.add_exp_str)
|
||
void registerMainExp(const std::string& expStr,
|
||
std::map<std::string, double>* mm_vars);
|
||
|
||
// 每个数据刷新周期调用(替代 refresh_fun_vars(false))
|
||
void refresh();
|
||
|
||
// 标记下周期重置(替代 is_fun_vars_need_reset_ = true)
|
||
void markNeedReset();
|
||
|
||
// 执行延迟重置(替代 auto_fun_vars_reset())
|
||
void autoReset();
|
||
|
||
// 立即强制重置(用于 alarm 后 PRR 的 fun_vars)
|
||
void forceReset();
|
||
|
||
private:
|
||
StatExp::FunVars fun_vars_;
|
||
bool need_reset_ = false;
|
||
};
|
||
```
|
||
|
||
---
|
||
|
||
## 五、与原实现的等价性验证矩阵
|
||
|
||
| 原有代码路径 | 新设计等价路径 | 验证点 |
|
||
|------------|-------------|--------|
|
||
| `act_start_done()` → true | `fb_fsm_.update()` → Started | 变量快照相同 |
|
||
| `act_start_done()` → false + setIdleFlag | `fb_fsm_.update()` → Idle + funVarsNeedReset=true | fun_reset 标记相同 |
|
||
| `act_not_hold()` → true | `fb_fsm_.update()` → NotHold | keep_mode 检查相同 |
|
||
| `act_done()` 变量更新部分 | `fb_fsm_.update()` → InProgress 中调用 `vars_.updateActionVars()` | mx/mi/mv2/up/dw/time 相同 |
|
||
| `act_done()` 反馈条件检查 | `checkFeedback(fbCond)` | exp_feedback_->evaluate() 相同 |
|
||
| `act_done()` → true + CondBound | `evaluateResultAndAlarm()` hasBoundCheck_=true | 上下限检测+报警相同 |
|
||
| `act_done()` → true + 非CondBound | `evaluateResultAndAlarm()` hasBoundCheck_=false | 布尔报警相同 |
|
||
| `act_timeout()` 正常超时 | `fb_fsm_.update()` → Timeout + clearActionAccumulators | 变量清零相同 |
|
||
| `act_timeout()` -32768 防溢出 | `checkOverflowPrevention()` | 溢出检测相同 |
|
||
| `get_prr()` → false 重置 | `fb_fsm_.forceReset()` | 状态标志清零相同 |
|
||
| `auto_fun_vars_reset()` | `FunVarsManager::autoReset()` | 延迟一周期重置相同 |
|
||
| `refresh_fun_vars(false)` | `FunVarsManager::refresh()` | funN 变量更新相同 |
|
||
| `exp_mpdule_ptr_->fun_reset()` on alarm | `FunVarsManager::forceReset()` | PRR fun_vars 重置相同 |
|
||
|
||
---
|
||
|
||
## 六、结论
|
||
|
||
上一版 FbStateMachine 的主要遗漏在于**低估了状态转换与变量操作的耦合程度**。反馈状态机的本质不是纯状态转换——它是一个**状态-变量协同机**,在每个状态转换点都需要精确的变量操作(快照、累积、清零)。
|
||
|
||
修正后的设计将这一协同完整建模:
|
||
- VarManager 提供 5 个新方法(snapshot/update/record/clear/overflowCheck)
|
||
- FbStateMachine 变为 7 状态(增加 Started 的独立表示和 Idle 的显式处理)
|
||
- 引入 FunVarsManager 统一两套 FunVars 的管理
|
||
- 通过等价性验证矩阵确保覆盖所有现有路径
|