eis/TestProject/RNG
2026-05-13 16:14:42 +08:00
..
json feat: add rng_models.json with model templates 2026-05-13 15:07:06 +08:00
model fix: prevent ValvePairModel stuck-state by freezing prev_action during delay 2026-05-13 15:43:56 +08:00
CMakeLists.txt build: add model/ source directory to CMake 2026-05-13 15:27:22 +08:00
Generator.cc fix: address code review issues 2026-05-13 15:46:06 +08:00
Generator.h refactor: replace hardcoded signal mappings with ModelRegistry 2026-05-13 15:24:32 +08:00
RandT.h fix: GuassRand use sigma as stddev directly instead of sqrt(sigma) 2026-05-13 15:53:25 +08:00
read_csv.hpp fix: qualify is_same_v with std:: in FlowData constructor 2026-05-13 16:02:27 +08:00
README.md docs: add comprehensive RNG project README 2026-05-13 16:14:42 +08:00
RNG_icei.cc Initial commit: EIS C++ project with multi-process code 2026-05-09 11:23:45 +08:00
RNG_icei.h Initial commit: EIS C++ project with multi-process code 2026-05-09 11:23:45 +08:00
RNG.cc fix: address code review issues 2026-05-13 15:46:06 +08:00
RNG.h Initial commit: EIS C++ project with multi-process code 2026-05-09 11:23:45 +08:00

RNG — 参数化随机数生成器

为 eqpalg 监控引擎提供仿真数据的测试工具。通过 JSON 配置和 DB2 表驱动,将可复用的数学模型绑定到信号项上,生成模拟量/布尔量的实时仿真数据写入共享内存,供 eqpalg-mon 消费和评估报警规则。

架构

rng_models.json          T_LOV_FDAAITEM (DB2)
      │                        │
      │  模型模板定义           │  信号→模型绑定 (tables[1] 字段)
      │                        │
      ▼                        ▼
   ModelRegistry ──────── Generator ────── BinaryTele ────── CMemFix<PLC_DATA> ──► 共享内存
        │
        ├── ConstantModel     (y = c)
        ├── NormalModel       (y = μ + σ·N(0,1))
        ├── LinearModel       (y = k·t + b)
        ├── SineModel         (y = A·sin(ω·t + φ) + offset)
        ├── UniformModel      (y = random(center±delta))
        ├── SpikeModel        (随机毛刺注入)
        ├── DriftModel        (线性漂移)
        ├── CsvReplayModel    (CSV 历史数据回放)
        ├── BoolRandomModel   (概率随机布尔)
        ├── BoolToggleModel   (固定周期翻转)
        ├── BoolCsvModel      (CSV 布尔回放)
        ├── ValvePairModel    (阀动作→到位传感器 时序仿真)
        └── CompositeModel    (base + noise 组合)

设计原则:模型模板与信号绑定分离。模型定义在 JSON 中,可复用;每个信号通过 DB2 的 tables[1] 字段选择模型,独立实例化,互不干扰。

编译

cd TestProject/RNG && mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
# 可执行文件: ~/bin/RNG

依赖GCC 10+, CMake 3.8+, vcpkg (nlohmann_json, mlpack, Armadillo), PACE/iPlature 框架。

配置

rng_models.json

路径:/users/dsc/code/TestProject/RNG/json/rng_models.json

定义可复用的模型模板。每个模板有 mode(模型类型)和 params(模型参数)。信号项的 defaultValue 自动作为模型的基值参数。

{
  "models": {
    "模板名称": { "mode": "模型类型", "params": { "参数名":  } }
  }
}

DB2 信号绑定

T_LOV_FDAAITEM 表中,tables[1] 字段char[40])填写模型引用。语法:

格式 含义 示例
模型名 引用 JSON 中的模型模板 normal_tiny
csv:文件:列号 内联 CSV 数据回放 csv:spbdata:1
基模型+噪声模型 组合模型(叠加噪声) linear_slow+normal_tiny
pair模型:动作模型 阀到位传感器引用动作信号 valve_px_std:toggle_2s
空或 default 默认模型 normal_tiny

模型参考

模拟量模型

所有模拟量模型实现 evaluate(size_t t) -> floatt 为时间索引(每 ~20ms 递增)。

constant — 固定值

y = cc 取自 defaultValue

"constant_zero": { "mode": "constant", "params": {} }

normal — 正态分布

y = μ + σ·N(0,1),μ 取自 defaultValue

参数 含义 默认值
sigma 标准差 0.01
"normal_tiny": { "mode": "normal", "params": { "sigma": 0.01 } }

linear — 线性变化

y = k·t + bb 取自 defaultValue

参数 含义 默认值
k 斜率(每周期增量) 0.0
"linear_slow": { "mode": "linear", "params": { "k": 0.001 } }

sine — 正弦波

y = A·sin(ω·t + φ) + offsetoffset 取自 defaultValue

参数 含义 默认值
A 振幅 1.0
omega 角频率 1.0
phi 初相位 0.0
"sine_ecc1": { "mode": "sine", "params": { "A": 5.0, "omega": 0.314, "phi": 0 } }

uniform — 均匀随机

y = center ± deltacenter 取自 defaultValue

参数 含义 默认值
delta 随机范围 0.01

spike — 随机毛刺

每个周期以 probability 概率触发一次幅值为 ±amplitude 的瞬时毛刺。

参数 含义 默认值
amplitude 毛刺幅度 1.0
probability 每周期触发概率 0.01
"spike_sharp": { "mode": "spike", "params": { "amplitude": 50, "probability": 0.05 } }

drift — 线性漂移

y = base + drift_rate·tbase 取自 defaultValue。模拟传感器缓慢退化。

参数 含义 默认值
drift_rate 每周期漂移量 0.0

csv — CSV 数据回放

从 CSV 文件读取指定列,循环回放。通常通过 tables[1] 内联语法使用,无需在 JSON 定义。

"csv_example": { "mode": "csv", "params": { "file": "C308速度毛刺仿真.csv", "column": 0 } }

CSV 文件存放路径:/users/dsc/code/TestProject/data_files/

布尔量模型

所有布尔量模型实现 evaluateBool(size_t t) -> bool

bool_random — 概率随机

参数 含义 默认值
prob_true 返回 true 的概率 0.5

bool_toggle — 固定周期翻转

参数 含义 默认值
period_ms 翻转周期(毫秒) 2000

周期前半段为 true后半段为 false。

"toggle_2s": { "mode": "bool_toggle", "params": { "period_ms": 2000 } }

bool_csv — CSV 布尔回放

从 CSV 读取整数列,非零值为 true。

valve_pair — 阀动作→到位传感器 时序仿真

模拟液压阀/气动阀动作信号与到位接近开关之间的时序关系。使用了四态状态机:

动作信号 A:
    ────────────┐                  ┌────────────────
                │                  │
                ├── on_delay ──→   ├── off_delay ──→
到位传感器 B:   │  ±jitter        │  ±jitter
    ────────────┘                  └────────────────
                └─ 阀芯移动 ──→    └─ 阀芯复位 ──→
参数 含义 默认值
on_delay_ms 阀开到位延迟ms 200
off_delay_ms 阀关到位延迟ms 150
delay_jitter_ms 延迟抖动范围(±均匀随机) 0
flash_prob 高电平期间每周期闪断概率 0
delay_over_prob 每次动作触发超时的概率 0
delay_over_ms 超时时的延迟值ms 0

状态机:

  • IDLE_LOW:等待动作信号上升沿
  • WAITING_RISE:动作上升,计数延迟,期间冻结边沿检测
  • HIGH:到位,监测动作下降沿或随机闪断
  • WAITING_FALL:动作下降,计数关延迟,期间冻结边沿检测

绑定方式:到位传感器信号的 tables[1] 使用配对语法:

tables[1] = "valve_px_std:toggle_2s"
              ↑                ↑
          valve_pair 模板    动作信号的模型名

运行时通过模型名查找动作信号的 IModel 实例,每个周期读取其 evaluateBool() 值。

一对多支持:同一个动作信号可被多个 valve_pair 传感器跟随,各自独立维护状态机。

组合模型Composite

通过 + 连接两个模型名,构成 base + noise 组合:

tables[1] = "linear_slow+normal_tiny"

CompositeModel 将两个模型的 evaluate() 结果相加。只适用于模拟量。

添加新模型

三步,不改现有代码逻辑:

  1. 创建模型类:在 model/ 下新建头文件,继承 IModel,实现 evaluate()evaluateBool()
struct ExponentialModel : IModel {
  float lambda, base;
  ExponentialModel(const json& p, float d) : lambda(p.value("lambda", 1.0f)), base(d) {}
  float evaluate(size_t t) override { return base * expf(-lambda * t); }
};
  1. 注册到工厂:在 ModelRegistry.cc 构造函数中添加一行
registerMode("exponential", [](const json& p, float d) { return std::make_unique<ExponentialModel>(p, d); });
  1. JSON 中添加模板(可选,也可以直接用 tables[1] 内联语法)
"exp_decay": { "mode": "exponential", "params": { "lambda": 0.01 } }

数据流

PACE 定时器 (每 20ms)
  │  TimeNotify(eventNo)
  ▼
Generator::wtite_in_shm(eventNo)
  │
  ├─ BinaryTele.ReBuild(eventNo)     ← 从 DB2 读取电文结构
  │
  ├─ Pass 1: for each item:
  │    ModelRegistry::getOrCreate(tables[1], defaultValue, item.name)
  │    → 按信号 item 名创建独立模型实例
  │
  ├─ Pass 2: for each item:
  │    model->linkPeers(registry)
  │    → valve_pair 模型查找动作信号实例
  │
  ├─ Pass 3: for each item:
  │    model->evaluate(t) / evaluateBool(t)
  │    → 生成值写入 binary_tele[i].value
  │
  └─ BinaryTele.GetTeleData() → CMemFix<PLC_DATA>::push()
     → 写入共享内存环形缓冲

共享内存区由 T_LOV_FDAAITEM 的事件号区分eqpalg-mon 按同样的事件号读取。

目录结构

TestProject/RNG/
├── json/
│   └── rng_models.json       # 模型模板配置
├── model/
│   ├── IModel.h              # 模型基类接口
│   ├── ConstantModel.h       # 固定值
│   ├── NormalModel.h         # 正态分布
│   ├── LinearModel.h         # 线性变化
│   ├── SineModel.h           # 正弦波
│   ├── UniformModel.h        # 均匀随机
│   ├── SpikeModel.h          # 随机毛刺
│   ├── DriftModel.h          # 线性漂移
│   ├── CsvReplayModel.h      # CSV 模拟量回放
│   ├── BoolRandomModel.h     # 布尔随机
│   ├── BoolToggleModel.h     # 布尔周期翻转
│   ├── BoolCsvModel.h        # CSV 布尔回放
│   ├── ValvePairModel.h      # 阀动作-到位传感器
│   ├── CompositeModel.h      # 组合模型
│   ├── ModelRegistry.h       # 工厂注册表(声明)
│   └── ModelRegistry.cc      # 工厂注册表(实现)
├── RNG.h / RNG.cc            # PACE 组件入口
├── RNG_icei.h / RNG_icei.cc  # ICE 接口实现
├── Generator.h / Generator.cc # 数据生成 + 共享内存写入
├── RandT.h                   # 底层随机数工具
├── read_csv.hpp              # CSV 文件读取
├── CMakeLists.txt            # CMake 构建
└── README.md                 # 本文档