Основно съдържание
Курс: Програмиране > Раздел 5
Урок 7: Трептения- Амплитуда и период на трептене
- Предизвикателство: Пружинка като дъга
- Трептене с ъглова скорост
- Предизвикателство: Езда на космически кораб
- Вълни
- Предизвикателство: Много вълни
- Задържане и сили: махалото
- Предизвикателство: Кукла махало
- Сили на пружина
- Проект: Извиващи се, пълзящи и въртящи се създания
© 2024 Khan AcademyУсловия за ползванеДекларация за поверителностПолитика за Бисквитки
Сили на пружина
В началото на този раздел разгледахме моделирането на просто хармонично движение, като свързахме вълната на синуса с интервал от пиксели и моделирахме топче на пружина, като използвахме вълната на синуса. Въпреки че използването на функцията
sin()
е бърз едноредов начин да получим нещо и да го изпълним, това няма да ни свърши работа, ако искаме да имаме топче, което виси на пружина в двуизмерно пространство и да отговаря на други сили в средата (вятър, гравитация и т.н.). За да постигнем подобна симулация (която е идентична на нашия пример с махалото, само че рамото ни сега е пружина), трябва да моделираме силите на пружината като използваме PVector
.Силата на пружината се изчислява според закона на Хук, наречен на Робърт Хук, английски физик, който е развил формулата през 1660. Първоначално Хук в формулирал закона си на латински: "Ut tensio, sic vis," или “Колкото е разтягането, толкова е и силата". Да помислим за това по този начин:
Силата на пружиниране е право пропорционална на разширяването на пружинирането.
С други думи, ако дръпнеш повече топчето, силата ще бъде по-голяма; ако дръпнеш по-малко топчето, силата ще бъде по-малка. Казано математически, законът гласи следното:
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.
Искаш ли да се присъединиш към разговора?
Все още няма публикации.