Skip to content

Instantly share code, notes, and snippets.

@ggerganov
Created May 16, 2020 12:30
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save ggerganov/092b86a59fa34926998953701ae22ca1 to your computer and use it in GitHub Desktop.
Save ggerganov/092b86a59fa34926998953701ae22ca1 to your computer and use it in GitHub Desktop.
Automatic ISS Docking in Javascript
// Auto-pilot for docking with the International Space Station
//
// The program uses Artificial Intelligence and Decision Trees (i.e. basic kinematics and a bunch of if statements)
// to perform docking with the ISS from any starting position.
//
// To use it:
// - open the SpaceX simulation website: https://iss-sim.spacex.com/
// - open the Developer's console and paste the contents of this file
//
// Demo: https://youtu.be/jWQQH2_UGLw
//
function el(v) { return document.getElementById(v); }
function blink(e) { e.style.backgroundColor='red'; setTimeout(()=>{ e.style.backgroundColor=''; }, 100); }
// Sensor data
function getPitch(i) { return parseFloat(el('pitch').children[i].innerText); }
function getYaw(i) { return parseFloat(el('yaw').children[i].innerText); }
function getRoll(i) { return parseFloat(el('roll').children[i].innerText); }
function getRange() { return parseFloat(el('range').children[1].innerText); }
function getRangeX() { return parseFloat(el('x-range').children[0].innerText); }
function getRangeY() { return parseFloat(el('y-range').children[0].innerText); }
function getRangeZ() { return parseFloat(el('z-range').children[0].innerText); }
function getRate() { return parseFloat(el('rate').children[1].innerText); }
// Controls
function moveForward() { e = el('translate-forward-button'); blink(e); e.click(); }
function moveBackward() { e = el('translate-backward-button'); blink(e); e.click(); }
function moveUp() { e = el('translate-up-button'); blink(e); e.click(); }
function moveDown() { e = el('translate-down-button'); blink(e); e.click(); }
function moveLeft() { e = el('translate-left-button'); blink(e); e.click(); }
function moveRight() { e = el('translate-right-button'); blink(e); e.click(); }
function yawLeft() { e = el('yaw-left-button'); blink(e); e.click(); }
function yawRight() { e = el('yaw-right-button'); blink(e); e.click(); }
function pitchUp() { e = el('pitch-up-button'); blink(e); e.click(); }
function pitchDown() { e = el('pitch-down-button'); blink(e); e.click(); }
function rollLeft() { e = el('roll-left-button'); blink(e); e.click(); }
function rollRight() { e = el('roll-right-button'); blink(e); e.click(); }
// Artificial Intelligence
var a = 0.1;
var dt = 0.100;
var cnt = 0;
var hist = {
yaw: [0, 0, 0],
roll: [0, 0, 0],
pitch: [0, 0, 0],
y: [0, 0, 0],
z: [0, 0, 0],
r: [0, 0, 0]
};
function AI(dt, x, v, a, finc, fdec) {
T = dt*Math.abs(v/a);
var target = x + v*T - 0.5*Math.sign(v)*a*T*T;
setTimeout(target < 0.0 ? finc : target > 0.0 ? fdec : ()=>{}, 0.8*Math.random()*dt*1000);
}
function v(x) {
var i = cnt - 3; if (i < 0) i += 3; var p0 = hist[x][i];
var i = cnt - 1; if (i < 0) i += 3; var p2 = hist[x][i];
return (p2 - p0)/(2*dt);
}
// Decision tree
function update() {
okYaw = Math.abs(getYaw(0)) < 2.0;
okRoll = Math.abs(getRoll(0)) < 2.0;
okPitch = Math.abs(getPitch(0)) < 2.0;
hist['yaw'][cnt] = getYaw(0);
hist['roll'][cnt] = getRoll(0);
hist['pitch'][cnt] = getPitch(0);
hist['y'][cnt] = getRangeY(0);
hist['z'][cnt] = getRangeZ(0);
hist['r'][cnt] = getRange() - 2.0;
if (++cnt > 2) cnt = 0;
if (okYaw && okRoll && okPitch) {
AI(dt, getRangeY(), v('y'), a, moveRight, moveLeft);
AI(dt, getRangeZ(), v('z'), a, moveUp, moveDown);
if (Math.abs(getRangeY() < 10.0) && Math.abs(getRangeZ() < 10.0)) {
if (getRange() > 2.0) {
AI(dt, getRange() - 2.0, v('r'), 0.5*a, moveBackward, moveForward);
} else {
if (getRate() < -0.15) {
moveBackward();
} else if (getRate() > -0.05) {
moveForward();
}
}
}
}
if (okYaw && okRoll && okPitch) {
AI(dt, getYaw(0), -getYaw(1), 0.2*a, yawLeft, yawRight);
AI(dt, getRoll(0), -getRoll(1), 0.2*a, rollLeft, rollRight);
AI(dt, getPitch(0), -getPitch(1), 0.2*a, pitchUp, pitchDown);
} else {
AI(dt, getYaw(0), v('yaw'), a, yawLeft, yawRight);
AI(dt, getRoll(0), v('roll'), a, rollLeft, rollRight);
AI(dt, getPitch(0), v('pitch'), a, pitchUp, pitchDown);
}
setTimeout(update, dt*1000);
}
update();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment