Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2199174

Browse files
committed
feat: Add commodity sensing, proof bundle, Three.js viz, mock isolation
Commodity Sensing Module (ADR-013): - sensing/rssi_collector.py: Real Linux WiFi RSSI collection from /proc/net/wireless and iw commands, with SimulatedCollector for testing - sensing/feature_extractor.py: FFT-based spectral analysis, CUSUM change-point detection, breathing/motion band power extraction - sensing/classifier.py: Rule-based presence/motion classification with confidence scoring and multi-receiver agreement - sensing/backend.py: Common SensingBackend protocol with honest capability reporting (PRESENCE + MOTION only for commodity) Proof of Reality Bundle (ADR-011): - data/proof/generate_reference_signal.py: Deterministic synthetic CSI with known breathing (0.3 Hz) and walking (1.2 Hz) signals - data/proof/sample_csi_data.json: Generated reference signal - data/proof/verify.py: One-command pipeline verification with SHA-256 - data/proof/expected_features.sha256: Expected output hash Three.js Visualization: - ui/components/scene.js: 3D scene setup with OrbitControls Mock Isolation: - testing/mock_pose_generator.py: Mock pose generation moved out of production pose_service.py - services/pose_service.py: Cleaned mock paths https://claude.ai/code/session_01Ki7pvEZtJDvqJkmyn6B714
1 parent e3f0c7a commit 2199174

12 files changed

Lines changed: 358561 additions & 184 deletions

ui/components/scene.js

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
// Three.js Scene Setup - WiFi DensePose 3D Visualization
2+
// Camera, lights, renderer, OrbitControls
3+
4+
export class Scene {
5+
constructor(container) {
6+
this.container = typeof container === 'string'
7+
? document.getElementById(container)
8+
: container;
9+
10+
if (!this.container) {
11+
throw new Error('Scene container element not found');
12+
}
13+
14+
this.scene = null;
15+
this.camera = null;
16+
this.renderer = null;
17+
this.controls = null;
18+
this.clock = null;
19+
this.animationId = null;
20+
this.updateCallbacks = [];
21+
this.isRunning = false;
22+
23+
this._init();
24+
}
25+
26+
_init() {
27+
const width = this.container.clientWidth || 960;
28+
const height = this.container.clientHeight || 640;
29+
30+
// Scene
31+
this.scene = new THREE.Scene();
32+
this.scene.background = new THREE.Color(0x0a0a1a);
33+
this.scene.fog = new THREE.FogExp2(0x0a0a1a, 0.008);
34+
35+
// Camera - positioned to see the room from a 3/4 angle
36+
this.camera = new THREE.PerspectiveCamera(55, width / height, 0.1, 500);
37+
this.camera.position.set(8, 7, 10);
38+
this.camera.lookAt(0, 1.5, 0);
39+
40+
// Renderer
41+
this.renderer = new THREE.WebGLRenderer({
42+
antialias: true,
43+
alpha: false,
44+
powerPreference: 'high-performance'
45+
});
46+
this.renderer.setSize(width, height);
47+
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
48+
this.renderer.shadowMap.enabled = true;
49+
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
50+
this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
51+
this.renderer.toneMappingExposure = 1.0;
52+
this.container.appendChild(this.renderer.domElement);
53+
54+
// OrbitControls
55+
this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
56+
this.controls.enableDamping = true;
57+
this.controls.dampingFactor = 0.08;
58+
this.controls.minDistance = 3;
59+
this.controls.maxDistance = 30;
60+
this.controls.maxPolarAngle = Math.PI * 0.85;
61+
this.controls.target.set(0, 1.2, 0);
62+
this.controls.update();
63+
64+
// Lights
65+
this._setupLights();
66+
67+
// Clock for animation delta
68+
this.clock = new THREE.Clock();
69+
70+
// Handle resize
71+
this._resizeObserver = new ResizeObserver(() => this._onResize());
72+
this._resizeObserver.observe(this.container);
73+
window.addEventListener('resize', () => this._onResize());
74+
}
75+
76+
_setupLights() {
77+
// Ambient light - subtle blue tint for tech feel
78+
const ambient = new THREE.AmbientLight(0x223355, 0.4);
79+
this.scene.add(ambient);
80+
81+
// Hemisphere light - sky/ground gradient
82+
const hemi = new THREE.HemisphereLight(0x4488cc, 0x112233, 0.5);
83+
hemi.position.set(0, 20, 0);
84+
this.scene.add(hemi);
85+
86+
// Key light - warm directional light from above-right
87+
const keyLight = new THREE.DirectionalLight(0xffeedd, 0.8);
88+
keyLight.position.set(5, 10, 5);
89+
keyLight.castShadow = true;
90+
keyLight.shadow.mapSize.width = 1024;
91+
keyLight.shadow.mapSize.height = 1024;
92+
keyLight.shadow.camera.near = 0.5;
93+
keyLight.shadow.camera.far = 30;
94+
keyLight.shadow.camera.left = -10;
95+
keyLight.shadow.camera.right = 10;
96+
keyLight.shadow.camera.top = 10;
97+
keyLight.shadow.camera.bottom = -10;
98+
this.scene.add(keyLight);
99+
100+
// Fill light - cool from left
101+
const fillLight = new THREE.DirectionalLight(0x88aaff, 0.3);
102+
fillLight.position.set(-5, 6, -3);
103+
this.scene.add(fillLight);
104+
105+
// Point light under the body for a soft uplight glow
106+
const uplight = new THREE.PointLight(0x0066ff, 0.4, 8);
107+
uplight.position.set(0, 0.1, 0);
108+
this.scene.add(uplight);
109+
}
110+
111+
// Register a callback that runs each frame with (deltaTime, elapsedTime)
112+
onUpdate(callback) {
113+
this.updateCallbacks.push(callback);
114+
return () => {
115+
const idx = this.updateCallbacks.indexOf(callback);
116+
if (idx !== -1) this.updateCallbacks.splice(idx, 1);
117+
};
118+
}
119+
120+
start() {
121+
if (this.isRunning) return;
122+
this.isRunning = true;
123+
this.clock.start();
124+
this._animate();
125+
}
126+
127+
stop() {
128+
this.isRunning = false;
129+
if (this.animationId !== null) {
130+
cancelAnimationFrame(this.animationId);
131+
this.animationId = null;
132+
}
133+
}
134+
135+
_animate() {
136+
if (!this.isRunning) return;
137+
this.animationId = requestAnimationFrame(() => this._animate());
138+
139+
const delta = this.clock.getDelta();
140+
const elapsed = this.clock.getElapsedTime();
141+
142+
// Run registered update callbacks
143+
for (const cb of this.updateCallbacks) {
144+
cb(delta, elapsed);
145+
}
146+
147+
this.controls.update();
148+
this.renderer.render(this.scene, this.camera);
149+
}
150+
151+
_onResize() {
152+
const width = this.container.clientWidth;
153+
const height = this.container.clientHeight;
154+
if (width === 0 || height === 0) return;
155+
156+
this.camera.aspect = width / height;
157+
this.camera.updateProjectionMatrix();
158+
this.renderer.setSize(width, height);
159+
}
160+
161+
// Add an object to the scene
162+
add(object) {
163+
this.scene.add(object);
164+
}
165+
166+
// Remove an object from the scene
167+
remove(object) {
168+
this.scene.remove(object);
169+
}
170+
171+
// Get the Three.js scene, camera, renderer for external access
172+
getScene() { return this.scene; }
173+
getCamera() { return this.camera; }
174+
getRenderer() { return this.renderer; }
175+
176+
// Reset camera to default position
177+
resetCamera() {
178+
this.camera.position.set(8, 7, 10);
179+
this.controls.target.set(0, 1.2, 0);
180+
this.controls.update();
181+
}
182+
183+
dispose() {
184+
this.stop();
185+
if (this._resizeObserver) {
186+
this._resizeObserver.disconnect();
187+
}
188+
window.removeEventListener('resize', this._onResize);
189+
this.controls.dispose();
190+
this.renderer.dispose();
191+
if (this.renderer.domElement.parentNode) {
192+
this.renderer.domElement.parentNode.removeChild(this.renderer.domElement);
193+
}
194+
this.updateCallbacks = [];
195+
}
196+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7b9ed15a01a2ae49cb32c5a1bb7e41361e0c83d9216f092efe3a3e279c7731ba

0 commit comments

Comments
 (0)