Skip to content
ROS Discourse — Community updates· marunigno-ship-it·· 3 hours agoSignalEditorial score83

Can a social reflex stop a robot but never restart it? Testing a dual-dwell safety gate (Webots)

Can a social reflex stop a robot but never restart it? Testing a dual-dwell safety gate (Webots)

Summary

The author explores a safety architecture for robots where perception can stop movement but not restart it, using a dual-dwell system in a Webots simulation. The design includes a 'Doer-Checker' pattern, a reflex layer with hysteresis, and a latch mechanism to prevent premature restarts. The system is tested in simulation and verified through replay, though it is not intended for real-world deployment without human oversight.

Editorial context

The author presents a deterministic safety architecture for robots, using a dual-channel system with a 'Doer-Checker' pattern to ensure that perception can stop a robot but not restart it. The system is tested in simulation and includes a replay mechanism for verification, though it is not intended for real-world deployment without human oversight.

Source: ROS Discourse — Community updates · Read original article ↗

Article text · Original source · English

On this page

Hi everyone,

Following up on my earlier experiments with supervisory gates (Demo 8) : Webots Demo 8: Supervisory Gate Multi-Fault Lifecycle & Watchdog Hardening (QERRA-v2 Classical) I’ve built a new test to evaluate the recovery side of a safety event.

My underlying vision in robotics is harmonious human-robot social collaboration —specifically in vulnerable spaces like hospitals or eldercare facilities & beyond. We want robots to react when someone calls for help or collapses.

But here is the friction I constantly see: to make a robot socially aware, we have to rely on probabilistic AI models. If we let an uncertified perception model dictate the motor controllers, a lagging thread or hallucination can turn a 70 kg robot into a runaway hazard. I wanted to build a deterministic “floor” underneath the AI.

The safety contract I wanted to test is simple: Perception can take away the permission to move, but it can never give it back.

Before sharing the data, I want to be completely upfront. I am not a classically trained robotics engineer or a certified safety assessor. I am an independent solo developer in Greece, and I build this with AI coding tools (Claude, Gemini). I am sharing this here because I want to learn from those of you actually deploying robots around humans, and see if this architecture holds up. (If i ever get an answer! :smiley: ).

The Architecture: Doer-Checker

I built a dual-channel pattern and tested it on a TIAGo base in Webots:

  • The “Doer” (Navigation Brain): An unprivileged process that proposes velocities (2.00 rad/s) over UDP. It has no direct access to the wheels.
  • The “Checker” (Supervisory Gate): A pure mathematical function step(state, params, inputs) → StepResult running on a strict 32 ms cycle. It is the only thing that writes to the actuators.
  • The Reflex Layer (QERRA-HSR): Evaluates distress. It enforces a 1.0s hysteresis dwell before it steps down from CRITICAL to CLEAR, preventing the robot from “chattering” if camera confidence fluctuates.
  • The Latch: After any trip, the Gate requires the cause to be clear for a continuous 1.0s, followed by an explicit operator reset.

The Run (14.0 Seconds, 438 Control Cycles)

This is a single continuous simulation take. Times below are from the audit log.

Sim time What happens Gate Response
0.03 s Boot TRIPPED (proposer not heard yet)
1.312 s Scripted reset Accepted → RUN at 2.00 rad/s
4.000 s Distress injected (0.85 conf), HSR CRITICAL TRIPPED on the same 32ms cycle (cycle 125), wheels clamped to 0.000
5.024 s Scripted reset while distress is active Refused (RESET_REJECTED_HAZARD)
7.008 s Injected distress removed Still TRIPPED
8.032 s HSR back to CLEAR (after 1.0s hysteresis dwell) Still TRIPPED, resets refused (RESET_REJECTED_NOT_READY)
9.056 s Reset on the first allowed cycle Accepted → RUN at 2.00 rad/s
14.016 s End of run, log closed

Note: “Same cycle” means the wheel command went to 0.000 on the exact control cycle the status became CRITICAL. (Time spent computing the Gate decision in Python: p50 = 1.38 ms, max = 4.50 ms).

A quick lesson learned: I initially predicted recovery at 8.2s. But there are actually two dwells stacking here: the reflex layer’s 1.0s dwell (to ensure the scene is calm), followed by the Gate’s own 1.0s internal safety dwell. The earliest reset possible was 9.03s. It was a great lesson in why writing down expected cycles before running is so important.

Replay Audit

Because the Gate is a pure function, every cycle is hash-chained into a JSONL log. Using an offline verifier (verify_log.py --replay), I fed the recorded inputs back through the function. All 438 cycles reproduced bit-for-bit with 0 execution divergences. (Head hash: eccb0d85416cf4a651205f34f3cc0d9275bff6e2b3baa512e4b23dbef0c2714a).

(Transparency note: While the replay is deterministic, live UDP on Windows is not. An earlier take of this scenario tripped at 10.2s due to a host scheduling load that stalled the proposer for 160ms. The gate failed-closed exactly as designed).

Honest Boundaries (What this does not show)

  1. No live detection. The 0.85 distress flag is a constant injected by my test script. Real CV detection (with false positives/negatives) is the hardest part, and is not tested here.
  2. No human in the loop. The resets are injected by a script to test the exact microsecond boundaries. Because of this, the video shows the robot auto-restarting after the dwells finish. In reality, a human must assess the scene before hitting that reset button.
  3. Not a certification claim. This is an independent simulation (Webots/Windows/Python), not an industrial RTOS. I am not affiliated with PAL Robotics.

My Questions for the Community

  1. If you run robots in shared spaces (hospitals, retail): after a protective stop caused by a person, what is your actual restart rule? Remote confirmation? A physical button on the chassis?
  2. Is “perception may only stop the robot, but never start it” a contract you use in practice, or do you let perception modify trajectories directly inside the safety layer?
  3. In a real ROS 2 stack, I envision putting a node like this directly between the final cmd_vel mux and the base controller, blocking all other publishers. Has anyone implemented a strict latch-and-reset pattern this deep in the stack? What went wrong?

Links:

  • Video (31s, Webots window, unedited):

Repository (Apache-2.0): GitHub - marunigno-ship-it/QERRA-v2-classical: Three-layer deterministic safety & ethical execution guard for autonomous robots (ROS 2 & Behavior Trees). Sub-ms physical reflex (QERRA-HSR) + moral filter (SEMEV-12) + values ranker (THRIVE). Fully auditable. · GitHub

Evidence logs: QERRA-v2-classical/docs/demo9 at main · marunigno-ship-it/QERRA-v2-classical · GitHub

Thank you for your time, and I welcome any brutal feedback you have on this architecture.

Marussa

Source:ROS Discourse — Community updates · discourse.openrobotics.org

Timezone · UTC

Article dates follow your selected timezone. Briefing editions use Hong Kong time (UTC+8).