Source code for ADCS.helpers.plot.sensors.disturbanceplot

"""Plot estimated disturbance-parameter histories."""

from __future__ import annotations

import numpy as np

from ..subplot import Subplot


__all__ = ["DisturbanceParameterPlot"]


def _parameters(disturbances) -> np.ndarray:
    values = []
    for disturbance in disturbances or ():
        length = int(getattr(disturbance, "estimated_vector_length", 0))
        if length <= 0:
            continue
        values.append(np.asarray(disturbance.main_param, dtype=float).reshape(-1))
    return np.concatenate(values) if values else np.empty(0)


[docs] class DisturbanceParameterPlot(Subplot): """Plot estimated disturbance parameters against truth parameters. Truth parameters are read from the true satellite disturbance models in the simulation result; estimates are read from each ``EstimatorState``. """ def __init__(self, *, title: str = "Disturbance Parameters", labels=None, units: str = "", plot_torque: bool = False): self.title = title self.labels = labels self.units = units self.plot_torque = plot_torque
[docs] def plot(self, ax, sim) -> None: runs = getattr(sim, "runs", None) or [sim] run = runs[0] estimates = np.vstack([ np.asarray(state.dist_param, dtype=float).reshape(-1) for state in run.est_state_hist ]) if self.plot_torque: truth = np.vstack([ np.asarray(run.satellite.dist_torques(state, os), dtype=float).reshape(3) for state, os in zip(run.state_hist, run.os_hist) ]) else: truth = _parameters(run.satellite.disturbances) time = np.asarray(run.time_s, dtype=float) n = estimates.shape[1] labels = self.labels or [rf"$d_{{{i}}}$" for i in range(n)] if len(labels) != n: raise ValueError("labels length must match disturbance-parameter dimension") for index in range(n): ax.plot(time, estimates[:, index], "--", label=f"{labels[index]} estimate") if self.plot_torque and truth.shape[1] == n: ax.plot(time, truth[:, index], "-", label=f"{labels[index]} truth") elif not self.plot_torque and truth.size == n: ax.plot(time, np.full(time.shape, truth[index]), "-", label=f"{labels[index]} truth") ax.set_title(self.title) ax.set_xlabel("Time [s]") ax.set_ylabel(self.units or "Parameter") ax.grid(True) ax.legend()