wikillm

Paper · 2024-12-13 · cs.RO, cs.AI, cs.LG, eess.SY

One Filter to Deploy Them All: Robust Safety for Quadrupedal Navigation in Unknown Environments

An observation-conditioned reachability value network takes a LiDAR scan, a disturbance bound and the robot state, and predicts an HJ safety value. Its gradient drives a QP filter that overrides a nominal controller when needed. Author-reported: 0.91 success in hard simulation on ABS-Agile (ABS 0.80), and 8/10 successes on a slippery Go1 course where ABS gets 2/10.

Safety filterHamilton-Jacobi reachabilityConformal predictionlegged-robotssafety-filterhamilton-jacobi-reachabilityvalue-functiondisturbance-estimationlidar

arXivPDFCodeMarkdown20 min read

AI-compiled by claude-haiku-5-5 on 2026-10-25, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.

In plain words

A walking robot dog follows a planner that is good in familiar places but may not know about a new obstacle, a slippery floor, or a heavier load. This paper adds a safety layer that sits between the planner and the walking controller. The layer is only allowed to change the robot's commands when the robot is about to get into trouble, and otherwise lets the planner decide.

The layer is driven by a small neural network that was trained offline on many made-up rooms. It looks at a laser scan of the surroundings, a guess of how much the robot's motion is being pushed off course, and the robot's position and heading. It then outputs a number that says how safe the situation is and a direction in which things get safer. When the number is low, a small optimisation nudges the planner's command as little as possible to keep the robot clear of trouble.

The authors' point is that one such layer can work with several different planners and walking controllers, and does not need to be redesigned for each one. The paper reports tests in simulation and on a real quadruped. Those tests show the layer keeping the robot clear of obstacles more often than a comparison method, especially on a slippery surface.

TL;DR

  • Safety filter for a quadruped: a learned Hamilton-Jacobi value function, conditioned on a LiDAR scan and an online disturbance-bound estimate, drives a least-restrictive QP filter over the nominal twist command §V §V-B.2.
  • The network is trained by supervised regression on value and spatial gradient, using ground truth from a reachability solver on 1,000 random environments §V-A §V-A.2 §V-A.3.
  • Failure probability is handled with conformal calibration of the network output, with a stated guarantee §V-A.4 eq. 11 eq. 12.
  • Author-reported: 100-trial simulation on a hard payload and friction setting; OCR reaches 0.91 success with ABS-Agile, versus 0.80 for ABS tab. III.
  • The released code departs from the paper in several places, including the threshold, the disturbance window and the disturbance formula (see Paper vs code).

Problem

Learned locomotion and planners often assume a known environment and known dynamics. A safety guarantee that depends on a fixed map or a fixed controller stops being valid when either changes §I §III. The authors want a filter that does not need the controller or the environment in advance §III.

The dynamics depend on the environment, through friction, payload and unseen obstacles. The failure set depends on the environment too §III §V. The paper treats the reduced-order model's modelling error as a bounded adversarial disturbance, which is conservative §V-A.1.

The paper assumes that the nominal policy outputs a planar twist command (forward speed and yaw rate) which a low-level controller tracks §III. It also assumes that the reduced-order model is accurate enough that the remaining error fits inside the estimated bounds §VIII.

Method

Reduced model. The robot is modelled as a 3-state Dubins car: planar position and heading. The control is a twist (v, w). The modelling error enters as an additive disturbance, bounded in position and in heading §V-A.1 eq. 10.

Training data. For each of 1,000 training environments and 100 validation environments, random circular obstacles are placed and a disturbance bound is sampled. A reachability solver computes the converged value and its gradient on a grid, over a 2 s horizon §V-A.2. Training pairs are made from robot origins outside obstacles, each with its LiDAR scan, and states sampled in the origin's frame that are not occluded §V-A.2.

Network. The value network V_ψ takes the relative state, the disturbance bound and the 100-ray LiDAR scan. It is an MLP with sine activations, chosen because they model spatial gradients well §V-A.3. The loss is a squared error on the value plus a squared error on its spatial gradient, averaged over N = 50,000 samples per batch §V-A.3.

Calibration. Let s_i be prediction errors on validation samples. Choose a confidence β and a violation rate ε. Find the largest k that satisfies a binomial tail bound. The calibration level δ is the (N − k)/N quantile of the errors. With probability at least 1 − β, the fraction of samples where the network overestimates the value by more than δ is at most ε §V-A.4 eq. 11 eq. 12. The proof is a split-conformal argument with a Beta distribution app. A eq. 17.

Disturbance estimation. At deployment, the robot compares its measured state with a disturbance-free prediction over a short window. The prediction horizon is 2 s. The estimated disturbance is the prediction error divided by that horizon §V-B.1 eq. 13. A sliding window of such estimates gives the bound. The bound keeps the middle fraction c of sorted values, and is set at the mean plus or minus b standard deviations §V-B.1 eq. 14. The paper uses c = 0.8, b = 2, and a window of 2 s §V-B.1.

Safety filter. When the value is above δ, the nominal command passes through unchanged §V-B.2 eq. 15. Otherwise a QP picks the command closest to the nominal one, subject to a worst-case margin from the disturbance bound, plus a slack variable with weight λ = 10^3 §V-B.2 eq. 16. The constraint uses the gradient of V_ψ, and the margin is taken over all disturbances in the bound §V-B.2. The filter is the smooth least-restrictive filter from the reachability literature §IV-B eq. 8 eq. 9.

Hierarchical use. The filter needs a high-level twist, so it works with any planner that outputs twists and a low-level tracker. For an end-to-end policy, the paper runs the policy unchanged while V_ψ > 0, and falls back to its own planner and tracker otherwise (Remark in §V-B.2).

Simulation nominal controllers. The paper combines three planners (predictive sampling, a naive goal-seeker, and a human teleoperator) with three low-level policies (Walk-These-Ways, Unitree's MPC, and the ABS recovery policy) §VI-A. Predictive sampling plans with a sampled MPC over 4 s, and cost is distance to goal plus a collision penalty §VI-A.1.

Pseudocode
# Training data for one environment  [§V-A.2]
# Input:  obstacles (1 to 10 circles), disturbance bounds
# Output: training samples (state, value, gradient, LiDAR scan)

def make_samples(obstacles, disturbance_bounds):
    # Ground-truth value on a 100 x 100 x 60 grid, 2 s horizon  [§V-A.2]
    value_grid = solve_reachability(obstacles, disturbance_bounds)
    samples = []
    for origin in sample_free_origins(obstacles, count=10):
        # LiDAR: 100 rays over [-pi, pi], clipped to [0.2, 10] m  [§V-A.2]
        scan = render_lidar(obstacles, origin)
        for state in sample_unoccluded_states(obstacles, origin, count=500):
            # State is expressed in the frame of the new origin  [§V-A.2]
            value, gradient = value_grid.query(state)
            samples.append((state, disturbance_bounds, scan, value, gradient))
    return samples
Pseudocode
# Value network loss  [§V-A.3]
# Input:  batch of samples with predicted values and gradients
# Output: scalar loss

def loss(pred_value, pred_grad, value, grad):
    # Squared error on the value  [§V-A.3]
    value_term = (pred_value - value) ** 2
    # Squared error on the spatial gradient  [§V-A.3]
    grad_term = sum((pred_grad - grad) ** 2)
    # Averaged over the batch of N samples  [§V-A.3]
    return mean(value_term + grad_term)
Pseudocode
# Calibration of the value network  [§V-A.4] [eq. 11] [eq. 12]
# Input:  beta, epsilon, N validation errors s_i = V_pred - V_true
# Output: calibration level delta (m)

def calibration_level(errors, beta, epsilon):
    # Largest k with binomial tail at most beta  [eq. 11]
    k = largest_k(errors_count=len(errors), epsilon=epsilon, beta=beta)
    # (N - k)/N quantile of the errors  [§V-A.4]
    delta = quantile(errors, (len(errors) - k) / len(errors))
    return delta
Pseudocode
# Online disturbance bound  [§V-B.1] [eq. 13] [eq. 14]
# Input:  last window of states, controls and time steps
# Output: bound on the disturbance, per state dimension

def estimate_bounds(states, controls, dts, horizon, window, c, b):
    # Disturbance = (measured - predicted) / horizon  [eq. 13]
    disturbances = per_step_disturbances(states, controls, dts, horizon)
    # Keep the middle fraction c of the sorted window  [§V-B.1]
    middle = central_fraction(disturbances, c)
    # Bound = |mean| +/- b standard deviations  [eq. 14]
    # The released code drops the absolute value, see Paper vs code
    center = abs(mean(middle))
    return center - b * std(middle), center + b * std(middle)
Pseudocode
# Adaptive safety filter  [§V-B.2] [eq. 15] [eq. 16]
# Input:  robot state, LiDAR scan, disturbance bounds, nominal twist
# Output: filtered twist (v, w)

def safety_filter(state, scan, bounds, nominal_twist, delta):
    # Calibrated value and its gradient at the current state  [§V-A.4]
    value, grad = value_network_with_gradient(state, scan, bounds)
    # Outside the boundary the nominal command passes through  [eq. 15]
    if value > delta:
        return nominal_twist
    # QP: closest twist to nominal, with worst-case margin  [eq. 16]
    # Slack s >= 0 keeps the QP feasible, weighted by lambda = 10^3  [§V-B.2]
    return solve_qp(nominal_twist, grad, bounds, state, slack_weight=1e3)

Hyperparameters

Paper values are listed first. Values found only in the released code are marked as code-only and are not claims of the paper. The paper does not say which hardware or software versions were used beyond the GPU and the Go1 platform §V-A.2 §VII.

NameValueWhereNotes
Training environments1,000§V-A.2Code: 1000 generate_value_network_data.py
Validation environments100§V-A.2Code: 100 generate_value_network_data.py
Obstacles per environment1 to 10 (uniform integer)§V-A.2Code: 1 to 10 generate_value_network_data.py generate_value_network_data.py
Obstacle radius0.1 to 1 m, uniform§V-A.2Code: same generate_value_network_data.py
Obstacle centresuniform in [-5, 5] m squared§V-A.2Code uses state_min and state_max generate_value_network_data.py
Disturbance boundsposition 0 to 1 m/s, heading 0 to 2 rad/s, uniform§V-A.2Code: same generate_value_network_data.py
Ground-truth grid100 x 100 x 60 over [-5, 5] m squared x [-pi, pi] rad§V-A.2Code: same generate_value_network_data.py
Reachability horizon2 s, converged§V-A.2Code: 2 generate_value_network_data.py
Control boundsv in [0, 2] m/s, abs(w) <= 2 rad/s§V-A.2Code: v in [0, 2], w in [-2, 2] generate_value_network_data.py
LiDAR rays100, evenly spaced over [-pi, pi]§V-A.2Code: 100 train_value_network.py
LiDAR rangeclipped to [0.2, 10] m§V-A.2Code: 0.2 to 10.0 m hardware.yaml
Origins per environment10§V-A.2Code: num_egos 10 train_value_network.py
States per origin500§V-A.2Code: num_rels 500 train_value_network.py
Batch size (samples)N = 50,000§V-A.2Code batch_size 10 train_value_network.py. Paper's 10 x 10 x 500 = 50,000 matches the per-batch count only if one batch item is one environment; not verified in the dataset class
NetworkMLP, 4 hidden layers of 512 neurons§V-A.3Code: hidden 512, num_hidden_layers 3 models.py. Code-only difference, see Paper vs code
Activationsine§V-A.3Code: sine train_value_network.py
Input normalisationnot stated§V-A.3Code means [0, 0, 0, 0.5, 1] and stds [4, 4, 1.8, 0.25, 0.5] for the 5 non-LiDAR inputs; LiDAR mean 8.5 and std 3 train_value_network.py
OptimizerAdam§V-A.3Code: Adam train_value_network.py
Learning rate1e-5§V-A.3Code: 1e-5 train_value_network.py
Loss weightsvalue and gradient terms, weights not stated§V-A.3Code: both 1 train_value_network.py
Training epochsnot stated (converges in about 8 h on one GPU)§V-A.3Code: 5000 train_value_network.py
Calibration confidence beta1e-12§V-A.4Code default 1e-12 calibrate_value_network.py
Calibration samples N10^7§V-A.4Code default 10^7 calibrate_value_network.py
Violation rate epsilon10^-1, 10^-2, 10^-3 tabulated; 10^-2 used§V-A.4 tab. IICode grid is 0.01 to 0.1 only calibrate_value_network.py
Calibration level delta0.22 / 0.49 / 0.99 m for epsilon 10^-1 / 10^-2 / 10^-3; 0.49 m used§V-A.4 tab. IICode: calibration adjustment -0.5 hardware.yaml
Filter thresholdvalue compared against delta§V-B.2 eq. 15Code: 0.35 on the calibrated output hardware.yaml. Code-only difference, see Paper vs code
Prediction horizon eta * k2 s§V-B.1Code: 2.0 s hardware.yaml
Window eta * phi2 s§V-B.1Code: 10.0 s, code-only hardware.yaml
Coverage c0.8§V-B.1Code: 0.8 hardware.yaml
Bound width b2 std§V-B.1Code: 2.0 hardware.yaml
Slack weight lambda10^3§V-B.2Code: 1000 safety_filter.py
Disturbance capnot stated§V-BCode-only: 1.0 m/s position, 2.0 rad/s heading hardware.yaml
PS samples N1000§VI-A.1Code: 1000 hardware.yaml
PS noise sigma0.5§VI-A.1Code: (max - min) / 4 per dimension, so 0.5 for v and 1.0 for w run_sims.py
PS horizon T4 s§VI-A.1Code: 4 run_sims.py
PS step eta0.2 s§VI-A.1Code: 0.2 hardware.yaml
PS collision penalty c10^9§VI-A.1Code default 1e9 navigation_task.py
NVE max headingpi/4§VI-A.1Naive planner not found in the code files searched
Simulation obstacles4, centres in [-2, 2] m squared§VI-DCode: 4 obstacles generate_sims.py
Simulation payload[-1, -0.5] U [0.5, 1] kg (hard)§VI-D tab. VCode samples [-1, 1] and rejects (-0.5, 0.5) generate_sims.py
Simulation friction[0.5, 0.75] U [1.25, 1.5] (hard)§VI-D tab. VCode samples [0.5, 1.5] and rejects (0.75, 1.25) generate_sims.py
Trial timeout60 s§VI-CNot checked in the code
Start and goal(-5, 0) m to (5, 0) m§VI-DNot checked in the code

Results

Author-reported. Simulation: Unitree Go1 in Isaac Sim, 100 trials per row, hard payload and friction setting §VI-D app. B. Hardware: Unitree Go1 with an RPLiDAR A2, 10 trials per row §VII tab. IV. Baselines: ABS, which is an end-to-end safety framework, and ablations without disturbance estimation (OCR \ DE) or calibration (OCR \ C) §VI-B.

Simulation, hard setting, 100 trials tab. III

ControllerFilterSR ↑Collision fraction ↓Timeout fraction ↓v̄ (m/s) ↑r̄ ↓q̄ (m) ↑
ABS-AgileNo Filter0.750.250.002.100.000.41
ABS-AgileABS0.800.200.002.030.030.41
ABS-AgileOCR \ DE0.400.350.250.980.620.41
ABS-AgileOCR \ C0.810.190.001.700.280.41
ABS-AgileOCR (ours)0.910.090.001.220.590.58
PS + WTWNo Filter0.720.280.001.360.000.43
PS + WTWOCR \ DE0.780.220.000.840.610.42
PS + WTWOCR \ C0.900.090.011.210.180.44
PS + WTWOCR (ours)1.000.000.000.970.420.66
NVE + WTWNo Filter0.200.800.001.700.000.31
NVE + WTWOCR \ DE0.210.790.000.930.610.37
NVE + WTWOCR \ C0.450.550.001.320.280.39
NVE + WTWOCR (ours)0.910.080.011.040.470.62

The main text notes that the OCR framework is compared with ABS on ABS-Agile and that the ABS framework is designed for that policy §VI-E.1. The table is the hard setting from the appendix app. B.

Hardware, 10 trials per row tab. IV

ControllerFilterNormal Successes ↑Normal Collisions ↓Normal Timeouts ↓Slippery Successes ↑Slippery Collisions ↓Slippery Timeouts ↓
ABS-AgileNo Filter910190
ABS-AgileABS910280
ABS-AgileOCR (ours)1000811
PS + WTWNo Filter550190
PS + WTWOCR (ours)910820
NVE + WTWNo Filter01000100
NVE + WTWOCR (ours)901820
PS + MPCNo Filter5500100
PS + MPCOCR (ours)1000910
NVE + MPCNo Filter01000100
NVE + MPCOCR (ours)901730

Simulation, all difficulty levels, 100 trials each tab. VI

DifficultyControllerFilterSR ↑Collision fraction ↓Timeout fraction ↓v̄ (m/s) ↑r̄ ↓q̄ (m) ↑
EasyABS-AgileNo Filter0.890.110.002.120.000.44
EasyABS-AgileABS Framework0.880.120.002.080.020.44
EasyABS-AgileOCR \ DE0.510.210.280.860.680.44
EasyABS-AgileOCR \ C0.880.120.001.770.260.46
EasyABS-AgileOCR (ours)0.950.050.001.240.600.56
EasyPS + WTWNo Filter0.800.200.001.460.000.44
EasyPS + WTWOCR \ DE0.850.150.000.840.620.43
EasyPS + WTWOCR \ C0.910.090.001.310.140.42
EasyPS + WTWOCR (ours)1.000.000.000.990.460.62
EasyNVE + WTWNo Filter0.250.750.001.820.000.36
EasyNVE + WTWOCR \ DE0.220.780.001.230.500.40
EasyNVE + WTWOCR \ C0.460.540.001.530.220.37
EasyNVE + WTWOCR (ours)0.980.020.001.060.480.58
MediumABS-AgileNo Filter0.830.170.002.120.000.43
MediumABS-AgileABS Framework0.870.130.002.050.020.43
MediumABS-AgileOCR \ DE0.530.270.201.020.610.45
MediumABS-AgileOCR \ C0.840.160.001.740.270.44
MediumABS-AgileOCR (ours)0.930.070.001.270.570.55
MediumPS + WTWNo Filter0.810.190.001.420.000.46
MediumPS + WTWOCR \ DE0.810.190.000.860.610.44
MediumPS + WTWOCR \ C0.830.170.001.330.120.46
MediumPS + WTWOCR (ours)0.990.010.001.000.420.65
MediumNVE + WTWNo Filter0.250.750.001.790.000.39
MediumNVE + WTWOCR \ DE0.220.780.001.110.560.40
MediumNVE + WTWOCR \ C0.420.580.001.470.220.39
MediumNVE + WTWOCR (ours)0.970.030.001.050.500.57
HardABS-AgileNo Filter0.750.250.002.100.000.41
HardABS-AgileABS Framework0.800.200.002.030.030.41
HardABS-AgileOCR \ DE0.400.350.250.980.620.41
HardABS-AgileOCR \ C0.810.190.001.700.280.41
HardABS-AgileOCR (ours)0.910.090.001.220.590.58
HardPS + WTWNo Filter0.720.280.001.360.000.43
HardPS + WTWOCR \ DE0.780.220.000.840.610.42
HardPS + WTWOCR \ C0.900.090.011.210.180.44
HardPS + WTWOCR (ours)1.000.000.000.970.420.66
HardNVE + WTWNo Filter0.200.800.001.700.000.31
HardNVE + WTWOCR \ DE0.210.790.000.930.610.37
HardNVE + WTWOCR \ C0.450.550.001.320.280.39
HardNVE + WTWOCR (ours)0.910.080.011.040.470.62

Hardware, all conditions, 10 trials tab. VII

ConditionControllerFilterCount of successes ↑Count of collisions ↓Count of timeouts ↓v̄ (m/s) ↑r̄ ↓q̄ (m) ↑
NormalABS-AgileNo Filter9101.670.000.29
NormalABS-AgileABS9101.590.020.29
NormalABS-AgileOCR (ours)10000.940.640.43
NormalPS + WTWNo Filter5501.530.000.32
NormalPS + WTWOCR (ours)9100.800.580.61
NormalNVE + WTWNo Filter0100N/AN/AN/A
NormalNVE + WTWOCR (ours)9010.770.610.55
NormalPS + MPCNo Filter5501.550.000.33
NormalPS + MPCOCR (ours)10000.810.540.58
NormalNVE + MPCNo Filter0100N/AN/AN/A
NormalNVE + MPCOCR (ours)9010.930.560.54
SlipperyABS-AgileNo Filter1901.380.000.33
SlipperyABS-AgileABS2801.490.030.22
SlipperyABS-AgileOCR (ours)8110.900.600.38
SlipperyPS + WTWNo Filter1901.040.000.52
SlipperyPS + WTWOCR (ours)8200.740.650.45
SlipperyNVE + WTWNo Filter0100N/AN/AN/A
SlipperyNVE + WTWOCR (ours)8200.610.680.39
SlipperyPS + MPCNo Filter0100N/AN/AN/A
SlipperyPS + MPCOCR (ours)9100.800.540.56
SlipperyNVE + MPCNo Filter0100N/AN/AN/A
SlipperyNVE + MPCOCR (ours)7300.820.570.32

Simulation environment parameters tab. V

Payload range (kg)Easy: [0, 0]Medium: [-1, 1]Hard: [-1, -0.5] U [0.5, 1]
Friction rangeEasy: [1, 1]Medium: [0.5, 1.5]Hard: [0.5, 0.75] U [1.25, 1.5]

Calibration levels tab. II (N = 10^7, beta = 10^-12)

Violation rate epsilon10^-110^-210^-3
Calibration level delta (m)0.220.490.99

Other reported figures. Safety rates across settings for 1,000 trials are plotted fig. 5. Disturbance estimates in a payload and friction case, and a sudden friction change, are plotted fig. 6. Trajectories on two hand-designed cases and the dead-end case are shown in fig. 7. Hardware slippery-floor runs are shown in fig. 8. Real-world demonstrations are in fig. 1, with videos on the project page (linked in the paper).

Paper vs code

Repository: albertklin/observation-conditioned-reachability, MIT licence, linked from the project page and owned by the first author's GitHub account LICENSE. Commit 92d14861fcb0bf9ca663738e93a7c156afa62b0a. The LICENSE copyright line names all three authors. The repository contains the training, data, calibration, filter and hardware code.

  • Network depth. The paper uses 4 hidden layers of 512 §V-A.3. The code builds an MLP with hidden size 512 and num_hidden_layers=3 models.py. The weight-layer count depends on how FCBlock in modules.py counts layers, which was not checked.
  • Loss scale. The paper's loss sums squared norms over the gradient components and averages over samples §V-A.3. The code uses nn.MSELoss on value and gradient, which averages over elements train_value_network.py train_value_network.py. This rescales the gradient term relative to the paper's by the number of gradient components.
  • Filter threshold. The paper switches to the QP when the uncalibrated network output is at most δ = 0.49 m §V-B.2 eq. 15. The code adds a calibration offset of -0.5 and switches when the calibrated value is below 0.35 safety_filter.py safety_filter.py filter.py. In raw network units that is about 0.85, not 0.49.
  • Disturbance window. The paper uses a 2 s window §V-B.1. The config sets window_horizon to 10 s hardware.yaml.
  • Integrator. The paper says the disturbance-free rollout uses Euler's method §V-B.1. The code uses runge_kutta_step for the rollout disturbance_estimator.py disturbance_estimator.py.
  • Bound formula. The paper's bound is |mean| plus or minus b times the standard deviation, applied to a window of disturbance norms for position §V-B.1 eq. 14. The code uses mean minus or plus b times the standard deviation, per dimension, with no absolute value disturbance_estimator.py. The hardware filter then takes the element-wise maximum of absolute bounds, takes the norm of the position part, and clips to 1.0 m/s and 2.0 rad/s filter.py.
  • Short history. When the history is shorter than the prediction horizon, the code uses half the cap as the disturbance bound filter.py. The paper does not say what happens in that case.
  • Calibration grid. The paper tabulates ε = 10^-3 with δ = 0.99 m tab. II. The code's calibration grid covers only 0.01 to 0.1 calibrate_value_network.py. The code computes the bound from the order statistics of a Beta distribution, which is a rearrangement of the paper's binomial form app. A.
  • Noise in the planner. The paper's predictive sampler uses σ = 0.5 §VI-A.1. The code uses (max - min) / 4, so 0.5 for speed and 1.0 for yaw rate run_sims.py.
  • Cluttered-scene adjustments. The paper says that for cluttered hardware scenes, it discards LiDAR beyond a front cone of π/2 rad and uses the uncalibrated output §VII. These are not separate flags in the code I read. The hardware LiDAR interface has its own focus settings lidar.py that were not compared with the paper.
  • Fallback. If the QP fails, the code uses a bang-bang fallback on the sign of the gradient safety_filter.py. The paper does not describe a fallback.
  • Frame. The code evaluates the network in the frame of the LiDAR capture, rotating the current relative state into that frame and the gradient back to world frame safety_filter.py. The paper says states are expressed in the frame of the new origin §V-A.2 but does not give the transform for deployment.
  • Simulation payload and friction. The sampling in generate_sims.py matches the paper's hard ranges, with the excluded middle bands generate_sims.py.
  • Predictive sampling. Horizon, step, samples and collision cost match run_sims.py hardware.yaml navigation_task.py. The sampler uses a Gaussian around the previous best sequence, as the paper says predictive_sampler.py.
  • Naive planner. I did not find the naive goal-seeking planner in the files I searched (scripts/run_sims.py, scripts/generate_sims.py, utils/online_environment.py). Results for it cannot be checked against code.
  • Baselines. The ABS framework and the Walk-These-Ways and Unitree MPC controllers are external §VI-A and are not in this repository, apart from libraries/walk-these-ways which is vendored.

Pitfalls

  • Threshold mismatch. The paper's equations switch at δ = 0.49 m on the raw output. The released hardware config switches at about 0.85 in raw units. An implementation that follows one source will behave differently from one that follows the other. Pick one and say so in your implementation.
  • Disturbance window. The paper says 2 s, the config says 10 s. A 10 s window reacts slowly to a change in friction, and the paper says the delay is a failure mode §VIII.
  • Conservatism. The authors say that the worst-case disturbance model makes the filter conservative in crowded spaces, and that it can stall in clutter §VIII §VII.
  • Guarantee scope. The calibration gives a probabilistic bound on the validation distribution. The authors say it does not carry over to the real world under distribution shift §VIII.
  • Quadratic program. The QP has a slack variable with a large weight. If the solver fails, the code uses a fallback that is not in the paper safety_filter.py.
  • Numerically sensitive estimation. The disturbance estimate is the state error divided by the 2 s horizon §V-B.1 eq. 13. Any error in the measured state, such as a time-stamp or a state-estimate jump, passes straight into the bound. The paper names latency and state-estimation issues as a source of large estimated disturbances §VIII.
  • Input scaling. The paper does not state input normalisation. The code's means and standard deviations are the only values in the repository train_value_network.py. Use them, or state your own.
  • Gradient supervision. The QP uses the network's spatial gradient, so the gradient is part of the deployed model, not only a training target §V-B.2 §V-A.3.
  • Figure numbers. The paper has no PDF in this workspace; figure numbers were taken from the LaTeX source order, which is how LaTeX numbers floats. Check against the compiled PDF before relying on them.
  • Hardware timing. The hardware config uses a 0.05 s robot period and a 0.2 s planner step hardware.yaml hardware.yaml. The estimator's window is set in seconds, so it depends on the control period. Check both when porting to another platform.

Lineage

  • Builds on: Hamilton-Jacobi reachability and its robust optimal control formulation §IV-A; the smooth least-restrictive filter from the reachability literature §IV-B; sinusoidal networks for gradient fitting, cited as DeepReach §V-A.3; conformal prediction, cited as split conformal calibration §V-A.4 app. A.
  • Compared against: ABS, an end-to-end safety framework with a recovery policy, used as the main baseline §VI-B tab. III tab. IV; ablations without disturbance estimation or calibration §VI-B.
  • Low-level policies used: Walk-These-Ways §VI-A.2; Unitree's MPC-based ROS package §VI-A.2; ABS recovery policy §VI-A.2.
  • Superseded by: not known from content already in this wiki.

Source and license

Adapted from “One Filter to Deploy Them All: Robust Safety for Quadrupedal Navigation in Unknown Environments” by Albert Lin, Shuang Peng, Somil Bansal (arXiv:2412.09989), used under CC BY 4.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors. Code citations refer to https://github.com/albertklin/observation-conditioned-reachability at commit 92d14861fcb0 (MIT). Any quoted code is shown under that license.