Source code for quantum_mind.sensing.sensors

"""Inertial sensor models: white noise, a drifting bias and a sample rate.

A :class:`Sensor` measures the acceleration along one axis as ``a + bias + noise``. The bias follows a random walk. These
are the standard first-order error terms of an accelerometer (Allan-variance noise terms: velocity random walk and bias
instability); the two presets differ in exactly the way that matters for fusion: a MEMS accelerometer is fast and drifts,
a cold-atom interferometer is slow and almost drift-free.

**The preset values are illustrative assumptions, not measurements of any product.** The atom-interferometer noise is
derived from the quantum limit (:func:`quantum_mind.sensing.atom_interferometer_sensitivity`) for the atom number and
interrogation time you pass; its bias walk is an assumption. Set every number for the sensors you care about.
"""
from __future__ import annotations

from dataclasses import dataclass

import numpy as np

from .limits import atom_interferometer_sensitivity

__all__ = ['Sensor', 'mems_accelerometer', 'atom_interferometer_accelerometer']

G = 9.80665


[docs] @dataclass(frozen=True) class Sensor: """One accelerometer. Attributes ---------- name : str rate_hz : float Samples per second. noise_std : float Standard deviation of the white noise of one sample, in m/s^2. bias_walk : float Bias random-walk density in (m/s^2)/sqrt(s). bias_std0 : float Standard deviation of the initial bias in m/s^2. """ name: str rate_hz: float noise_std: float bias_walk: float bias_std0: float def __post_init__(self): if self.rate_hz <= 0 or self.noise_std <= 0 or self.bias_walk < 0 or self.bias_std0 < 0: raise ValueError('rate and noise must be positive, bias terms non-negative')
[docs] def mems_accelerometer(rate_hz=100.0, noise_density_ug=100.0, bias_walk=2e-4, bias_std0=0.02): """A MEMS accelerometer: fast, noisy, with a drifting bias (illustrative values). Parameters ---------- rate_hz : float, optional Output rate. noise_density_ug : float, optional Velocity random walk expressed as an acceleration noise density in micro-g per root hertz. bias_walk : float, optional Bias random-walk density in (m/s^2)/sqrt(s). bias_std0 : float, optional Initial bias spread in m/s^2. Returns ------- Sensor """ sigma = noise_density_ug * 1e-6 * G * np.sqrt(rate_hz) return Sensor('MEMS accelerometer', rate_hz, float(sigma), bias_walk, bias_std0)
[docs] def atom_interferometer_accelerometer(n_atoms=1e6, interrogation_time=0.1, cycle_time=1.0, contrast=0.5, bias_walk=1e-8, bias_std0=1e-6): """A cold-atom interferometer accelerometer: slow, very sensitive, almost drift-free (illustrative values). The per-shot noise comes from the standard quantum limit for ``n_atoms`` and ``interrogation_time``; the rate is one sample per ``cycle_time`` (atom preparation and detection dominate it). The bias walk and initial bias are assumptions. Returns ------- Sensor """ sigma = atom_interferometer_sensitivity(n_atoms, interrogation_time, contrast) return Sensor('atom interferometer', 1.0 / cycle_time, float(sigma), bias_walk, bias_std0)