Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/autonoma.ca.git

Corrects gravity and other signage problems

Author djarvis <email>
Date 2024-12-17 14:17:24 GMT-0800
Commit 0819c99060bb75c99d3fc5ad36fc07bbb19f46f8
Parent 0d18a4c
calculators/rocket/payload/Atmosphere.js
STRATOSPHERE: [{
range: [11, 20],
- temperature: (altitude) => 216.65
+ temperature: (_) => 216.65
}, {
range: [20, 32],
temperature: (altitude) => 196.65 + altitude
}, {
range: [32, 47],
temperature: (altitude) => 139.05 + 2.8 * altitude
}],
MESOSPHERE: [{
range: [47, 51],
- temperature: (altitude) => 270.65
+ temperature: (_) => 270.65
}, {
range: [51, 71],
temperature: (altitude) => 413.45 - 2.8 * altitude
}, {
range: [71, 84.852],
temperature: (altitude) => 356.65 - 2.0 * altitude
}],
THERMOSPHERE: [{
range: [84.852, 91],
- temperature: (altitude) => 186.8673
+ temperature: (_) => 186.8673
}, {
range: [91, 110],
temperature: (altitude) => 263.1905 - 76.3232 * Math.sqrt(1 - Math.pow((altitude - 91) / -19.9429, 2))
}, {
range: [110, 120],
temperature: (altitude) => 240 + 12 * (altitude - 110)
}, {
range: [120, 1000],
temperature: (altitude) => {
- const ξ = (altitude - 120) * (6356.766 + 120) / (6356.766 + altitude);
- return 1000 - 640 * Math.exp(-0.01875 * ξ);
+ const E = (altitude - 120) * (6356.766 + 120) / (6356.766 + altitude);
+ return 1000 - 640 * Math.exp(-0.01875 * E);
}
}, {
range: [1000, Infinity],
- temperature: (altitude) => 1000
+ temperature: (_) => 1000
}]
};
temperature(altitude) {
- let result;
const temperatures = Layer.TEMPERATURES[this.name];
+ let result;
for (let t of temperatures) {
constructor(latitude) {
+ console.assert(typeof latitude === 'number');
+ console.assert(latitude !== undefined);
+
this.latitude = latitude;
}
layerValue(altitude, callback) {
+ console.assert( altitude >= 0 );
+
let result;
calculators/rocket/payload/Earth.js
constructor(latitude) {
+ console.assert(typeof latitude === 'number');
+ console.assert(latitude !== undefined);
+
this.atmosphere = new Atmosphere(latitude);
}
calculators/rocket/payload/FlightRecorder.js
}
+ maxAltitude() {
+ return this.altitudes.max();
+ }
+
azimuth(time, value) {
this.azimuths.record(time, value);
}
horizontalVelocity(time, value) {
this.horizontalVelocities.record(time, value);
+ }
+
+ maxHorizontalVelocity() {
+ return this.horizontalVelocities.max();
}
mass(time, value) {
this.masses.record(time, value);
+ }
+
+ minMass() {
+ return this.masses.min();
}
calculators/rocket/payload/Rocket.js
*/
constructor(wetMass, payloadMass) {
+ this.mass = wetMass;
this.payloadMass = payloadMass;
this.dryMass = wetMass * 0.1 + this.payloadMass;
- this.mass = wetMass;
this.azimuth = 0.0;
*/
translocate(latitude, altitude) {
+ console.assert(altitude >= 0);
+
this.latitude = latitude;
this.altitude = altitude;
apogee(targetAltitude) {
this.targetAltitude = targetAltitude;
- }
- /**
- * Calculates the gravitational acceleration at the current position.
- *
- * @returns {number} Gravitational acceleration (meters per second squared).
- */
- gravity() {
- return this.planet.gravity(this.latitude, this.altitude);
+ this.hVelocityTarget = this.planet.orbitalSpeed(
+ this.latitude, this.targetAltitude
+ );
}
rotational() {
return this.planet.rotationalSpeed(this.latitude, this.altitude);
- }
-
- /**
- * Calculates the orbital speed required at the current latitude and
- * target altitude.
- *
- * @returns {number} Orbital speed (meters per second).
- */
- orbital() {
- return this.planet.orbitalSpeed(this.latitude, this.targetAltitude);
}
/**
* Launches the rocket with an initial velocity.
*
- * @param {number} initialVelocity - Initial velocity as a fraction of the
- * speed of sound (dimensionless).
+ * @param {number} velocity - Initial velocity (Mach).
*/
- launch(initialVelocity) {
- this.exhaustVelocity = this.specificImpulse * this.gravity();
- this.maximumAcceleration = 5.0 * this.gravity();
- this.vVelocity = initialVelocity * this.planet.soundSpeed(this.altitude);
+ launch(velocity) {
+ const g = this.planet.gravity(this.latitude, this.targetAltitude);
+ this.exhaustVelocity = this.specificImpulse * g;
- this.hVelocity = this.rotational();
- this.hVelocityTarget = this.orbital();
- this.massFlowRate = Math.abs(this.drag()[1]) /
- this.exhaustVelocity * 1.001;
+ this.hVelocityInitial = this.rotational();
+ this.hVelocity = this.hVelocityInitial;
+ this.vVelocity = velocity * this.planet.soundSpeed(this.altitude);
+ this.maxAcceleration = 5.0 * 9.8;
+
+ const drag = this.drag();
+ this.massFlowRate = Math.abs(this.drag()[1]) / this.exhaustVelocity * 1.001;
+ this.tThrust = this.exhaustVelocity * this.massFlowRate;
+
+ const vThrust = -drag[1];
+ const hThrust = Math.sqrt(this.tThrust ** 2 - vThrust ** 2);
+
+ this.vAcceleration = drag[1] / this.mass + g + vThrust / this.mass;
+ this.hAcceleration = drag[0] / this.mass + hThrust / this.mass;
}
drag() {
const rho = this.planet.airDensity(this.altitude);
- const vHorNet = this.hVelocity - this.rotational();
- const speedTotal = this.magnitude(vHorNet, this.vVelocity);
+ const vHorNet = this.hVelocity - this.hVelocityInitial;
+ let speedTotal = this.magnitude(vHorNet, this.vVelocity);
+
+ if (speedTotal === 0) {
+ speedTotal = 1e-10;
+ }
+
const dragForce = 0.5 * rho * this.ballisticCoefficient *
speedTotal ** 2;
const ratio = [-vHorNet / speedTotal, -this.vVelocity / speedTotal];
- return [ratio[0] * dragForce, ratio[1] * dragForce];
+ return [dragForce * ratio[0], dragForce * ratio[1]];
}
/**
* Checks if the rocket is still flying, i.e., if it has fuel and has not
* reached the target altitude.
*
* @returns {boolean} True if the rocket is flying.
*/
flying() {
- return (this.mass > this.dryMass && this.altitude < this.targetAltitude)
- || (this.hVelocity < this.hVelocityTarget && this.altitude > 0);
+ return this.mass > this.dryMass && this.altitude < this.targetAltitude && this.altitude > 0;
}
const absDrag = Math.abs(drag[1]);
- if (accMag > this.maximumAcceleration &&
+ if (accMag > this.maxAcceleration &&
this.exhaustVelocity * this.massFlowRate * 0.98 > absDrag) {
this.massFlowRate *= 0.99;
this.massFlowRate = 0.0;
}
+
+ console.assert(this.massFlowRate >= 0);
// Compute the total thrust.
this.tThrust = this.exhaustVelocity * this.massFlowRate;
const thrusting = this.tThrust > 0;
const vThrust = thrusting ? -drag[1] : 0;
const hThrust = thrusting ? Math.sqrt(this.tThrust ** 2 - vThrust ** 2) : 0;
+ const g = -this.planet.gravity(this.latitude, this.altitude);
+ this.vAcceleration = drag[1] / this.mass + g + vThrust / this.mass;
this.hAcceleration = drag[0] / this.mass + hThrust / this.mass;
- this.vAcceleration = drag[1] / this.mass + this.gravity() + vThrust / this.mass;
this.vVelocity += this.vAcceleration * step;
magnitude(x, y) {
return Math.sqrt(x ** 2 + y ** 2);
+ }
+
+ emptyMass() {
+ return this.dryMass;
+ }
+
+ initialOrbitalVelocity() {
+ return this.hVelocityInitial;
}
}
calculators/rocket/payload/Telemetry.js
+Array.prototype.max = function () {
+ let maxVal = this[0];
+
+ for (let i = 1; i < this.length; i++) {
+ if (this[i] > maxVal) {
+ maxVal = this[i];
+ }
+ }
+
+ return maxVal;
+};
+
+Array.prototype.min = function () {
+ let minVal = this[0];
+
+ for (let i = 1; i < this.length; i++) {
+ if (this[i] < minVal) {
+ minVal = this[i];
+ }
+ }
+
+ return minVal;
+};
+
class Telemetry {
constructor(measureName) {
this.times.push(time);
this.values.push(value);
+ }
+
+ max() {
+ return this.values.max();
+ }
+
+ min() {
+ return this.values.min();
}
plot(plotName, yLabel) {
const data = this.times.map((time, index) => ({
time: time,
value: this.values[index]
}));
+ const minYValue = d3.min(data, d => d.value);
const maxYValue = d3.max(data, d => d.value);
- const numDigits = maxYValue.toFixed(0).length;
+ const numDigits = Math.max(minYValue.toFixed(0).length, maxYValue.toFixed(0).length);
const margin = {
top: 30,
const y = d3.scaleLinear()
- .domain([0, maxYValue])
+ .domain([minYValue, maxYValue])
.range([height, 0]);
.style('font-family', 'sans-serif')
.style('fill', '#333')
- .text('Time (seconds)');
+ .text('Time (s)');
const formattedYLabel = yLabel.replace('^2', '²');
calculators/rocket/payload/calculator.js
class Simulation {
- constructor() {}
+ constructor() {
+ }
init() {
- const initialVelocity = $('#initial_velocity').val();
- const initialLatitude = $('#initial_latitude').val();
- const initialAltitude = $('#initial_altitude').val();
+ const velocity = $('#initial_velocity').val();
+ const latitude = $('#initial_latitude').val();
+ const altitude = $('#initial_altitude').val();
const targetAltitude = $('#target_altitude').val() * 1000.0;
- const rocketDiameter = $('#diameter').val();
+ const diameter = $('#diameter').val();
const wetMass = $('#wet_mass').val();
const payloadMass = $('#payload_mass').val();
const dragCoefficient = $('#drag_coefficient').val();
const specificImpulse = $('#specific_impulse').val();
- this.planet = new Earth(initialLatitude);
+ this.planet = new Earth(latitude);
this.rocket = new Rocket(wetMass, payloadMass);
+
+ $('#orbital_velocity').val(
+ this.planet.orbitalSpeed(latitude, targetAltitude).toFixed(2)
+ );
this.rocket.on(this.planet);
- this.rocket.fuselage(rocketDiameter, dragCoefficient, specificImpulse);
- this.rocket.translocate(initialLatitude, initialAltitude);
+ this.rocket.fuselage(diameter, dragCoefficient, specificImpulse);
+ this.rocket.translocate(latitude, altitude);
this.rocket.apogee(targetAltitude);
- this.rocket.launch(initialVelocity);
+ this.rocket.launch(velocity);
}
time += TIME_STEP;
}
+
+ const altitude = $('#initial_altitude').val();
+
+ $('#air_density').val(
+ this.planet.airDensity(altitude).toFixed(2)
+ );
+ $('#initial_orbital_velocity').val(
+ this.rocket.initialOrbitalVelocity().toFixed(2)
+ );
+ $('#rocket_velocity').val(
+ blackBox.maxHorizontalVelocity().toFixed(2)
+ );
+ $('#rocket_altitude').val(
+ (blackBox.maxAltitude() / 1000.0).toFixed(2)
+ );
+ $('#dry_mass').val(
+ this.rocket.emptyMass().toFixed(2)
+ );
+ $('#final_mass').val(
+ blackBox.minMass().toFixed(2)
+ );
blackBox.plot();
calculators/rocket/payload/index.html
section, below. Based on Professor Aaron Ridley's
<a href="https://github.com/aaronjridley/Kepler/blob/main/OrbitalInsertion/launch.py">implementation</a>.
- </p><form id="calculator"><button class="submit">Simulate</button><fieldset id="mission"><legend>Mission</legend><label for="initial_velocity">Initial velocity (Mach)</label><input tabindex="3" class="variable" type="number" step="1" min="0" value="6" id="initial_velocity" name="initial_velocity"><label for="initial_latitude">Initial latitude (°)</label><input tabindex="4" class="variable" type="number" step="any" min="0" value="1.469167" id="initial_latitude" name="initial_latitude"><label for="initial_altitude">Initial altitude (m)</label><input tabindex="5" class="variable" type="number" step="1" min="0" value="6212" id="initial_altitude" name="initial_altitude"><label for="target_altitude">Target altitude (km)</label><input tabindex="6" class="variable" type="number" step="1" min="1" value="400" id="target_altitude" name="target_altitude"></fieldset><fieldset id="rocket"><legend>Rocket</legend><label for="diameter">Diameter (m)</label><input tabindex="7" class="variable" type="number" step="any" min="0" value="0.6" id="diameter" name="diameter"><label for="wet_mass">Wet mass (kg)</label><input tabindex="8" class="variable" type="number" step="10" min="1" value="250" id="wet_mass" name="wet_mass" oninput="this.value = Math.abs(this.value)"><label for="payload">Payload mass (kg)</label><input tabindex="9" class="variable" type="number" step="1" min="1" value="25" id="payload_mass" name="payload_mass" oninput="this.value = Math.abs(this.value)"><label for="drag_coefficient">Drag coefficient</label><input tabindex="10" class="variable" type="number" step="any" min="0" value="0.219" id="drag_coefficient" name="drag_coefficient"><label for="specific_impulse">Specific impulse (s)</label><input tabindex="11" class="variable" type="number" step="10" min="1" value="1700" id="specific_impulse" name="specific_impulse"></fieldset><fieldset id="result"><legend>Result</legend><div id="plots"></div></fieldset></form><a name="equations"></a><h1>Equations</h1><p>
+ </p><form id="calculator"><button class="submit">Simulate</button><fieldset id="mission"><legend>Mission</legend><label for="initial_velocity">Initial velocity (Mach)</label><input tabindex="3" class="variable" type="number" step="0.1" min="0" value="8.5" id="initial_velocity" name="initial_velocity"><label for="initial_latitude">Initial latitude (°)</label><input tabindex="4" class="variable" type="number" step="any" min="0" value="1.469167" id="initial_latitude" name="initial_latitude"><label for="initial_altitude">Initial altitude (m)</label><input tabindex="5" class="variable" type="number" step="1" min="0" value="6212" id="initial_altitude" name="initial_altitude"><label for="target_altitude">Target altitude (km)</label><input tabindex="6" class="variable" type="number" step="1" min="1" value="400" id="target_altitude" name="target_altitude"></fieldset><fieldset id="rocket"><legend>Rocket</legend><label for="diameter">Diameter (m)</label><input tabindex="7" class="variable" type="number" step="any" min="0" value="0.6" id="diameter" name="diameter"><label for="wet_mass">Wet mass (kg)</label><input tabindex="8" class="variable" type="number" step="10" min="1" value="250" id="wet_mass" name="wet_mass" oninput="this.value = Math.abs(this.value)"><label for="payload">Payload mass (kg)</label><input tabindex="9" class="variable" type="number" step="1" min="1" value="25" id="payload_mass" name="payload_mass" oninput="this.value = Math.abs(this.value)"><label for="drag_coefficient">Drag coefficient</label><input tabindex="10" class="variable" type="number" step="any" min="0" value="0.219" id="drag_coefficient" name="drag_coefficient"><label for="specific_impulse">Specific impulse (s)</label><input tabindex="11" class="variable" type="number" step="10" min="1" value="1400" id="specific_impulse" name="specific_impulse"></fieldset><fieldset id="totals"><legend>Summary</legend><label for="air_density">
+ Air density (kg/m<sup>3</sup>)
+ </label><input type="text" value="" readonly id="air_density" name="air_density"><label for="initial_orbital_velocity">
+ Initial orbital velocity (m/s)
+ </label><input type="text" value="" readonly id="initial_orbital_velocity" name="initial_orbital_velocity"><label for="orbital_velocity">
+ Target orbital velocity (m/s)
+ </label><input type="text" value="" readonly id="orbital_velocity" name="orbital_velocity"><label for="rocket_velocity">
+ Maximum velocity (m/s)
+ </label><input type="text" value="" readonly id="rocket_velocity" name="rocket_velocity"><label for="rocket_altitude">
+ Maximum altitude (km)
+ </label><input type="text" value="" readonly id="rocket_altitude" name="rocket_altitude"><label for="dry_mass">
+ Dry mass (kg)
+ </label><input type="text" value="" readonly id="dry_mass" name="dry_mass"><label for="final_mass">
+ Final mass (kg)
+ </label><input type="text" value="" readonly id="final_mass" name="final_mass"><label for="payload_delivered">
+ Payload delivered
+ </label><input type="text" value="" readonly id="payload_delivered" name="payload_delivered"></fieldset></form><h2>Results</h2><div id="plots"></div><a name="equations"></a><h1>Equations</h1><p>
This section describes equation inputs and outputs.
</p><h2>Cross-section area</h2><p>
calculators/rocket/payload/launch.xsl
<label for="initial_velocity">Initial velocity (Mach)</label>
<input tabindex="3"
- class="variable" type="number" step="1" min="0" value="6"
+ class="variable" type="number" step="0.1" min="0" value="8.5"
id="initial_velocity" name="initial_velocity" />
<label for="specific_impulse">Specific impulse (s)</label>
<input tabindex="11"
- class="variable" type="number" step="10" min="1" value="1700"
+ class="variable" type="number" step="10" min="1" value="1400"
id="specific_impulse" name="specific_impulse" />
</fieldset>
- <fieldset id="result">
- <legend>Result</legend>
- <div id="plots">
- </div>
+ <fieldset id="totals">
+ <legend>Summary</legend>
+
+ <label for="air_density">
+ Air density (kg/m<sup>3</sup>)
+ </label>
+ <input
+ type="text" value="" readonly="readonly"
+ id="air_density" name="air_density" />
+
+ <label for="initial_orbital_velocity">
+ Initial orbital velocity (m/s)
+ </label>
+ <input
+ type="text" value="" readonly="readonly"
+ id="initial_orbital_velocity" name="initial_orbital_velocity" />
+
+ <label for="orbital_velocity">
+ Target orbital velocity (m/s)
+ </label>
+ <input
+ type="text" value="" readonly="readonly"
+ id="orbital_velocity" name="orbital_velocity" />
+
+ <label for="rocket_velocity">
+ Maximum velocity (m/s)
+ </label>
+ <input
+ type="text" value="" readonly="readonly"
+ id="rocket_velocity" name="rocket_velocity" />
+
+ <label for="rocket_altitude">
+ Maximum altitude (km)
+ </label>
+ <input
+ type="text" value="" readonly="readonly"
+ id="rocket_altitude" name="rocket_altitude" />
+
+ <label for="dry_mass">
+ Dry mass (kg)
+ </label>
+ <input
+ type="text" value="" readonly="readonly"
+ id="dry_mass" name="dry_mass" />
+
+ <label for="final_mass">
+ Final mass (kg)
+ </label>
+ <input
+ type="text" value="" readonly="readonly"
+ id="final_mass" name="final_mass" />
+
+ <label for="payload_delivered">
+ Payload delivered
+ </label>
+ <input
+ type="text" value="" readonly="readonly"
+ id="payload_delivered" name="payload_delivered" />
</fieldset>
</form>
+
+ <h2>Results</h2>
+ <div id="plots">
+ </div>
<a name="equations" />
Delta 225 lines added, 62 lines removed, 163-line increase