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>
46 lines
1.6 KiB
Python
46 lines
1.6 KiB
Python
from components import ATemperatureSensor
|
|
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, 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.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):
|
|
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
|