orbital-capture-bc / gen_bc_data.mjs
dcharlot-physicalai-bmi's picture
orbital-capture-bc: 1282-param on-device capture policy (BC from MPPI)
070a4c0 verified
Raw
History Blame Contribute Delete
1.48 kB
// Generate a behavior-cloning dataset from the MPPI expert: for many capture
// rollouts, record (relative state -> optimal control) pairs in the corridor
// frame (x = along the approach axis, y = lateral). A small policy is then
// distilled from this to fly the approach on-device.
import { meanMotion, cwStepEuler, mppiPlan } from '../core/physics.mjs';
import fs from 'node:fs';
const n = meanMotion(450e3);
const DT = 1.0; // matches the core MPPI timestep
const RUNS = 240;
const data = []; // [x, y, vx, vy, ax, ay]
let seed = 1, captured = 0;
for (let run = 0; run < RUNS; run++) {
let s = [14 + Math.random() * 34, (Math.random() * 2 - 1) * 16,
(Math.random() * 2 - 1) * 0.3, (Math.random() * 2 - 1) * 0.3];
let nominal = Array.from({ length: 28 }, () => [0, 0]);
for (let step = 0; step < 260; step++) {
nominal = mppiPlan(s, nominal, n, {}, seed++);
const u = nominal[0];
data.push([s[0], s[1], s[2], s[3], u[0], u[1]]);
s = cwStepEuler(s, u, n, DT);
nominal = [...nominal.slice(1), [0, 0]];
const range = Math.hypot(s[0], s[1]), speed = Math.hypot(s[2], s[3]);
if (range < 0.5 && speed < 0.05 && Math.abs(s[1]) < 0.4) { captured++; break; }
}
}
fs.writeFileSync(new URL('./bc_data.json', import.meta.url),
JSON.stringify({ cols: ['x', 'y', 'vx', 'vy', 'ax', 'ay'], rows: data, dt: DT }));
console.log(`wrote bc_data.json — ${data.length} samples from ${RUNS} rollouts (${captured} captured)`);