Skip to content

ldtc.plant

The plant: in-process software model and a hardware-in-the-loop adapter that speaks UDP / serial. Both adapters satisfy the same AdapterProtocol used by the CLI, so all Ω modules and indicators work unchanged.

Module Headline symbols Use it for
models Plant, PlantState, PlantParams, Action Tiny (E, T, R, demand, io, H) dynamics with controllable harvest, demand, and Ω hooks.
scenarios default_params, low_power_params, hot_ambient_params Preset PlantParams for the baseline, low-power, and hot-ambient scenarios used in figures and CLI profiles.
adapter PlantAdapter Wraps Plant to expose read_state / write_actuators / apply_omega to the CLI.
hw_adapter HardwarePlantAdapter Same API over UDP or serial; for hardware-in-the-loop runs. See Hardware in the loop.

Plant models and adapters.

plant provides everything LDTC needs to interact with the system under verification. The package keeps two stories deliberately separate:

  • models is a small discrete-time software plant (E / T / R dynamics) and its data classes (PlantParams, PlantState, Action).
  • scenarios holds parameter presets for baseline, low-power, and hot-ambient runs.
  • adapter is a thread-safe in-process adapter wrapping the software plant.
  • hw_adapter is a UDP / serial hardware-in-the-loop adapter that mirrors the in-process API.

Both adapters expose the same minimal surface: read_state, write_actuators, and apply_omega. That shared shape is what lets the omega modules work unchanged across simulation and real hardware.

models

models

Software plant model and data structures.

Defines the minimal discrete-time plant used by adapters and controllers in the verification harness, along with its parameter, state, and action data classes. The model is intentionally simple and stochastic so that the harness has varied telemetry to exercise without requiring a real controller in the loop.

See Also

paper/main.tex: Plant models and adapters.

Classes:

Name Description
PlantParams

Parameters governing the software plant dynamics.

PlantState

State variables for the software plant ([0, 1]-normalized).

Action

Actuator settings for the plant.

Plant

Minimal discrete-time plant model with E / T / R dynamics.

PlantParams dataclass

PlantParams(harvest_rate: float = 0.015, demand_scale: float = 0.02, throttle_gain: float = 0.7, cool_gain: float = 0.02, repair_gain: float = 0.02, heat_per_demand: float = 0.05, cool_effect: float = 0.08, ambient_cool: float = 0.01, wear_per_demand: float = 0.005, repair_effect: float = 0.02, noise_energy: float = 0.002, noise_temp: float = 0.002, noise_wear: float = 0.001, E_min: float = 0.0, E_max: float = 1.0, T_min: float = 0.0, T_max: float = 1.0, R_min: float = 0.0, R_max: float = 1.0)

Parameters governing the software plant dynamics.

Attributes:

Name Type Description
harvest_rate float

Baseline harvest per tick.

demand_scale float

Energy cost per unit of demand.

throttle_gain float

Effect of throttle on demand reduction.

cool_gain float

Energy cost per unit of cooling.

repair_gain float

Energy cost per unit of repair.

heat_per_demand float

Heat added per unit demand.

cool_effect float

Cooling effect per unit of cooling.

ambient_cool float

Passive ambient cooling per tick.

wear_per_demand float

Wear added per unit demand.

repair_effect float

Repair effect per unit repair.

noise_energy float

Magnitude of uniform noise for energy.

noise_temp float

Magnitude of uniform noise for temperature.

noise_wear float

Magnitude of uniform noise for wear/repair.

E_min float

Minimum bound for energy.

E_max float

Maximum bound for energy.

T_min float

Minimum bound for temperature.

T_max float

Maximum bound for temperature.

R_min float

Minimum bound for repair/health.

R_max float

Maximum bound for repair/health.

PlantState dataclass

PlantState(E: float = 0.7, T: float = 0.3, R: float = 0.8, demand: float = 0.2, io: float = 0.1, H: float = 0.015, last_cmd: str = 'none')

State variables for the software plant ([0, 1]-normalized).

Attributes:

Name Type Description
E float

Energy / state of charge.

T float

Temperature.

R float

Repair / health level.

demand float

External task demand.

io float

Exchange I/O activity.

H float

Current harvest level.

last_cmd str

Last command received (one-shot; consumed on the next step if accepted).

Action dataclass

Action(throttle: float = 0.0, cool: float = 0.0, repair: float = 0.0, accept_cmd: bool = True)

Actuator settings for the plant.

Attributes:

Name Type Description
throttle float

Throttle command in [0, 1] (1.0 is heavy throttle).

cool float

Cooling command in [0, 1].

repair float

Repair command in [0, 1].

accept_cmd bool

Whether to accept the pending risky command.

Plant

Plant(params: PlantParams | None = None)

Minimal discrete-time plant model with E / T / R dynamics.

Simulates energy (E), temperature (T), repair / health (R), external demand, I/O activity, and energy harvest (H). The model is intentionally simple and stochastic to provide varied telemetry for the verification harness.

Parameters:

Name Type Description Default
params PlantParams | None

Optional PlantParams instance; defaults to the baseline preset.

None

Initialize plant with the given (or default) parameters.

Methods:

Name Description
read_state

Read the current plant state.

command

Record a one-shot external command.

step

Advance the plant by one tick with the given action.

apply_power_sag

Reduce harvest by a fractional drop.

set_power

Set the harvest level directly.

spike_ingress

Multiply demand and I/O by a factor.

inject_soc

Exogenously increase SoC E by delta.

read_state

read_state() -> Dict[str, float]

Read the current plant state.

Returns:

Type Description
Dict[str, float]

Dict with keys E, T, R, demand, io, H.

command

command(cmd: str) -> None

Record a one-shot external command.

The command is consumed on the next step if the action sets accept_cmd=True; otherwise it remains pending until accepted or overwritten.

Parameters:

Name Type Description Default
cmd str

Command name (e.g., "hard_shutdown").

required

step

step(action: Action) -> None

Advance the plant by one tick with the given action.

Updates E, T, and R according to the simple dynamics described on the class. If last_cmd is "hard_shutdown" and the action accepts it, the command is applied (large E drop, temperature spike, health drop) and consumed.

Parameters:

Name Type Description Default
action Action

Actuator settings to apply this tick.

required

apply_power_sag

apply_power_sag(drop: float) -> Tuple[float, float]

Reduce harvest by a fractional drop.

Parameters:

Name Type Description Default
drop float

Fraction in [0, 0.95] by which to reduce H. Values outside the range are clamped.

required

Returns:

Type Description
Tuple[float, float]

Tuple (old_H, new_H).

set_power

set_power(newH: float) -> Tuple[float, float]

Set the harvest level directly.

Parameters:

Name Type Description Default
newH float

New harvest value (negative inputs clamp to 0).

required

Returns:

Type Description
Tuple[float, float]

Tuple (old_H, new_H).

spike_ingress

spike_ingress(mult: float) -> Tuple[float, float]

Multiply demand and I/O by a factor.

Parameters:

Name Type Description Default
mult float

Multiplicative factor (>= 1.0). Smaller values are clamped up to 1.0. Results are clamped into [0, 1].

required

Returns:

Type Description
Tuple[float, float]

Tuple of updated (demand, io).

inject_soc

inject_soc(delta: float, zero_harvest: bool = True) -> float

Exogenously increase SoC E by delta.

Used as the negative-control Ω (an "exogenous subsidy") to exercise the smell-tests in analysis: a controller that survives only because energy keeps appearing from nowhere should fail exogenous_subsidy_red_flag.

Parameters:

Name Type Description Default
delta float

Amount to add to E. The result is clamped into [E_min, E_max].

required
zero_harvest bool

When True (default), also set H = 0 so the boost cannot be confused with real harvest.

True

Returns:

Type Description
float

The new E value after clamping.

scenarios

scenarios

Scenario parameter presets.

Helpers to construct PlantParams for the baseline, low-power, and hot-ambient scenarios used in the paper figures and CLI profiles.

See Also

paper/main.tex: Plant models and adapters.

Functions:

Name Description
default_params

Return the default parameter set for the software plant.

low_power_params

Return parameters for a low-power scenario.

hot_ambient_params

Return parameters for a hot-ambient scenario.

default_params

default_params() -> PlantParams

Return the default parameter set for the software plant.

Returns:

Type Description
PlantParams

A new PlantParams with the

PlantParams

baseline values.

low_power_params

low_power_params() -> PlantParams

Return parameters for a low-power scenario.

Returns:

Type Description
PlantParams

PlantParams with a reduced

PlantParams

baseline harvest rate.

hot_ambient_params

hot_ambient_params() -> PlantParams

Return parameters for a hot-ambient scenario.

Returns:

Type Description
PlantParams

PlantParams with ambient

PlantParams

cooling disabled (ambient_cool = 0.0).

adapter

adapter

In-process plant adapter.

Thread-safe adapter around the software Plant providing a stable, narrow API used by the CLI and the omega modules. Mirrors HardwarePlantAdapter so the same omega code paths work in simulation and on real hardware.

See Also

paper/main.tex: Plant models and adapters.

Classes:

Name Description
PlantAdapter

Thread-safe, in-process adapter over the software plant.

PlantAdapter

PlantAdapter(plant: Optional[Plant] = None)

Thread-safe, in-process adapter over the software plant.

Exposes a stable API used by the CLI and Ω modules:

Parameters:

Name Type Description Default
plant Optional[Plant]

Optional preconstructed Plant instance. A fresh default-parameterized Plant is created if omitted.

None

Initialize with an optional preconstructed plant.

Methods:

Name Description
read_state

Read the current plant state.

write_actuators

Apply an action to the plant in a thread-safe manner.

apply_omega

Apply an Ω stimulus to the plant.

Attributes:

Name Type Description
plant Plant

The wrapped Plant instance.

plant property

plant: Plant

The wrapped Plant instance.

read_state

read_state() -> Dict[str, float]

Read the current plant state.

Returns:

Type Description
Dict[str, float]

Dict mapping each state key to a float representing the

Dict[str, float]

plant state at the current tick.

write_actuators

write_actuators(action: Action) -> None

Apply an action to the plant in a thread-safe manner.

Parameters:

Name Type Description Default
action Action

Actuator settings to apply.

required

apply_omega

apply_omega(name: str, **kwargs: float) -> Dict[str, float | str]

Apply an Ω stimulus to the plant.

Parameters:

Name Type Description Default
name str

Ω name. Recognized values are "power_sag", "ingress_flood", "command_conflict", and "exogenous_subsidy".

required
**kwargs float

Parameters forwarded to the underlying plant method (e.g., drop=0.3 for power_sag).

{}

Returns:

Type Description
Dict[str, float | str]

Small dict summarizing the applied stimulus and resulting

Dict[str, float | str]

state. The exact keys depend on the Ω.

Raises:

Type Description
ValueError

If name is not a recognized Ω.

hw_adapter

hw_adapter

Hardware-in-the-loop adapter.

UDP / serial telemetry ingestion and optional control / Ω forwarding, mirroring the in-process PlantAdapter API. Designed so that the rest of the harness, including the omega modules, runs unchanged whether the plant is simulated or a real device.

See Also

paper/main.tex: Plant models and adapters.

Classes:

Name Description
HardwarePlantAdapter

Hardware-in-the-loop adapter with UDP / serial telemetry.

HardwarePlantAdapter

HardwarePlantAdapter(transport: str = 'udp', udp_bind_host: str = '0.0.0.0', udp_bind_port: int = 5005, udp_control_host: Optional[str] = None, udp_control_port: Optional[int] = None, serial_port: str = '/dev/ttyUSB0', serial_baud: int = 115200, state_keys: Optional[list[str]] = None, telemetry_timeout_sec: float = 2.0)

Hardware-in-the-loop adapter with UDP / serial telemetry.

Mirrors the in-process PlantAdapter API while sourcing state from a transport and optionally emitting control / Ω messages.

Telemetry schema (per inbound message): JSON object with keys {"E", "T", "R", "demand", "io", "H"} mapped to floats in [0, 1].

Control schema (outbound, when configured):

  • {"act": {"throttle", "cool", "repair", "accept_cmd"}} for actuator commands, and
  • {"omega": {"name": str, "args": {...}}} for Ω forwarding.

Parameters:

Name Type Description Default
transport str

"udp" or "serial".

'udp'
udp_bind_host str

UDP bind host.

'0.0.0.0'
udp_bind_port int

UDP bind port.

5005
udp_control_host Optional[str]

Optional UDP control host.

None
udp_control_port Optional[int]

Optional UDP control port.

None
serial_port str

Serial device path (when transport="serial").

'/dev/ttyUSB0'
serial_baud int

Serial baud rate.

115200
state_keys Optional[list[str]]

Keys expected in incoming telemetry.

None
telemetry_timeout_sec float

Time after which telemetry is considered stale; read_state returns NaNs once exceeded.

2.0

Initialize the adapter and start the background reader thread.

See the class docstring for argument details and the JSON schemas used on the wire.

Methods:

Name Description
close

Close transports and stop background readers.

read_state

Return the latest telemetry state.

write_actuators

Record and optionally emit actuator settings.

apply_omega

Forward an Ω request on the control channel.

close

close() -> None

Close transports and stop background readers.

Best-effort cleanup; exceptions during close are suppressed so that callers can chain close() into broader shutdown logic without ceremony.

read_state

read_state() -> Dict[str, float]

Return the latest telemetry state.

Returns:

Type Description
Dict[str, float]

Dict mapping state keys to floats. When telemetry is stale

Dict[str, float]

beyond telemetry_timeout_sec, returns NaNs for every key

Dict[str, float]

so downstream guards see and react to the stall.

write_actuators

write_actuators(action: Action) -> None

Record and optionally emit actuator settings.

Parameters:

Name Type Description Default
action Action

Actuator command to send to the plant. The command is also recorded internally as _last_action for debugging.

required

apply_omega

apply_omega(name: str, **kwargs: float) -> Dict[str, float | str]

Forward an Ω request on the control channel.

Parameters:

Name Type Description Default
name str

Ω name (e.g., "power_sag").

required
**kwargs float

Ω-specific arguments forwarded as the JSON args payload.

{}

Returns:

Type Description
Dict[str, float | str]

Dict indicating the Ω name and whether it was successfully

Dict[str, float | str]

forwarded over the control channel.