openphysicalai 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. openphysicalai-0.2.1/PKG-INFO +203 -0
  2. openphysicalai-0.2.1/README.md +185 -0
  3. openphysicalai-0.2.1/openphysicalai/__init__.py +9 -0
  4. openphysicalai-0.2.1/openphysicalai/budget.py +59 -0
  5. openphysicalai-0.2.1/openphysicalai/cli.py +115 -0
  6. openphysicalai-0.2.1/openphysicalai/injection.py +64 -0
  7. openphysicalai-0.2.1/openphysicalai/interfaces.py +47 -0
  8. openphysicalai-0.2.1/openphysicalai/perception.py +237 -0
  9. openphysicalai-0.2.1/openphysicalai/planners.py +159 -0
  10. openphysicalai-0.2.1/openphysicalai/profiler.py +226 -0
  11. openphysicalai-0.2.1/openphysicalai/render.py +124 -0
  12. openphysicalai-0.2.1/openphysicalai/report.py +39 -0
  13. openphysicalai-0.2.1/openphysicalai/runner.py +401 -0
  14. openphysicalai-0.2.1/openphysicalai/server.py +113 -0
  15. openphysicalai-0.2.1/openphysicalai/sim.py +312 -0
  16. openphysicalai-0.2.1/openphysicalai/skills.py +50 -0
  17. openphysicalai-0.2.1/openphysicalai/stats.py +15 -0
  18. openphysicalai-0.2.1/openphysicalai/store.py +36 -0
  19. openphysicalai-0.2.1/openphysicalai/tasks.py +124 -0
  20. openphysicalai-0.2.1/openphysicalai.egg-info/PKG-INFO +203 -0
  21. openphysicalai-0.2.1/openphysicalai.egg-info/SOURCES.txt +27 -0
  22. openphysicalai-0.2.1/openphysicalai.egg-info/dependency_links.txt +1 -0
  23. openphysicalai-0.2.1/openphysicalai.egg-info/entry_points.txt +2 -0
  24. openphysicalai-0.2.1/openphysicalai.egg-info/requires.txt +13 -0
  25. openphysicalai-0.2.1/openphysicalai.egg-info/top_level.txt +1 -0
  26. openphysicalai-0.2.1/pyproject.toml +23 -0
  27. openphysicalai-0.2.1/setup.cfg +4 -0
  28. openphysicalai-0.2.1/tests/test_core.py +25 -0
  29. openphysicalai-0.2.1/tests/test_sim.py +32 -0
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.4
2
+ Name: openphysicalai
3
+ Version: 0.2.1
4
+ Summary: OpenPhysicalAI Lab core: budget-aware, latency-coupled evaluation for Physical AI
5
+ License-Expression: Apache-2.0
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: mujoco>=3.1
9
+ Requires-Dist: numpy>=1.24
10
+ Requires-Dist: psutil>=5.9
11
+ Provides-Extra: sim
12
+ Requires-Dist: mujoco>=3.1; extra == "sim"
13
+ Provides-Extra: gpu
14
+ Requires-Dist: psutil; extra == "gpu"
15
+ Requires-Dist: nvidia-ml-py; extra == "gpu"
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest; extra == "dev"
18
+
19
+ <div align="center">
20
+
21
+ # 🤖 OpenPhysicalAI Lab (`v0.2.1`)
22
+
23
+ **Real-Time Embodied AI Simulation, Closed-Loop Failure Recovery & Hardware Budget Benchmarking — Engineered to Run Inside 4 GB VRAM.**
24
+
25
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
26
+ [![Phase-1 Gate](https://img.shields.io/badge/Phase--1_Gate-200%2F200_(100%25)-brightgreen.svg)](#verified-benchmarks--scientific-results)
27
+ [![MuJoCo](https://img.shields.io/badge/MuJoCo-3.16.0_3D_GPU-orange.svg)](#system-architecture)
28
+ [![Hardware Tier](https://img.shields.io/badge/Verified_Tier-OPAI--4G_(RTX_3050_4GB)-76b900.svg)](#community-hardware-leaderboard)
29
+ [![Platform](https://img.shields.io/badge/Platform-Windows_11_%7C_Linux_%7C_macOS-informational.svg)](#quick-start)
30
+
31
+ </div>
32
+
33
+ ---
34
+
35
+ ## ⚡ Why OpenPhysicalAI Lab?
36
+
37
+ Most embodied AI frameworks assume you have a 24 GB RTX 4090 or an 80 GB datacenter GPU. **OpenPhysicalAI Lab** proves that deterministic 3D physics, vision perception, local LLM task planning, and closed-loop failure recovery can run **entirely locally on a 4 GB VRAM laptop (`OPAI-4G`)**.
38
+
39
+ Unlike static benchmarks that pause the physics engine while the LLM thinks, OpenPhysicalAI Lab enforces **Real-Time Mode**: the physical world keeps moving while the planner reasons, exposing the true **Latency Tax** of slow models and measuring capability under strict **VRAM, System RAM, Latency, and Energy (Joule) Budget Cards**.
40
+
41
+ ---
42
+
43
+ ## 🏗️ System Architecture
44
+
45
+ ```mermaid
46
+ flowchart LR
47
+ subgraph Sim["MuJoCo 3.16 Real-Time Engine (432 FPS)"]
48
+ World["5-DOF Arm + Parallel Gripper\nTable, Cubes, Conveyor"]
49
+ Inject["Seeded Failure Injector\n(Slip, Displacement, Noise)"]
50
+ Render["3D OpenGL GPU Renderer\n(Shadows + Orthographic Vision)"]
51
+ end
52
+
53
+ subgraph Percep["Perception & Kinematics"]
54
+ Vision["Vision / Oracle Detector\n(~1 mm Accuracy)"]
55
+ Kalman["Alpha-Beta Velocity Tracker\n(Latency Lead Compensation)"]
56
+ end
57
+
58
+ subgraph Agent["Closed-Loop Recovery Agent"]
59
+ Verifier["Tiered Verifiers\n(V0 Oracle | V1 Proprio | V2 Camera)"]
60
+ Planner["Local Ollama LLM Planner\n(Gemma 2 2B / Qwen3 4B JSON)"]
61
+ end
62
+
63
+ subgraph Telemetry["NVML & Budget Auditor"]
64
+ Profiler["NVML + Ollama /api/ps\n(VRAM, RAM, Watts, Temp)"]
65
+ Card["SQLite + Signed\nBudget Card (.md / .csv)"]
66
+ end
67
+
68
+ World --> Inject --> Render --> Vision --> Kalman
69
+ Kalman --> Verifier --> Planner
70
+ Planner -- "Hold Policy Advances World by Δt_plan" --> World
71
+ Sim -.-> Profiler --> Card
72
+ Agent -.-> Profiler
73
+ ```
74
+
75
+ ---
76
+
77
+ ## ✅ What Is Real & Verified
78
+
79
+ | Subsystem | Implementation Status |
80
+ |---|---|
81
+ | **Physics Engine** | Real MuJoCo 3.16.0: 5-DOF robotic arm, parallel friction gripper, table, multi-size cubes, open-top container, and kinematic moving conveyor. Analytic IK + Cartesian skill primitives. |
82
+ | **3D GPU Rendering** | Native `mujoco.Renderer` 3D perspective camera (distance 0.92 m, elevation -26°, azimuth 135°) with directional shadow mapping (~432 FPS / 2.3 ms/frame on RTX 3050 Laptop GPU) + 1 mm accurate orthographic vision pipeline. |
83
+ | **Phase-1 Gate** | Deterministic scripted pick-and-place passes **200/200 random scenes (100.0%)** (`python python/gate1.py`). |
84
+ | **Benchmark Tasks** | 5 seeded, cross-process deterministic tasks: `pick_place`, `smallest`, spatial (`left_of`), `multi_object`, and `dynamic` (moving conveyor cube). |
85
+ | **Local LLM Planners** | Rule-based baseline + Ollama local LLMs (`gemma2:2b`, `qwen3:4b-instruct-2507-q4_K_M`) with strict JSON-schema output and kinematic action validation. |
86
+ | **Agent Architectures** | Open-Loop (blind execution), Closed-Loop (abort on anomaly), and Recovery Agent (active failure detection, diagnosis, re-observation, and replanning). |
87
+ | **Hardware Profiler** | Tracks process-tree RSS, system RAM, NVML Compute/Graphics VRAM, Ollama `/api/ps` VRAM, GPU power (W), energy per episode (J), core temperature (°C), and thermal throttling. |
88
+
89
+ ---
90
+
91
+ ## 📊 Verified Benchmarks & Scientific Results
92
+
93
+ All benchmarks below were executed on an HP Victus 15 (**OPAI-4G Reference Tier**: NVIDIA GeForce RTX 3050 Laptop GPU 4.0 GB VRAM, 16 GB System RAM, Windows 11, MuJoCo 3.16.0).
94
+
95
+ ### 1. Local LLM Planner Speed & Footprint (OPAI-4G Tier)
96
+
97
+ | Local Model (Ollama) | Weights Size | Peak Device VRAM | Warm Planning Latency | Throughput | Schema Compliance |
98
+ ### 1. Local LLM Planner Speed & Footprint (OPAI-4G Tier, N=20 per Model, Real-Time Mode)
99
+
100
+ All models evaluated under identical real-time closed-loop pick-and-place tasks on an NVIDIA GeForce RTX 3050 Laptop GPU (4.0 GB VRAM):
101
+
102
+ | Local Model (Ollama) | Weights Size | Peak Device VRAM | Warm Planning Latency (p50 / p95) | Throughput | TSR (95% CI, N=20) | Notes |
103
+ |---|---|---|---|---|---|---|
104
+ | **`qwen2.5:3b`** | 1.9 GB | 2.57 GB | **469 ms / 493 ms** | 70.6 tok/s | **100.0%** (83.9%–100.0%) | Fastest response, reliable spatial parsing |
105
+ | **`gemma2:2b`** | 1.6 GB | 2.36 GB | **715 ms / 751 ms** | 69.5 tok/s | **100.0%** (83.9%–100.0%) | Consistent schema compliance & low footprint |
106
+ | **`llama3.2:1b`** | 1.3 GB | 1.97 GB | **577 ms / 608 ms** | 99.9 tok/s | **0.0%** (0.0%–16.1%) | Fast generation, but frequent JSON/action schema violations |
107
+
108
+ ### 2. Verifier Honesty Benchmark (Moderate Perturbation, Real-Time Mode, N=100 per Cell)
109
+
110
+ Evaluated with Rule-Based Recovery Agent under moderate failure injection (slip probability $p=0.25$, displacement, and wrong placement). Raw JSON exported in `verifier_benchmark_summary_N100.json`:
111
+
112
+ | Agent | Verifier Level | Mode | TSR (95% CI, N=100) | Injections | Detect Rate | Recover Rate | Missed Failures | False Alarms | Planning p95 |
113
+ |---|---|---|---|---|---|---|---|---|---|
114
+ | **Recovery** | **V0 (Simulator Oracle)** | realtime | **74.0%** (64.6%–81.6%) | 138 | 97.1% | 52.2% | **0.0%** | 0.0% | 0.03 ms |
115
+ | **Recovery** | **V1 (Proprioception Only)** | realtime | **68.0%** (58.3%–76.3%) | 124 | 87.9% | 51.4% | **3.7%** | 0.0% | 0.03 ms |
116
+ | **Recovery** | **V2 (Proprio + Camera Vision)**| realtime | **73.0%** (63.6%–80.7%) | 137 | 96.4% | 51.5% | **0.3%** | 0.0% | 0.03 ms |
117
+
118
+ > [!IMPORTANT]
119
+ > **Key Verifier Finding**: Proprioceptive verification alone (`V1`) suffers a **3.7% missed-failure rate** because joint sensors cannot detect when a placed object lands outside the container boundary (`wrong_placement`). Vision verification (`V2`) closes this gap, reducing missed failures to **0.3%**, approaching oracle upper bound (`V0`).
120
+
121
+ ### 3. The Latency Tax on Dynamic Conveyor Tasks
122
+
123
+ Measured on the `dynamic` task with moving cube at $0.02\text{ m/s}$, single-frame perception, without velocity lead compensation:
124
+
125
+ | Agent Architecture | Verifier | Execution Mode | Planner Delay ($\Delta t$) | TSR (95% CI, N=50) | Physical Mechanism |
126
+ |---|---|---|---|---|---|
127
+ | **Closed-Loop (Rule)** | V1 | sync | 0 ms | **38.0%** (25.9%–51.8%) | Physics paused while planning |
128
+ | **Closed-Loop (Rule)** | V1 | realtime | 0 ms | **38.0%** (25.9%–51.8%) | Real-time baseline |
129
+ | **Closed-Loop (Rule)** | V1 | realtime | 1,000 ms (1.0 s) | **0.0%** (0.0%–7.1%) | Cube shifts ~20 mm past gripper capture zone |
130
+ | **Closed-Loop (Rule)** | V1 | realtime | 2,000 ms (2.0 s) | **0.0%** (0.0%–7.1%) | Stale observation causes complete grasp miss |
131
+ | **Recovery (Velocity-Lead)**| V1 | realtime | 1,000 ms (1.0 s) | **100.0%** (72.2%–100.0%) | Forward-projected intercept overcomes latency tax |
132
+
133
+ > [!NOTE]
134
+ > Physical AI agents relying purely on reactive perception fail when planner latency exceeds the physical dynamic timescale. Latency compensation (velocity projection $\hat{v} \cdot (\tau_{\text{plan}} + \tau_{\text{travel}})$) restores 100% reliability even at multi-second planning delays.
135
+
136
+ ---
137
+
138
+ ## 🚀 Quick Start
139
+
140
+ ### 1. One-Click Windows Launch (Desktop App)
141
+ Clone the repository and double-click `start-app.bat`, or run from terminal:
142
+
143
+ ```bash
144
+ git clone https://github.com/VedantJadhav701/OpenphysicalAI-lab.git
145
+ cd OpenphysicalAI-lab
146
+
147
+ # Optional: activate your existing Conda environment (auto-detected by main.js)
148
+ conda activate thermo_agent
149
+
150
+ npm install
151
+ npm start
152
+ ```
153
+
154
+ ### 2. Pull the Recommended 4GB-Tier Local LLM Planner
155
+
156
+ ```bash
157
+ ollama pull gemma2:2b
158
+
159
+ # Or for the 4B Qwen3 planner:
160
+ ollama pull qwen3:4b-instruct-2507-q4_K_M
161
+ ```
162
+
163
+ ### 3. Headless CLI & Phase-1 Gate Verification
164
+
165
+ ```bash
166
+ python python/gate1.py
167
+ pytest python/tests
168
+ python -m openphysicalai.cli run --task pick_place --perception vision --perturb moderate --verifier V2 --episodes 50
169
+ ```
170
+
171
+ ---
172
+
173
+ ## 🏆 Community Hardware Leaderboard
174
+
175
+ Run the benchmark suite on your machine, generate a signed Budget Card (`budget_card_run_*.md`), and submit a Pull Request to add your hardware configuration below!
176
+
177
+ | Contributor | Device / GPU | Tier Class | Planner Model | Peak Device VRAM | Planning p95 | Recovery TSR | Energy / Ep | Budget Status |
178
+ |---|---|---|---|---|---|---|---|---|
179
+ | **@VedantJadhav701** | HP Victus 15 (RTX 3050 4GB, 16GB RAM) | `OPAI-4G` | `gemma2:2b` | 2.10 GB | 698 ms | 100.0% | ~92 J | ✅ PASS |
180
+ | **@VedantJadhav701** | HP Victus 15 (RTX 3050 4GB, 16GB RAM) | `OPAI-4G` | `qwen3:4b-q4_K_M` | 2.53 GB | 1344 ms | 100.0% | 133.6 J | ✅ PASS |
181
+ | *Your GitHub Handle* | *Add your GPU / Apple Silicon / CPU* | *OPAI-4G/8G/16G* | *Any Ollama Model* | *Measured GB* | *Measured ms* | *Measured %* | *Measured J* | *Submit PR!* |
182
+
183
+ ---
184
+
185
+ ## 🗂️ Repository Layout
186
+
187
+ ```text
188
+ ├── main.js / preload.js # Electron main process, Conda auto-discovery, single-instance lock
189
+ ├── start-app.bat # One-click Windows launcher
190
+ ├── src/ # iOS-style Electron frontend UI
191
+ ├── python/
192
+ │ ├── gate1.py # 200-scene deterministic Phase-1 physics gate
193
+ │ ├── tests/ # Pytest unit & integration test suite
194
+ │ └── openphysicalai/ # Core engine: sim, tasks, skills, perception, render (3D GPU),
195
+ │ # planners, injection, runner, profiler, budget, store, cli
196
+ └── docs/ # Architectural roadmap & experimental specifications
197
+ ```
198
+
199
+ ---
200
+
201
+ ## 📄 License
202
+
203
+ Licensed under the Apache License 2.0 — see [LICENSE](LICENSE) for full details.
@@ -0,0 +1,185 @@
1
+ <div align="center">
2
+
3
+ # 🤖 OpenPhysicalAI Lab (`v0.2.1`)
4
+
5
+ **Real-Time Embodied AI Simulation, Closed-Loop Failure Recovery & Hardware Budget Benchmarking — Engineered to Run Inside 4 GB VRAM.**
6
+
7
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
8
+ [![Phase-1 Gate](https://img.shields.io/badge/Phase--1_Gate-200%2F200_(100%25)-brightgreen.svg)](#verified-benchmarks--scientific-results)
9
+ [![MuJoCo](https://img.shields.io/badge/MuJoCo-3.16.0_3D_GPU-orange.svg)](#system-architecture)
10
+ [![Hardware Tier](https://img.shields.io/badge/Verified_Tier-OPAI--4G_(RTX_3050_4GB)-76b900.svg)](#community-hardware-leaderboard)
11
+ [![Platform](https://img.shields.io/badge/Platform-Windows_11_%7C_Linux_%7C_macOS-informational.svg)](#quick-start)
12
+
13
+ </div>
14
+
15
+ ---
16
+
17
+ ## ⚡ Why OpenPhysicalAI Lab?
18
+
19
+ Most embodied AI frameworks assume you have a 24 GB RTX 4090 or an 80 GB datacenter GPU. **OpenPhysicalAI Lab** proves that deterministic 3D physics, vision perception, local LLM task planning, and closed-loop failure recovery can run **entirely locally on a 4 GB VRAM laptop (`OPAI-4G`)**.
20
+
21
+ Unlike static benchmarks that pause the physics engine while the LLM thinks, OpenPhysicalAI Lab enforces **Real-Time Mode**: the physical world keeps moving while the planner reasons, exposing the true **Latency Tax** of slow models and measuring capability under strict **VRAM, System RAM, Latency, and Energy (Joule) Budget Cards**.
22
+
23
+ ---
24
+
25
+ ## 🏗️ System Architecture
26
+
27
+ ```mermaid
28
+ flowchart LR
29
+ subgraph Sim["MuJoCo 3.16 Real-Time Engine (432 FPS)"]
30
+ World["5-DOF Arm + Parallel Gripper\nTable, Cubes, Conveyor"]
31
+ Inject["Seeded Failure Injector\n(Slip, Displacement, Noise)"]
32
+ Render["3D OpenGL GPU Renderer\n(Shadows + Orthographic Vision)"]
33
+ end
34
+
35
+ subgraph Percep["Perception & Kinematics"]
36
+ Vision["Vision / Oracle Detector\n(~1 mm Accuracy)"]
37
+ Kalman["Alpha-Beta Velocity Tracker\n(Latency Lead Compensation)"]
38
+ end
39
+
40
+ subgraph Agent["Closed-Loop Recovery Agent"]
41
+ Verifier["Tiered Verifiers\n(V0 Oracle | V1 Proprio | V2 Camera)"]
42
+ Planner["Local Ollama LLM Planner\n(Gemma 2 2B / Qwen3 4B JSON)"]
43
+ end
44
+
45
+ subgraph Telemetry["NVML & Budget Auditor"]
46
+ Profiler["NVML + Ollama /api/ps\n(VRAM, RAM, Watts, Temp)"]
47
+ Card["SQLite + Signed\nBudget Card (.md / .csv)"]
48
+ end
49
+
50
+ World --> Inject --> Render --> Vision --> Kalman
51
+ Kalman --> Verifier --> Planner
52
+ Planner -- "Hold Policy Advances World by Δt_plan" --> World
53
+ Sim -.-> Profiler --> Card
54
+ Agent -.-> Profiler
55
+ ```
56
+
57
+ ---
58
+
59
+ ## ✅ What Is Real & Verified
60
+
61
+ | Subsystem | Implementation Status |
62
+ |---|---|
63
+ | **Physics Engine** | Real MuJoCo 3.16.0: 5-DOF robotic arm, parallel friction gripper, table, multi-size cubes, open-top container, and kinematic moving conveyor. Analytic IK + Cartesian skill primitives. |
64
+ | **3D GPU Rendering** | Native `mujoco.Renderer` 3D perspective camera (distance 0.92 m, elevation -26°, azimuth 135°) with directional shadow mapping (~432 FPS / 2.3 ms/frame on RTX 3050 Laptop GPU) + 1 mm accurate orthographic vision pipeline. |
65
+ | **Phase-1 Gate** | Deterministic scripted pick-and-place passes **200/200 random scenes (100.0%)** (`python python/gate1.py`). |
66
+ | **Benchmark Tasks** | 5 seeded, cross-process deterministic tasks: `pick_place`, `smallest`, spatial (`left_of`), `multi_object`, and `dynamic` (moving conveyor cube). |
67
+ | **Local LLM Planners** | Rule-based baseline + Ollama local LLMs (`gemma2:2b`, `qwen3:4b-instruct-2507-q4_K_M`) with strict JSON-schema output and kinematic action validation. |
68
+ | **Agent Architectures** | Open-Loop (blind execution), Closed-Loop (abort on anomaly), and Recovery Agent (active failure detection, diagnosis, re-observation, and replanning). |
69
+ | **Hardware Profiler** | Tracks process-tree RSS, system RAM, NVML Compute/Graphics VRAM, Ollama `/api/ps` VRAM, GPU power (W), energy per episode (J), core temperature (°C), and thermal throttling. |
70
+
71
+ ---
72
+
73
+ ## 📊 Verified Benchmarks & Scientific Results
74
+
75
+ All benchmarks below were executed on an HP Victus 15 (**OPAI-4G Reference Tier**: NVIDIA GeForce RTX 3050 Laptop GPU 4.0 GB VRAM, 16 GB System RAM, Windows 11, MuJoCo 3.16.0).
76
+
77
+ ### 1. Local LLM Planner Speed & Footprint (OPAI-4G Tier)
78
+
79
+ | Local Model (Ollama) | Weights Size | Peak Device VRAM | Warm Planning Latency | Throughput | Schema Compliance |
80
+ ### 1. Local LLM Planner Speed & Footprint (OPAI-4G Tier, N=20 per Model, Real-Time Mode)
81
+
82
+ All models evaluated under identical real-time closed-loop pick-and-place tasks on an NVIDIA GeForce RTX 3050 Laptop GPU (4.0 GB VRAM):
83
+
84
+ | Local Model (Ollama) | Weights Size | Peak Device VRAM | Warm Planning Latency (p50 / p95) | Throughput | TSR (95% CI, N=20) | Notes |
85
+ |---|---|---|---|---|---|---|
86
+ | **`qwen2.5:3b`** | 1.9 GB | 2.57 GB | **469 ms / 493 ms** | 70.6 tok/s | **100.0%** (83.9%–100.0%) | Fastest response, reliable spatial parsing |
87
+ | **`gemma2:2b`** | 1.6 GB | 2.36 GB | **715 ms / 751 ms** | 69.5 tok/s | **100.0%** (83.9%–100.0%) | Consistent schema compliance & low footprint |
88
+ | **`llama3.2:1b`** | 1.3 GB | 1.97 GB | **577 ms / 608 ms** | 99.9 tok/s | **0.0%** (0.0%–16.1%) | Fast generation, but frequent JSON/action schema violations |
89
+
90
+ ### 2. Verifier Honesty Benchmark (Moderate Perturbation, Real-Time Mode, N=100 per Cell)
91
+
92
+ Evaluated with Rule-Based Recovery Agent under moderate failure injection (slip probability $p=0.25$, displacement, and wrong placement). Raw JSON exported in `verifier_benchmark_summary_N100.json`:
93
+
94
+ | Agent | Verifier Level | Mode | TSR (95% CI, N=100) | Injections | Detect Rate | Recover Rate | Missed Failures | False Alarms | Planning p95 |
95
+ |---|---|---|---|---|---|---|---|---|---|
96
+ | **Recovery** | **V0 (Simulator Oracle)** | realtime | **74.0%** (64.6%–81.6%) | 138 | 97.1% | 52.2% | **0.0%** | 0.0% | 0.03 ms |
97
+ | **Recovery** | **V1 (Proprioception Only)** | realtime | **68.0%** (58.3%–76.3%) | 124 | 87.9% | 51.4% | **3.7%** | 0.0% | 0.03 ms |
98
+ | **Recovery** | **V2 (Proprio + Camera Vision)**| realtime | **73.0%** (63.6%–80.7%) | 137 | 96.4% | 51.5% | **0.3%** | 0.0% | 0.03 ms |
99
+
100
+ > [!IMPORTANT]
101
+ > **Key Verifier Finding**: Proprioceptive verification alone (`V1`) suffers a **3.7% missed-failure rate** because joint sensors cannot detect when a placed object lands outside the container boundary (`wrong_placement`). Vision verification (`V2`) closes this gap, reducing missed failures to **0.3%**, approaching oracle upper bound (`V0`).
102
+
103
+ ### 3. The Latency Tax on Dynamic Conveyor Tasks
104
+
105
+ Measured on the `dynamic` task with moving cube at $0.02\text{ m/s}$, single-frame perception, without velocity lead compensation:
106
+
107
+ | Agent Architecture | Verifier | Execution Mode | Planner Delay ($\Delta t$) | TSR (95% CI, N=50) | Physical Mechanism |
108
+ |---|---|---|---|---|---|
109
+ | **Closed-Loop (Rule)** | V1 | sync | 0 ms | **38.0%** (25.9%–51.8%) | Physics paused while planning |
110
+ | **Closed-Loop (Rule)** | V1 | realtime | 0 ms | **38.0%** (25.9%–51.8%) | Real-time baseline |
111
+ | **Closed-Loop (Rule)** | V1 | realtime | 1,000 ms (1.0 s) | **0.0%** (0.0%–7.1%) | Cube shifts ~20 mm past gripper capture zone |
112
+ | **Closed-Loop (Rule)** | V1 | realtime | 2,000 ms (2.0 s) | **0.0%** (0.0%–7.1%) | Stale observation causes complete grasp miss |
113
+ | **Recovery (Velocity-Lead)**| V1 | realtime | 1,000 ms (1.0 s) | **100.0%** (72.2%–100.0%) | Forward-projected intercept overcomes latency tax |
114
+
115
+ > [!NOTE]
116
+ > Physical AI agents relying purely on reactive perception fail when planner latency exceeds the physical dynamic timescale. Latency compensation (velocity projection $\hat{v} \cdot (\tau_{\text{plan}} + \tau_{\text{travel}})$) restores 100% reliability even at multi-second planning delays.
117
+
118
+ ---
119
+
120
+ ## 🚀 Quick Start
121
+
122
+ ### 1. One-Click Windows Launch (Desktop App)
123
+ Clone the repository and double-click `start-app.bat`, or run from terminal:
124
+
125
+ ```bash
126
+ git clone https://github.com/VedantJadhav701/OpenphysicalAI-lab.git
127
+ cd OpenphysicalAI-lab
128
+
129
+ # Optional: activate your existing Conda environment (auto-detected by main.js)
130
+ conda activate thermo_agent
131
+
132
+ npm install
133
+ npm start
134
+ ```
135
+
136
+ ### 2. Pull the Recommended 4GB-Tier Local LLM Planner
137
+
138
+ ```bash
139
+ ollama pull gemma2:2b
140
+
141
+ # Or for the 4B Qwen3 planner:
142
+ ollama pull qwen3:4b-instruct-2507-q4_K_M
143
+ ```
144
+
145
+ ### 3. Headless CLI & Phase-1 Gate Verification
146
+
147
+ ```bash
148
+ python python/gate1.py
149
+ pytest python/tests
150
+ python -m openphysicalai.cli run --task pick_place --perception vision --perturb moderate --verifier V2 --episodes 50
151
+ ```
152
+
153
+ ---
154
+
155
+ ## 🏆 Community Hardware Leaderboard
156
+
157
+ Run the benchmark suite on your machine, generate a signed Budget Card (`budget_card_run_*.md`), and submit a Pull Request to add your hardware configuration below!
158
+
159
+ | Contributor | Device / GPU | Tier Class | Planner Model | Peak Device VRAM | Planning p95 | Recovery TSR | Energy / Ep | Budget Status |
160
+ |---|---|---|---|---|---|---|---|---|
161
+ | **@VedantJadhav701** | HP Victus 15 (RTX 3050 4GB, 16GB RAM) | `OPAI-4G` | `gemma2:2b` | 2.10 GB | 698 ms | 100.0% | ~92 J | ✅ PASS |
162
+ | **@VedantJadhav701** | HP Victus 15 (RTX 3050 4GB, 16GB RAM) | `OPAI-4G` | `qwen3:4b-q4_K_M` | 2.53 GB | 1344 ms | 100.0% | 133.6 J | ✅ PASS |
163
+ | *Your GitHub Handle* | *Add your GPU / Apple Silicon / CPU* | *OPAI-4G/8G/16G* | *Any Ollama Model* | *Measured GB* | *Measured ms* | *Measured %* | *Measured J* | *Submit PR!* |
164
+
165
+ ---
166
+
167
+ ## 🗂️ Repository Layout
168
+
169
+ ```text
170
+ ├── main.js / preload.js # Electron main process, Conda auto-discovery, single-instance lock
171
+ ├── start-app.bat # One-click Windows launcher
172
+ ├── src/ # iOS-style Electron frontend UI
173
+ ├── python/
174
+ │ ├── gate1.py # 200-scene deterministic Phase-1 physics gate
175
+ │ ├── tests/ # Pytest unit & integration test suite
176
+ │ └── openphysicalai/ # Core engine: sim, tasks, skills, perception, render (3D GPU),
177
+ │ # planners, injection, runner, profiler, budget, store, cli
178
+ └── docs/ # Architectural roadmap & experimental specifications
179
+ ```
180
+
181
+ ---
182
+
183
+ ## 📄 License
184
+
185
+ Licensed under the Apache License 2.0 — see [LICENSE](LICENSE) for full details.
@@ -0,0 +1,9 @@
1
+ """OpenPhysicalAI Lab core (early scaffold).
2
+
3
+ Interfaces and budget logic only. MuJoCo backend, scheduler and real policies
4
+ arrive in Phase 1+ (see docs/OpenPhysicalAI_Lab_Plan_v3.md).
5
+ """
6
+ __version__ = "0.2.1"
7
+
8
+ from .budget import Budget, BudgetCheck, evaluate_budget # noqa: F401
9
+ from .stats import wilson_interval # noqa: F401
@@ -0,0 +1,59 @@
1
+ """Budget contract: separate caps for process-attributed and device-wide usage."""
2
+ from __future__ import annotations
3
+
4
+ from dataclasses import dataclass, field
5
+ from typing import Dict, List, Optional
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class Budget:
10
+ vram_process_peak_gb: float = 3.2
11
+ vram_device_peak_gb: float = 3.8
12
+ ram_process_peak_gb: float = 8.0
13
+ ram_system_peak_gb: float = 14.0
14
+ planning_ms_p95: float = 2500.0
15
+ profile: str = "standard"
16
+
17
+
18
+ @dataclass
19
+ class BudgetCheck:
20
+ name: str
21
+ value: Optional[float]
22
+ cap: float
23
+ ok: bool
24
+ note: str = ""
25
+
26
+
27
+ @dataclass
28
+ class BudgetResult:
29
+ passed: bool
30
+ checks: List[BudgetCheck] = field(default_factory=list)
31
+
32
+
33
+ def evaluate_budget(budget: Budget, observed: Dict[str, Optional[float]], not_applicable: tuple = ()) -> BudgetResult:
34
+ """Compare observed peaks to caps. A missing observation is a failure of measurement, not a pass.
35
+ `not_applicable` lists keys that do not apply on this machine (e.g. VRAM caps on a CPU-only machine)."""
36
+ spec = [
37
+ ("vram_process_peak_gb", budget.vram_process_peak_gb),
38
+ ("vram_device_peak_gb", budget.vram_device_peak_gb),
39
+ ("ram_process_peak_gb", budget.ram_process_peak_gb),
40
+ ("ram_system_peak_gb", budget.ram_system_peak_gb),
41
+ ("planning_ms_p95", budget.planning_ms_p95),
42
+ ]
43
+ checks: List[BudgetCheck] = []
44
+ for name, cap in spec:
45
+ v = observed.get(name)
46
+ if name in not_applicable:
47
+ checks.append(BudgetCheck(name, None, cap, True, "not applicable"))
48
+ elif v is None:
49
+ checks.append(BudgetCheck(name, None, cap, False, "not measured"))
50
+ else:
51
+ checks.append(BudgetCheck(name, float(v), cap, float(v) <= cap))
52
+ return BudgetResult(all(c.ok for c in checks), checks)
53
+
54
+
55
+ PROFILES = {
56
+ "relaxed": Budget(3.2, 3.8, 8.0, 14.0, 4000.0, "relaxed"),
57
+ "standard": Budget(3.2, 3.8, 8.0, 14.0, 2500.0, "standard"),
58
+ "strict": Budget(3.2, 3.8, 8.0, 14.0, 500.0, "strict"),
59
+ }
@@ -0,0 +1,115 @@
1
+ """opai CLI (scaffold): `opai profile`, `opai check-budget`."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+ import platform
7
+ import shutil
8
+ import subprocess
9
+ import sys
10
+
11
+ from . import __version__
12
+ from .budget import Budget, evaluate_budget
13
+ from .profiler import gpu_snapshot
14
+
15
+
16
+ def cmd_profile(_args) -> int:
17
+ info = {
18
+ "version": __version__,
19
+ "os": platform.platform(),
20
+ "python": sys.version.split()[0],
21
+ "gpu": gpu_snapshot(),
22
+ }
23
+ print(json.dumps(info, indent=2))
24
+ return 0
25
+
26
+
27
+ def cmd_doctor(_args) -> int:
28
+ import psutil
29
+ g = gpu_snapshot()
30
+ mem = psutil.virtual_memory()
31
+ cls = "CPU-only"
32
+ if g:
33
+ t = g["total_gb"]
34
+ cls = "OPAI-2G" if t <= 3 else "OPAI-4G" if t <= 6 else "OPAI-8G" if t <= 12 else "OPAI-16G"
35
+ doc = {
36
+ "version": __version__,
37
+ "platform": platform.platform(),
38
+ "python": sys.version.split()[0],
39
+ "processor": platform.processor(),
40
+ "cpu_count_physical": psutil.cpu_count(logical=False),
41
+ "cpu_count_logical": psutil.cpu_count(logical=True),
42
+ "ram_total_gb": round(mem.total / (1024**3), 2),
43
+ "ram_available_gb": round(mem.available / (1024**3), 2),
44
+ "hardware_class": cls,
45
+ "gpu": g,
46
+ }
47
+ print(json.dumps(doc, indent=2))
48
+ return 0
49
+
50
+
51
+ def cmd_check_budget(args) -> int:
52
+ observed = json.loads(args.observed)
53
+ res = evaluate_budget(Budget(), observed)
54
+ print("PASS" if res.passed else "FAIL")
55
+ for c in res.checks:
56
+ print(f" {'ok ' if c.ok else 'BAD'} {c.name}: {c.value} / {c.cap} {c.note}")
57
+ return 0 if res.passed else 1
58
+
59
+
60
+ def cmd_run(args) -> int:
61
+ from .report import budget_card
62
+ from .runner import RunConfig, run
63
+ cfg_dict = {k: v for k, v in vars(args).items() if k not in ("cmd", "fn", "export_json") and v is not None}
64
+ cfg = RunConfig.from_dict(cfg_dict)
65
+ cfg.frames = False
66
+
67
+ reproduce_cmd = (
68
+ f"opai run --task {cfg.task} --policy {cfg.policy} --agent {cfg.agent} "
69
+ f"--perception {cfg.perception} --verifier {cfg.verifier} --perturb {cfg.perturb} "
70
+ f"--mode {cfg.mode} --budget {cfg.budget} --episodes {cfg.episodes} --seed {cfg.seed}"
71
+ )
72
+
73
+ def emit(e):
74
+ if e.get("event") == "progress" and e["done"] % 10 == 0:
75
+ print(f" episode {e['done']}/{e['total']} successes {e['successes']}", file=sys.stderr)
76
+
77
+ res = run(cfg, emit=emit)
78
+ res["reproduce_command"] = reproduce_cmd
79
+ card_text = budget_card(res)
80
+ print(card_text)
81
+ print(f"\nReproduce command:\n {reproduce_cmd}\n")
82
+
83
+ if getattr(args, "export_json", None):
84
+ out_path = args.export_json
85
+ with open(out_path, "w") as f:
86
+ json.dump(res, f, indent=2)
87
+ print(f"Exported raw run data to {out_path}")
88
+
89
+ return 0
90
+
91
+
92
+ def main(argv=None) -> int:
93
+ p = argparse.ArgumentParser(prog="opai")
94
+ sub = p.add_subparsers(dest="cmd", required=True)
95
+ sub.add_parser("profile").set_defaults(fn=cmd_profile)
96
+ sub.add_parser("doctor", help="inspect host hardware, NVML, and budget class").set_defaults(fn=cmd_doctor)
97
+ cb = sub.add_parser("check-budget")
98
+ cb.add_argument("observed", help='JSON, e.g. \'{"vram_process_peak_gb": 2.1}\'')
99
+ cb.set_defaults(fn=cmd_check_budget)
100
+ r = sub.add_parser("run", help="headless benchmark run, prints a Budget Card")
101
+ for name, default in (("task", "pick_place"), ("policy", "rule"), ("agent", "recovery"), ("perception", "oracle"), ("verifier", "V1"),
102
+ ("perturb", "clean"), ("mode", "sync"), ("budget", "standard")):
103
+ r.add_argument("--" + name, default=default)
104
+ r.add_argument("--episodes", type=int, default=50)
105
+ r.add_argument("--seed", type=int, default=0)
106
+ r.add_argument("--extra-latency-ms", dest="extra_latency_ms", type=float, default=0.0)
107
+ r.add_argument("--velocity-lead", dest="velocity_lead", action=argparse.BooleanOptionalAction, default=True)
108
+ r.add_argument("--export-json", dest="export_json", type=str, default=None, help="path to export raw run.json")
109
+ r.set_defaults(fn=cmd_run)
110
+ args = p.parse_args(argv)
111
+ return args.fn(args)
112
+
113
+
114
+ if __name__ == "__main__":
115
+ raise SystemExit(main())
@@ -0,0 +1,64 @@
1
+ """Seeded failure / perturbation injection. Ground truth of what was injected is logged for scoring
2
+ only and is never exposed to the agent."""
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from dataclasses import dataclass, field
7
+ from typing import Dict, List
8
+
9
+ import numpy as np
10
+
11
+ LEVELS = {
12
+ "clean": {"p": 0.00, "pos_noise": 0.000, "pix_noise": 0.0},
13
+ "mild": {"p": 0.10, "pos_noise": 0.010, "pix_noise": 8.0},
14
+ "moderate": {"p": 0.25, "pos_noise": 0.020, "pix_noise": 16.0},
15
+ "severe": {"p": 0.40, "pos_noise": 0.035, "pix_noise": 28.0},
16
+ }
17
+
18
+ EXPECTED_DIAGNOSIS = {"grasp_slip": "object_dropped", "object_displaced": "grasp_miss", "wrong_placement": "wrong_placement"}
19
+
20
+
21
+ @dataclass
22
+ class Injector:
23
+ level: str
24
+ rng: np.random.Generator
25
+ log: List[Dict] = field(default_factory=list)
26
+
27
+ def __post_init__(self):
28
+ self.cfg = LEVELS[self.level]
29
+
30
+ @property
31
+ def pos_noise(self) -> float:
32
+ return self.cfg["pos_noise"]
33
+
34
+ @property
35
+ def pix_noise(self) -> float:
36
+ return self.cfg["pix_noise"]
37
+
38
+ def _roll(self) -> bool:
39
+ return self.cfg["p"] > 0 and self.rng.random() < self.cfg["p"]
40
+
41
+ def displace(self, world, oid: str, step: int) -> bool:
42
+ if self._roll():
43
+ ang = self.rng.uniform(0, 2 * math.pi)
44
+ d = self.rng.uniform(0.06, 0.09)
45
+ x0, y0 = world.obj_pos(oid)[:2]
46
+ nx, ny = x0 + d * math.cos(ang), y0 + d * math.sin(ang)
47
+ nx, ny = min(max(nx, 0.10), 0.36), min(max(ny, -0.25), 0.25)
48
+ world.teleport(oid, nx - x0, ny - y0)
49
+ self.log.append({"type": "object_displaced", "step": step, "object": oid})
50
+ return True
51
+ return False
52
+
53
+ def slip(self, step: int) -> bool:
54
+ if self._roll():
55
+ self.log.append({"type": "grasp_slip", "step": step})
56
+ return True
57
+ return False
58
+
59
+ def placement_offset(self, step: int):
60
+ if self._roll():
61
+ ang = self.rng.uniform(0, 2 * math.pi)
62
+ self.log.append({"type": "wrong_placement", "step": step})
63
+ return 0.12 * math.cos(ang), 0.12 * math.sin(ang)
64
+ return 0.0, 0.0