58 lines
3.2 KiB
JavaScript
58 lines
3.2 KiB
JavaScript
const fs = require('fs');
|
|
const html = fs.readFileSync('defense_sim.html', 'utf8');
|
|
const script = html.match(/<script>([\s\S]*?)<\/script>/)[1];
|
|
function extractFn(src, name) {
|
|
const re = new RegExp('function ' + name + '\\(', 'g');
|
|
const m = re.exec(src);
|
|
if (!m) return null;
|
|
let i = m.index, depth = 0, start = src.indexOf('{', i);
|
|
for (let j = start; j < src.length; j++) {
|
|
if (src[j] === '{') depth++;
|
|
else if (src[j] === '}') { depth--; if (depth === 0) return src.slice(i, j + 1); }
|
|
}
|
|
return null;
|
|
}
|
|
const fns = ['targetTrajectory','detectFromRadars','estimatePosition3D','estimateTrajectory','computeInterceptPoint','perpDistToLine','gaussianNoise','kmToPixels'];
|
|
eval(fns.map(n => extractFn(script, n)).filter(Boolean).join('\n'));
|
|
const MEASUREMENT_ERROR = 20.0, IR_ERROR = 3.0, SCALE = 10;
|
|
|
|
// Single prop-drone trial, fixed geometry for reproducibility
|
|
const P = { startDist:15, speed:30, cruiseMin:200, cruiseMax:200, descentStart:3, terminalAlt:0 };
|
|
const numRadars=8, numDrones=24, radarRange=20, droneSpeed=100, irRange=5, cityRadius=10, droneLine=8, dt=0.5;
|
|
const startAngle = Math.PI/3; // fixed
|
|
const startPos = [P.startDist*Math.cos(startAngle), P.startDist*Math.sin(startAngle)];
|
|
const targetAngle = Math.PI/3; // straight radial approach
|
|
const targetDist = 2;
|
|
const targetPos = [targetDist*Math.cos(targetAngle), targetDist*Math.sin(targetAngle)];
|
|
const cruiseAlt = 200;
|
|
const trajectory = targetTrajectory(startPos, targetPos, cruiseAlt, P.speed, P.descentStart, P.terminalAlt);
|
|
const radarPositions = [];
|
|
for (let i=0;i<numRadars;i++){const a=2*Math.PI*i/numRadars,d=cityRadius+2;radarPositions.push([d*Math.cos(a),d*Math.sin(a),0]);}
|
|
|
|
let time=0, detectionTime=null, observations=[];
|
|
function getTruePos(t){let b=trajectory[0],bd=1e18;for(const p of trajectory){const d=Math.abs(p.t-t);if(d<bd){bd=d;b=p;}}return b;}
|
|
|
|
for (let step=0; step<20 && detectionTime===null; step++) {
|
|
time += dt;
|
|
const tp = getTruePos(time);
|
|
const pos = [tp.x, tp.y, tp.z/1000];
|
|
const detections = detectFromRadars(pos, radarPositions, radarRange, gaussianNoise);
|
|
if (detections.length>0) observations.push({x:pos[0],y:pos[1],z:pos[2]*1000,t:time});
|
|
if (observations.length>=3) {
|
|
detectionTime = time;
|
|
const posEst = estimatePosition3D(detections, radarPositions);
|
|
if (posEst) observations[observations.length-1] = {x:posEst[0]/1000,y:posEst[1]/1000,z:posEst[2],t:time};
|
|
console.log(`=== detection at t=${time.toFixed(1)}s, ${observations.length} observations ===`);
|
|
console.log('true target pos (km):', pos.map(v=>v.toFixed(3)));
|
|
if (posEst) console.log('posEst (km):', posEst.map(v=>v.toFixed(3)));
|
|
console.log('observations (x km, y km, z m, t s):');
|
|
for (const o of observations) console.log(' ', o.x.toFixed(4), o.y.toFixed(4), o.z.toFixed(2), o.t.toFixed(1));
|
|
const traj = estimateTrajectory(observations);
|
|
const velMs = [traj.vel[0]*1000, traj.vel[1]*1000, traj.vel[2]];
|
|
console.log('vel (raw):', traj.vel.map(v=>v.toExponential(3)));
|
|
console.log('velMs:', velMs.map(v=>v.toFixed(2)));
|
|
console.log('speedEst:', Math.sqrt(velMs[0]**2+velMs[1]**2+velMs[2]**2).toFixed(1), 'R2:', traj.r2.toFixed(3));
|
|
break;
|
|
}
|
|
}
|