If you're seeing this message, it means we're having trouble loading external resources on our website.

Ако си зад уеб филтър, моля, увери се, че домейните *. kastatic.org и *. kasandbox.org са разрешени.

Основно съдържание

Сили на пружина

В началото на този раздел разгледахме моделирането на просто хармонично движение, като свързахме вълната на синуса с интервал от пиксели и моделирахме топче на пружина, като използвахме вълната на синуса. Въпреки че използването на функцията sin() е бърз едноредов начин да получим нещо и да го изпълним, това няма да ни свърши работа, ако искаме да имаме топче, което виси на пружина в двуизмерно пространство и да отговаря на други сили в средата (вятър, гравитация и т.н.). За да постигнем подобна симулация (която е идентична на нашия пример с махалото, само че рамото ни сега е пружина), трябва да моделираме силите на пружината като използваме PVector.
Силата на пружината се изчислява според закона на Хук, наречен на Робърт Хук, английски физик, който е развил формулата през 1660. Първоначално Хук в формулирал закона си на латински: "Ut tensio, sic vis," или “Колкото е разтягането, толкова е и силата". Да помислим за това по този начин:
Силата на пружиниране е право пропорционална на разширяването на пружинирането.
С други думи, ако дръпнеш повече топчето, силата ще бъде по-голяма; ако дръпнеш по-малко топчето, силата ще бъде по-малка. Казано математически, законът гласи следното:
Fпружина=kx
  • k е константа, а нейната стойност скалира силата. Дали пружината е силно еластична или е доста твърда?
  • x се отнася до отместването на пружината, т.е. разликата между текущата ѝ дължина и дължината в покой. Дължината в покой е дефинирана като дължината на пружината в състояние на равновесие.
Не забравяй, че силата е вектор, затова трябва да изчислим както големината, така и посоката. Да разгледаме още една диаграма на пружината и да отбележим всички неща, които можем да имаме дадени в програмата.
Да въведем следните три начални променливи, както е показано на горната диаграма, с някакви разумни стойности.
var anchor = new PVector(100, 10);
var bob = new PVector(110, 100);
var restLength = 20;
Първо да използваме закона на Хук, за да изчислим големината на силата. Трябва да знаем k и x. k е лесно: това е константа, затова нека си измислим нещо.
var k = 0{,}1;
x е може би малко по-трудно. Трябва да знаем "разликата между текущата дължина и дължината в покой". Дължината в покой е дефинирана от променливата restLength. Каква е текущата дължина? Това е разстоянието между опорната точка и топчето. А как можем да изчислим това разстояние? Ами големината на вектора, който сочи от опорната точка към топчето? (Забележи, че това е съвсем същият процес, който използвахме, когато изчислявахме разстоянието в раздела Гравитационно привличане.)
var dir = PVector.sub(bob, anchor);
var currentLength = dir.mag();
var x = currentLength - restLength;
След като намерихме всички елементи, необходими за големината на силата, (-1 * k * x), трябва да разберем посоката, която е единичен вектор, сочещ в посока на силата. Добрите новини са, че вече имаме този вектор. Нали? Само преди момент си мислехме: "Как можем да изчислим това разстояние? Ами големината на вектора, който сочи от началото към топчето?” Същият този вектор е посоката на силата!
В горната диаграма можем да видим, че ако разтегнем пружината извън дължината ѝ в покой, трябва да има сила, която я издърпва обратно към началото. А ако се свие под дължината си в покой, силата трябва да я отблъсква напред от началото. Тази смяна на посоките се взима предвид във формулата с -1. И така всичко, което трябва да направим, е да нормализираме PVector, който използвахме за изчисляването на разстоянието! Да разгледаме кода и да сменим името на променливата на PVector с “force.”
var k = 0{,}01;
var force = PVector.sub(bob, anchor);
var currentLength = force.mag();
var x = currentLength - restLength;
// Посока на силата на пружината, единичен вектор
force.normalize();
// Обединяване: посока и големина!
force.mult(-1 * k * x);
След като вече имаме алгоритъм, който да изчислява вектора на силата на пружината, остава въпросът: каква обектно-ориентирана структура трябва да използваме? Това отново е една от онези ситуации, в които няма "правилен" отговор. Има няколко възможности; това коя ще изберем зависи от целта на програмата и личния ти стил на писане. Все пак, тъй като досега работихме с обекта Mover, да продължим да използваме същия подход. Да приемем, че нашият обект Mover е "топчето" на пружината. Топчето трябва да има позиция, скорост и ускорение – вектори – за да да се движи по екрана. Идеално – вече го имаме! Вероятно топчето изпитва и силата на гравитацията чрез метода applyForce(). Остава само още една стъпка – трябва да приложим силата на пружиниране:
var bob = new Bob();

draw = function()  {
  // Нашата измислена сила на гравитацията
  var gravity = new PVector(0, 1);
  bob.applyForce(gravity);
  // Трябва също да изчислим и приложим сила на пружиниране!
  var spring = ????
  bob.applyForce(spring);

  // Нашите стандартни методи update() и display() 
  bob.update();
  bob.display();
};
Една от възможностите е да напишем целия код за силата на пружиниране в основния цикъл на draw(). Но да помислим няколко хода напред, когато може би ще имаме няколко топчета и няколко пружини, заради което има смисъл да добавим нов обект, Spring. Както е показано на горната диаграма, обектът Bob следи за движението на топчето; обектът Spring следи за движението на пружината и нейната дължина в покой и изчислява силата на пружиниране върху топчето.
Това ни позволява да напишем този прекрасен код, за да ги свържем заедно:
var bob = new Bob();
var spring = new Spring();

draw = function()  {
  // Нашата измислена сила на гравитацията
  var gravity = new PVector(0, 1);
  bob.applyForce(gravity);
  // Spring.connect() ще се погрижи за 
  // изчисляването и прилагането на силата на пружиниране
  spring.connect(bob);

  // Нашите стандартни методи update() и display()
  bob.update();
  bob.display();
};
Може би забелязваш, че това е доста подобно на онова, което направихме в раздела за Гравитация с един привличащ обект attractor. Там написахме нещо такова:
var force = attractor.calculateAttraction(mover);
mover.applyForce(force);
Аналогичната ситуация тук с пружинирането ще бъде:
var force = spring.calculateForce(bob);
bob.applyForce(force);
Въпреки това, в този пример, всичко, което направим е:
spring.connect(bob);
Какво ни дава това? Защо не извикаме applyForce() върху топчето? Отговорът е, разбира се, че трябва да приложим applyForce() върху топчето. Само че вместо да го направим в draw(), просто демонстрираме, че напълно разумна (и понякога предпочитана) алтернтива би било да помолим метода connect() вътрешно да се заеме с извикването на applyForce() върху топчето.
Spring.prototype.connect(bob) {
  var force = /* малко интересни изчисления */;
  bob.applyForce(force);
};
Защо го правим по един начин с обекта Attractor и по друг с обекта Spring? Когато учихме за силите за първи път, беше по-ясно да покажем всички сили, приложени в главния draw() цикъл, и се надявам, че това ти е помогнало да научиш за натрупването на сили. След като сега сме по-уверени с това, вероятно ще бъде по-просто да включим някои детайли в самите обекти.
Да обобщим нещата в долната програма. Добавихме няколко неща: (1) обектът Bob включва функции за взаимодействие с мишката, за да може топчето да се мести по прозореца, и (2), обектът Spring включва функция, която оганичава дължината на връзката между някакъв минимум и някакъв максимум.

Курсът "Компютърни симулации на физични явления" е производeн на "Природата на кода" от Даниел Шифман, използвана от Creative Commons Attribution-NonCommercial 3,0 Unported License.

Искаш ли да се присъединиш към разговора?

Все още няма публикации.
Разбираш ли английски? Натисни тук, за да видиш още дискусии в английския сайт на Кан Академия.