Моделирование поступательного и вращательного движения груза под действием силы упругости

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск

Формулировка задачи[править]

В рамках данной модели необходимо было создать груз с произвольным количеством прикрепленных к нему пружин, для которых можно задать коэффициенты упругости, и визуализировать его поступательное и вращательное движение под действием сил упругости и силы тяжести.

Используемые формулы[править]

  • Сила упругости
[math]\vec{F} = k\vartriangle\vec{L}[/math]
  • Второй закон Ньютона
[math] m\vec{a}=\sum\limits^{n}_{i=1} {\vec{F_i}} + m\vec{g} [/math]
  • Теорема Штейнера
[math] I = I_c + md^2 [/math] где [math]d[/math] - это расстояние от центра масс до оси вращения, а [math]I_c[/math] - Момент инерции тела относительно центра масс.
  • Основное уравнение вращения твердого тела вокруг оси
[math] I\ddot{\varphi} = \sum\limits^{n}_{i=1} {\left ( \vec{r_i}\times\vec{F_i} \right )}[/math] где [math]r_i[/math] - это плечо силы [math]F_i[/math], а [math]\varphi[/math] - угол поворота ТТ.

Основные допущения и ограничения[править]

  • Для повышения производительности количество пружин ограничено девятью.
  • Между грузом и границами области отсутствует сила трения.

Инструкция по использованию[править]

  • Разместите пружины, нажав на область груза и протянув пружинку в любое место пространства, не отпуская кнопки мыши.
  • Для начала моделирования нажмите кнопку "start".
  • Если вы хотите перейти в режим перемещения груза мышкой - нажмите "move/add string". В этом режиме вы можете перемешать груз мышью. Чтобы вернуться в режим добавления пружин, снова нажмите кнопку"move/add string".
  • Чтобы менять коэффициенты упругости пружин, меняйте положения ползунков. Каждой пружине соответствует ползунок такого же цвета.
  • Чтобы сбросить груз и пружины в начальное положение, нажмите кнопку "clear".

Модель[править]


Текст программы на языке JavaScript (разработчик Тишков Максим 3630103/90003):

Файл "script.js"

  1 window.addEventListener('load',main,false);
  2 function main() {
  3 	
  4 ctx = canvas_example.getContext('2d');
  5 var w = canvas_example.width;
  6 var h = canvas_example.height;	
  7 //Draw quality
  8 var fps = 60;
  9 var dt = 1/fps;
 10 var g =9.8;
 11 //cargo parameters
 12 var mass = 1;
 13 var h_cargo=100;
 14 var w_cargo = 200;
 15 var x_cargo= h/2;
 16 var y_cargo = w/2; 
 17 var  F_mass = mass*g;
 18 var F_y=0;
 19 var F_y_str = 0;
 20 var F_x_str = 0;
 21 var F_x = 0 ;	
 22 var a_x =0;
 23 var a_y = 0;
 24 var v_x =0;
 25 var v_y =0;
 26 
 27 var r_diag = Math.sqrt((w_cargo/2)**2+(h_cargo/2)**2)
 28 var axis_x = x_cargo;
 29 var axis_y = y_cargo;
 30 var vector_l =[];
 31 var moment_of_inertia = 0;
 32 var r_inertia_x = 0;
 33 var r_inertia_y = 0;
 34 var r_inertia = 0;
 35 var moment_of_force = 0;
 36 var angular_acceleration = 0 ;
 37 var angular_velocity = 0 ;
 38 var rotation_angle = 0;
 39 var rotation_angle_s = 0;
 40 var x_cargo_new = x_cargo;
 41 var y_cargo_new = y_cargo;
 42 
 43 var string_move = false;
 44 var x_inProgress = [0, 0];
 45 var y_inProgress = [0, 0];
 46 var K_l = [];
 47 
 48 var offset = {x: 0, y: 0};
 49 var offset_x_str = [];
 50 var offset_y_str = [];
 51 var main_start = false;
 52 var strings = [];
 53 var flag_to_drag = false;
 54 
 55 
 56 function addElement(n){
 57 	document.body.insertAdjacentHTML("afterbegin", "<div style=\"LEFT: 820px; POSITION: absolute; TOP: "+(10+20*n)+"px\"><input type=range id=volume"+n+" name=volume min=0 max=1 value = 0.3 step = 0.1></div>")	
 58 }
 59 
 60 start.onclick = function() {
 61 	   main_start = true;   
 62 }
 63 
 64 drag.onclick = function() {
 65 	if(flag_to_drag){
 66 	   flag_to_drag = false;       	   
 67 	}
 68     else {
 69 	flag_to_drag = true;
 70 	}	
 71 }
 72 
 73 clear.onclick = function() {
 74 ctx.clearRect(0,0,w,h);
 75 h_cargo=100;
 76 w_cargo = 200;
 77 x_cargo= h/2;
 78 y_cargo = w/2;
 79 F_y=0;
 80 F_y_str = 0;
 81 F_x_str = 0;
 82 F_x = 0 ;	
 83 a_x =0;
 84 a_y = 0;
 85 v_x =0;
 86 v_y =0;	
 87 axis_x = x_cargo;
 88 axis_y = y_cargo;
 89 r_inertia_x = 0;
 90 r_inertia_y = 0;
 91 r_inertia = 0;
 92 moment_of_inertia = 0;
 93 r_inertia = 0;
 94 moment_of_force = 1;
 95 angular_acceleration = 0 ;
 96 angular_velocity = 0 ;
 97 rotation_angle = 0;
 98 rotation_angle_s = 0;
 99 string_move = false;
100 x_inProgress[0] = 0;
101 x_inProgress[0] = 0;
102 x_inProgress[1] = 0 ;
103 y_inProgress[1] = 0 ;
104 K_l.length = 0;
105 offset_x_str.length = 0;
106 offset_y_str.length = 0;
107 main_start = false;
108 for (var i = 0; i<=strings.length-1; i++){
109   document.getElementById('volume'+i).remove();
110 }
111 strings.length = 0;
112 flag_to_drag = false;	
113 	
114 }
115 
116  function getMouseCoords(e){
117 		var m = {};
118 		var rect = canvas_example.getBoundingClientRect();		
119 		m.x = e.clientX - rect.left;
120 		m.y =e.clientY - rect.top;
121 		return m;
122 }	
123 	
124 canvas_example.onmousedown = function(e){
125 		var m = getMouseCoords(e);
126 		x_start = m.x;
127 		y_start = m.y;
128    if(flag_to_drag){	   	 
129 	   if ((Math.abs((x_start-x_cargo)*Math.cos(rotation_angle)+(y_start-y_cargo )*Math.sin(rotation_angle))<w_cargo/2) && (Math.abs(-(x_start-x_cargo )*Math.sin(rotation_angle)+(y_start-y_cargo )*Math.cos(rotation_angle))<h_cargo/2)) {
130 	 main_start = false;
131 	 canvas_example.style.cursor = "move";
132 	offset.x = m.x-x_cargo;
133 	offset.y=  m.y-y_cargo;
134 	offset_x_a = m.x - axis_x;
135     offset_y_a = m.y -axis_y;
136 	v_x =0;
137 	v_y =0;
138 	angular_velocity = 0;
139 	 for (var i = 0; i<=strings.length-1; i++){
140 		 offset_x_str.push(m.x-strings[i].x_start);
141 		 offset_y_str.push(m.y-strings[i].y_start);
142 	 }	 
143       }	   
144    }   
145     else {    
146 	if ((Math.abs((x_start-x_cargo)*Math.cos(rotation_angle)+(y_start-y_cargo )*Math.sin(rotation_angle))<w_cargo/2) && (Math.abs(-(x_start-x_cargo )*Math.sin(rotation_angle)+(y_start-y_cargo )*Math.cos(rotation_angle))<h_cargo/2)) {
147 			string_move = true; 
148 			x_inProgress[0] = m.x;
149 			y_inProgress[0] = m.y;
150 			ctx.beginPath();
151 			 ctx.strokeStyle= 'black';
152 			 ctx.moveTo(x_start ,y_start);
153 			 ctx.lineTo(x_inProgress[1],y_inProgress[1]);
154 			ctx.stroke();
155 			ctx.clearRect(0,0,w,h);
156 			canvas_example.style.cursor = "pointer";
157 			console.log(1);
158 		 }
159 	}	
160 }
161 	
162 canvas_example.onmousemove = function(e) {
163 	var m = getMouseCoords(e);
164   if((flag_to_drag)&&(main_start == false)){ 
165 	  x_cargo = m.x-offset.x;
166 	  y_cargo = m.y-offset.y;
167 	  axis_x = m.x-offset_x_a;
168 	  axis_y = m.y-offset_y_a;     
169 	 	 for (var i = 0; i<=strings.length-1; i++){
170 						 strings[i].x_start = m.x-offset_x_str[i]; 
171 						 strings[i].y_start = m.y-offset_y_str[i]; 
172 				     }	    
173    }  
174 	else{
175 		if (string_move) {			
176 			x_inProgress[1] = m.x;
177 			y_inProgress[1] = m.y;								
178 			 for(var i =0 ;i<=10;i++){
179 				ctx.beginPath();
180 				ctx.strokeStyle= 'white';
181 				ctx.moveTo(x_start ,y_start);
182 				ctx.lineTo(x_inProgress[0],y_inProgress[0]);
183 				ctx.stroke();
184 			 }		
185 			ctx.beginPath();
186 			 ctx.strokeStyle= 'black';
187 			 ctx.moveTo(x_start ,y_start);
188 			 ctx.lineTo(x_inProgress[1],y_inProgress[1]);
189 			ctx.stroke();			
190 			x_inProgress[0] = x_inProgress[1];
191 			y_inProgress[0] = y_inProgress[1]
192 		}	
193     }
194 }	
195 
196 canvas_example.onmouseup = function(e){
197 		var m = getMouseCoords(e);		
198 	if(flag_to_drag){  
199 	  main_start = true;  
200 	  offset_x_str.length = 0;
201 	  offset_y_str.length = 0;
202 	 }   
203 		if (string_move) {
204 			 ctx.clearRect(0,0,w,h);
205 			string_move = false;
206 			x_end = m.x ;
207 			y_end = m.y ;
208 			
209 			if ((Math.abs((x_start-x_cargo)*Math.cos(rotation_angle)+(y_start-y_cargo )*Math.sin(rotation_angle))<w_cargo/2) && (Math.abs(-(x_start-x_cargo )*Math.sin(rotation_angle)+(y_start-y_cargo )*Math.cos(rotation_angle))<h_cargo/2)) {
210 			
211 				 if (x_end!=x_start&&y_end!=y_start&&strings.length<=9){
212 					K_l.push(new addElement(strings.length));	
213 					strings.push(new string (x_start, y_start, x_end, y_end, document.getElementById('volume'+strings.length).value));
214 					if (main_start){
215 					}
216 					
217 				 }
218 				 
219 			}
220 		}
221 canvas_example.style.cursor = "default";
222 }	
223 	
224 function draw() {	           
225 					if(main_start||flag_to_drag) { 
226 					ctx.clearRect(0,0,w,h);
227 					}
228 					
229 					ctx.beginPath();
230 				ctx.fillStyle = 'black';
231 				ctx.translate(axis_x, axis_y);	
232 			    ctx.rotate(rotation_angle);		
233 				ctx.fillRect(-w_cargo/2 - r_inertia_x , -h_cargo/2 - r_inertia_y , w_cargo , h_cargo);
234 				ctx.fillStyle = 'grey';
235 				ctx.fillRect(-w_cargo/2 - r_inertia_x +5, -h_cargo/2 +5 - r_inertia_y , w_cargo -10 , h_cargo - 10);
236 				ctx.rotate(-rotation_angle);
237 				
238 			  ctx.setTransform(1, 0, 0, 1, 0, 0);
239 			if (strings.length>=0) {
240 				for (var i=0; i<=strings.length-1; i++) {
241 										strings[i].draw_elasticy(i);            
242 				}			
243 			}					
244 }				
245 				
246 function phys() {
247 			if(main_start) {					
248 				    if ((x_cargo+v_x*2*dt+r_diag*Math.cos(Math.acos(-w_cargo/2/r_diag)+rotation_angle)<=0)|| (x_cargo+v_x*2*dt+r_diag*Math.cos(Math.acos(w_cargo/2/r_diag)+rotation_angle)>=w)||(x_cargo+v_x*2*dt+r_diag*Math.cos(Math.acos(-w_cargo/2/r_diag)+rotation_angle)>=w)||(x_cargo+v_x*2*dt+r_diag*Math.cos(Math.acos(w_cargo/2/r_diag)+rotation_angle)<=0)       ||    (x_cargo+v_x*2*dt-r_diag*Math.cos(Math.acos(-w_cargo/2/r_diag)+rotation_angle)<=0)|| (x_cargo+v_x*2*dt-r_diag*Math.cos(Math.acos(w_cargo/2/r_diag)-rotation_angle)>=w)||(x_cargo+v_x*2*dt+r_diag*Math.cos(Math.acos(-w_cargo/2/r_diag)-rotation_angle)>=w)||(x_cargo+v_x*2*dt-r_diag*Math.cos(Math.acos(w_cargo/2/r_diag)+rotation_angle)<=0)){
249 						 // v_x = 0;
250 						 
251 						 v_x = -v_x/5;
252 						 v_y = v_y*0.9;
253 						
254 						angular_velocity = - angular_velocity*0.9;
255 					}
256 					 if ((y_cargo+v_y*2*dt+r_diag*Math.sin(Math.asin(-h_cargo/2/r_diag)+rotation_angle)<=0)||(y_cargo+v_y*2*dt+r_diag*Math.sin(Math.asin(-h_cargo/2/r_diag)+rotation_angle)>=h)|| (y_cargo+v_y*2*dt+r_diag*Math.sin(Math.asin(h_cargo/2/r_diag)+rotation_angle)<=0)||(y_cargo+v_y*2*dt+r_diag*Math.sin(Math.asin(h_cargo/2/r_diag)+rotation_angle)>=h)   ||   (y_cargo+v_y*2*dt-r_diag*Math.sin(Math.asin(-h_cargo/2/r_diag)+rotation_angle)<=0)||(y_cargo+v_y*2*dt-r_diag*Math.sin(Math.asin(-h_cargo/2/r_diag)+rotation_angle)>=h)|| (y_cargo+v_y*2*dt-r_diag*Math.sin(Math.asin(h_cargo/2/r_diag)+rotation_angle)<=0)||(y_cargo+v_y*2*dt-r_diag*Math.sin(Math.asin(h_cargo/2/r_diag)+rotation_angle)>=h)){
257 						 // v_y = 0;
258 						 v_y = -v_y/5;
259 						 v_x = v_x*0.9;
260 						 
261 						 angular_velocity = - angular_velocity*0.9;
262 					}	
263 				
264 					for (var i = 0; i<=strings.length-1; i++){
265 						F_x_str = F_x_str + strings[i].F_elasticy_x(i);
266 						F_y_str = F_y_str +strings[i].F_elasticy_y(i);					
267 					}
268 					
269 				F_y = F_mass + F_y_str;
270 				F_x =F_x_str;
271 				a_x = F_x/mass;
272 				a_y = F_y/mass;
273 				
274 				v_x = v_x + a_x*dt;
275 				v_y = v_y + a_y*dt;
276 							
277 				x_cargo = x_cargo+v_x*dt;
278 				y_cargo = y_cargo+v_y*dt;
279 				
280 				axis_x = axis_x+v_x*dt;
281 			    axis_y = axis_y+v_y*dt; 
282 					 for (var i = 0; i<=strings.length-1; i++){
283 						 strings[i].x_start = strings[i].x_start+ v_x*dt; 
284 						 strings[i].y_start = strings[i].y_start+ v_y*dt; 	
285 				     }				
286 	//ROTATION
287 			axis_x = x_cargo;
288 			axis_y = y_cargo;
289 			var minus = 0;
290 			for (var i = 0; i<=strings.length-1; i++){
291 				if(strings[i].F_elasticy_x(i)!=0 || strings[i].F_elasticy_y(i)!=0){
292 				axis_x = axis_x + strings[i].x_start;
293 				axis_y = axis_y + strings[i].y_start;					
294 			}
295 			else
296 				minus = minus +1;
297 			}			
298 			axis_x = axis_x/(strings.length+1-minus);
299 			axis_y = axis_y/(strings.length+1-minus);
300 			r_inertia = Math.sqrt((axis_x-x_cargo)**2+(axis_y-y_cargo)**2);
301 			r_inertia_x = (axis_x-x_cargo)*Math.cos(rotation_angle)+(axis_y-y_cargo)*Math.sin(rotation_angle);
302 			r_inertia_y = -(axis_x-x_cargo)*Math.sin(rotation_angle)+(axis_y-y_cargo)*Math.cos(rotation_angle);				
303 			moment_of_inertia = mass*(h_cargo**2+w_cargo**2)/12 + mass*(r_inertia**2);
304 			flag_to_inertia = false;						
305 			for (var i = 0; i<=strings.length-1; i++){
306 				moment_of_force = moment_of_force + (strings[i].x_start-axis_x)*strings[i].F_elasticy_y(i)-(strings[i].y_start-axis_y)*strings[i].F_elasticy_x(i);				
307 			}
308 			moment_of_force = (moment_of_force+(x_cargo-axis_x)*F_mass);			
309 			angular_acceleration =  moment_of_force/moment_of_inertia;			
310 			angular_velocity = angular_velocity + angular_acceleration*dt;			
311 			rotation_angle =rotation_angle + angular_velocity*dt;;
312 			if (rotation_angle>=2*Math.PI){
313 			rotation_angle = rotation_angle - 2*Math.PI
314 			}					
315 			rotation_angle_s = angular_velocity*dt;
316 			if (rotation_angle_s>=2*Math.PI){
317 			rotation_angle_s = rotation_angle_s - 2*Math.PI
318 			}
319               var new_x = axis_x + (x_cargo-axis_x)*Math.cos(rotation_angle_s) -  (y_cargo-axis_y)*Math.sin(rotation_angle_s)
320 			  var new_y =axis_y + (x_cargo-axis_x)*Math.sin(rotation_angle_s) +  (y_cargo-axis_y)*Math.cos(rotation_angle_s); 
321 			  x_cargo = new_x;
322 			  y_cargo = new_y;
323 				for (var i = 0; i<=strings.length-1; i++){
324 				      var new_x =axis_x + (strings[i].x_start-axis_x)*Math.cos(rotation_angle_s) -  (strings[i].y_start-axis_y)*Math.sin(rotation_angle_s);
325 					  var new_y = axis_y + (strings[i].x_start-axis_x)*Math.sin(rotation_angle_s) +  (strings[i].y_start-axis_y)*Math.cos(rotation_angle_s);
326 						 strings[i].x_start = new_x; 
327 						 strings[i].y_start = new_y; 	
328 				     }			
329 			}
330 			if(flag_to_drag==true){
331 				
332 				for (var i = 0; i<=strings.length-1; i++){
333 						F_x_str = F_x_str + strings[i].F_elasticy_x(i);
334 						F_y_str = F_y_str +strings[i].F_elasticy_y(i);					
335 					}
336 				F_y = F_mass + F_y_str;
337 				F_x =F_x_str;		
338 			}			
339 F_y_str =0;
340 F_x_str =0;
341 moment_of_force = 0;		
342 }
343 		
344 				
345 function control() {
346 				phys();
347 				draw();
348 }
349 				
350 setInterval(control,dt);
351 }