Robust Mahalanobis Applications : Surveillance anomaly detection
Description
Online Robust Mahalanobis is a statistical method for anomaly detection in robotic joint residuals. It measures how far a new sample deviates from a healthy baseline distribution using a robust Mahalanobis distance metric that is resistant to outliers. The method updates estimates of location and scatter online using averaged stochastic gradient descent, enabling real-time anomaly scoring. It is designed to detect faults such as payload changes in robotic arms by flagging samples that fall outside a learned healthy range. The approach improves on classical Mahalanobis distance by using robust estimators (geometric median and median covariation matrix) to avoid masking effects caused by outliers. This technique is presented as a research and utility module rather than a vulnerability or active threat.
Reddit Discussion
Online Robust Mahalanobis scores each sample by how far it is from the centre of the healthy joint residual, measured in units of the residual's own spread.
- What it is
The healthy residuals of a robot joint form a cloud around zero. Its shape is not a sphere: the joints are correlated, and a fault along one direction costs more than a fault along another. The classical way to measure distance in this cloud is the Mahalanobis distance: subtract the mean, divide by the covariance, take the Euclidean norm of the result. A sample that is far in units of its own distribution is anomalous.
The classical estimator uses the sample mean and the sample covariance. Both are sensitive to outliers. A single extreme sample can drag the mean far from the cloud, and inflate the covariance along its own direction so much that the same outlier looks normal under the new metric — the masking effect. Robust estimates of location and scatter fix this.
This module uses the geometric median for location and the median covariation matrix (MCM) for scatter. Both are 50 % breakdown estimators: half the samples must be corrupted before the estimate moves, against one outlier for the mean. Both are estimated online by averaged stochastic gradient (ASGD), one sample at a time.
The score of a sample is the Mahalanobis distance under the current MCM:
D(x) = sqrt( sum_j (1 / delta_j) * <x - m\_bar, P\_j>^2 )
where m_bar is the current location estimate, P_j is the j-th eigenvector of the averaged MCM V_bar, and delta_j the corresponding eigenvalue. The sum is over the d eigenvalues: it is the Mahalanobis distance written without inverting the matrix, using the eigendecomposition instead.
- How it works
Two running estimates are maintained. m tracks the geometric median, V tracks the MCM. Both are updated by averaged stochastic gradient, one sample at a time.
For the geometric median, the paper's recurrence is
m_{n+1} = m_n + gamma_{n+1} * (X_{n+1} - m_n) / ||X_{n+1} - m_n|| m_bar_{n+1} = m_bar_n + (1 / (n + 2)) * (m_{n+1} - m_bar_n)
The first line is a stochastic gradient step toward the sample, normalised so that every step has the same length. The normalisation is the robustness: a distant sample moves m by at most gamma_{n+1}, no matter how far it is. The second line averages the iterates, which accelerates convergence (Cardot, Cénac and Zitt 2013).
For the MCM, the same shape:
V_{n+1} = V_n + gamma_{n+1} * (outer_{n+1} - V_n) / ||outer_{n+1} - V_n||_F V_bar_{n+1} = V_bar_n + (1 / (n + 2)) * (V_{n+1} - V_bar_n)
with outer_{n+1} = (X_{n+1} - m_bar_n) (X_{n+1} - m_bar_n)^T the centred outer product of the new sample. The gradient is again normalised, this time to unit Frobenius norm.
The step size is
gamma_n = c_gamma * (n + n0) ** (-gamma_exp)
with gamma_exp in (1/2, 1) for convergence (Cardot and Godichon-Baggioni 2017).
The first n_init samples are not used for the ASGD updates. They are kept in a small buffer and used to compute an initial estimate of the location and scatter, from which the ASGD starts. Without the initialisation the ASGD gradients, whose scale is unit and not the scale of the data, would never reach the data.
- Smallest example
import numpy as np from dense_armor.utility.anomaly.mahalanobis import ( OnlineRobustMahalanobis, ) rng = np.random.default_rng(0) det = OnlineRobustMahalanobis(feature_keys=["a", "b"], n_init=200) for _ in range(500): x = rng.standard_normal(2) det.learn_one({"a": float(x[0]), "b": float(x[1])}) print(f"healthy {det.score_one({'a': 0.0, 'b': 0.0}):.3f}") print(f"far {det.score_one({'a': 10.0, 'b': 10.0}):.3f}")
healthy 0.080 far 15.880
The healthy point sits at the centre of the cloud: under a standard bivariate Gaussian its Mahalanobis distance is small, and the score is 0.080. The far point is ten units away along both axes: the distance is large, and the score rises to 15.880, well past the default threshold of 7.0, the classical value for low-dimensional Gaussians.
- On a real arm
The residual of joints 1-4 on a SyntheticArm payload fault. The fault (5 kg added at t = 2 s) shifts the residual on joints 1-5 by tens of N·m; the healthy run stays within ±0.15 N·m.
from pathlib import Path from dense_armor.utility.anomaly.mahalanobis import ( OnlineRobustMahalanobis, ) from dense_armor.utility.datasets import SyntheticArm ds = SyntheticArm( Path("test/fixtures/urdf/panda.urdf"), period_s=2.0, rate_hz=50.0, n_cycles=4, fault_at_s=2.0, fault="payload", payload_mass=5.0, noise_std=(1e-3, 5e-3, 5e-2), seed=0, ) det = OnlineRobustMahalanobis( feature_keys=["r0", "r1", "r2", "r3"], threshold=7.0, ) for sig, _ in ds.stream(): q, qd, qdd = ds.trajectory(sig.t) tau_nom = ds.nominal_torque(q, qd, qdd) x = {f"r{j}": float(sig[f"tau_{j}"] - tau_nom[j]) for j in range(4)} _ = det.score_one(x) _ = det.learn_one(x)

Top: SyntheticArm. The fault sends the score past 100 in the first few samples after t = 2 s, then the score drops as the ASGD updates the location and the scatter estimate towards the new distribution — but the detector has already flagged every post-fault sample until the update catches up. Bottom: DriftStream. The score rises cleanly at the drift and stays above the threshold.
- The learned 95 % region¶
The Mahalanobis distance is a scalar, but the metric it uses is a d-dimensional ellipsoid. Plotting it in two dimensions makes the shape visible.

Two joints' residuals, first 200 samples of healthy training (green dots), then 30 fault samples (red crosses). The black ellipse is the 95 % quantile of the MCM currently estimated: a new sample inside the ellipse has Mahalanobis distance below chi2_2(0.95), outside it is flagged. The fault samples all fall outside.
- Numbers¶
SyntheticArm (200 samples, 100 healthy, 100 fault) and DriftStream (2000 samples, one sudden drift at half), every detector built with its defaults.
StreamProtocolROC-AUCFalse alarms on the healthy partThreshold at the last healthy sampleSyntheticArmlearn-on-healthy1.0000.0007.0000SyntheticArmlearn-on-all1.0000.0007.0000DriftStreamlearn-on-healthy0.9930.0007.0000DriftStreamlearn-on-all0.9380.0007.0000
The default n_init is 100, and on SyntheticArm the healthy part has exactly 100 samples: in the benchmark run the detector is still in its initialisation when the healthy part ends, so every healthy score is 0.0 and the false-alarm value 0.000 on SyntheticArm follows from that, not from a decision of the detector. The class is the most accurate of the five on this repository's benchmark and the fastest (0.036 ms per sample on the arm).
Details¶
Where the rules come from¶
Guillot, Godichon-Baggioni, Robin and Sansonnet (arXiv:2601.03957) introduce the online median and MCM in Section 3. The recurrence for the geometric median is equation 8, for the MCM equation 10. The Mahalanobis distance under the MCM is Equation (1) in Section 2.2. The step size gamma_n = c * n ** -gamma with gamma in (1/2, 1) is from Cardot, Cénac and Zitt (2013) and Cardot and Godichon-Baggioni (2017).
The paper's full method also reconstructs the eigenvalues of the true covariance from the MCM by a Robbins-Monro scheme (equations 4-5) and scales the distances by chi2_d(0.5) / med(D_1..n) (equation 1). Neither step is implemented here.
Choices stated explicitly¶
Offline initialisation. The geometric median is initialised by the Weiszfeld algorithm (Guillot et al., equation 6). The MCM is initialised by the empirical average of the centred outer products, not the Weiszfeld offline MCM of Section A.2: with n_init of tens of samples the average is more stable than the Weiszfeld iteration, which for small samples can converge to a rank-one solution. The online ASGD refines the estimate as soon as new samples arrive.
Step length cap. A max_step_frac cap on the ASGD step (default 0.1) prevents a single large sample from moving V by more than a fraction of its own norm. Without the cap, c_gamma = 1 and gamma_exp = 0.7 can move V by 1 in Frobenius norm in one step, much larger than the scale of the data, and the average oscillates through zero. This is a numerical safeguard, not part of the paper.
Eigenvalue floor. Every eigenvalue of V_bar is floored at trace(V_bar) / d * 1e-3. The floor keeps the score bounded when the ASGD first steps drive V through zero, without changing the shape of the metric. Also a numerical safeguard.
No chi-squared scaling. The paper's equation 1 divides the distances by the median of the past distances, so that the calibrated threshold is the median of a chi2_d distribution. This module does not apply the scaling: the threshold is the one the user calibrates, and the default 7.0 is the classical value for low-dimensional Gaussians.
Step index. Guillot et al. use gamma_n = c_gamma (n + n0)^(-gamma) with n counted from the first sample (0.0395 c_gamma for the first update after n_init = 100 with gamma = 0.7). Here n also counts from the first sample (n = n_init + k at the k-th update) and the offset is one larger, gamma_n = c_gamma (n + n0 + 1)^(-gamma): the first update after n_init = 100 uses 0.0393 c_gamma. The averaged estimates use the weight 1 / (n + 1) with the same n, which is the paper's 1 / (n + 2) for the previous step index. The offset of one in gamma_n is a choice of this implementation.
Threshold. A fixed float, default 7.0.
Measured cost¶
At the benchmark defaults (n_init=100, 4 features), on one CPU thread:
0.036 ms per sample for learn_one + score_one on the arm stream;
memory flat: d + d^2 arrays, independent of the stream length.
The budget_s declared by the class is 0.005 s.
The bug the module fixes¶
The literal Section 3.2 update of Guillot et al. (page 7) without the step cap and without the eigenvalue floor was reimplemented outside the library and run on the 80 healthy residuals that follow n_init = 20, on the issue scenario (joint 1 of the SyntheticArm payload fault, period_s=2.0, rate_hz=50.0, n_cycles=2, payload_mass=5.0, seed 0).
With c_gamma = 1.0 the running average V_bar crosses the zero matrix: the final trace(V_bar) is -2.88e-04. Scoring each sample before the update, 19 of the 80 steps have a non-positive eigenvalue and the maximum score is 11.36; scoring after the update, 20 steps and a maximum of 5.96. The cause is the scale of the normalised step against the scale of V: the step has Frobenius norm ~0.04, while V itself is of order 2.6e-03, so V_bar moves through the origin and 1 / delta diverges. With c_gamma equal to the variance of the residual (2.57e-03): 0 steps, trace(V_bar) = +1.37e-03, maximum 3.70.
The two guards are max_step_frac = 0.1 and the eigenvalue floor trace(V_bar) / d * 1e-3. On the same 80 samples with the guards the maximum stays below the threshold. The reproduction is the module's test test_mahalanobis_healthy_scores_stay_below_threshold, which uses the 100 healthy residuals of the issue scenario with n_init = 20 and asserts the maximum is 3.739 < 7 (80 of the 100 scores non-zero).
OCSVM is the alternative when the fault is not a shift but a change of the distribution's shape.
Link: https://tatopenn-cell.github.io/Dense-Armor/anomaly/mahalanobis/
Links cited in this discussion
AI-Powered Analysis
Machine-generated threat intelligence
Technical Analysis
The Online Robust Mahalanobis method computes anomaly scores by measuring the Mahalanobis distance of new samples from a healthy joint residual distribution, using robust estimators for location (geometric median) and scatter (median covariation matrix). These estimators have a 50% breakdown point, meaning they resist corruption from up to half the samples. The method updates estimates online via averaged stochastic gradient descent, allowing real-time adaptation to new data. The anomaly score is the Mahalanobis distance calculated without matrix inversion, using eigendecomposition of the median covariation matrix. This approach mitigates the masking effect seen in classical estimators that use sample mean and covariance, which are sensitive to outliers. The method has been demonstrated on synthetic robotic arm data to detect payload faults and drift anomalies with high accuracy and low false alarm rates. It is a statistical anomaly detection technique rather than a security vulnerability or exploit.
Potential Impact
This content describes a statistical anomaly detection technique for robotic systems and does not represent a security vulnerability or threat. There is no direct impact on software security or system integrity. The method aims to improve fault detection in robotics by robustly identifying anomalous sensor readings. No exploitation or malicious activity is associated with this technique.
Defensive Guidance
Not applicable. This is a research and utility method for anomaly detection, not a vulnerability or threat requiring remediation or patching.
Technical Details
- Source Type
- Subreddit
- cybersecurity
- Reddit Score
- 0
- Discussion Level
- minimal
- Content Source
- reddit_link_post
- Post Type
- link
- Newsworthiness Assessment
- {"score":27,"reasons":["external_link","established_author","very_recent"],"isNewsworthy":true}
- Has External Source
- true
- Trusted Domain
- false
Threat ID: 6ad409412cdf04f6566f2baa
Added to database: 10/17/2026, 23:48:17 UTC
Last enriched: 10/17/2026, 23:48:20 UTC
Last updated: 10/18/2026, 03:18:11 UTC
Views: 7
Community Reviews
0 reviewsCrowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.
Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.
Actions
Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.
Need more coverage?
Upgrade to Pro Console for AI refresh and higher limits.
For incident response and remediation, OffSeq services can help resolve threats faster.
Latest Threats
Check if your credentials are on the dark web
Instant breach scanning across billions of leaked records. Free tier available.