It's cheating but not as much. It's setting the "motion vector" aka setting the speed at current instant. It's just skipping the controls which are normally setting the "motion vector". For the orientation it's totally cheating though using camera.lookat(target).
How does it deal with code blocks normally defined by indentation? (As an aside, indentation being part of syntax is the only thing keeping me disgusted with python - I like the language otherwise.)
it doesn't :) though it works fine if your terminal allows multiline input:
python -c "
for x in stuff:
this(x)
that(x)
"
at some point i even wrote a hacky little wrapper that let you use braces and replaced¹ them with spaces+newlines, something like this:
pyc-wrap "for x in stuff { this(x); that(x); }"
i can dig the code up if you need it :)
========
though after that i sort of went of the deep end adding perl-style "it" ($_) variables for loop variables:
for stuff { this($); that($);
(yes, closing braces at the end were optional...)
and for the result of the previous line:
2; $+1; hex($);
# roughly translates to:
x = 2; x = x+1; x = hex(x);
surprisingly pleasant to use for shell-like tasks actually!
edit: almost forgot - if during execution you used a name `foo` not found in locals/globals, `foo` was treated as an external command, and resolved to something like
lambda *args: os.system('foo', *args)
so that you could (sorta) easily call external commands. fun times :)
---
¹ slightly more involved than a dumb code.replace('{', ':\n') because you need to maintain the indent level... but around that level of sophistication
browser console is a pretty under rated feature. I wish it was used more extensively to teach people how to code. so many cool little hacks you can do on public web pages that cement new concepts quickly.
Very simple P-controller based autopilot derived from the one-liner:
let a = setInterval(() => {
// retrieve values from simulation
let roll = fixedRotationZ;
let pitch = fixedRotationX;
let yaw = fixedRotationY;
let rpy = new THREE.Vector3(roll, pitch, yaw);
let rollRate = -rateRotationZ/10.0;
let pitchRate = -rateRotationX/10.0;
let yawRate = -rateRotationY/10.0;
let rpyRate = new THREE.Vector3(rollRate, pitchRate, yawRate);
let pos = camera.position.clone();
let posRate = motionVector.clone();
let targetPos = issObject.position.clone();
let targetRpy = new THREE.Vector3(0,0,0);
let dRpy = targetRpy.clone().sub(rpy);
// P-controller controls target roll,pitch,yaw-rate (targetRpyRate) to reach target orientation
let targetRpyRate = new THREE.Vector3(
dRpy.x/1.0,
dRpy.y/1.0,
dRpy.z/1.0
);
let minRpyRate = new THREE.Vector3(-1.5, -1.5, -1.5);
let maxRpyRate = new THREE.Vector3(+1.5, +1.5, +1.5);
targetRpyRate.clamp(minRpyRate, maxRpyRate)
let dRpyRate = targetRpyRate.clone().sub(rpyRate);
// don't calculate with displayed x,y,z but the internal coordinates
// (z-axis is forward and backward)
let dPos = targetPos.clone().sub(pos);
let d = dPos.length();
// P-controller controls target motion (targetPosRate) to reach target position
let targetPosRate = new THREE.Vector3(
dPos.x / 100.0,
dPos.y / 100.0,
dPos.z / 100.0
);
let minPosRate = new THREE.Vector3(-0.1, -0.1, -0.01);
let maxPosRate = new THREE.Vector3(+0.1, +0.1, +0.01);
// thresholds for bang contRol
let dRpyRateControlThreshold = new THREE.Vector3(0.0, 0.0, 0.0);
let dPosRateControlThreshold = new THREE.Vector3(0.001, 0.001, 0.001);
// define some phases where we want to have different movement behaviour
if (dRpyRate.length() > 0.1)
{
// not correctly oriented, stop movement
targetPosRate.x = 0;
targetPosRate.y = 0;
targetPosRate.z = 0;
}
else if (Math.abs(dPos.z) < 20)
{
// we are very close, slow approach, larger P-control in lateral
// directions to correct remaining errors
minPosRate.z = -0.005;
maxPosRate.z = +0.005;
dPosRateControlThreshold.x = 0.01;
dPosRateControlThreshold.y = 0.01;
targetPosRate.x = dPos.x;
targetPosRate.y = dPos.y;
}
else if (Math.abs(dPos.z) < 50)
{
// we are getting, close, slow down
minPosRate.z = -0.01;
maxPosRate.z = +0.01;
minPosRate.x = -0.01;
minPosRate.y = -0.01;
maxPosRate.x = +0.01;
maxPosRate.y = +0.01;
}
else if (Math.abs(dPos.z) < 100)
{
// slow down
minPosRate.z = -0.1;
maxPosRate.z = +0.1;
}
else if ((Math.abs(dPos.x) < 0.05) && (Math.abs(dPos.y) < 0.05))
{
// lateral position correct, use maximum approaching speed
minPosRate.z = -0.2;
maxPosRate.z = +0.2;
}
targetPosRate.clamp(minPosRate, maxPosRate);
let dPosRate = targetPosRate.clone().sub(posRate);
// bang control to reach target roll pitch and yaw rate
if (dRpyRate.x < -dRpyRateControlThreshold.x)
rollRight();
else if (dRpyRate.x > +dRpyRateControlThreshold.x)
rollLeft();
if (dRpyRate.y < -dRpyRateControlThreshold.y)
pitchDown();
else if (dRpyRate.y > +dRpyRateControlThreshold.y)
pitchUp();
if (dRpyRate.z < -dRpyRateControlThreshold.z)
yawRight();
else if (dRpyRate.z > +dRpyRateControlThreshold.z)
yawLeft();
// bang control to reach target motion
if (dPosRate.x < -dPosRateControlThreshold.x)
translateLeft();
else if (dPosRate.x > +dPosRateControlThreshold.x)
translateRight();
if (dPosRate.y < -dPosRateControlThreshold.y)
translateDown();
else if (dPosRate.y > +dPosRateControlThreshold.y)
translateUp();
if (dPosRate.z < -dPosRateControlThreshold.z)
translateForward();
else if (dPosRate.z > +dPosRateControlThreshold.z)
translateBackward();
},100);
I would like to see a real autopilot written in javascript that you can paste into the console.