xxxxxxxxxx
210
// Display parameters
var cnv = {
w: 500,
h: 500
};
var pivot = {
x: cnv.w / 2,
y: cnv.h / 2
};
var fr = 90;
var tracer;
// The parameters of the problem
const dt = 1.0 / 1000;
// The variables of the problem
var dp1, dp2;
var vp1, vp2;
// setup capture
// let framerate = 90;
// var capturer = new CCapture( {format: 'webm', framerate, name: 'double_pendulum', quality: 95, verbose: true} );
// let canvas;
function setup() {
// put setup code here
var cnvs = createCanvas(cnv.w, cnv.h);
// canvas = cnvs.canvas;
frameRate(fr);
tracer = createGraphics(cnv.w, cnv.h);
// Create double-pendulum instances
dp1 = new DoublePendulum(1, 5, 5, 5, 0);
// dp2 = new DoublePendulum();
dp1.initialize(dt, 0, 0, 0.2, 0.067);
// dp2.initialize(dt, 3, 3.0001745, 0, 0);
dp1.setColor(120, 0, 0);
// dp2.setColor(0, 0, 120);
dp1.pivot = createVector(pivot.x, pivot.y);
// dp2.pivot = createVector(pivot.x, pivot.y);
vp1 = dp1.loc2;
// vp2 = dp2.loc2;
// Start the capturer
// capturer.start();
// draw();
// noLoop();
}
function draw() {
// Black background, white pendulum
background(220);
// tracer
let w1 = 1.9*exp(-(dp1.mom2**2)/10) + 0.7
// let w2 = 1.9*exp(-(dp2.mom2**2)/10) + 0.7
tracer.strokeCap(SQUARE);
tracer.stroke(150, 0, 0, 100);
tracer.strokeWeight(w1);
tracer.line(vp1.x, vp1.y, dp1.loc2.x, dp1.loc2.y);
// tracer.stroke(0, 0, 150, 100);
// tracer.strokeWeight(w2);
// tracer.line(vp2.x, vp2.y, dp2.loc2.x, dp2.loc2.y);
if(frameCount%8 == 0) tracer.background(220, 5);
image(tracer, 0, 0);
vp1 = dp1.loc2;
// vp2 = dp2.loc2;
dp1.paint();
// dp2.paint();
dp1.step();
// dp2.step();
dp1.integrate();
// dp2.integrate();
// if(frameCount >= 60) {
// noLoop();
// }
// if(frameCount >= 3600) {
// capturer.stop();
// capturer.save();
// noLoop();
// }
// else capturer.capture(canvas);
}
function integrator(a, da) {
// Euler method
let a_ = a.map(function(num, idx) {
return num + dt * da[idx];
});
return a_;
}
class DoublePendulum {
constructor(U = 1, g1 = 1, g2 = 1, del1 = 0, del2 = 0) {
this.U = U;
this.g1 = g1;
this.g2 = g2;
this.del1 = del1;
this.del2 = del2;
this.pvt = createVector(0, 0);
// this.Lscale = 0.4 * cnv.h / (len1 + len2);
this.Lscale = 1.5*cnv.h;
}
initialize(dt, phi1 = 0, phi2 = 0, z1 = 0, z2 = 0) {
this.dt = dt;
this.q1 = phi1;
this.q2 = phi2;
this.p1 = z1;
this.p2 = z2;
this.length1 = (2*z1 + z2 - 1/6) * sqrt(-z1 + z2 + 1/3);
this.length2 = sqrt((2*z1 + z2 - 1/6)*(-z1 + z2 + 1/3)*(-z2 + 1/6));
}
setColor(r, g, b) {
this.bob1 = color(r, g, b);
function lighten(clr) {
return (255 - clr)*0.3 + clr;
}
this.bob2 = color(lighten(r), lighten(g), lighten(b));
}
set pivot(vec) {
this.pvt = vec;
}
step() {
let q1 = this.q1;
let q2 = this.q2;
let z1 = this.p1;
let z2 = this.p2;
let U = this.U;
let g1 = this.g1;
let g2 = this.g2;
let del1 = this.del1;
let del2 = this.del2;
let Na = 2 * z1 + z2 - 1/6;
let Nb = -z1 + z2 + 1/3;
let Nd = -z2 + 1/6;
this.length1 = Na*sqrt(Nb);
this.length2 = sqrt(Na*Nb*Nd);
// console.log(Na, Nb, Nd);
// console.log(z1, z2);
this.dq1 = U * (Na + Nb + Nd) + 4 * g1 * sqrt(Nb) * cos(q1) + 2 * g2 * sqrt(Nb * Nd / Na) * cos(q2) - g1 * Na / sqrt(Nb) * cos(q1) - g2 * sqrt(Na * Nd / Nb) * cos(q2) - del1;
this.dq2 = U * (Na + Nb + Nd) + 2 * g1 * sqrt(Nb) * cos(q1) + g2 * sqrt(Nb * Nd / Na) * cos(q2) + g1 * Na / sqrt(Nb) * cos(q1) + g2 * (sqrt(Na * Nd / Nb) - sqrt(Na * Nb / Nd)) * cos(q2) + (del1 - del2);
this.dp1 = 2 * g1 * Na * sqrt(Nb) * sin(q1);
this.dp2 = 2 * g2 * sqrt(Na * Nb * Nd) * sin(q2);
}
integrate() {
// RK2 method
this.q1 = this.q1 + this.dt * this.dq1;
this.q2 = this.q2 + this.dt * this.dq2;
this.p1 = this.p1 + this.dt * this.dp1;
this.p2 = this.p2 + this.dt * this.dp2;
}
get loc1() {
let x = this.pvt.x + this.length1 * this.Lscale * sin(this.q1);
let y = this.pvt.y + this.length1 * this.Lscale * cos(this.q1);
return createVector(x, y);
}
get loc2() {
let x = this.loc1.x + this.length2 * this.Lscale * sin(this.q2);
let y = this.loc1.y + this.length2 * this.Lscale * cos(this.q2);
return createVector(x, y);
}
get mom1() {
return this.p1;
}
get mom2() {
return this.p2;
}
paint() {
ellipseMode(CENTER);
fill(5);
ellipse(this.pvt.x, this.pvt.y, 5);
stroke(20);
fill(this.bob1);
line(this.pvt.x, this.pvt.y, this.loc1.x, this.loc1.y);
ellipse(this.loc1.x, this.loc1.y, 12);
fill(this.bob2);
line(this.loc1.x, this.loc1.y, this.loc2.x, this.loc2.y);
ellipse(this.loc2.x, this.loc2.y, 12);
}
}