Hauptinhalt
Programmierung
Kurs: Programmierung > Lerneinheit 5
Lektion 5: Kräfte- Newtonsche Bewegungsgesetze
- Challenge: Schwebender Ballon
- Bewegung von vielen Objekten
- Challenge: Wandbälle
- Gravitation und Reibung modellieren
- Challenge: Liegende Polizisten
- Widerstand in Luft und Flüssigkeit
- Challenge: Sinkendes Treibholz
- Anziehungskraft der Gravitation
- Challenge: Kunstwerk-Generator
- Gegenseitige Anziehung
- Challenge: Gegenseitige Abstoßung
- Projekt: Angenehmes und fürchterliche Räuber
© 2023 Khan AcademyNutzungsbedingungenDatenschutzerklärungCookie-Meldung
Newtonsche Bewegungsgesetze
Im letzten Beispiel des letzten Tutorials haben wir gesehen, wie wir eine dynamische Beschleunigung berechnen können, die auf einem Vektor basiert, der von einem Kreis auf dem Bildschirm zur Mausposition zeigt. Die resultierende Bewegung ähnelte einer magnetischen Anziehung zwischen Kreis und Maus, als ob eine Kraft den Kreis in Richtung Maus ziehen würde.
In diesem Abschnitt werden wir unser Verständnis für das Konzept einer Kraft und ihre Beziehung zur Beschleunigung formalisieren. Unser Ziel ist es, am Ende dieses Abschnitts zu verstehen, wie man mehrere Objekte auf dem Bildschirm bewegt und auf eine Vielzahl von Umgebungskräften reagiert.
Bevor wir beginnen die praktischen Gesetze von Kräften in Code zu simulieren, wollen wir die Bedeutung einer Kraft in der realen Welt untersuchen. Genau wie das Wort “Vektor”, wird auch “Kraft” für ganz unterschiedliche Dinge verwendet. Es kann eine starke Intensität, wie in “Sie schob den Felsen mit großer Kraft” oder “Er sprach mit starken Worten” bedeuten. HIer schauen wir uns aber eine sehr formal defnierte Form von Kraft an, welche aus Isaac Newtons Gesetz der Bewegung stammt:
Eine Kraft ist ein Vektor, der ein Objekt mit Masse beschleunigt.
Die gute Nachricht ist, dass wir den ersten Teil der Definition wiedererkennen: eine Kraft ist ein Vektor. Gottseidank haben wir soeben ein ganzes Kapitel lang gelernt was ein Vektor ist und wie man diesen mit
PVector
programmiert!Schauen wir uns nun die drei Gesetze der Bewegung von Isaac Newton im Zusammenhang mit dem Konzept der Kraft an.
Erstes newtonsches Gesetz
Das erste newtonsche Gesetz wird oft vereinfacht so wiedergegeben:
Ein Körper in Ruhe verharrt im Zustand der Ruhe und ein Körper in Bewegung verharrt in Bewegung.
Aber hier fehlt ein wichtiges Element im Zusammenhang mit Kräften. Vollständig lautet es daher:
Ein Körper verharrt im Zustand der Ruhe oder der gleichförmig geradlinigen Translation, sofern er nicht durch einwirkende Kräfte zur Änderung seines Zustands gezwungen wird.
Als Newton dies formulierte, war die vorherschende Theorie der Bewegung von Aristoteles schon fast 2000 Jahre alt. Sie sagt aus, dass, wenn ein Körper sich bewegt, eine gewisse Kraft notwendig ist, um ihn in Bewegung zu halten. Außer wenn der Körper geschoben oder gezogen wird, wird er sich verlangsamen oder stoppen. Richtig?
Natürlich ist das nicht richtig. Wenn es keine Kraft gibt, ist auch keine Kraft notwendig, um den Körper in Bewegung zu halten. Ein Körper (wie ein Ball), der in in der Erdatmosphäre geworfen wird, verlangsamt sich wegen des Luftwiderstandes (einer Kraft). Die Geschwindigkeit eines Körpers bleibt nur beim Fehlen von jeglichen Kräften konstant oder wenn diese sich gegenseitig aufheben, d.h. ihre Summe Null ist konstant. Dies wird oft als Gleichgewicht bezeichnet. Ein fallender Ball erreicht eine Endgeschwindigkeit (welche konstant bleibt) sobald die Kraft des Luftwiderstandes gleich wie die Schwerkraft ist.
In unserer ProcessingJS-Welt können wir das erste newtonsche Gesetz folgendermaßen formulieren:
Der
PVector
der Geschwindigkeit eines Körpers bleibt konstant, wenn dieser im Zustand des Gleichgewichts ist.Vorläufig überspringen wir das zweite Gesetzt (wohl das wichtigste Gesetz für unsere Zwecke) und betrachten zuerst das dritte Gesetz.
Drittes newtonsches Gesetz
Diese Gesetz wird oft so angegeben:
Für jede Aktion gibt es eine gleiche und entgegengesetzte Reaktion.
So wie das Gesetz angegeben ist, führt es häufig zu Verwirrung. Einerseits klingt es als ob eine Kraft eine andere bewirkt. Ja, wenn du jemanden stößt, kann dieser beschließen aktiv zurückzustoßen. Aber wenn wir das dritte newtonsche Gesetz besprechen, geht es nicht um diese Art von Aktion und Reaktion.
Nehmen wir an, du drückst gegen eine Wand. Die Wand entscheidet sich nicht aktiv gegen dich zurückzudrücken. Es gibt keine “Ursprungskraft”. Dein Stoß beinhaltet einfach beide Kräfte, welche als “Aktions-/Reaktions-Paar” bezeichnet werden.
Daher ist es besser wenn wir das Gesetz so angeben:
Kräfte treten immer paarweise auf. Beide Kräfte sind gleich stark, haben aber eine entgegengesetzte Richtung.
Nun, dies führt immer noch zu Verwirrung, da es sich so anhört, als würden sich diese Kräfte immer gegenseitig aufheben. Dies ist aber nicht der Fall. Beachte, dass die Kräfte auf verschiedene Körper wirken. Und nur weil die beiden Kräfte gleich sind, heißt das nicht, dass die Bewegungen gleich sind (oder, dass die Körper ihre Bewegung stoppen).
Versuch einmal einen stillstehenden LKW anzuschieben. Obwohl der LKW viel stärker als du ist, wird er, anders als ein fahrender, dich niemals überwältigen und zurückwerfen. Die Kraft welche du auf ihn ausübst ist gleich und in entgegengesetzter Richtung zur Kraft welche auf dich ausgeübt wird. Das Ergebnis hängt von einer Vielzahl von anderen Faktoren ab. Wenn der LKW auf einem vereisten Abhang steht, schaffst du es vielleicht, ihn in Bewegung zu versetzen. Wenn es aber ein sehr großer LWK auf einem Feldweg ist und du stark genug schiebst (vielleicht sogar mit Anlauf), kannst du dir sogar die Hand verletzen.
Was passiert, wenn du Rollschuhe trägst, während du den LWK anschiebst?
In unserer ProcessingJS-Welt können wir das zweite newtonsche Gesetz folgendermaßen formulieren:
Wenn wir einen
PVector
f haben, der eine Kraft von Körper A auf Körper B darstellt, dann gibt es immer auch die Kraft PVector.mult(f,-1);
, welche Körper B auf Körper A ausübt.Wir werden aber sehen, dass wir in der Welt von ProcessingJS diese Regel oben nicht immer erfüllen müssen. Manchmal, wie im Fall der Anziehungskraft zwischen Körpern, wollen wir gleiche und entgegengesetzte Kräfte modellieren. In anderen Fällen, wie z.B. wenn wir einfach sagen “Es hat Wind”, dann werden wir die Kraft welche der Körper auf die Luft ausübt einfach ignorieren. In der Tat modellieren wir die Luft gar nicht! Beachte, wir lassen uns nur von der Physik aus der realen Welt inspirieren und simulieren nicht jedes Detail mit perfekter Präzision.
Zweites newtonsches Gesetz
Und nun kommen wir zum wichtigsten Gesetz für Programmier von ProcessingJS.
Dieses Gesetz wird oft so angegeben:
Kraft ist gleich Masse mal Beschleunigung.
Oder:
Weshalb ist dies für uns das wichtigste Gesetz? Nun, schreiben wir es einfach mal anders.
Die Beschleunigung ist direkt proportional zur Kraft und umgekehrt proportional zur Masse. Wenn du geschoben wirst, bedeutet dies, dass je stärker du geschoben wirst, du dich umso schneller bewegen wirst (Beschleunigung). Je schwerer du bist, umso langsamer bewegst du dich.
Gewicht und Masse
Die Masse eines Körpers ist ein Maß für die Menge an Materie des Körpers (gemessen in Kilogramm).
Gewicht, oft irrtümlich für Masse verwendet, ist technisch die Kraft der Schwerkraft auf ein Objekt. Von Newtons zweitem Gesetz, können wir es als Masse mal der Erdbeschleunigung berechnen (
w = m * g
). Gewicht wird in Newton gemessen.Dichte wird als die Menge der Masse pro Maßeinheit des Volumens (zum Beispiel Gramm pro Kubikzentimeter) definiert).
Beachte, dass ein Körper mit einer Masse von einem Kilogramm auch auf dem Mond eine Masse von einem Kilogramm hat. Er würde dort aber nur ein Sechstel davon wiegen.
Was ist aber Masse in der Welt von ProcessingJS? Nun, wir arbeiten doch mit Pixeln? Um es Anfangs einfacher zu machen, stellen wir uns vor, dass in unserer Pixel-Welt jeder unserer Körper eine Masse von 1 hat.
F/1 = F
. Daher:Die Beschleunigung eines Körpers ist gleich der Kraft. Das ist großartig! Schließlich haben wir im Kapitel Vektoren gesehen, dass Beschleunigung der Schlüssel zur Steuerung der Bewegung unserer Objekte auf dem Bildschirm ist. Die Position wird durch die Geschwindigkeit und die Geschwindigkeit durch die Beschleunigung definiert. Und mit der Beschleunigung hat alles begonnen. Nun lernen wir, dass in Wahrheit alles mit der Kraft beginnt.
Nun verwenden wir alles was wir gelernt haben, um unser Objekt
Mover
, welches derzeit eine Position, Geschwindigkeit und Beschleunigung hat, zu erweitern. Nun wollen wir zu diesem Objekt auch noch Kräfte hinzufügen, damit wir sagen können:mover.applyForce(wind); // Wende eine Windkraft an
oder:
mover.applyForce(gravity); // Wende eine Schwerkraft an
wobei der Wind und die Schwerkraft beides
PVector
en sind. Gemäß dem zweiten newtonschen Gesetz können wir diese Funktion so implementieren:Mover.prototype.applyForce = function(force) {
this.acceleration = force;
};
Kräfteaddition
Das sieht ziemlich gut aus. Schließlich ist acceleration = force eine wörtliche Übersetzung des zweiten newtonschen Gesetzes (ohne die Masse). Dennoch gibt es hier ein ziemlich großes Problem. Kehren wir zurück dazu, was wir eigentlich erreichen möchten: ein bewegtes Objekt auf dem Bildschirm erstellen, welches auf Wind und Schwerkraft reagiert.
mover.applyForce(wind);
mover.applyForce(gravity);
mover.update();
mover.display();
Stellen wir uns für einen Moment vor, wir seien der Computer. Zuerst rufen wir
applyForce()
mit Wind auf. Nun wird der Beschleunigung des Mover
der PVector
für Wind zugewiesen. Danach rufen wir applyForce()
mit der Schwerkraft auf. Und nun wird der Beschleunigung des Mover
der PVector
für die Schwerkraft zugewiesen. Schlussendlich rufen wir update()
auf. Was passiert nun in update()
? Die Beschleunigung wird zur Geschwindigkeit addiert.velocity.add(acceleration);
Wir sehen zwar keinen Fehler im Programm, aber Zoink! Wir haben ein großes Problem. Was ist der Wert der Beschleunigung wenn er zu Geschwindigkeit addiert wird? Es ist gleich der Gravitationskraft. Der Wind ging vergessen! Wenn wir
applyForce()
mehrfach aufrufen, werden die vorhergehenden Aufrufe überschrieben. Wie können wir mehr als eine Kraft handhaben?Die Wahrheit ist, dass wir anfangs eine vereinfachte Version vom zweiten newtonschen Gesetz verwenden haben. Hier die etwas genauere Version:
Die Summe der Kräfte ist gleich Masse mal Beschleunigung.
Unsere Beschleunigung ist gleich der Summe aller Kräfte dividiert durch die Masse. Das macht durchaus Sinn. Wie wir im ersten newtonschen Gesetz gesehen haben, befindet sich ein Körper dann im Gleichgewicht (keine Beschleunigung) wenn alle Kräfte zusammen Null ergeben. Wir implementieren dies durch einen Prozess, der Kräfteaddition genannt wird. Er ist eigentlich ganz einfach. Wir müssen einfach alle Kräfte addieren. Zu jedem Zeitpunkt kann es 1, 2, 6, 12 oder 303 Kräfte geben. Solange unser Objekt weiß wie man sie addiert, ist es egal, wie viele Kräfte auf es einwirken.
Passen wir nun also die Methode
applyForce()
so an, dass jede neue Kraft zur Beschleunigung addiert wird:Mover.prototype.applyForce = function(force) {
this.acceleration.add(force);
};
Wir sind aber noch nicht ganz fertig. Kräfteaddition hat noch mehr Faktoren. Da wir alle Kräfte zu einem bestimmten Zeitpunkt addieren, müssen wir sicherstellen, dass wir die Beschleunigung vor jedem Aufruf von
update()
auf Null zurücksetzen. Schauen wir uns den Wind noch einmal an. Manchmal ist der Wind sehr stark, manchmal schwach und manchmal gibt es gar keinen Wind. Zu einem bestimmten Zeitpunkt könnte es eine starke Windböe geben, wenn z. B. der Benutzer gerade die Maus klickt:if (mouseIsPressed) {
var wind = new PVector(0.5, 0);
mover.applyForce(wind);
}
Wenn der Benutzer die Maus loslässt, hört der Wind auf, und das Objekt bewegt sich gemäß dem ersten Newtonschen Gesetz mit konstanter Geschwindigkeit weiter. Wenn wir jedoch vergessen hätten, die Beschleunigung auf Null zu setzen, wäre der Windstoß immer noch wirksam. Schlimmer noch, er würde sich aus dem vorhergehenden Frame aufaddieren, da wir Kräfte akkumulieren!
Die Beschleunigung hat in unserer Simulation keinen Speicher; sie wird einfach auf der Grundlage der zu einem bestimmten Zeitpunkt vorhandenen Umgebungskräfte berechnet. Das ist anders als z. B. die Position, die sich merken muss, wo das Objekt im vorherigen Frame war, um sich korrekt zum nächsten Frame zu bewegen.
Der einfachste Weg die Beschleunigung bei jedem Frame zurückzusetzen ist es den PVector am Schluss von jedem update() mit 0 zu multiplizieren.
Mover.prototype.update = function() {
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.acceleration.mult(0);
};
Mit Masse umgehen
OK. Bevor wir die Kräfte komplett in unser Objekt
Mover
integriert haben und wir uns die Beispiele anschauen können, fehlt aber noch ein kleiner Zusatz. Schließlich ist ja das zweite newtonsche Gesetz F, with, vector, on top, equals, M, A, with, vector, on top und nicht A, with, vector, on top, equals, F, with, vector, on top. Die Masse ist ganz einfach nur eine zusätzliche Eigenschaft in unserem Objekt, aber wir müssen uns dies etwas genauer anschauen, da sich eine kleine Komplikation ergibt.Maßeinheiten
Da wir nun die Masse einführen, ist es wichtig, eine kurze Anmerkung zu Maßeinheiten zu machen. In der realen Welt werden Dinge in bestimmten Einheiten gemessen. Wir sagen, dass zwei Objekte 3 Meter voneinander entfernt sind, der Baseball sich mit einer Geschwindigkeit von 90 Meilen pro Stunde bewegt oder diese Bowlingkugel eine Masse von 6 Kilogramm hat. Wie wir später in diesem Kurs sehen werden, wollen wir manchmal die realen Einheiten berücksichtigen. In diesem Abschnitt werden wir sie jedoch größtenteils ignorieren.
Unsere Maßeinheiten sind hier in Pixeln ("Diese beiden Kreise sind 100 Pixel voneinander entfernt") und Frames der Animation ("Dieser Kreis bewegt sich mit einer Geschwindigkeit von 2 Pixeln pro Frame"). Im Fall der Masse gibt es keine Maßeinheit, die wir verwenden können. Wir werden einfach Zahlen erfinden. In diesem Beispiel wählen wir willkürlich die Zahl 10 aus. Es gibt keine Maßeinheit, obwohl es Ihnen vielleicht Spaß macht, eine eigene Einheit zu erfinden, wie "1 Moog" oder "1 Yurkle".
Zur Veranschaulichung werden wir die Objektmasse mit der Objektgröße verknüpfen - wenn also die Masse des Objekts 10 beträgt, können wir einen Kreis mit Radius 10 zeichnen. Auf diese Weise lässt sich die Masse eines Objekts leicht veranschaulichen und die Wirkung der Masse in unseren Programmen verstehen. In der realen Welt sagt die Größe jedoch nicht unbedingt etwas über die Masse aus. Eine kleine Metallkugel könnte aufgrund ihrer höheren Dichte eine viel größere Masse haben als ein großer Luftballon.
Die Masse ist ein Skalar (Dezimalwert) und kein Vektor, da sie nur eine Zahl ist, welche die Menge an Materie in einem Objekt beschreibt. Wir können auch ganz verrückte Dinge machen, wie z.B. die Fläche einer Form für die Masse nehmen. Aber es ist viel einfacher zu sagen, “Hey die Masse diese Objektes ist…ähm, keine Ahnung… sagen wir 10?”
var Mover = function() {
this.mass = 10;
this.position = new PVector(random(width), random(height));
this.velocity = new PVector(0, 0);
this.acceleration = new PVector(0, 0);
};
Dies ist zwar noch nicht so toll, denn es wird erst spannend wenn wir Objekte mit unterschiedlichen Massen haben. Aber ist ein guter Anfang. Aber woher nehmen wir die Masse? Wir verwenden sie beim Anwenden vom zweiten newtonschen Gesetz auf unser Objekt.
Mover.prototype.applyForce = function(force) {
force.div(this.mass);
this.acceleration.add(force);
};
Aber schon wieder! Obwohl unser Code ganz vernünftig aussieht, haben wir hier ein großes Problem. Stell dir die folgende Situation mit zwei Objekten
Mover
vor, welche beide von einer Windkraft weggeblasen werden.var m1 = new Mover();
var m2 = new Mover();
var wind = new PVector(1, 0);
m1.applyForce(wind);
m2.applyForce(wind);
Stellen wir uns wieder vor wir seien der Computer.
m1.applyForce()
erhält die Windkraft (1,0), dividiert diese durch seine Masse (10) und addiert sie zur Beschleunigung.code | wind |
---|---|
var wind = new PVector(1, 0); | (1, 0) |
m1.applyForce(wind) | (0.1, 0) |
OK. Weiter geht es mit dem Objekt
m2
. Es erhält ebenfalls die Windstärke - (1,0). Warten Sie. Ein Moment. Was ist der Wert der Windkraft? Bei genauerem Hinsehen ist die Windstärke jetzt tatsächlich (0,1,0)!Erinnerst du dich an diesen Detail zur die Arbeit mit Objekten?
In JavaScript hält eine Variable, die ein Objekt enthält (z. B. ein
PVector
), tatsächlich einen Zeiger auf dieses Objekt im Speicher. Wenn du das Objekt an eine Funktion übergibst, übergibst du nicht eine Kopie, sondern den ursprünglichen Zeiger. Wenn also eine Funktion eine Änderung an diesem Objekt vornimmt (wie hier bei der Division durch die Masse), dann wird dieses Objekt dauerhaft verändert! Das ist der Grund, warum die Dinge hier schief laufen. Wir wollen nicht, dass
m2
eine Kraft erhält, die durch die Masse von Objekt m1
geteilt wird. Wir wollen, dass es diese Kraft in seinem ursprünglichen Zustand erhält - (1,0). Und so müssen wir uns schützen und eine Kopie des PVectors f
machen, bevor wir ihn durch die Masse teilen. Glücklicherweise hat das Objekt
PVector
eine bequeme Methode um eine Kopie zu erstellen—get()
. get()
gibt ein neues PVector
-Objekt mit den gleichen Daten zurück. So können wir applyForce()
wie folgt ändern:Mover.prototype.applyForce = function(force) {
var f = force.get();
f.div(this.mass);
this.acceleration.add(f);
};
Wir könnten stattdessen in der Methode auch die statische Version von
div()
, welche wir im vorherigen Kapitel kennengelernt haben, verwenden.Mover.prototype.applyForce = function(force) {
var f = PVector.div(force, this.mass);
this.acceleration.add(f);
};
Das wichtigste ist aber, einen Weg zu finden, bei dem der ursprüngliche Kraftvektor nicht verändert wird, damit er auf mehrere
Mover
angewandt werden kann.Kräfte erzeugen
Wir wissen was eine Kraft ist (ein Vektor), und wir wissen wie wir diese Kräfte mit Objekten verwenden (wir dividieren durch die Masse und addieren sie zum Beschleunigungsvektor des Objektes). Was fehlt noch? Nun, wir müssen zuerst herausfinden wie wir die Kraft erzeugen. Von wo kommen die Kräfte?
In diesem Kapitel schauen wir uns zwei Methoden an, wie Kräfte in der Welt von ProcessingJS erzeugt werden können:
- Erfinde eine Kraft! Du bist ja ein Programmierer, der Schöpfer deiner Welt. Es gibt keinen Grund weshalb du nicht einfach eine Kraft erfinden und verwenden kannst.
- Eine Kraft modellieren! Ja, Kräfte existieren in der realen Welt. Und die Physik-Lehrbücher enthalten oft Formeln für diese Kräfte. Wer können diese Formeln nehmen und sie in Quellcode umschreiben und so die Kräfte aus der realen Welt modellieren.
Der einfachste Weg, eine Kraft zu erzeugen, ist einfache eine Zahl zu wählen. Beginnen wir mit der Simulation von Wind. Wie wäre es mit einer Windkraft welche nach rechts zeigt und ziemlich schwach ist? Angenommen wir haben einen
Mover
m
, dann sieht unser Code so aus:var wind = new PVector(0.01, 0);
m.applyForce(wind);
Das Resultat ist nicht besonders interessant, aber ein guter Anfang. Wir erzeugen einen
PVector
, initialisieren ihn und übergeben ihm ein Objekt, welches ihn auf seine Beschleunigung anwendet. Wenn wir zwei Kräfte haben, wie z.B. Wind und Schwerkraft (etwas stärker, zeigt nach unten), können wir das Folgende schreiben:var wind = new PVector(0{,}01, 0);
var gravity = new PVector(0, 0{,}1);
m.applyForce(wind);
m.applyForce(gravity);
Nun haben wir zwei Kräfte welche mit unterschiedlichen Beträgen in verschiedene Richtungen zeigen und wenden diese auf das Objekt
m
an. Nun kommen wir langsam vorwärts. Wir haben nun eine Welt für unsere Objekte in ProcessingJS erschaffen, eine Umgebung in der sie sich wirklich bewegen können.Wenn wir all dies zusammensetzen, sieht unser Programm folgendermaßen aus:
Woow! Wir haben in diesem Kapitel viel gelernt, und jetzt können wir schon so viel machen. Lernen wir, unsere Kräfte richtig einzusetzen!
Der Kurs "Natürliche Simulationen" ist eine Bearbeitung von "The Nature of Code" von Daniel Shiffman, und wird unter der Creative Commons Attribution-NonCommercial 3,0 Unported Lizenz verwendet.
Willst du an der Diskussion teilnehmen?
Noch keine Beiträge.