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.
from s2s_standard_v1_3 import PhysicsEngine
result = PhysicsEngine().certify(
imu_raw={
"timestamps_ns": timestamps,
"accel": accel_data, # [[x,y,z], ...] m/s²
"gyro": gyro_data, # [[x,y,z], ...] rad/s
},
segment="forearm"
)
print(result["tier"]) # GOLD / SILVER / BRONZE / REJECTED
print(result["physical_law_score"]) # 0–100
print(result["laws_passed"])
print(result["laws_failed"])
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 a different question. Not "does this data look human?" but "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.
Validated results across 6 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 |
Install
pip install s2s-certify
# With PyTorch ML integration:
pip install "s2s-certify[ml]"
# With Streamlit dashboard:
pip install "s2s-certify[dashboard]"
Zero runtime dependencies. Pure Python 3.9+.
Quick CLI
s2s-certify yourfile.csv
s2s-certify yourfile.csv --output report.json --segment forearm
Auto-detects columns: acc_x/acc_y/acc_z, ax/ay/az, gyro_x/gyro_y/gyro_z, gx/gy/gz, etc.
5-Layer Architecture
S2S implements a complete Physical AI pipeline from raw sensor data to natural language intent:
| Layer | What | Status |
|---|---|---|
| 1 | Physics certification — does data obey Newton? | ✅ Complete |
| 2 | Quality prediction — dual-head AI on certified data | ✅ Complete |
| 3 | Motion retrieval — text query → certified motion | ✅ Complete |
| 4 | Action sequencing — chain, fill gaps, recognize intent | ✅ Complete |
| 5 | Scenario understanding — video + language input | ❌ Planned |
Layer 1 — Physics Certification
7 biomechanical laws validated at runtime. Each law only runs when the required sensors are present — missing sensors do not penalise the score.
| 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 |
Body segment parameters
| Segment | I (kg·m²) | K (N·m/rad) | Tremor band (Hz) | Jerk check |
|---|---|---|---|---|
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 | skipped |
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 — Quality Prediction
Dual-head model trained on certified pairs:
from s2s_standard_v1_3.s2s_ml_interface import S2SFeatureExtractor, physics_loss
# 15-dim feature vector: 7 pass/fail + 7 scores + 1 overall
extractor = S2SFeatureExtractor(segment="forearm")
features = extractor(imu_raw)
# Physics-informed training loss
loss = task_loss + physics_loss(scores, lambda_phys=0.1)
# Formula: λ × mean(1 − score/100)
Results: quality prediction 72.2% accuracy, smoothness correlation r=0.941.
Layer 3 — Motion Retrieval
10,686 certified windows across 6 datasets, 64-dim embeddings.
# From experiments/step3_retrieval_v2.py
# "pick up cup" → returns nearest GOLD certified motions
# Ranking: semantic 0.30 + embedding cosine 0.25 + physics 0.25 + smoothness 0.15 + tier 0.05
Layer 4 — Action Sequencing
4a — Next action prediction
Trained on 21,896 consecutive certified window pairs from 5 datasets (NinaPro, Amputee, RoboTurk, PAMAP2, WESAD):
from experiments.layer4_sequence_model import predict_next
next_features = predict_next(current_13dim_features)
# mean correlation r=0.958 | smoothness r=0.927 | jerk r=0.958
4b — Gap filling
Given start and end keyframes, fills intermediate windows. Trained on 87,529 quadruplet samples at t=1/3, 1/2, 2/3:
from experiments.layer4b_gap_filling import fill_gap
intermediates = fill_gap(start_features, end_features, n_steps=3)
Results vs linear interpolation:
| 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 |
The neural network captures the non-linear bell-shaped velocity profile of human arm motion (Flash & Hogan 1985) that linear interpolation misses.
4c — Intent recognition
Maps motion sequences to natural language labels:
from experiments.layer4c_intent_recognition import query_by_text, classify_motion
# Text → motion
matches = query_by_text("pick up cup", top_k=5)
# Returns: "pick object" (0.484), "drinking" (0.411), "hand grasp" (0.287)
# Motion → intent
intent = classify_motion(motion_features, top_k=3)
Results: top-1 34.5%, top-3 60.2%, top-5 75.9% on 71 labels.
All 6 sensor certifiers
IMU — PhysicsEngine
from s2s_standard_v1_3 import PhysicsEngine
result = PhysicsEngine().certify(imu_raw={...}, segment="forearm")
EMG — EMGStreamCertifier
from s2s_standard_v1_3.s2s_emg_certify_v1_3 import EMGStreamCertifier
ec = EMGStreamCertifier(n_channels=8, sampling_hz=1000.0) # min 500Hz
cert = ec.push_frame(ts_ns, [ch0, ch1, ch2, ch3, ch4, ch5, ch6, ch7])
GOLD: SNR ≥ 20dB + burst fraction ≥ 5% (threshold = 3× baseline RMS).
PPG — PPGStreamCertifier
from s2s_standard_v1_3.s2s_ppg_certify_v1_3 import PPGStreamCertifier
pc = PPGStreamCertifier(n_channels=2, sampling_hz=100.0) # min 25Hz
cert = pc.push_frame(ts_ns, [red, ir])
print(cert["vitals"]["heart_rate_bpm"])
print(cert["vitals"]["hrv_rmssd_ms"])
print(cert["vitals"]["breathing_bpm"])
LiDAR — LiDARStreamCertifier
from s2s_standard_v1_3.s2s_lidar_certify_v1_3 import LiDARStreamCertifier
# 1D time-of-flight:
lc = LiDARStreamCertifier(mode='scalar', device_id='tof_01')
cert = lc.push_frame(ts_ns, [distance_m])
# 3D point cloud:
lc3d = LiDARStreamCertifier(mode='pointcloud', n_points_per_frame=360)
cert = lc3d.push_frame(ts_ns, [x0,y0,z0, x1,y1,z1, ...])
GOLD: variance ≥ 0.01m² AND frame delta ≥ 0.5mm. Synthetic: frame delta < 1e-9m.
Thermal — ThermalStreamCertifier
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) # 768 floats in °C
print(cert["human_presence"]["human_present"])
print(cert["human_presence"]["body_heat_fraction"])
Human detected: ≥5% pixels in 28–38.5°C. GOLD: ≥15% body pixels + spatial range ≥5°C + frame delta ≥0.05°C.
Multi-sensor Fusion — FusionCertifier
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)
fc.add_ppg_cert(ppg_cert)
fc.add_thermal_cert(thermal_cert)
fc.add_lidar_cert(lidar_cert)
result = fc.certify()
print(result["human_in_loop_score"]) # 0–100
fc.reset() # clear for reuse
Human-in-Loop score: 40pts stream quality + 40pts pairwise coherence + 20pts biological bonuses. Any SUSPECT_SYNTHETIC flag → score=0, REJECTED.
Real-time streaming
from s2s_standard_v1_3.s2s_stream_certify_v1_3 import StreamCertifier
import time
sc = StreamCertifier(
sensor_names=["accel_x","accel_y","accel_z","gyro_x","gyro_y","gyro_z"]
)
cert = sc.push_frame(ts_ns=time.time_ns(), values=[ax, ay, az, gx, gy, gz])
Or pipe from device:
python3 -m s2s_standard_v1_3.s2s_stream_certify_v1_3 --mode tcp --port 9876
REST API
python3 -m s2s_standard_v1_3.s2s_api_v1_3 --port 8080 \
--sign-key keys/server.private.pem \
--registry registry.json
| Method | Path | Description |
|---|---|---|
| GET | /health |
Health + active sessions |
| GET | /version |
Version + sensors |
| POST | /certify/imu |
Batch IMU certification |
| POST | /certify/emg |
Batch EMG certification |
| POST | /certify/lidar |
Batch LiDAR (scalar or pointcloud) |
| 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 |
| DELETE | /stream/{id} |
End session |
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)
python3 -m s2s_standard_v1_3.s2s_signing_v1_3 keygen --out keys/device_001
python3 -m s2s_standard_v1_3.s2s_signing_v1_3 verify cert.json --pubkey keys/device_001.public.pem
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")
Data ingestion
# Convert CSV to .s2s binary
python3 -m s2s_standard_v1_3.convert_to_s2s input.csv -o output.s2s \
--remove-nans \
--inject-jitter-stdns 4500 \
--sign-key keys/device_001.private.pem
# Batch certify .s2s files
python3 -m s2s_standard_v1_3.s2s_emg_certify_v1_3 data/*.s2s --out-json-dir certs/emg/
python3 -m s2s_standard_v1_3.s2s_ppg_certify_v1_3 data/*.s2s --out-json-dir certs/ppg/
Biological origin detection
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.7 = biological motor control
print(verdict["recommendation"]) # ACCEPT / REVIEW / REJECT
BFS = 0.3×(1/CV) + 0.4×(1−kurtosis_norm) + 0.3×(1−Hurst). Validated on all 10 NinaPro DB5 subjects.
Validated datasets
| Dataset | Hz | Device | Segment | Windows |
|---|---|---|---|---|
| NinaPro DB5 | 2000Hz | Forearm EMG+IMU | forearm | 9,552 |
| PAMAP2 | 100Hz | Body IMU (3 sensors) | forearm | 13,094 |
| UCI HAR | 50Hz | Waist IMU | walking | 10,299 |
| WISDM 2019 | 20Hz | Wrist phone | forearm | 46,946 |
| PhysioNet PTT-PPG | 500Hz | Wrist PPG+IMU | forearm | 1,164 |
| RoboTurk Open-X | 15Hz | 7-DOF robot arm | forearm | 901 |
| WESAD | 700Hz | Chest+Wrist IMU+BVP | upper_arm | 8,995 |
Project structure
s2s_standard_v1_3/
s2s_physics_v1_3.py ← PhysicsEngine — 7 laws, zero dependencies
s2s_emg_certify_v1_3.py ← EMG certifier (≥500Hz)
s2s_ppg_certify_v1_3.py ← PPG certifier — HR, HRV, breathing
s2s_lidar_certify_v1_3.py ← LiDAR (1D scalar + 3D pointcloud)
s2s_thermal_certify_v1_3.py ← Thermal — human body heat detection
s2s_fusion_v1_3.py ← 5-sensor fusion, Human-in-Loop score
s2s_stream_certify_v1_3.py ← Real-time streaming (stdin / TCP :9876)
s2s_api_v1_3.py ← REST API server (stdlib, zero deps)
s2s_signing_v1_3.py ← Ed25519 signing + HMAC-SHA256 fallback
s2s_registry_v1_3.py ← Device registry — trust tiers, revocation
s2s_ml_interface.py ← PyTorch Dataset, feature extractor, physics loss
convert_to_s2s.py ← CSV → .s2s binary
cli.py ← s2s-certify CLI entry point
constants.py ← TLV registry, tiers, sensor profiles
experiments/
layer4_sequence_model.py ← Layer 4a: next action prediction (r=0.958)
layer4b_gap_filling.py ← Layer 4b: gap filling (+5.5% vs linear)
layer4c_intent_recognition.py← Layer 4c: motion→intent (top-5 75.9%)
extract_sequences.py ← Extract consecutive certified pairs
extract_sequences_pamap2_wesad.py ← Add PAMAP2+WESAD to training data
step3_retrieval_v2.py ← Motion retrieval, semantic embeddings
level5_dualhead.py ← Dual-head quality+motion prediction
corruption_experiment.py ← Quality floor proof
results_layer4.json ← Layer 4a results
results_layer4b.json ← Layer 4b results
results_layer4c.json ← Layer 4c results
results_wesad_f1.json ← WESAD +3.1% F1 result
wesad_adapter.py ← WESAD certification (chest+wrist+BVP)
wesad_f1_benchmark.py ← F1 comparison certified vs all windows
s2s_pipeline.py ← NinaPro pipeline CLI
wisdm_adapter.py ← WISDM 2019 adapter
amputee_adapter.py ← EMG amputee adapter
s2s_dataset_adapter.py ← UCI HAR, PAMAP2, Berkeley MHAD adapter
tests/
test_physics_laws.py ← 110/110 tests passing
test_emg_ppg.py
test_fusion.py
Live demos
→ IMU Demo · → Physical AI Demo · → Live API
Paper
→ PDF · DOI: 10.5281/zenodo.18878307
License
BSL-1.1 — free for research and non-commercial use. Apache 2.0 from 2028-01-01.
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 s2s_certify-1.6.0.tar.gz.
File metadata
- Download URL: s2s_certify-1.6.0.tar.gz
- Upload date:
- Size: 95.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9385f5f0f6ec82266588914e1f58db7351da8d380e5bec85b7d3854da1e4bcb6
|
|
| MD5 |
3a8ab159c9c91872136f257d3fa260ca
|
|
| BLAKE2b-256 |
82b2cd44dcfe6ff818efa77ef5403add7692f6b58ecb1d029a59849f8ef078e4
|
File details
Details for the file s2s_certify-1.6.0-py3-none-any.whl.
File metadata
- Download URL: s2s_certify-1.6.0-py3-none-any.whl
- Upload date:
- Size: 92.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65305c0aa1b3f761c3f03f6e090314ec789c5193f4ca7109b55c96daca89d382
|
|
| MD5 |
d47263ed33de1c63b30b1e1d097b9d91
|
|
| BLAKE2b-256 |
d7c87601042b22edc7e064a29147fe5045dfe702b4f771858085babc5f45e62a
|