Skip to main content

Physics-certified motion data toolkit for Physical AI training

Project description

S2S — Physics Certification for Motion Data

Bad robot and human motion training data costs you months. S2S finds it in seconds.

Using S2S on your data? Open a GitHub Discussion — I will personally help you integrate it with your dataset for free. Looking for the first 5 research partners.

PyPI DOI License python dependencies tests

from s2s_standard_v1_3 import S2SPipeline

pipe = S2SPipeline(segment="forearm")
result = pipe.certify(
    imu_raw={"timestamps_ns": ts, "accel": acc, "gyro": gyro},
    instruction="pick up the cup",   # optional: text intent
    video_frame=jpeg_bytes,          # optional: JPEG from camera/VR/sim
)

print(result["tier"])          # GOLD / SILVER / BRONZE / REJECTED
print(result["score"])         # 0–100
print(result["source_type"])   # HIL_BIOLOGICAL
print(result["intent"])        # "pick object"  (0.887 similarity)
print(result["next_motion"])   # 8-dim next action prediction
print(result["clip_sim"])      # scene-instruction visual match

Why this exists

Most motion datasets contain bad data — corrupted recordings, synthetic signals that violate physics, mislabeled actions. You cannot see it by looking at the numbers. Your model trains on it anyway.

S2S asks: does this data obey the physics of human movement? A perfect statistical fake fails if it violates Newton's Second Law, segment resonance, or rigid body kinematics.

S2S does not replace existing AI systems. It adds a physics reality-check to any visual or physical AI pipeline. Camera, VR render, AR overlay, simulation frame — all go through the same 7-law certification before becoming training data.

For robotics and embodied AI pipelines, S2S covers the full data trust checklist: synchronized stream alignment (±50ms enforcement), physical consistency (7 laws), provenance (Ed25519 signing), biological origin validation (Hurst exponent), segment-level quality control (GOLD/SILVER/BRONZE/REJECTED), and rejection of fake or corrupted windows.

Validated results across 7 datasets:

Dataset Hz Sensors Result
UCI HAR 50Hz IMU +2.51% F1 vs corrupted baseline
PAMAP2 100Hz IMU ×3 +4.23% F1 kinematic chain vs single sensor
WISDM 2019 20Hz IMU +1.74% F1 vs corrupted baseline
WESAD 700Hz IMU + BVP +3.1% F1 stress classification
RoboTurk Open-X 15Hz Robot arm 21.9% of teleoperation data rejected as physically invalid
NinaPro DB5 2000Hz Forearm EMG+IMU 9,552 windows certified
PhysioNet PTT-PPG 500Hz Wrist PPG+IMU 1,164 windows certified

Real-time performance

Certified on real NinaPro DB5 data (2000Hz, 500-sample windows):

Metric Value
Mean latency 2.8ms
Window duration 250ms
CPU overhead 1.1%
Real-time feasible ✅ Yes (89× faster than real-time)
Prosthetics safety threshold 50ms — S2S is 18× below

Laws run on IMU-only data (no gyro hardware):

  • resonance_frequency: RUNS (conf=26)
  • rigid_body_kinematics: RUNS (conf=45, zero gyro = low coupling)
  • jerk_bounds: RUNS (conf=92) ← primary detector at 2000Hz
  • imu_internal_consistency: RUNS (conf=45)
  • newton_second_law: skipped (needs EMG)
  • ballistocardiography: skipped (needs PPG)
  • joule_heating: skipped (needs thermal)

With full sensor stack (IMU + EMG + PPG + gyro): all 7 laws run.

Install

pip install s2s-certify
pip install "s2s-certify[ml]"        # with PyTorch — enables Layers 4 and 5
pip install "s2s-certify[dashboard]" # with Streamlit

Layer 5 visual understanding also requires:

pip install git+https://github.com/openai/CLIP.git
pip install sentence-transformers

Full 7-layer demo output

Run on a real DROID robot manipulation episode:

python3.9 s2s_demo.py --droid ~/droid_data/droid_100/1.0.0
════════════════════════════════════════════════════════════
  S2S — Full Chain Demo  (v1.6.2)
  7 Layers: Physics → Biology → Motion → Visual
════════════════════════════════════════════════════════════

  S2SPipeline(segment=forearm,
    Layer1(Physics) + Layer2(BioSession) + Layer4a(NextAction) +
    Layer4b(GapFill) + Layer4c(Intent) + Layer3(Retrieval) + Layer5(CLIP))

[INPUT] Instruction: 'Put the marker inside the silver pot'
        Video frame: 31,964 bytes JPEG

  ───────────────────────────────────────────────────────
  LAYER 1 — Physics Certification
  ───────────────────────────────────────────────────────
  tier                   SILVER
  score                  66/100
  source_type            HIL_BIOLOGICAL
  laws_passed            ['resonance_frequency', 'rigid_body_kinematics',
                          'jerk_bounds', 'imu_internal_consistency', ...]
  laws_failed            []

  ───────────────────────────────────────────────────────
  LAYER 2 — Biological Origin (Session)
  ───────────────────────────────────────────────────────
  biological_grade       NOT_BIOLOGICAL
  hurst                  0.4917       (synthetic test signal, <0.70)
  bfs_score              0.7468
  n_windows              9
  recommendation         REJECT
  note                   HUMAN grade requires real session data (NinaPro r=0.929)

  ───────────────────────────────────────────────────────
  LAYER 3 — Semantic Motion Retrieval
  ───────────────────────────────────────────────────────
  match_1                1.0000  Put the marker inside the silver pot
  match_2                0.7268  Put the marker inside the blue cup
  match_3                0.6658  Take the marker from the bowl and put it on the table

  ───────────────────────────────────────────────────────
  LAYER 4a — Next Action Prediction
  ───────────────────────────────────────────────────────
  next_motion_8dim       [-0.846, 1.354, 2.997, -0.908, 1.326, 2.946, -0.143, -0.400]
  note                   pos_xyz + vel_xyz + jerk_rms + smoothness

  ───────────────────────────────────────────────────────
  LAYER 4b — Gap Filling (3 intermediates)
  ───────────────────────────────────────────────────────
  t=1/4                  [5.717, 4.739, 11.777, 0.345]
  t=2/4                  [5.888, 4.883, 11.695, 0.384]
  t=3/4                  [5.956, 4.943, 11.316, 0.406]

  ───────────────────────────────────────────────────────
  LAYER 4c — Intent Recognition
  ───────────────────────────────────────────────────────
  intent                 Put the marker inside the silver pot
  confidence             1.0000
  method                 text query override

  ───────────────────────────────────────────────────────
  LAYER 5 — Visual Understanding (CLIP)
  ───────────────────────────────────────────────────────
  clip_sim               0.2253
  visual_input           31,964 byte JPEG
  instruction            Put the marker inside the silver pot

════════════════════════════════════════════════════════════
  CHAIN SUMMARY
════════════════════════════════════════════════════════════
  Physics tier:       SILVER (score 66/100)
  Biological grade:   NOT_BIOLOGICAL (Hurst 0.4917, synthetic test signal)
  Top intent:         Put the marker inside the silver pot (1.0)
  Next motion:        ✓ predicted
  Gap fill:           ✓ 3 intermediates
  Scene similarity:   0.2253

  Full chain: sensor → physics → biology → intent → motion → visual
════════════════════════════════════════════════════════════

Layer 5 — Visual discrimination stress test

Same scene, three different instructions — proves the system is not random:

Instruction Similarity vs correct
"Put the marker inside the silver pot" (correct) 0.2253 baseline
"pick up the blue cup and place on shelf" (wrong object) 0.2108 −7%
"walking down the street" (completely irrelevant) 0.1327 −41%

An irrelevant command scores 41% lower on the same scene. Zero-shot, no fine-tuning.


Reproducible benchmark

Run in one command:

pip install s2s-certify
git clone https://github.com/timbo4u1/S2S
cd S2S
python3.9 experiments/s2s_demo_benchmark.py

Expected output:

real_human (NinaPro/PAMAP2/WESAD): 20/21 certified (95%)
corrupted_spikes (NinaPro+injected): 3/3 correctly downgraded to BRONZE
pure_synthetic (Gaussian noise):     1/5 rejected (Gaussian can satisfy laws by chance)
Overall: 24/29 (83%) — adaptive window fix applied April 2026

Note: WESAD/NinaPro run 3/7 laws (no gyro). PAMAP2 runs 7/7 laws.

PAMAP2 without S2S filtering: baseline F1
PAMAP2 with S2S filtering:    +4.23% F1
WESAD stress classification:  +3.1% F1
RoboTurk teleoperation data:  21.9% rejected as physically invalid

Full results: experiments/s2s_reference_benchmark.json

Status & Roadmap

The core 7-layer pipeline is complete and working. Next development direction depends on what real users need.

If you are using S2S on your data — even just experimenting — open a GitHub Discussion or email s2s.physical@proton.me. One sentence about your use case helps more than you think.

Current planned work without user input:

  • Layer 6: LLM semantic reasoning (jerk limits from natural language)
  • CLIP fine-tuning on DROID (0.23 → 0.6+ scene similarity)
  • Amputee-specific physics thresholds (Issue #5)

Architecture

Layer 1  Physics Certification    7 biomechanical laws, GOLD/SILVER/BRONZE/REJECTED
Layer 2  Biological Origin        Hurst exponent H≥0.70, HUMAN/NOT_BIOLOGICAL
Layer 3  Motion Retrieval         text → certified motion, 11,246 windows, 6 datasets
Layer 4a Next Action Prediction   Transformer, mean r=0.929, 21,896 training pairs
Layer 4b Gap Filling              +5.5% over linear interpolation, Flash & Hogan 1985
Layer 4c Intent Recognition       top-5 75.9%, 71 labels, sentence-transformers
Layer 5  Visual Understanding     CLIP ViT-B/32, frame-synced at 15Hz

Layer 1 — Physics Certification

7 biomechanical laws validated at runtime:

Law Equation Requires What it catches
Newton's Second Law F = ma IMU + EMG EMG force must lead acceleration by ~75ms
Segment Resonance ω = √(K/I) IMU Physiological tremor 8–12Hz for forearm
Rigid Body Kinematics a = α×r + ω²×r IMU + gyro Gyro and accel must co-vary on a rigid body
Ballistocardiography F = ρQv IMU + PPG Heartbeat recoil visible in wrist IMU at PPG rate
Joule Heating Q = 0.75×P×t EMG + thermal EMG bursts must produce thermal elevation
Motor Control Jerk d³x/dt³ ≤ 500 m/s³ IMU Human motion limit (Flash & Hogan 1985)
IMU Internal Consistency Var(accel) ~ Var(gyro) IMU + gyro Independent generators produce zero coupling

Missing sensors are skipped — they do not penalise the score.

Body segment parameters

Segment I (kg·m²) K (N·m/rad) Tremor band (Hz)
forearm 0.020 1.5 8–12
upper_arm 0.065 2.5 5–9
hand 0.004 0.3 10–16
finger 0.0003 0.05 15–25
head 0.020 1.2 3–8
walking 10.0 50.0 1–3

Tier system

Tier Condition
GOLD score ≥ 75 AND passed ≥ n_laws − 1
SILVER score ≥ 55
BRONZE score ≥ 35
REJECTED >30% laws failed OR score < 35

Layer 2 — Biological Origin

pe = PhysicsEngine()
for window in session_windows:
    pe.certify(imu_raw=window, segment="forearm")

verdict = pe.certify_session()
print(verdict["biological_grade"])   # HUMAN / LOW_BIOLOGICAL_FIDELITY / NOT_BIOLOGICAL
print(verdict["hurst"])              # ≥0.70 = biological motor control
print(verdict["recommendation"])     # ACCEPT / REVIEW / REJECT

Layer 3 — Motion Retrieval

pipe = S2SPipeline(segment="forearm")
matches = pipe.query_intent("pick up the cup", top_k=3)
# [("pick object", 0.484), ("drinking", 0.411), ("Put the marker inside the blue cup", 0.379)]

Layer 4 — Action Sequencing

4a — Next action prediction (mean r=0.929)

result = pipe.certify(imu_raw=window)
print(result["next_motion"])  # 8-dim: pos_xyz + vel_xyz + jerk_rms + smoothness

4b — Gap filling (+5.5% over linear interpolation)

gaps = pipe.fill_gap(start_features, end_features, n_steps=3)
Position Neural r Linear r Improvement
t=0.33 0.944 0.889 +0.055
t=0.50 0.960 0.909 +0.051
t=0.67 0.945 0.889 +0.056

4c — Intent recognition (top-5 accuracy 75.9%)

result = pipe.certify(imu_raw=window, instruction="pick up cup")
print(result["intent"])       # "pick object"
print(result["intent_sim"])   # 0.887

Layer 5 — Visual Understanding

Frame-synchronized CLIP ViT-B/32 at 15Hz. Each motion window pairs with the video frame at that exact timestep. Accepts any visual input: camera, VR render, AR overlay, simulation frame.

result = pipe.certify(
    imu_raw=window,
    instruction="Put the marker inside the silver pot",
    video_frame=jpeg_bytes,
)
print(result["clip_sim"])   # 0.2253

All 6 sensor certifiers

from s2s_standard_v1_3 import PhysicsEngine
result = PhysicsEngine().certify(imu_raw={...}, segment="forearm")

from s2s_standard_v1_3.s2s_emg_certify_v1_3 import EMGStreamCertifier
ec   = EMGStreamCertifier(n_channels=8, sampling_hz=1000.0)
cert = ec.push_frame(ts_ns, [ch0..ch7])

from s2s_standard_v1_3.s2s_ppg_certify_v1_3 import PPGStreamCertifier
pc   = PPGStreamCertifier(n_channels=2, sampling_hz=100.0)
cert = pc.push_frame(ts_ns, [red, ir])

from s2s_standard_v1_3.s2s_lidar_certify_v1_3 import LiDARStreamCertifier
lc   = LiDARStreamCertifier(mode='scalar')
cert = lc.push_frame(ts_ns, [distance_m])

from s2s_standard_v1_3.s2s_thermal_certify_v1_3 import ThermalStreamCertifier
tc   = ThermalStreamCertifier(frame_width=32, frame_height=24)
cert = tc.push_frame(ts_ns, flat_pixels)

from s2s_standard_v1_3.s2s_fusion_v1_3 import FusionCertifier
fc = FusionCertifier(device_id="glove_v2")
fc.add_imu_cert(imu_cert)
fc.add_emg_cert(emg_cert)
result = fc.certify()
print(result["human_in_loop_score"])   # 0–100

Cryptographic signing

from s2s_standard_v1_3.s2s_signing_v1_3 import CertSigner, CertVerifier

signer, verifier = CertSigner.generate()
signer.save_keypair("keys/device_001")
signed = signer.sign_cert(cert_dict)
ok, reason = verifier.verify_cert(signed)

Device registry

from s2s_standard_v1_3.s2s_registry_v1_3 import DeviceRegistry

reg = DeviceRegistry("registry.json")
reg.register(
    device_id="glove_v2_001",
    sensor_profile="imu_9dof",
    owner="you@example.com",
    expected_jitter_ns=4500.0,
    public_key_pem=signer.export_public_pem(),
    trust_tier="PROVISIONAL",
)
ok, reason, device = reg.validate_cert(cert_dict)
reg.promote("glove_v2_001")

REST API

python3 -m s2s_standard_v1_3.s2s_api_v1_3 --port 8080
Method Path Description
POST /certify/imu Batch IMU certification
POST /certify/emg Batch EMG certification
POST /certify/lidar Batch LiDAR
POST /certify/thermal Batch thermal frames
POST /certify/ppg Batch PPG certification
POST /certify/fusion Fuse 2–5 stream certs
POST /stream/frame Push frame to persistent session
GET /health Health + active sessions

LeRobot / Hugging Face Integration

Certify any LeRobot dataset episode directly:

from s2s_standard_v1_3.adapters.lerobot import certify_lerobot_dataframe
import pandas as pd

df = pd.read_parquet('episode_000000.parquet')
result = certify_lerobot_dataframe(df, hz=30.0, segment='forearm')

print(result['pass_rate'])     # 0.847
print(result['summary_tier'])  # SILVER
print(result['rejected'])      # windows with physics violations

For datasets with real IMU/acceleration streams. Standard simulation datasets (PushT, ALOHA) use joint positions — pass accel_cols explicitly for those. See adapters/lerobot.py for details.

Real-Time Safety Gate

Monitor sensor data quality in real-time — 1.44ms latency at 2000Hz:

from s2s_standard_v1_3 import RealTimeSafetyGate

gate = RealTimeSafetyGate(segment="forearm", strikes=3)

for ts_ns, accel, gyro in sensor_stream:
    is_safe, reason, cert = gate.push(ts_ns, accel, gyro)
    if not is_safe:
        print(f"UNSAFE: {reason}")
        # halt pipeline / alert operator / log event

States:

  • SAFE — SILVER or GOLD, data is physically trustworthy
  • DEGRADED — BRONZE, quality reduced but not dangerous
  • UNSAFE — 3 consecutive REJECTED windows, action required

Latency: 2.8ms per window at 2000Hz (1.1% CPU overhead). Three-strike logic prevents false triggers from single noise samples.

Roadmap — Layer 6: Semantic Reasoning

The current 7 layers certify that motion is physically real and visually consistent. Layer 6 adds semantic reasoning — bridging natural language intent to physics constraints:

User says:   "Feed the baby"
Layer 5:     sees spoon, bowl, baby face
Layer 6:     translates to physics constraints:
               jerk ≤ 50 m/s³  (gentle)
               speed ≤ 0.3 m/s
               trajectory toward face
             Layer 1 validates before robot executes

Requires LLM cross-attention to physical trajectory space. Planned after first external users.


Quick CLI

s2s-certify yourfile.csv
s2s-certify yourfile.csv --output report.json --segment forearm

Live demos

→ IMU Demo · → Physical AI Demo · → Live API · → Paper PDF · DOI: 10.5281/zenodo.18878307


Support this project

S2S is free for research. If it saved you time or helped your pipeline:

Crypto donations (any amount):

Network Address
USDT TRC20 TXRSTigHsk5QgAiuN2JJyByRuXmawVxdBP
ETH ERC20 0x6E7B9d022DC49bfc21C3011E15A0bF2868ec9c26
SOL 4gVZxGec3GefmkME4UXpn1CmrzvsiHguASqArxnSjSHY

Or open a GitHub Discussion — feedback is worth more than money at this stage.

License

BSL-1.1 — free for research and non-commercial use. Apache 2.0 from 2028-01-01.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

s2s_certify-1.6.4.tar.gz (119.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

s2s_certify-1.6.4-py3-none-any.whl (110.4 kB view details)

Uploaded Python 3

File details

Details for the file s2s_certify-1.6.4.tar.gz.

File metadata

  • Download URL: s2s_certify-1.6.4.tar.gz
  • Upload date:
  • Size: 119.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for s2s_certify-1.6.4.tar.gz
Algorithm Hash digest
SHA256 44ef752ba30983253b088984691dadf9e07602a1c33068a18b8a128eeb9d775a
MD5 bccd7a084a7a5bfa97dd92263a3439f5
BLAKE2b-256 52fe029c17bbfb87be7cf4de4a0fcc040f12650e32d7dd3e446b6b2f1a0026ba

See more details on using hashes here.

File details

Details for the file s2s_certify-1.6.4-py3-none-any.whl.

File metadata

  • Download URL: s2s_certify-1.6.4-py3-none-any.whl
  • Upload date:
  • Size: 110.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for s2s_certify-1.6.4-py3-none-any.whl
Algorithm Hash digest
SHA256 cc18f160a59758a7c258b31c56d26f454f434882c94654b99d949490254635fe
MD5 1fbe6e36e396e720f92c7677430f5e24
BLAKE2b-256 eff401ac169b7e6b37cfe301be5a27850315ab69b4ffbde39cafb4a559f9e338

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page