cosmo/docs/火箭发送模拟/simtest.js

119 lines
3.5 KiB
JavaScript
Raw Normal View History

2026-07-21 12:09:51 +00:00
import { CONSTANTS, PRESETS } from "./src/types";
let h = 0, x = 0, vx = 0, vy = 0, v = 0, pitch = 90, t = 0;
let currentStage = 0;
let fuel = PRESETS[0].stages[0].fuelMass;
const currentEvents = [];
let maxQ = 0;
let isRunning = true;
for (let i = 0; i < 50000; i++) {
const dt = 0.1;
const rocket = PRESETS[0];
const { area, cd, stages } = rocket;
const stage = stages[currentStage];
const { dryMass, maxThrust, isp } = stage;
let upperStagesMass = 0;
for (let j = currentStage + 1; j < stages.length; j++) {
upperStagesMass += stages[j].dryMass + stages[j].fuelMass;
}
const m = dryMass + fuel + upperStagesMass;
const mDotMax = maxThrust / (isp * CONSTANTS.g0);
let actualThrottle = 1;
if (fuel <= 0 && currentStage < stages.length - 1) {
currentStage++;
fuel = stages[currentStage].fuelMass;
if (!currentEvents.find((e) => e.name === `stageSep${currentStage}`)) {
currentEvents.push({ name: `stageSep${currentStage}`, time: t });
}
} else if (fuel <= 0) {
actualThrottle = 0;
fuel = 0;
}
const currentThrust = maxThrust * actualThrottle;
const mDot = mDotMax * actualThrottle;
if (actualThrottle > 0) {
fuel -= mDot * dt;
if (fuel < 0) fuel = 0;
}
v = Math.sqrt(vx * vx + vy * vy);
const pitching = h > 500;
if (pitching) {
pitch = 90 * Math.exp(-h / 30000);
}
if (h <= 500) {
pitch = 90;
}
const pitchRad = (pitch * Math.PI) / 180;
const fg = (CONSTANTS.G * (CONSTANTS.M_EARTH * m)) / Math.pow(CONSTANTS.R_EARTH + h, 2);
const centrifugalY = (m * vx * vx) / (CONSTANTS.R_EARTH + h);
const rho = h > 100000 ? 0 : CONSTANTS.RHO_0 * Math.exp(-h / CONSTANTS.H);
const currentQ = 0.5 * rho * v * v;
const fd = currentQ * cd * area;
const thrustX = currentThrust * Math.cos(pitchRad);
const thrustY = currentThrust * Math.sin(pitchRad);
const vDirX = v > 0 ? vx / v : 0;
const vDirY = v > 0 ? vy / v : 1;
const dragX = fd * vDirX;
const dragY = fd * vDirY;
const netForceX = thrustX - dragX;
const netForceY = thrustY - dragY - fg + centrifugalY;
let ax = netForceX / m;
let ay = netForceY / m;
if (h <= 0 && vy <= 0 && netForceY <= 0) {
ay = 0; ax = 0; vx = 0; vy = 0; h = 0; pitch = 90;
}
vx += ax * dt;
vy += ay * dt;
x += vx * dt;
h += vy * dt;
if (h < 0) h = 0;
t += dt;
v = Math.sqrt(vx * vx + vy * vy);
if (h > 10 && v > 1 && !currentEvents.find((e) => e.name === "liftoff")) {
currentEvents.push({ name: "liftoff", time: t });
}
if (currentQ > maxQ) maxQ = currentQ;
if (maxQ > 20000 && currentQ < maxQ * 0.95 && !currentEvents.find((e) => e.name === "maxq")) {
currentEvents.push({ name: "maxq", time: t });
}
if (currentStage === stages.length - 1 && fuel <= 0 && t > 10 && !currentEvents.find((e) => e.name === "meco")) {
currentEvents.push({ name: "meco", time: t });
}
if (h >= 100000 && !currentEvents.find((e) => e.name === "karman")) {
currentEvents.push({ name: "karman", time: t });
}
if (vx >= 7800 && !currentEvents.find((e) => e.name === "orbit")) {
currentEvents.push({ name: "orbit", time: t });
}
if (i % 500 === 0) {
console.log(`t: ${t.toFixed(1)}, stage: ${currentStage}, h: ${(h/1000).toFixed(1)}km, v: ${v.toFixed(1)}m/s, vx: ${vx.toFixed(1)}, pitch: ${pitch.toFixed(1)}, fuel: ${fuel.toFixed(0)}, FnetY: ${netForceY.toFixed(0)}`);
}
if (currentEvents.find((e) => e.name === "meco") && t > currentEvents.find((e) => e.name === "meco").time + 3) {
console.log("SIM ENDED");
break;
}
}
console.log(currentEvents);