Свободные колебания механической системы с двумя степенями свободы — различия между версиями
Материал из Department of Theoretical and Applied Mechanics
Den.syzr (обсуждение | вклад) (→Код программы) |
Den.syzr (обсуждение | вклад) |
||
Строка 386: | Строка 386: | ||
* three.js | * three.js | ||
* dat.gui.js | * dat.gui.js | ||
+ | |||
+ | == Возможности программы == | ||
+ | |||
+ | * Изменение начальных условий; | ||
+ | * Вывод графиков координаты центра масс и угла наклона стержня. |
Текущая версия на 06:25, 14 июня 2018
Задача: Смоделировать свободные колебания механической системы с двумя степенями свободы.
Исполнитель: Сызранцев Денис, гр. 23632/2.
Реализация[править]
Код программы[править]
1 <!DOCTYPE html>
2 <html>
3
4 <head>
5 <title>Д24 Вариант №12</title>
6 <script type="text/javascript" src="http://tm.spbstu.ru/htmlets/libs/three.min.js"></script>
7 <script type="text/javascript" src="http://tm.spbstu.ru/htmlets/libs/stats.min.js"></script>
8 <script type="text/javascript" src="http://tm.spbstu.ru/htmlets/libs/dat.gui.min.js"></script>
9 <style>
10 body{
11 margin: 0;
12 overflow: hidden;
13 }
14 </style>
15 </head>
16 <body>
17 <table>
18 <tr>
19 <div id="Stats-output">
20 </div>
21 <div id="WebGL-output">
22 </div>
23 <div>
24 <canvas id="canvas_example1" width=1 height=1></canvas><br>
25 </div>
26 <div>
27 <canvas id="canvas_example2" width=1 height=1></canvas><br>
28 </div>
29 <script type="text/javascript">
30 var ctx1 = canvas_example1.getContext('2d');
31 var w1 = canvas_example1.width = window.innerWidth;
32 var h1 = canvas_example1.height = window.innerHeight/4;
33
34 var ctx2 = canvas_example2.getContext('2d');
35 var w2 = canvas_example2.width = window.innerWidth;
36 var h2 = canvas_example2.height = window.innerHeight/4;
37
38 var WebW = window.innerWidth;
39 var WebH = window.innerHeight/2;
40 var stats=initStats();
41 var scene=new THREE.Scene();
42 var camera=new THREE.PerspectiveCamera(45,WebW/WebH,0.1,1000);
43 var renderer=new THREE.WebGLRenderer();
44 scene.background=new THREE.Color(0xEEEEEE);
45 camera.position.set(0,0,15);
46 camera.lookAt(new THREE.Vector3(0,0,0));
47 renderer.setClearColor(new THREE.Color(0xFFFFFF,1.0));
48 renderer.setSize(WebW, WebH);
49 renderer.shadowMap.enabled=true;
50
51 var material1 = new THREE.MeshPhongMaterial( {
52 color: 0x156289,
53 emissive: 0x072534,
54 side: THREE.DoubleSide,
55 flatShading: true
56 } )
57
58 var material2 = new THREE.MeshPhongMaterial( {
59 color: 0xF9FFF5,
60 emissive: 0x072534,
61 side: THREE.DoubleSide,
62 flatShading: true
63 } )
64
65 var rc=0.2,lc=5,n=20,by=-5,sl=0.7;
66 var rod=new THREE.Mesh(new THREE.CylinderGeometry(rc,rc,lc,32,0),material1);
67 var base=new THREE.Mesh(new THREE.BoxGeometry(lc,0.7,0.7),material2);
68 base.position.set(0,by,0);
69
70 for(var k=1;k<=3;k++)
71 for(var i=0;i<=n;i++)
72 {
73 var nexus=new THREE.Mesh(new THREE.CylinderGeometry(0.05,0.05,sl),new THREE.MeshLambertMaterial({color:0xF9FFF5}));
74 nexus.name=k+"-"+i;
75 nexus.castShadow=true;
76 scene.add(nexus);
77 }
78 var ambientLight=new THREE.AmbientLight(0x0F0F0F);
79 var spotLight=new THREE.SpotLight(0xFFFFFF);
80
81 rod.castShadow=true;
82 spotLight.castShadow=true;
83
84 scene.add(base);
85 scene.add(rod);
86 scene.add(ambientLight);
87 scene.add(spotLight);
88
89 document.getElementById("WebGL-output").appendChild(renderer.domElement);
90
91 var l,m,g,c1,c2,c3;
92 var k1,k2,mu1,mu2;
93 var A1,A2,b1,b2;
94 var y0,f0,v0,w0;
95 var a11,a12,a22;
96 var c11,c12,c22;
97 var yt,ft;
98 var Y,F;
99 var t=0,dt,fl=true;
100 var cnt=new function()
101 {
102 this.dt=0.002;
103 this.y0=0.5;
104 this.f0=5;
105 this.v0=0.5;
106 this.w0=0.5;
107 this.l=1;
108 this.m=6;
109 this.g = 9.8;
110 this.c1=2000;
111 this.c2=3000;
112 this.c3=4000;
113 this.a11 = this.m;
114 this.a12 = 0;
115 this.a22 = (this.m*Math.pow(this.l,2))/3;
116 this.c11 = this.c1+this.c2+this.c3;
117 this.c12 = (this.c1+this.c2/2-this.c3)*this.l;
118 this.c22 = (this.c1+this.c2/4+this.c3)*Math.pow(this.l,2);
119 this.Y = this.m*this.g/(this.c1+this.c2+this.c3);
120 this.F = (Math.asin(2*this.m*this.g/(Math.pow(this.l,2)*(this.c3-this.c2/4-this.c1))))/2
121 this.pause=function(){fl=false;}
122 this.resume=function(){fl=true;}
123 this.redraw=function()
124 {
125 t=0;
126 y0=cnt.y0;
127 f0=Math.PI*cnt.f0/180;
128 v0=cnt.v0;
129 w0=cnt.w0;
130 dt=cnt.dt;
131 l=cnt.l;
132 m=cnt.m;
133 c1=cnt.c1;
134 c2=cnt.c2;
135 c3=cnt.c3;
136 a11=cnt.a11;
137 a12=cnt.a12;
138 a22=cnt.a22;
139 c11=cnt.c11;
140 c12=cnt.c12;
141 c22=cnt.c22;
142 Y=cnt.Y;
143 F=cnt.F;
144 scene.remove(rod);
145 scene.remove(base);
146 rod=new THREE.Mesh(new THREE.CylinderGeometry(rc,rc,l*10,32,0),material1);
147 base=new THREE.Mesh(new THREE.BoxGeometry(l*10+2,0.7,0.7),material2);
148 base.position.set(0,by,0);
149 scene.add(rod);
150 scene.add(base);
151 ctx1.clearRect(0,0,w1,h1);
152 ctx2.clearRect(0,0,w2,h2);
153 Yt = [];
154 Ft = [];
155 init();
156 };
157 };
158
159 var gui=new dat.GUI();
160 gui.add(cnt,'dt',0.001,0.005);
161 gui.add(cnt,'y0',-1,1);
162 gui.add(cnt,'f0',-15,15);
163 gui.add(cnt,'v0',-0.7,0.7);
164 gui.add(cnt,'w0',-0.7,0.7);
165 gui.add(cnt,'l',0.5,2);
166 gui.add(cnt,'m',1,12);
167 gui.add(cnt,'c1',500,10000);
168 gui.add(cnt,'c2',500,10000);
169 gui.add(cnt,'c3',500,10000);
170 gui.add(cnt,'pause');
171 gui.add(cnt,'resume');
172 gui.add(cnt,'redraw');
173 cnt.redraw();
174 render();
175
176 function render()
177 {
178 stats.update();
179 if(fl)t+=dt;
180 yt = Y+A1*Math.sin(k1*t+b1)+A2*Math.sin(k2*t+b2);;
181 ft = F+mu1*A1*Math.sin(k1*t+b1)+mu2*A2*Math.sin(k2*t+b2);
182 rod.position.y=yt;
183 rod.rotation.z=ft+Math.PI/2;
184
185 for(var k=1;k<=3;k++)
186 {
187 var ys,yf,xs,xf;
188 if(k==1){
189 ys=by;
190 yf=yt-5*l*Math.sin(ft);
191 xs = -5*l;
192 xf = -5*l*Math.cos(ft);
193 }
194 if(k==2){
195 ys=by;
196 yf=yt-5*l*Math.sin(ft)/2;
197 xs = -5*l/2;
198 xf = -5*l*Math.cos(ft)/2;
199 }
200 if(k==3){
201 ys=by;
202 yf=yt+5*l*Math.sin(ft);
203 xs = 5*l;
204 xf = 5*l*Math.cos(ft);
205 }
206 var lengty=Math.abs(ys-yf);
207 var lengtx=Math.abs(xs-xf);
208 var dly=lengty/(n+1);
209 var dlx=lengtx/(n+1);
210 for(var i=0;i<=n;i++)
211 {
212 var nexus=scene.getObjectByName(k+"-"+i);
213 nexus.position.y=ys+(i+1/2)*dly;
214 if ((k==1)||(k==2)){
215 nexus.position.x=xs+i*dlx;
216 }else{
217 nexus.position.x=xs-i*dlx;
218 }
219 if ((k==2)||(k==3)){
220 if(i%2==0)nexus.rotation.z=Math.acos(Math.sqrt(Math.pow(dly,2)+Math.pow(dlx,2))/sl);
221 else nexus.rotation.z=-Math.acos(Math.sqrt(Math.pow(dly,2)+Math.pow(dlx,2))/sl);
222 }else{
223 if(i%2==0)nexus.rotation.z=-Math.acos(Math.sqrt(Math.pow(dly,2)+Math.pow(dlx,2))/sl);
224 else nexus.rotation.z=Math.acos(Math.sqrt(Math.pow(dly,2)+Math.pow(dlx,2))/sl);
225 }
226 }
227 }
228 renderer.render(scene,camera);
229 requestAnimationFrame(render);
230 }
231 function init()
232 {
233 k1 = Math.sqrt((a11*c22+a22*c11-Math.sqrt(Math.pow(a11*c22+a22*c11,2)-4*a11*a22*(c11*c22-Math.pow(c12,2))))/(2*a11*a22));
234 k2 = Math.sqrt((a11*c22+a22*c11+Math.sqrt(Math.pow(a11*c22+a22*c11,2)-4*a11*a22*(c11*c22-Math.pow(c12,2))))/(2*a11*a22));
235 mu1 = -(c11-a11*Math.pow(k1,2))/(c12-a12*Math.pow(k1,2));
236 mu2 = -(c11-a11*Math.pow(k2,2))/(c12-a12*Math.pow(k2,2));
237 if ((f0==0)&&(y0==0)&&(w0==0)&&(v0==0)){
238 b1=Math.atan(k1*(1-mu2)/(1-mu2));
239 b2=Math.atan(k2*(1-mu1)/(1-mu1));
240 }else{
241 b1=Math.atan(k1*(f0-mu2*y0)/(w0-mu2*v0));
242 b2=Math.atan(k2*(f0-mu1*y0)/(w0-mu1*v0));
243 }
244 if ((f0==0)&&(y0==0)&&(b1==0)){
245 A1=(Math.sqrt(Math.pow((w0-mu2*v0),2)+Math.pow((k1*(f0-mu2*y0)),2)))/((mu1-mu2)*k1);
246 }else{
247 A1=(f0-mu2*y0)/(mu1-mu2)/Math.sin(b1);
248 }
249 if ((f0==0)&&(y0==0)&&(b2==0)){
250 A2=(Math.sqrt(Math.pow((w0-mu1*v0),2)+Math.pow((k2*(f0-mu1*y0)),2)))/((mu2-mu1)*k2);
251 }else{
252 A2=(f0-mu1*y0)/(mu2-mu1)/Math.sin(b2);
253 }
254 rod.position.set(0,y0,0);
255 rod.rotation.z=Math.PI/2+f0;;
256 spotLight.position.set(50,60,50);
257 for(var k=1;k<=3;k++)
258 for(var i=0;i<=n;i++)
259 {
260 var nexus=scene.getObjectByName(k+"-"+i);
261 nexus.position.set(0,rc+0.7/2,0);
262 }
263 }
264 function initStats()
265 {
266 var stats = new Stats();
267 stats.setMode(0);
268 stats.domElement.style.position='absolute';
269 stats.domElement.style.left='0px';
270 stats.domElement.style.top='0px';
271 document.getElementById("Stats-output").appendChild(stats.domElement);
272 return stats;
273 }
274
275 var Yt = [];
276 var Ft = [];
277 var dx = 10;
278
279
280 function physics(){
281 if (Yt.length > 400) Yt.shift();
282 Yt.push(yt);
283 if (Ft.length > 400) Ft.shift();
284 Ft.push(ft);
285 }
286 function draw(){
287 var N1 = Yt.length
288 var min1 = Yt[0]
289 var max1 = Yt[0]
290 for (var i = 1; i<N1; i++){
291 // if (Yt[i]<min1) min1 = Yt[i];
292 // if (Yt[i]>max1) max1 = Yt[i];
293 if (Math.abs(Yt[i]>max1)) max1 = Math.abs(Yt[i]);
294 }
295 ctx1.clearRect(0,0,w1,h1);
296 ctx1.beginPath();
297 ctx1.strokeStyle = "#000000";
298 ctx1.moveTo(dx,0);
299 ctx1.lineTo(dx,h1);
300 ctx1.moveTo(0,h1/2);
301 ctx1.lineTo(w1,h1/2);
302 //ctx1.moveTo(0,0);
303 ctx1.stroke();
304 ctx1.beginPath();
305 ctx1.strokeStyle = "#3F0CE8";
306 for (var i = 0; i<N1; i++){
307 // var plot_h1 = max1-min1;
308 // var y1 = (Yt[i]-min1)/plot_h1*h1;
309 var plot_h1 = 2*max1;
310 var y1 = Yt[i]/plot_h1*h1;
311 ctx1.lineTo(i/(N1-1)*w1,h1/2-y1);
312 }
313 ctx1.stroke();
314 var N2 = Ft.length
315 var min2 = Ft[0]
316 var max2 = Ft[0]
317 for (var i = 1; i<N2; i++){
318 //if (Ft[i]<min2) min2 = Ft[i];
319 //if (Ft[i]>max2) max2 = Ft[i];
320 if (Math.abs(Ft[i]>max2)) max2 = Math.abs(Ft[i]);
321 }
322 ctx2.clearRect(0,0,w2,h2);
323 ctx2.strokeStyle = "#000000";
324 ctx2.beginPath();
325 ctx2.moveTo(dx,0);
326 ctx2.lineTo(dx,h2);
327 ctx2.moveTo(0,h2/2);
328 ctx2.lineTo(w2,h2/2);
329 //ctx2.moveTo(0,0);
330 ctx2.stroke();
331 ctx2.beginPath();
332 ctx2.strokeStyle = "#FF0000";
333 for (var i = 0; i<N2; i++){
334 //var plot_h2 = max2-min2;
335 //var y2 = (Ft[i]-min2)/plot_h2*h2;
336 //ctx2.lineTo(i/(N2-1)*w2,h2-y2);
337 var plot_h2 = 2*max2;
338 var y2 = Ft[i]/plot_h2*h2;
339 ctx2.lineTo(i/(N2-1)*w2,h2/2-y2);
340 }
341 ctx2.stroke();
342 }
343
344 function control(){
345 physics();
346 draw();
347 }
348
349
350 window.onload=init;
351 setInterval(control, 1000/60);
352 window.addEventListener('resize', function () {
353 w1 = canvas_example1.width = window.innerWidth;
354 h1 = canvas_example1.height = window.innerHeight/4;
355 w2 = canvas_example2.width = window.innerWidth;
356 h2 = canvas_example2.height = window.innerHeight/4;
357 WebW = window.innerWidth;
358 WebH = window.innerHeight/2;
359 renderer.setSize(WebW, WebH);
360 camera.aspect = WebW / WebH;
361 });
362
363
364 </script>
365 </body>
366 </html>
Используемые библиотеки[править]
- three.js
- dat.gui.js
Возможности программы[править]
- Изменение начальных условий;
- Вывод графиков координаты центра масс и угла наклона стержня.