noc03-doublePendulum

doublePendulum

Add some features:

  • change color
  • change mass of the circle
  • change length of the linkage
  • draw the trace

Thus I can play with the trace to see waht happens when the mass and length changes. And if press space bar, the trace will be cleared.

source code

ofApp.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#pragma once
#include "ofMain.h"
#include "ofxGui.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
void keyPressed(int key);
// in case not using Gui
// float phi1, omega1, phi2, omega2;
// float mass1, mass2;
// float length1, length2;
float x1, y1, x2, y2;
float cx, cy;
double k1[4], l1[4], k2[4], l2[4];
double domega1(double phi1, double phi2, double omega1, double omega2);
double domega2(double phi1, double phi2, double omega1, double omega2);
double gc;
double dt;
double friction;
ofEasyCam cam;
ofxPanel gui;
ofParameter<double>mass1,mass2,length1,length2;
ofParameter<double>phi1, omega1, phi2, omega2;
ofParameter<ofColor>color;
ofParameter<bool>bDrawLine;
ofParameter<bool>bDrawPoint;
ofMesh mesh;
};

ofApp.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
// fast easy way to see trace
// ofSetBackgroundAuto(false);
ofBackground(0);
gc = 9.81;
dt = 0.01;
friction=0.0;
cx = ofGetWidth()/2;
cy = 200;
// in case not using Gui
// length1 = 0.59;
// length2 = 0.75;
// mass1 = 3;
// mass2 = 1;
// phi1 = ofDegToRad(-100);
// phi1 = ofDegToRad(40);
// omega1 = 5.1;
// omega2 = 1.1;
ofSetLineWidth(0.3);
ofNoFill();
gui.setup();
gui.add(color.set("color",
ofFloatColor(1,1,1,1),
ofFloatColor(0,0,0,0),
ofFloatColor(1,1,1,1)));
gui.add(mass1.set("mass1",40.0,0.0,200));
gui.add(mass2.set("mass2",32.0,0.0,200));
gui.add(length1.set("length1",1.5,0.0,5));
gui.add(length2.set("length2",0.75,0.0,5));
gui.add(phi1.set("phi1",ofDegToRad(-120),ofDegToRad(-360*3),ofDegToRad(360*3)));
gui.add(phi2.set("phi2",ofDegToRad(90),ofDegToRad(-360*3),ofDegToRad(360*3)));
gui.add(omega1.set("omega1",ofDegToRad(0),ofDegToRad(-360*3),ofDegToRad(360*3)));
gui.add(omega2.set("omega2",ofDegToRad(0),ofDegToRad(-360*3),ofDegToRad(360*3)));
gui.add(bDrawLine.set("bDrawLine",true,true,false));
gui.add(bDrawPoint.set("bDrawPoint",false,true,false));
// try every mode !!!
// mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP);
mesh.setMode(OF_PRIMITIVE_LINE_STRIP);
}
//--------------------------------------------------------------
void ofApp::update(){
k1[0] = dt*omega1;
l1[0] = dt*domega1(phi1, phi2, omega1, omega2);
k1[1] = dt*(omega1+l1[0]/2);
l1[1] = dt*domega1(phi1+k1[0]/2, phi2, omega1+l1[0]/2, omega2);
k1[2] = dt*(omega1+l1[1]/2);
l1[2] = dt*domega1(phi1+k1[1]/2, phi2, omega1+l1[1]/2, omega2);
k1[3] = dt*(omega1+l1[2]);
l1[3] = dt*domega1(phi1+k1[2], phi2, omega1+l1[2], omega2);
k2[0] = dt*omega2;
l2[0] = dt*domega2(phi1, phi2, omega1, omega2);
k2[1] = dt*(omega2+l2[0]/2);
l2[1] = dt*domega2(phi1, phi2+k2[0]/2, omega1, omega2+l2[0]/2);
k2[2] = dt*(omega2+l2[1]/2);
l2[2] = dt*domega2(phi1, phi2+k2[1]/2, omega1, omega2+l2[1]/2);
k2[3] = dt*(omega2+l2[2]);
l2[3] = dt*domega2(phi1, phi2+k2[2], omega1, omega2+l2[2]);
phi1 = phi1 + (k1[0]+2*k1[1]+2*k1[2]+k1[3])/6;
omega1 = omega1 + (l1[0]+2*l1[1]+2*l1[2]+l1[3])/6;
phi2 = phi2 + (k2[0]+2*k2[1]+2*k2[2]+k2[3])/6;
omega2 = omega2 + (l2[0]+2*l2[1]+2*l2[2]+l2[3])/6;
x1=(float)(cx+100*length1*sin(phi1));
y1=(float)(cy+100*length1*cos(phi1));
x2=(float)(x1+100*length2*sin(phi2));
y2=(float)(y1+100*length2*cos(phi2));
if(bDrawPoint == false){
bDrawLine = true;
}
length1 += 0.0003;
length2 += 0.0005;
}
//--------------------------------------------------------------
void ofApp::draw(){
// cam.begin();
if(bDrawLine){
ofSetColor(255);
ofDrawLine((float)cx, (float)cy, -1, x1, y1, -1);
ofDrawLine(x1, y1, -1, x2, y2, -1);
ofDrawCircle(x1, y1, 5);
ofDrawCircle(x2, y2, 5);
ofDrawCircle(cx,cy,5);
}
if(bDrawPoint){
ofSetColor(color);
ofBeginShape();
mesh.addVertex(ofVec3f(x2,y2,-1));
mesh.draw();
ofEndShape();
}
gui.draw();
// cam.end();
}
//--------------------------------------------------------------
double ofApp:: domega1(double phi1, double phi2, double omega1, double omega2) {
return (-gc*(2*mass1+ mass2)* sin(phi1)-mass2*gc* sin(phi1-2*phi2)-2* sin(phi1-phi2)*mass2*(omega2*omega2*length2+omega1*omega1*length1* cos(phi1-phi2)) )/ (length1*( 2*mass1 + mass2 - mass2 * cos(2*phi1-2*phi2)))-friction * omega1;
}
//--------------------------------------------------------------
double ofApp:: domega2(double phi1, double phi2, double omega1, double omega2) {
return 2*sin(phi1-phi2)*(omega1*omega1*length1*(mass1+mass2)+gc*(mass1+mass2)*cos(phi1)+omega2*omega2*length2*mass2* cos(phi1-phi2))/ (length2*( 2*mass1 + mass2 - mass2* cos(2*phi1-2*phi2))) -friction*omega2;
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key){
if(key == ' '){
mesh.clear();
}
}