Skip to content

Deviation Correlation

correlation

Temporal correlation of absolute trajectory deviations (see ATEResult.correlation).

ComponentCorrelation dataclass

ComponentCorrelation(
    lags: ndarray,
    autocorrelation: ndarray,
    pairs: ndarray,
    white_noise_share: float,
    correlation_time: float,
    effective_samples: float,
    std: float,
    window_centers: ndarray,
    window_std: ndarray,
)

Temporal correlation of one deviation component.

Attributes:

  • lags (ndarray) –

    Time lags [s].

  • autocorrelation (ndarray) –

    Autocorrelation of each lag (NaN if too few pairs of samples).

  • pairs (ndarray) –

    Number of pairs of samples of each lag.

  • white_noise_share (float) –

    Share of the variance that is white noise (uncorrelated from one deviation to the next, e.g. measurement noise of the reference); the rest is correlated.

  • correlation_time (float) –

    Correlation time of the correlated part [s]: lag at which the autocorrelation drops below 1/e of the correlated share; 0 for white noise, inf if it does not drop within the largest lag.

  • effective_samples (float) –

    Approximate number of independent deviations of the correlated part.

  • std (float) –

    Standard deviation of the component (around its mean).

  • window_centers (ndarray) –

    Centers of the windows of window_std [s].

  • window_std (ndarray) –

    Standard deviation in consecutive windows.

DeviationCorrelation dataclass

DeviationCorrelation(
    sampling_interval: float,
    num_samples: int,
    components: dict[str, ComponentCorrelation] = dict(),
    cross_correlation_directed: ndarray = (
        lambda: full((3, 3), nan)
    )(),
    cross_correlation_xyz: ndarray = (
        lambda: full((3, 3), nan)
    )(),
)

Temporal correlation of the deviations of an ATE result.

Deviations of trajectories (e.g. GNSS/INS) are usually correlated in time over seconds to minutes. Then, neighboring epochs do not provide independent information, and the number of independent deviations is much smaller than the number of epochs. The deviations are described as white noise (e.g. measurement noise of the reference) plus a correlated part, whose correlation time is given. Gaps (e.g. losses of a total station's lock) are respected: no deviation is correlated across a gap.

Attributes:

  • sampling_interval (float) –

    Typical time between the deviations [s].

  • num_samples (int) –

    Number of deviations.

  • components (dict[str, ComponentCorrelation]) –

    Correlation of each component (see COMPONENT_LABELS).

  • cross_correlation_directed (ndarray) –

    Correlation coefficients of along-track, horizontal and vertical cross-track at the same epochs (3x3).

  • cross_correlation_xyz (ndarray) –

    Correlation coefficients of x, y and z at the same epochs (3x3).

from_ate_result classmethod

from_ate_result(
    ate_result: ATEResult,
    max_lag: float = DEFAULT_MAX_LAG,
    window: float = DEFAULT_WINDOW,
) -> DeviationCorrelation

Analyzes the deviations of an ATE result in chronological order.

Parameters:

  • ate_result (ATEResult) –

    Result to analyze.

  • max_lag (float, default: DEFAULT_MAX_LAG ) –

    Largest lag of the autocorrelation [s], at most n / 10 sampling intervals. Defaults to DEFAULT_MAX_LAG.

  • window (float, default: DEFAULT_WINDOW ) –

    Length of the windows of the windowed standard deviations [s], at most a tenth of the duration (at least MIN_WINDOWS windows). Defaults to DEFAULT_WINDOW.

Source code in trajectopy\results\correlation.py
@classmethod
def from_ate_result(
    cls, ate_result: "ATEResult", max_lag: float = DEFAULT_MAX_LAG, window: float = DEFAULT_WINDOW
) -> "DeviationCorrelation":
    """Analyzes the deviations of an ATE result in chronological order.

    Args:
        ate_result (ATEResult): Result to analyze.
        max_lag (float, optional): Largest lag of the autocorrelation [s], at most n / 10 sampling intervals.
            Defaults to DEFAULT_MAX_LAG.
        window (float, optional): Length of the windows of the windowed standard deviations [s], at most a
            tenth of the duration (at least MIN_WINDOWS windows). Defaults to DEFAULT_WINDOW.
    """
    timestamps = ate_result.trajectory.timestamps
    if (duration := float(np.ptp(timestamps)) if len(timestamps) else 0.0) > 0:
        window = min(window, duration / MIN_WINDOWS)
    values = {
        "along": ate_result.pos_dev_along,
        "cross_h": ate_result.pos_dev_cross_h,
        "cross_v": ate_result.pos_dev_cross_v,
        "x": ate_result.pos_dev_x,
        "y": ate_result.pos_dev_y,
        "z": ate_result.pos_dev_z,
    }
    if ate_result.has_orientation:
        values |= {"roll": ate_result.rot_dev_x, "pitch": ate_result.rot_dev_y, "yaw": ate_result.rot_dev_z}

    step = sampling_interval(timestamps)
    correlation = cls(sampling_interval=step, num_samples=len(timestamps))
    # all components at once: the grid of the epochs and the pairs of each lag are the same
    lags, rho, pairs = autocorrelation(timestamps, np.column_stack(list(values.values())), max_lag=max_lag)
    for column, (name, component) in enumerate(values.items()):
        # white noise (e.g. of the reference) drops at once and would hide the correlated part
        correlated = white_noise_split(lags, rho[:, column], pairs)
        tau = correlation_time(lags, rho[:, column], level=correlated) if correlated > 0 else 0.0
        window_centers, window_std = windowed_std(timestamps, component, window)
        correlation.components[name] = ComponentCorrelation(
            lags=lags,
            autocorrelation=rho[:, column],
            pairs=pairs,
            white_noise_share=1.0 - correlated,
            correlation_time=tau,
            # the time covered by the deviations, without gaps
            effective_samples=effective_samples(len(component), len(component) * step, tau),
            std=float(np.std(component)) if len(component) else float("nan"),
            window_centers=window_centers,
            window_std=window_std,
        )

    correlation.cross_correlation_directed = _correlation_matrix(ate_result.abs_dev.directed_pos_dev)
    correlation.cross_correlation_xyz = _correlation_matrix(ate_result.abs_dev.pos_dev)
    return correlation