Real-time safety guard pipeline for robot arms — clamp, reject, or fallback on unsafe actions.
Project description
DAM — Detachable Action Monitor
See where your policy breaks — before your hardware does.
Install · Quick Start · Isaac Sim · Architecture · Docs
https://github.com/user-attachments/assets/a10711ea-a419-4aee-ba06-de1e2d437d49
Install
pip install robot-dam # includes torch, lerobot, mcap, dam-rs (Rust extension)
pip install robot-dam[isaac] # + Isaac Sim 6.0 adapter
pip install robot-dam[full] # + ROS2, REST API, QP solver, everything
Or from source:
git clone https://github.com/ez945y/DAM.git && cd DAM
make setup
What It Does
ML policies always output the next action — they have no idea when something is unsafe. DAM intercepts every action and evaluates it through a layered guard pipeline before it reaches hardware. Each action is either passed, clamped (adjusted to stay safe), or rejected.
The goal isn't to hide failures. It's to make them visible and easier to understand.
Important: DAM is experimental research software, not a certified safety system.
Quick Start
git clone https://github.com/ez945y/DAM.git
cd DAM
make setup # Python venv + Rust extension + npm install (~3 min)
make run # Backend :8080 + Console :3000
Open http://localhost:3000 — the demo Stackfile replays a dataset through the full guard pipeline without hardware.
CLI
.venv/bin/dam doctor # check environment
.venv/bin/dam callbacks # list 18 built-in safety checks
.venv/bin/dam validate examples/stackfiles/*.yaml # schema-check Stackfiles
.venv/bin/dam run examples/stackfiles/demo.yaml --cycles 200 --task demo
Make Targets
| Command | What it does |
|---|---|
make setup |
First-time install (venv + Rust + npm) |
make run |
Backend + pre-built frontend |
make dev |
Backend + frontend with hot-reload |
make test |
Full test suite (688+ Python tests + 109 frontend tests) |
make record |
Safe IL recording with DAM guards |
make callbacks |
List all 18 built-in safety checks |
make validate |
Validate example Stackfiles |
Safe Recording for Imitation Learning
During data collection, DAM smooths motions and catches bad data before it enters your dataset. Integrates with LeRobot — one file configures hardware, safety boundaries, and recording.
make record # reads examples/stackfiles/safety.yaml
make record ARGS="--dataset.num_episodes=20" # CLI args override YAML
Python API (3 levels)
import dam
# One input dict per cycle: "action" is the command to validate, every other
# key is an observation group. Returns the safe command in the action's form.
# Level 1: one-liner (notebooks)
safe_action = dam.guardrail({"joints": obs, "action": action}, stackfile="safety.yaml")
# Level 2: stateful guard (recording loops + Isaac Sim)
guard = dam.Guardrail("safety.yaml", task="record") # prints the obs/action contract
safe_action = guard({"joints": obs, "action": action}) # mirrors the action's type
# Level 3: lerobot pipeline (one line addition)
from dam import GuardrailProcessorStep
robot_action_processor.steps.insert(0, GuardrailProcessorStep("safety.yaml"))
The recorded dataset contains only safe actions — your policy trains on data that already respects physical constraints. See Safe Recording Guide for full details.
Isaac Sim Integration
DAM works as a drop-in safety filter for Isaac Sim 6.0+ control loops. Accepts and returns torch.Tensor on any device — no CPU↔GPU copies needed.
import dam
from dam.adapter.isaac import IsaacSafetyFilter
# Single env — IsaacSafetyFilter accepts torch.Tensor directly
filt = IsaacSafetyFilter("franka_safety.yaml", task="manipulation")
safe_action = filt(action_tensor, obs_tensor) # same device/dtype
# Multi-env (Isaac Lab) — vectorized filter
filt = IsaacSafetyFilter("franka_safety.yaml", task="manipulation", num_envs=4096)
safe_actions = filt(actions_batch, obs_batch) # (N, J) → (N, J)
# Auto-detect from ArticulationView
filt = IsaacSafetyFilter.from_articulation(franka_view, "franka_safety.yaml")
Bundled presets: so101_follower, franka_emika_panda. See examples/isaac_franka_demo.py for the full demo.
Architecture
Guard Layers
| Layer | What it checks | Example checks |
|---|---|---|
| L0 OOD Detection | Is the observation in-distribution? | Real-NVP / Memory Bank anomaly scoring |
| L1 Physical Kinematics | Can this move physically happen? | Joint limits, workspace bounds, velocity caps |
| L2 Task Execution | Does this make sense for the task? | Gripper sequence, progress enforcement |
| L3 Hardware Monitoring | Is the hardware healthy? | Temperature, current, voltage, heartbeat |
L0 and L1 run in parallel. The final decision is the most restrictive outcome across all active layers.
Stackfile Configuration
Everything is configured in a YAML Stackfile:
boundaries:
joint_position_limits:
layer: L1
type: single
nodes:
- callback: joint_position_limits
params:
upper: [1.8243, 1.7691, 1.8326, 1.8067, 3.0741, 1.7453]
lower: [-1.8243, -1.7691, -1.8326, -1.8067, -3.0741, 0.0]
Start from examples/stackfiles/minimal.yaml or see the Stackfile Walkthrough.
18 Built-in Safety Checks
Run dam callbacks to list them all:
- L0: OOD detector (Real-NVP, Memory Bank, Welford)
- L1: Joint position/velocity limits, workspace bounds, keep-out zones, orientation, geofence, Cartesian velocity, smoothness
- L2: Task gripper sequence enforcement
- L3: Temperature, current, voltage, force/torque, hardware watchdog, host health
Documentation
| Goal | Start here |
|---|---|
| Learn DAM step by step | Learn DAM |
| Read a Stackfile | Stackfile Walkthrough |
| Common config edits | Common Stackfile Edits |
| Understand the console | Console Walkthrough |
| Prepare for hardware | Hardware Readiness |
| Troubleshooting | Troubleshooting |
Contributing
See Contributing. We welcome safety testing, hardware adapters, performance optimization, and example Stackfiles.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file robot_dam-0.7.0.tar.gz.
File metadata
- Download URL: robot_dam-0.7.0.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e40cc6e70269d5b04aaea06310d102175f4990292c80b4f22d468369c469e6ff
|
|
| MD5 |
39dfd95a980131a65bc9aa10e4f2caca
|
|
| BLAKE2b-256 |
6e986e5b1badd281a7034ae063739082372c2ebb261af409c64777960629f9fa
|
Provenance
The following attestation bundles were made for robot_dam-0.7.0.tar.gz:
Publisher:
release.yml on ez945y/DAM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
robot_dam-0.7.0.tar.gz -
Subject digest:
e40cc6e70269d5b04aaea06310d102175f4990292c80b4f22d468369c469e6ff - Sigstore transparency entry: 1822612356
- Sigstore integration time:
-
Permalink:
ez945y/DAM@78f030bf5dd087af01da6f51f2aeb4a4b0d17481 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/ez945y
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@78f030bf5dd087af01da6f51f2aeb4a4b0d17481 -
Trigger Event:
push
-
Statement type:
File details
Details for the file robot_dam-0.7.0-py3-none-any.whl.
File metadata
- Download URL: robot_dam-0.7.0-py3-none-any.whl
- Upload date:
- Size: 338.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
954139edf0d1f4938a79d3e5a394ba512d602bf0f3fb9c19a6575598a838c307
|
|
| MD5 |
a3e6273e5170dbf782a11c1b24e6cfe8
|
|
| BLAKE2b-256 |
5b18e83d1e3806c8769aafe804b1325b519d50433829c3607b2bedd07c246eb1
|
Provenance
The following attestation bundles were made for robot_dam-0.7.0-py3-none-any.whl:
Publisher:
release.yml on ez945y/DAM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
robot_dam-0.7.0-py3-none-any.whl -
Subject digest:
954139edf0d1f4938a79d3e5a394ba512d602bf0f3fb9c19a6575598a838c307 - Sigstore transparency entry: 1822612424
- Sigstore integration time:
-
Permalink:
ez945y/DAM@78f030bf5dd087af01da6f51f2aeb4a4b0d17481 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/ez945y
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@78f030bf5dd087af01da6f51f2aeb4a4b0d17481 -
Trigger Event:
push
-
Statement type: