double pendulums

swing togeteher or perish

Log in to post a comment.

Canvas.setpenopacity(-0.1);

const N = 40; // min=5, max=40, step=1
const M = 50; // min=10, max=100, step=1
const L1 = 50; // min=10, max=90, step=1
const L2 = 50; // min=10, max=90, step=1
const delta = 0.03; // min = 0.01, max=2.0, step = 0.01
const d_max = 5; // min=1, max=15, step=0.1
const dt = 0.03; // min=0.01, max=0.1, step=0.01
const g = 2.5; // min=1, max=20, step=0.1

const turtles = []
const phi1 = []
const phi2 = []
const speed1 = []
const speed2 = []
const done = []

const m1 = 1, m2 = 1

for (let i = 0; i < N; i++) {
    turtles[i] = new Turtle();
    
    phi1[i] = []
    phi2[i] = []
    speed1[i] = []
    speed2[i] = []
    done[i] = []
    
    p1 = Math.random() * 2 * Math.PI
    p2 = Math.random() * 2 * Math.PI
    
    for (let j = 0; j < M; j++) {
        done[i][j] = false
        
        phi1[i][j] = p1 - delta/2 + delta/(M - 1)*j
        phi2[i][j] = p2 - delta/2 + delta/(M - 1)*j
        speed1[i][j] = 0
        speed2[i][j] = 0
    }
}

function walk(i) {
    let n_active = 0
    
    for (let i = 0; i < N; i++) {
        if (! done[i][0]) {
            n_active++
            
            let not_done = 0
            let x0 = 0, y0 = 0
            
            for (let j = 0; j < M; j++) {
                if (! done[i][j]) {
                    not_done++
                    
                    let prvx1 = L1 * Math.sin(phi1[i][j])
                    let prvy1 = L1 * Math.cos(phi1[i][j])

                    let prvx2 = prvx1 + L2 * Math.sin(phi2[i][j])
                    let prvy2 = prvy1 + L2 * Math.cos(phi2[i][j])

                    let p1 = phi1[i][j], p2 = phi2[i][j]
                    let o1 = speed1[i][j], o2 = speed2[i][j]
                    
                    let omega1 = (-g * (2 * m1 + m2) * Math.sin(p1) - m2 * g * Math.sin(p1 - 2 * p2) - 2 * Math.sin(p1 - p2) * m2 * (o2**2 * L2 + o1**2 * L1 * Math.cos(p1 - p2))) / (L1 * (2 * m1 + m2 - m2 * Math.cos(2 * p1 - 2 * p2)))
                    let omega2 = 2 * Math.sin(p1 - p2) * (o1**2  * L1 * (m1 + m2) + g * (m1 + m2) * Math.cos(p1) + o2**2 * L2 * m2 * Math.cos(p1 - p2)) / (L2 * (2 * m1 + m2 - m2 * Math.cos(2 * p1 - 2 * p2)))
                    
                    speed1[i][j] += omega1 * dt
                    speed2[i][j] += omega2 * dt
                    
                    phi1[i][j] += speed1[i][j] * dt
                    phi2[i][j] += speed2[i][j] * dt
                    
                    let newx1 = L1 * Math.sin(phi1[i][j])
                    let newy1 = L1 * Math.cos(phi1[i][j])

                    let newx2 = newx1 + L2 * Math.sin(phi2[i][j])
                    let newy2 = newy1 + L2 * Math.cos(phi2[i][j])
                    
                    if (j == 0) {
                        x0 = newx2
                        y0 = newy2
                    }
                    else if ((newx2 - x0)**2 + (newy2 - y0)**2 > d_max**2) {
                        done[i][j] = true
                    }
                    
                    turtles[i].jump(prvx2, prvy2)
                    turtles[i].goto(newx2, newy2)
                }
            }
            
            if (not_done == 1) {
                done[i][0] = true
            }
        }
    }
    
    return (n_active > 0) && (i < 10000)
}