mirror of
https://github.com/osmarks/random-stuff
synced 2025-02-10 08:00:11 +00:00
changes to things
This commit is contained in:
parent
723eb34e40
commit
307c513a9b
13
aidans_bad_code.py
Normal file
13
aidans_bad_code.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
class Primes:
|
||||||
|
def __init__(self, max):
|
||||||
|
self.internal = range(2,max+1)
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
i = self.internal.__iter__().__next__()
|
||||||
|
self.internal = filter(lambda n : n % i != 0, self.internal)
|
||||||
|
return i
|
||||||
|
|
||||||
|
def __iter__(self): return self
|
||||||
|
|
||||||
|
for i in Primes(100):
|
||||||
|
print(i)
|
67
isqgrav.html
Normal file
67
isqgrav.html
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf8">
|
||||||
|
<canvas id="canvas-but-good" width=768 height=768></canvas>
|
||||||
|
<div id="info"></div>
|
||||||
|
<script>
|
||||||
|
const canv = document.getElementById("canvas-but-good")
|
||||||
|
const info = document.getElementById("info")
|
||||||
|
const centerX = canv.width / 2
|
||||||
|
const centerY = canv.height / 2
|
||||||
|
const scale = 0.5
|
||||||
|
const G = 0.1
|
||||||
|
|
||||||
|
const vzero = [0, 0]
|
||||||
|
const vadd = ([a, b], [c, d]) => [a + c, b + d]
|
||||||
|
const vscale = (a, [b, c]) => [a * b, a * c]
|
||||||
|
const vsub = (a, b) => vadd(vscale(-1, a), b)
|
||||||
|
const vmag = ([a, b]) => Math.hypot(a, b)
|
||||||
|
const vnorm = v => vscale(1 / vmag(v), v)
|
||||||
|
const vsum = vs => vs.reduce(vadd, vzero)
|
||||||
|
|
||||||
|
const objects = [] /*[
|
||||||
|
{ x: [0.5, 0.25], v: vzero, m: 1 },
|
||||||
|
{ x: [-0.25, -0.5], v: vzero, m: 0.5 },
|
||||||
|
{ x: [0.25, 0.75], v: vzero, m: 2 }
|
||||||
|
]*/
|
||||||
|
for (let i = 0; i < (1.99 * Math.PI); i += Math.PI / 12) {
|
||||||
|
objects.push({ x: [ Math.cos(i), Math.sin(i) ], v: vzero, m: Math.exp(Math.random() - 0.5) })
|
||||||
|
}
|
||||||
|
|
||||||
|
const ctx = canv.getContext("2d")
|
||||||
|
let previousTimestamp = null
|
||||||
|
function step(timestamp) {
|
||||||
|
const previousPreviousTimestamp = previousTimestamp
|
||||||
|
previousTimestamp = timestamp
|
||||||
|
if (!timestamp) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const timestep = (timestamp - previousPreviousTimestamp) / 1000
|
||||||
|
|
||||||
|
ctx.fillStyle = "black"
|
||||||
|
ctx.fillRect(0, 0, canv.width, canv.height)
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
for (const object of objects) {
|
||||||
|
object.x = vadd(object.x, vscale(timestep, object.v))
|
||||||
|
const F = vsum(objects.filter(x => x !== object).map(x =>
|
||||||
|
vscale(G * (object.m * x.m) * (vmag(vsub(object.x, x.x)) ** -2), vnorm(vsub(object.x, x.x)))
|
||||||
|
))
|
||||||
|
object.v = vadd(object.v, vscale(timestep, vscale(1 / object.m, F)))
|
||||||
|
//console.log(F, object.x, object.v)
|
||||||
|
ctx.beginPath()
|
||||||
|
const disp = vscale(scale, object.x)
|
||||||
|
ctx.arc(centerX + disp[0] * centerX, centerY + disp[1] * centerY, 4 * Math.cbrt(object.m), 0, 2 * Math.PI, false)
|
||||||
|
ctx.fillStyle = `hsl(${i * 73}deg, 100%, 60%)`
|
||||||
|
ctx.fill()
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
const E_k = objects.map(x => 1/2 * x.m * vmag(x.v) ** 2).reduce((a, b) => a + b)
|
||||||
|
// extra division by 2 due to double-counting
|
||||||
|
const E_p = objects.map(o1 => objects.filter(o2 => o2 !== o1).map(o2 => -1/2 * o1.m * o2.m * G * (vmag(vsub(o1.x, o2.x)) ** -1)).reduce((a, b) => a + b)).reduce((a, b) => a + b)
|
||||||
|
info.innerHTML = `E<sub>k</sub>=${E_k.toFixed(2)}<br>E<sub>p</sub>=${E_p.toFixed(2)}<br>sum=${E_k+E_p}`
|
||||||
|
|
||||||
|
requestAnimationFrame(step)
|
||||||
|
}
|
||||||
|
requestAnimationFrame(step)
|
||||||
|
</script>
|
43
pid-controller.py
Normal file
43
pid-controller.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import time
|
||||||
|
import collections
|
||||||
|
|
||||||
|
PIDState = collections.namedtuple("PIDState", ["Kp", "Ki", "Kd", "last_time", "integral", "last_error"])
|
||||||
|
|
||||||
|
def init(Kp, Ki, Kd): return PIDState(Kp, Ki, Kd, None, 0, None)
|
||||||
|
def step(state, error, deriv, ts=None):
|
||||||
|
ts = ts if ts is not None else time.time()
|
||||||
|
integral = state.integral
|
||||||
|
if state.last_time:
|
||||||
|
tdiff = ts - state.last_time
|
||||||
|
integral += 0.5 * (state.last_error + error) * tdiff # approximate actually integrating using a trapzeium
|
||||||
|
output = state.Kp * error + state.Ki * integral + state.Kd * deriv
|
||||||
|
return PIDState(Kp=state.Kp, Ki=state.Ki, Kd=state.Kd, last_time=ts, integral=integral, last_error=error), output
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import matplotlib.pyplot as plt, numpy as np
|
||||||
|
def extract_series(l, ix): return list(map(lambda x: x[ix], l))
|
||||||
|
values = [(10, -10, 0, 0, 0)]
|
||||||
|
state = init(10, 4, -0.3)
|
||||||
|
setpoint = -5
|
||||||
|
max_time = 2
|
||||||
|
timestep = 0.05
|
||||||
|
times = np.arange(0, max_time, timestep)
|
||||||
|
for t in times:
|
||||||
|
current_pv = values[-1][0]
|
||||||
|
error = setpoint - current_pv
|
||||||
|
deriv = (error - (state.last_error or 0)) / timestep
|
||||||
|
state, output = step(state, error, deriv, ts=t)
|
||||||
|
output = max(min(output, 10), -10)
|
||||||
|
print(output, current_pv, error)
|
||||||
|
new_pv = current_pv + (output + 1) * 0.05
|
||||||
|
values.append((new_pv, error, output, state.integral, deriv))
|
||||||
|
#print(values)
|
||||||
|
values = values[1:]
|
||||||
|
plt.axis([0, max_time, -10, 10])
|
||||||
|
plt.plot(times, extract_series(values, 0), label="PV")
|
||||||
|
plt.plot(times, extract_series(values, 1), label="error")
|
||||||
|
plt.plot(times, extract_series(values, 2), label="output")
|
||||||
|
plt.plot(times, extract_series(values, 3), label="integ")
|
||||||
|
plt.plot(times, extract_series(values, 4), label="deriv")
|
||||||
|
plt.legend()
|
||||||
|
plt.show()
|
@ -9,6 +9,7 @@
|
|||||||
const centerY = canv.height / 2
|
const centerY = canv.height / 2
|
||||||
const scale = 0.5
|
const scale = 0.5
|
||||||
const G = 0.1
|
const G = 0.1
|
||||||
|
const stepsPerSecond = 1000
|
||||||
|
|
||||||
const vzero = [0, 0]
|
const vzero = [0, 0]
|
||||||
const vadd = ([a, b], [c, d]) => [a + c, b + d]
|
const vadd = ([a, b], [c, d]) => [a + c, b + d]
|
||||||
@ -35,18 +36,27 @@
|
|||||||
if (!timestamp) {
|
if (!timestamp) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const timestep = (timestamp - previousPreviousTimestamp) / 1000
|
const deltaT = (timestamp - previousPreviousTimestamp) / 1000
|
||||||
|
const stepCount = Math.min(Math.ceil(deltaT * stepsPerSecond), 20)
|
||||||
|
const timestep = deltaT / stepCount
|
||||||
|
console.log(stepCount, deltaT)
|
||||||
|
|
||||||
|
for (let j = 0; j < stepCount; j++) {
|
||||||
|
for (const object of objects) {
|
||||||
|
object.x = vadd(object.x, vscale(timestep, object.v))
|
||||||
|
const F = vsum(objects.filter(x => x !== object).map(x =>
|
||||||
|
vscale(G * (object.m * x.m) * (vmag(vsub(object.x, x.x)) ** 2), vnorm(vsub(object.x, x.x)))
|
||||||
|
))
|
||||||
|
object.v = vadd(object.v, vscale(timestep, vscale(1 / object.m, F)))
|
||||||
|
//console.log(F, object.x, object.v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx.fillStyle = "black"
|
ctx.fillStyle = "black"
|
||||||
ctx.fillRect(0, 0, canv.width, canv.height)
|
ctx.fillRect(0, 0, canv.width, canv.height)
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
for (const object of objects) {
|
for (const object of objects) {
|
||||||
object.x = vadd(object.x, vscale(timestep, object.v))
|
|
||||||
const F = vsum(objects.filter(x => x !== object).map(x =>
|
|
||||||
vscale(G * (object.m * x.m) * (vmag(vsub(object.x, x.x)) ** 2), vnorm(vsub(object.x, x.x)))
|
|
||||||
))
|
|
||||||
object.v = vadd(object.v, vscale(timestep, vscale(1 / object.m, F)))
|
|
||||||
//console.log(F, object.x, object.v)
|
//console.log(F, object.x, object.v)
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
const disp = vscale(scale, object.x)
|
const disp = vscale(scale, object.x)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user