Source code for opengnc.sensors.sun_sensor_array

"""Coarse sun sensor array model."""

from __future__ import annotations

from typing import Any

import numpy as np

from opengnc.sensors.sensor import Sensor, SensorMeasurement


[docs] class CoarseSunSensorArray(Sensor): """Array of coarse sun sensors (CSS).""" quantity = "sun_intensity_array" units = "sensor_unit" frame = "body" def __init__( self, boresights: list[np.ndarray] | None = None, i_max: float = 1.0, noise_std: float = 0.01, name: str = "CSSArray", ) -> None: super().__init__(name) if boresights is None: boresights_list = [ np.array([1.0, 0.0, 0.0]), np.array([-1.0, 0.0, 0.0]), np.array([0.0, 1.0, 0.0]), np.array([0.0, -1.0, 0.0]), np.array([0.0, 0.0, 1.0]), np.array([0.0, 0.0, -1.0]), ] else: boresights_list = boresights self.boresights = [b / np.linalg.norm(b) for b in boresights_list] self.i_max = i_max self.noise_std = noise_std
[docs] def measure(self, true_sun_vec: np.ndarray | None = None, *args: Any, **kwargs: Any) -> SensorMeasurement: if true_sun_vec is None: if not args: raise ValueError("true_sun_vec is required.") true_sun_vec = np.asarray(args[0]) sun_unit = true_sun_vec / np.linalg.norm(true_sun_vec) measurements = [] for boresight in self.boresights: cos_theta = float(np.dot(sun_unit, boresight)) i_meas = self.i_max * max(0.0, cos_theta) i_meas += np.random.normal(0, self.noise_std) measurements.append(float(max(0.0, i_meas))) values = np.array(measurements) return self.build_measurement(values, metadata={"boresights": [b.copy() for b in self.boresights], "i_max": self.i_max})
[docs] def measurement_noise_std(self) -> np.ndarray: return np.full(len(self.boresights), float(self.noise_std), dtype=float)