{
   "author" : "xavieredavenport",
   "name" : "Damped Driven Double Pendulum Sonification and Visualization",
   "description" : "ctrl+enter to run\r\nctrl+. to stop\r\n\r\nVersion 1.\r\nA little toy physics simulation of a double pendulum with damping and drive. The math is a little inconsistent in SuperCollider when dealing with numbers super small and super large, especially when trig functions are involved. I've tried to mitigate the errors by using sinPi instead of regular sin, but you still have to be careful when setting system variables. A strong damping is a must, and you have to be very careful when adding a drive to the system. Otherwise, we see the expected chaotic behavior for a range of easier-to-calculate parameters.\r\n\r\nPitch is determined by the distance of the second pendulum bob from the center of the screen, while amplitude is determined by the velocity of the bob.",
   "ancestor_list" : [],
   "labels" : [
      "sonification",
      "physics",
      "pendulum"
   ],
   "code" : "(\r\n\r\n///////////////////////\r\n// Variable declaration\r\n///////////////////////\r\n\r\nvar centerx = 410, centery = 410, //Coordinates used to offset the pendulum fixed point\r\nr1 = 200, //Length of pendulum rod 1\r\nr2 = 200, //Length of pendulum rod 2\r\nm1 = 20, //Mass of pendulum bob 1\r\nm2 = 20, //Mass of pendulum bob 2\r\na1 = pi+(rrand(0.0001,0.0009)), //Initial angle of pendulum 1\r\na2 = pi, //Initial angle of pendulum 2\r\na1_v = 0, //Initial velocity of pendulum 1\r\na2_v = 0, //Initial velocity of pendulum 2\r\ng = 1.0, //Gravitational constant\r\n\r\ntime_step = 1.0,\r\ntime = 0,\r\nk1 = 10.0, //Damping coefficient of pendulum 1\r\nk2 = 10.0, //Damping coefficient of pendulum 2, usually same as pendulum 1\r\nforce1 = 0.0, //Magnitude of oscillation strength\r\nforce2 = 0.0, //This is usually kept at 0\r\n//freq1 = sqrt(g/r1)*sqrt(2+sqrt(2))/100,\r\nfreq1 = 0.0, //Drive frequency for pendulum 1\r\nfreq2 = 0.0, //Drive frequency for pendulum 2\r\niterations = 0, //Total frames drawn\r\nalpha, beta, deltheta, num1, num2, num3, num4, gamma, den, //mathematical functions\r\na1_a, a2_a,  // accelerations\r\nx1, y1, x2, y2, // positions\r\n\r\npitch = 440,\r\n\r\n///////////////////////\r\n// Window setup\r\n///////////////////////\r\n\r\n\r\nwidth = 820, height = 820,\r\nw = Window(\"Double Pendulum\", Rect(99, 99, width, height), false),\r\nu = UserView(w, Rect(0, 0, width, height));\r\n\r\nu.clearOnRefresh = true;\r\nu.background = Color.white;\r\nw.front;\r\nu.frameRate = 40;\r\nu.animate = true;\r\nCmdPeriod.doOnce({if(w.isClosed.not, {w.close})});\r\n\r\n\r\n\r\n\r\n///////////////////////\r\n// Synthdef(s)\r\n///////////////////////\r\n\r\n\r\nSynthDef(\\gliss, {\r\n\targ freq=440, gate=1, amp=0.0, out=0;\r\n\tvar sig, env;\r\n\tfreq = Lag.kr(freq, 1);\r\n\tamp = Lag.kr(amp, 1);\r\n\tenv = EnvGen.kr(Env.asr, gate, doneAction:2);\r\n\tsig = SinOsc.ar(freq)!2;\r\n\tsig = sig * amp;\r\n\tsig = sig * env;\r\n\tOut.ar(out, sig);\r\n}).add;\r\n\r\n\r\nx = Synth(\\gliss);\r\n\r\nu.drawFunc = {\r\n\r\n\r\n\r\n\r\n\t///////////////////////\r\n\t// Equations\r\n\t///////////////////////\r\n\r\n\talpha = (k1 * a1_v) - (force1 * cosPi(freq1 * time));\r\n\tbeta = (k2 * a2_v) - (force2 * cosPi(freq2 * time));\r\n\tdeltheta = a1-a2;\r\n\r\n\tnum1 = m2 * r1 * a1_v * a1_v * sinPi(2 * deltheta);\r\n\tnum2 = 2 * m2 * r2 * a2_v * a2_v * sinPi(deltheta);\r\n\tnum3 = 2 * g * m2 * cosPi(a2)*sinPi(deltheta);\r\n\tnum4 = 2 * g * m1 * sinPi(a1);\r\n\tgamma = (2*alpha) - (2*beta*cosPi(deltheta));\r\n\tden = (-2 * r1*m1) + (r1*m2*sinPi(deltheta)*sinPi(deltheta));\r\n\ta1_a = (num1 + num2 + num3 + num4 + gamma)/den;\r\n\r\n\tnum1 = m2 * r2 * a2_v * a2_v * sinPi(2 * deltheta);\r\n\tnum2 = 2 * (m1+m2) * r1 * a1_v*a1_v * sinPi(deltheta);\r\n\tnum3 = 2 * g * (m1+m2) * cosPi(a1)*sinPi(deltheta);\r\n\tgamma = (2*alpha*cosPi(deltheta)) - (2*(m1+m2)*beta/m2);\r\n\tden = (2 * r2*m1) + (r2*m2*sinPi(deltheta)*sinPi(deltheta));\r\n\ta2_a = (num1 + num2 + num3 + gamma)/den;\r\n\r\n\tx1 = r1 * sinPi(a1);\r\n\ty1 = r1 * cosPi(a1);\r\n\r\n\tx2 = x1 + (r2 * sinPi(a2));\r\n\ty2 = y1 + (r2 * cosPi(a2));\r\n\r\n\r\n\r\n\t///////////////////////\r\n\t// Advance position\r\n\t///////////////////////\r\n\r\n\ta1_v = a1_v + a1_a;\r\n\ta2_v = a2_v + a2_a;\r\n\ta1 = a1 + a1_v;\r\n\ta2 = a2 + a2_v;\r\n\r\n\r\n\t///////////////////////\r\n\t// Create Window and draw pendulum\r\n\t///////////////////////\r\n\r\n\r\n\tPen.strokeColor = Color.blue;\r\n\tPen.width = 2;\r\n\tPen.moveTo(centerx@centery);\r\n\tPen.lineTo((centerx+x1)@(centery+y1));\r\n\tPen.lineTo((centerx+x2)@(centery+y2));\r\n\tPen.stroke;\r\n\tPen.strokeOval(Rect(centerx+x1-5, centery+y1-5, 10, 10));\r\n\tPen.strokeOval(Rect(centerx+x2-5, centery+y2-5, 10, 10));\r\n\r\n\tpitch = sqrt((x2*x2)+(y2*y2));\r\n\r\n\tx.set(\\freq, pitch);\r\n\tx.set(\\amp, a2_v*5);\r\n\r\n\ttime = time + time_step;\r\n\r\n\titerations = iterations + 1;\r\n};\r\n\r\n)",
   "id" : "1-5f4",
   "is_private" : null
}
