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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user