Dave Jarvis' Repositories

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

Adds comments, restructures html, removes inputs

Author djarvis <email>
Date 2024-12-03 23:52:42 GMT-0800
Commit 3cb38eb279a9a927de5de812b72c0bf54de87c8c
Parent e89468d
calculators/README.md
```
+Transform the variables:
+
+``` bash
+java -jar $HOME/archive/saxon/saxon-he-12.5.jar launch.xsl ../../../index.xsl
+```
calculators/rocket/payload/Rocket.js
class Rocket {
+ /**
+ * Initializes the Rocket object with wet mass and payload mass.
+ * Calculates dry mass and sets initial azimuth and altitude.
+ *
+ * @param {number} wetMass - Total mass including fuel (kilograms).
+ * @param {number} payloadMass - Mass of the payload (kilograms).
+ */
constructor(wetMass, payloadMass) {
- this.wetMass = wetMass;
this.payloadMass = payloadMass;
- this.dryMass = this.wetMass * 0.1 + this.payloadMass;
- this.mass = this.wetMass;
+ this.dryMass = wetMass * 0.1 + this.payloadMass;
+ this.mass = wetMass;
this.azimuth = 0.0;
+ this.altitude = 0.0;
}
+ /**
+ * Associates the rocket with a specific planet.
+ *
+ * @param {object} planet - An object representing the planet.
+ */
on(planet) {
this.planet = planet;
}
+ /**
+ * Sets the fuselage properties including diameter, drag coefficient,
+ * and specific impulse.
+ *
+ * @param {number} diameter - Diameter of the rocket (meters).
+ * @param {number} dragCoefficient - Drag coefficient (dimensionless).
+ * @param {number} specificImpulse - Specific impulse (seconds).
+ */
fuselage(diameter, dragCoefficient, specificImpulse) {
const crossSectionalArea = Math.PI * (diameter / 2) ** 2;
this.ballisticCoefficient = dragCoefficient * crossSectionalArea;
this.specificImpulse = specificImpulse;
}
+ /**
+ * Sets the rocket's latitude and altitude for the launch.
+ *
+ * @param {number} latitude - Latitude of the launch site (degrees).
+ * @param {number} altitude - Altitude of the launch site (meters).
+ */
translocate(latitude, altitude) {
this.latitude = latitude;
this.altitude = altitude;
}
+ /**
+ * Sets the target apogee (maximum altitude) for the rocket's flight.
+ *
+ * @param {number} targetAltitude - Target altitude (meters).
+ */
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);
+ }
+
+ /**
+ * Calculates the rotational speed of the planet at the current latitude
+ * and altitude.
+ *
+ * @returns {number} Rotational speed (meters per second).
+ */
+ 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).
+ */
launch(initialVelocity) {
this.exhaustVelocity = this.specificImpulse * this.gravity();
this.maximumAcceleration = 5.0 * this.gravity();
this.vVelocity = initialVelocity * this.planet.soundSpeed(this.altitude);
- this.hVelocity = this.planet.rotationalSpeed(this.latitude, this.altitude);
- this.hVelocityTarget = this.planet.orbitalSpeed(this.latitude, this.targetAltitude);
- this.massFlowRate = Math.abs(this.drag()[1]) / this.exhaustVelocity * 1.001;
+ this.hVelocity = this.rotational();
+ this.hVelocityTarget = this.orbital();
+ this.massFlowRate = Math.abs(this.drag()[1]) /
+ this.exhaustVelocity * 1.001;
}
+ /**
+ * Attaches a flight recorder to the rocket.
+ *
+ * @param {object} blackBox - An object representing the flight recorder.
+ */
recorder(blackBox) {
this.flightRecorder = blackBox;
}
+ /**
+ * Calculates the drag force experienced by the rocket.
+ *
+ * @returns {Array<number>} Drag force components [horizontal, vertical]
+ * (newtons).
+ */
drag() {
const rho = this.planet.airDensity(this.altitude);
- const vHorNet = this.hVelocity - this.planet.rotationalSpeed(this.latitude, this.altitude);
- const totalSpeed = Math.sqrt(vHorNet ** 2 + this.vVelocity ** 2);
- const magnitude = 0.5 * rho * this.ballisticCoefficient * totalSpeed ** 2;
- const ratio = [-vHorNet / totalSpeed, -this.vVelocity / totalSpeed];
+ const vHorNet = this.hVelocity - this.rotational();
+ const speedTotal = this.magnitude(vHorNet, this.vVelocity);
+ const dragForce = 0.5 * rho * this.ballisticCoefficient *
+ speedTotal ** 2;
+ const ratio = [-vHorNet / speedTotal, -this.vVelocity / speedTotal];
- return [ratio[0] * magnitude, ratio[1] * magnitude];
+ return [ratio[0] * dragForce, ratio[1] * dragForce];
}
+ /**
+ * 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;
}
+ /**
+ * Simulates the flight of the rocket for a given time step.
+ *
+ * @param {number} step - Time step for the simulation (seconds).
+ */
fly(step) {
const drag = this.drag();
if (this.hVelocity < this.hVelocityTarget) {
- const accMag = Math.sqrt(this.hAcceleration ** 2 + this.vAcceleration ** 2);
+ const accMag = this.magnitude(this.hAcceleration, this.vAcceleration);
const absDrag = Math.abs(drag[1]);
- if (accMag > this.maximumAcceleration && this.exhaustVelocity * this.massFlowRate * 0.98 > absDrag) {
+ if (accMag > this.maximumAcceleration &&
+ this.exhaustVelocity * this.massFlowRate * 0.98 > absDrag) {
this.massFlowRate *= 0.99;
}
+
if (this.exhaustVelocity * this.massFlowRate < absDrag) {
this.massFlowRate = absDrag / this.exhaustVelocity * 1.1;
}
} else {
this.massFlowRate = 0.0;
}
- this.totalThrust = this.exhaustVelocity * this.massFlowRate;
+ // Compute the total thrust.
+ this.tThrust = this.exhaustVelocity * this.massFlowRate;
- const thrusting = this.totalThrust > 0;
+ const thrusting = this.tThrust > 0;
const vThrust = thrusting ? -drag[1] : 0;
- const hThrust = thrusting ? Math.sqrt(this.totalThrust ** 2 - vThrust ** 2) : 0;
+ const hThrust = thrusting ? Math.sqrt(this.tThrust ** 2 - vThrust ** 2) : 0;
this.hAcceleration = drag[0] / this.mass + hThrust / this.mass;
}
+ /**
+ * Records the rocket's flight data at a given time.
+ *
+ * @param {number} time - The current simulation time (seconds).
+ */
record(time) {
if (this.flightRecorder) {
this.flightRecorder.azimuth(time, this.azimuth);
this.flightRecorder.horizontalVelocity(time, this.hVelocity);
this.flightRecorder.horizontalAcceleration(time, this.hAcceleration);
this.flightRecorder.altitude(time, this.altitude);
this.flightRecorder.verticalVelocity(time, this.vVelocity);
this.flightRecorder.verticalAcceleration(time, this.vAcceleration);
- this.flightRecorder.thrustAcceleration(time, this.totalThrust / this.mass);
+ this.flightRecorder.thrustAcceleration(time, this.tThrust / this.mass);
this.flightRecorder.mass(time, this.mass);
}
+ }
+
+ /**
+ * Calculates the magnitude of two values.
+ *
+ * @param {number} x - First value.
+ * @param {number} y - Second value.
+ * @returns {number} Magnitude.
+ */
+ magnitude(x, y) {
+ return Math.sqrt(x ** 2 + y ** 2);
}
}
calculators/rocket/payload/calculator.js
import FlightRecorder from './FlightRecorder.js';
import Rocket from './Rocket.js';
+import $ from './Selector.js';
document.querySelectorAll('.submit').forEach(button => {
button.addEventListener('click', function (event) {
event.preventDefault();
- const INITIAL_VELOCITY = 8.0; // Mach
- const INITIAL_LATITUDE = 1.469167; // degrees
- const INITIAL_ALTITUDE = 6212.0; // meters
- const TARGET_ALTITUDE = 400.0 * 1000.0; // meters
+ const INITIAL_VELOCITY = $('#initial_velocity').val(); // Mach
+ const INITIAL_LATITUDE = $('#initial_latitude').val(); // degrees
+ const INITIAL_ALTITUDE = $('#initial_altitude').val(); // meters
+ const TARGET_ALTITUDE = $('#target_altitude').val() * 1000.0; // meters
- const ROCKET_DIAMETER = 0.6;
- const WET_MASS = 250.0;
- const PAYLOAD_MASS = 25.0;
- const DRAG_COEFFICIENT = 0.29;
- const SPECIFIC_IMPULSE = 1400.0; // seconds
+ const ROCKET_DIAMETER = $('#diameter').val();
+ const WET_MASS = $('#wet_mass').val();
+ const PAYLOAD_MASS = $('#payload_mass').val();
+ const DRAG_COEFFICIENT = $('#drag_coefficient').val();
+ const SPECIFIC_IMPULSE = $('#specific_impulse').val(); // seconds
const blackBox = new FlightRecorder();
calculators/rocket/payload/index.html
-<!DOCTYPE html><!DOCTYPE HTML><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1user-scalable=yes"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="description" content="A hard sci-fi novel about automated food production, sentient machines, and surveillance societies."><link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"><style media="screen" type="text/css">
+<!DOCTYPE HTML><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1user-scalable=yes"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="description" content="A hard sci-fi novel about automated food production, sentient machines, and surveillance societies."><link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"><style media="screen" type="text/css">
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}/*# sourceMappingURL=normalize.min.css.map */
</style><link rel="stylesheet" type="text/css" media="screen" href="../../../themes/simple.css"><link rel="stylesheet" type="text/css" media="screen" href="../../../themes/form.css"><link rel="stylesheet" type="text/css" media="screen" href="../../../themes/calculator.css"><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css" integrity="sha512-fHwaWebuwA7NSF5Qg/af4UeDx9XqUpYpOGgubo3yWu+b2IQR4UeQwbb42Ti7gVAjNtVoI/I9TEoYeu9omwcC6g==" crossorigin="anonymous" referrerpolicy="no-referrer"><link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:200|Libre+Baskerville" rel="stylesheet"></head><body><div class="page"><header class="section header"><h1>Orbital Launch Insertion</h1></header><nav class="section menu"></nav><main class="section content"><p>
Helps determine whether a payload can be inserted into a stable orbit.
Form field values are explained in the <a href="#equations">Equations</a>
section, below.
- </p><form id="calculator"><button class="submit">Simulate</button><fieldset id="environment"><legend>Environment</legend><label for="surface_temperature">Surface temperature (℃)</label><input tabindex="1" class="variable" type="number" step="1" min="-80" value="25" id="surface_temperature" name="surface_temperature"><label for="relative_humidity">Relative humidity</label><input tabindex="2" class="variable" type="number" step="0.01" min="0" value="86.34" id="surface_temperature" name="surface_temperature"></fieldset><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="8" 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="1" 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="1" min="1" value="1700" id="specific_impulse" name="specific_impulse"></fieldset><button class="submit">Simulate</button><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="1" min="0" value="8" 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="1" 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="1" min="1" value="1700" id="specific_impulse" name="specific_impulse"></fieldset><button class="submit">Simulate</button><fieldset id="result"><legend>Result</legend><div id="plots"></div></fieldset></form><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
<button class="submit">Simulate</button>
- <fieldset id="environment">
- <legend>Environment</legend>
- <label for="surface_temperature">Surface temperature (&#x2103;)</label>
- <input tabindex="1"
- class="variable" type="number" step="1" min="-80" value="25"
- id="surface_temperature" name="surface_temperature" />
-
- <label for="relative_humidity">Relative humidity</label>
- <input tabindex="2"
- class="variable" type="number" step="0.01" min="0" value="86.34"
- id="surface_temperature" name="surface_temperature" />
- </fieldset>
-
<fieldset id="mission">
<legend>Mission</legend>
calculators/variables.xml
<rocket>
<sound>thoom</sound>
- <fuel>metallic hydrogen</fuel>
+ <fuel>
+ <name>metallic hydrogen</name>
+ <impulse>
+ <value>1400</value>
+ <unit>s</unit>
+ </impulse>
+ </fuel>
<dilute>water</dilute>
<combat>basilisk</combat>
- <speed>
- <value>29000</value>
- <unit>kilometers per hour</unit>
- </speed>
+ <mass>
+ <wet>
+ <value>250</value>
+ <unit>kg</unit>
+ </wet>
+ <dry>
+ <value>10</value>
+ <unit>%</unit>
+ </dry>
+ <payload>
+ <value>25</value>
+ <unit>kg</unit>
+ </payload>
+ </mass>
+ <properties>
+ <diameter>
+ <value>0.5</value>
+ <unit>m</unit>
+ </diameter>
+ <length>
+ <value>4</value>
+ <unit>m</unit>
+ </length>
+ <drag>
+ <value>0.219</value>
+ </drag>
+ </properties>
+ <launch>
+ <temperature>
+ <surface>
+ <value>25</value>
+ <unit>Celsius</unit>
+ </surface>
+ </temperature>
+ <velocity>
+ <value>8</value>
+ <unit>Mach</unit>
+ </velocity>
+ <latitude>
+ <value>1.469167</value>
+ <unit>degrees</unit>
+ </latitude>
+ <altitude>
+ <value>6212</value>
+ <unit>m</unit>
+ </altitude>
+ </launch>
</rocket>
<satellite>
index.xsl
<xsl:template match="/">
- <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html&gt;</xsl:text>
<html lang="en">
<head>
Delta 193 lines added, 47 lines removed, 146-line increase