fix: add period_ms to linear and drift models to prevent unbounded divergence

Without period, y=k*t+b and y=base+drift_rate*t grow infinitely, which is
unrealistic for industrial simulation. period_ms makes t wrap modulo the period,
producing sawtooth patterns that simulate per-cycle behavior (e.g. tension build-up
per coil, sensor drift per shift).
This commit is contained in:
Huamonarch 2026-05-13 16:34:00 +08:00
parent 256aa07c1c
commit e4233cc23d
4 changed files with 31 additions and 11 deletions

View File

@ -100,10 +100,13 @@ y = k·t + bb 取自 `defaultValue`。
| 参数 | 含义 | 默认值 | | 参数 | 含义 | 默认值 |
|------|------|--------| |------|------|--------|
| k | 斜率(每周期增量) | 0.0 | | k | 斜率(每 tick 增量) | 0.0 |
| period_ms | 周期mst 按周期取模 | 0无限 |
`period_ms > 0`t = (实际 tick) % (period_ms / 20),模拟每周期重复的线性过程(如带钢卷取时张力逐渐增大然后释放)。`period_ms = 0` 时不取模。
```json ```json
"linear_slow": { "mode": "linear", "params": { "k": 0.001 } } "linear_slow": { "mode": "linear", "params": { "k": 0.001, "period_ms": 600000 } }
``` ```
#### sine — 正弦波 #### sine — 正弦波
@ -147,7 +150,14 @@ y = base + drift_rate·tbase 取自 `defaultValue`。模拟传感器缓慢退
| 参数 | 含义 | 默认值 | | 参数 | 含义 | 默认值 |
|------|------|--------| |------|------|--------|
| drift_rate | 每周期漂移量 | 0.0 | | drift_rate | 每 tick 漂移量 | 0.0 |
| period_ms | 周期mst 按周期取模 | 0无限 |
`period_ms > 0` 时形成锯齿波漂移:每个周期内从 base 线性漂移到 base + drift_rate·period_ticks然后复位模拟每个生产周期内的退化-复位行为。
```json
"drift_slow": { "mode": "drift", "params": { "drift_rate": 0.0001, "period_ms": 3600000 } }
```
#### csv — CSV 数据回放 #### csv — CSV 数据回放

View File

@ -3,14 +3,14 @@
"constant_zero": { "mode": "constant", "params": {} }, "constant_zero": { "mode": "constant", "params": {} },
"normal_tiny": { "mode": "normal", "params": { "sigma": 0.01 } }, "normal_tiny": { "mode": "normal", "params": { "sigma": 0.01 } },
"normal_med": { "mode": "normal", "params": { "sigma": 0.5 } }, "normal_med": { "mode": "normal", "params": { "sigma": 0.5 } },
"linear_slow": { "mode": "linear", "params": { "k": 0.001 } }, "linear_slow": { "mode": "linear", "params": { "k": 0.001, "period_ms": 600000 } },
"linear_fast": { "mode": "linear", "params": { "k": 0.05 } }, "linear_fast": { "mode": "linear", "params": { "k": 0.05, "period_ms": 120000 } },
"sine_ecc1": { "mode": "sine", "params": { "A": 5.0, "omega": 0.314, "phi": 0 } }, "sine_ecc1": { "mode": "sine", "params": { "A": 5.0, "omega": 0.314, "phi": 0 } },
"sine_ecc2": { "mode": "sine", "params": { "A": 3.0, "omega": 0.628, "phi": 1.57 } }, "sine_ecc2": { "mode": "sine", "params": { "A": 3.0, "omega": 0.628, "phi": 1.57 } },
"spike_sharp": { "mode": "spike", "params": { "amplitude": 50, "probability": 0.05 } }, "spike_sharp": { "mode": "spike", "params": { "amplitude": 50, "probability": 0.05 } },
"spike_mild": { "mode": "spike", "params": { "amplitude": 10, "probability": 0.15 } }, "spike_mild": { "mode": "spike", "params": { "amplitude": 10, "probability": 0.15 } },
"drift_slow": { "mode": "drift", "params": { "drift_rate": 0.0001 } }, "drift_slow": { "mode": "drift", "params": { "drift_rate": 0.0001, "period_ms": 3600000 } },
"drift_fast": { "mode": "drift", "params": { "drift_rate": 0.005 } }, "drift_fast": { "mode": "drift", "params": { "drift_rate": 0.005, "period_ms": 600000 } },
"toggle_2s": { "mode": "bool_toggle", "params": { "period_ms": 2000 } }, "toggle_2s": { "mode": "bool_toggle", "params": { "period_ms": 2000 } },
"toggle_5s": { "mode": "bool_toggle", "params": { "period_ms": 5000 } }, "toggle_5s": { "mode": "bool_toggle", "params": { "period_ms": 5000 } },
"toggle_10s": { "mode": "bool_toggle", "params": { "period_ms": 10000 } }, "toggle_10s": { "mode": "bool_toggle", "params": { "period_ms": 10000 } },

View File

@ -5,7 +5,12 @@ using json = nlohmann::json;
struct DriftModel : IModel { struct DriftModel : IModel {
float base, drift_rate; float base, drift_rate;
size_t period_ticks;
DriftModel(const json& params, float defaultVal) DriftModel(const json& params, float defaultVal)
: base(defaultVal), drift_rate(params.value("drift_rate", 0.0f)) {} : base(defaultVal), drift_rate(params.value("drift_rate", 0.0f))
float evaluate(size_t t) override { return base + drift_rate * t; } , period_ticks(params.value("period_ms", 0) / 20) {}
float evaluate(size_t t) override {
if (period_ticks > 0) t %= period_ticks;
return base + drift_rate * t;
}
}; };

View File

@ -5,7 +5,12 @@ using json = nlohmann::json;
struct LinearModel : IModel { struct LinearModel : IModel {
float k, b; float k, b;
size_t period_ticks;
LinearModel(const json& params, float defaultVal) LinearModel(const json& params, float defaultVal)
: k(params.value("k", 0.0f)), b(defaultVal) {} : k(params.value("k", 0.0f)), b(defaultVal)
float evaluate(size_t t) override { return k * t + b; } , period_ticks(params.value("period_ms", 0) / 20) {}
float evaluate(size_t t) override {
if (period_ticks > 0) t %= period_ticks;
return k * t + b;
}
}; };