sensor: model real temp sensor noise in TempSensorSim

Replaces the opaque variance/√12 formula with two explicit noise components:

  sigma (default 0.05 °C) — white Gaussian noise, calibrated against the
  20260628T184903 Sud-0010 log (detrended hold-phase tick-to-tick std ≈ 0.053 °C).

  stirrer_sigma / stirrer_tau — optional AR(1) low-frequency component for
  stirrer-induced fluctuations (off by default); steady-state std equals
  stirrer_sigma, correlation time equals stirrer_tau ticks.

plant_factory.py updated to use sigma=0.05 instead of the old variance=0.01
(which gave std ≈ 0.003 °C — far too quiet).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 19:17:48 +02:00
co-authored by Claude Sonnet 4.6
parent 9be0e49a63
commit ca1953c9ee
2 changed files with 30 additions and 4 deletions
+29 -3
View File
@@ -3,17 +3,43 @@ import numpy as np
class TempSensorSim(ATemperatureSensor):
"""Simulated temperature sensor with two independent noise components.
sigma -- white Gaussian noise std [°C]; calibrated against the
20260628T184903 Sud-0010 log: detrended hold-phase
tick-to-tick std ≈ 0.053 °C.
stirrer_sigma -- steady-state std [°C] of a slow AR(1) process that
models stirrer-induced low-frequency temperature
fluctuations at the sensor. Zero by default (off).
stirrer_tau -- correlation time [ticks] of the AR(1) process;
stirrer_sigma * sqrt(2/stirrer_tau) is the per-tick
innovation std so that the steady-state variance equals
stirrer_sigma².
"""
def name(self):
return "FakeTemp"
def __init__(self, temp_offset=0.0, variance=0.0, **kwargs):
def __init__(self, sigma=0.05, stirrer_sigma=0.0, stirrer_tau=20.0,
temp_offset=0.0, **kwargs):
ATemperatureSensor.__init__(self)
self.temp_set = 19.99
self.offset = temp_offset
self.variance = variance
self.sigma = sigma
self.stirrer_sigma = stirrer_sigma
self.stirrer_tau = stirrer_tau
self._stirrer_state = 0.0
def set_fake_temp(self, temp):
self.temp_set = temp
def temperature(self):
return self.temp_set + self.offset + self.variance * np.random.normal(0, 1) / np.sqrt(12.0)
white = self.sigma * np.random.normal() if self.sigma > 0 else 0.0
if self.stirrer_sigma > 0:
alpha = 1.0 / self.stirrer_tau
innovation = self.stirrer_sigma * np.sqrt(2.0 * alpha) * np.random.normal()
self._stirrer_state = (1.0 - alpha) * self._stirrer_state + innovation
return self.temp_set + self.offset + white + self._stirrer_state