Моделирование поступательного и вращательного движения груза под действием силы упругости
Материал из Department of Theoretical and Applied Mechanics
Версия от 12:55, 1 июня 2020; Tishkovmaxim (обсуждение | вклад)
Содержание
Формулировка задачи[править]
В рамках данной модели необходимо было создать груз с произвольным количеством прикрепленных к нему пружин, для которых можно задать коэффициенты упругости, и визуализировать его поступательное и вращательное движение под действием сил упругости и силы тяжести.
Используемые формулы[править]
- Сила упругости
- Второй закон Ньютона
- Теорема Штейнера
- где - это расстояние от центра масс до оси вращения, а - Момент инерции тела относительно центра масс.
- Основное уравнение вращения твердого тела вокруг оси
- где - это плечо силы , а - угол поворота ТТ.
Основные допущения и ограничения[править]
- Для повышения производительности количество пружин ограничено девятью.
- Между грузом и границами области отсутствует сила трения.
Инструкция по использованию[править]
- Разместите пружины, нажав на область груза и протянув пружинку в любое место пространства, не отпуская кнопки мыши.
- Для начала моделирования нажмите кнопку "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 }