Hallo,
ich versuche die Dynamiken eines simplen Pendels mittels RK4/Euler-Verfahren zu simulieren (wie es analytisch geht, ist mir relativ bekannt).
Das Vektor-Diagramm sollte doch eigentlich so aussehen:
Erklärung: Auf den "Bob"(= Kugel) wirken sowohl die Gravitations -als auch "Zug"kraft vom "Bob" zum Seil.
Der Winkel "theta" ist nichts anderes als das Skalarprodukt der normierten Vektoren g und d.
Man stelle sich vor der Bob befinde sich in den Extremstellen (genau dann wenn exemplarisch die Y-Koordinate des Bobs und des Zentrums übereinstimmen).
Das die Formel (a = g + (-d * |g| * theta)) Sinn macht ist offensichtlich: Wenn der Bob sich in jener Extremstelle befindet, liegen die Vektoren g und d orthogonal zueinander:
Das Skalarprodukt ist also 0.
Setzt man das in die Formel ein
a = g + (-d * 0 * theta) = g dann wirkt in jener Extremstelle ausschließlich die Gravitationskraft, was ja auch richtig sein sollte.
Dennoch "reißt" der Bob in der Simulation einfach ab... Habe es mit verschiedenen Delta-Werten versucht: Stets ist die Geschwindigkeit in Y Richtung einfach zu hoch, sodass der Bob gar nicht hochgezogen wird.
Ich mache also irgendwo was falsch.
Wo und vor allem was?
Hier der Source-Code:
Die Form:
Spoiler anzeigen
Hier die numerische Integrator-Klasse:
IApproximation:
RK4:
Spoiler anzeigen
Liebe Grüße!
EDIT: Okay, wenigstens eine kleine Besserung.
Benutzt man stattdessen folgende Formel:
a = (1 - |theta|) * g + (-d * |g| * |theta|) reißt er wenigstens nicht ab.
Eine Pendel-Simulation ist das dennoch nicht, eher eine "Sprungfeder" -Simulation...
_
ich versuche die Dynamiken eines simplen Pendels mittels RK4/Euler-Verfahren zu simulieren (wie es analytisch geht, ist mir relativ bekannt).
Das Vektor-Diagramm sollte doch eigentlich so aussehen:
Erklärung: Auf den "Bob"(= Kugel) wirken sowohl die Gravitations -als auch "Zug"kraft vom "Bob" zum Seil.
Der Winkel "theta" ist nichts anderes als das Skalarprodukt der normierten Vektoren g und d.
Man stelle sich vor der Bob befinde sich in den Extremstellen (genau dann wenn exemplarisch die Y-Koordinate des Bobs und des Zentrums übereinstimmen).
Das die Formel (a = g + (-d * |g| * theta)) Sinn macht ist offensichtlich: Wenn der Bob sich in jener Extremstelle befindet, liegen die Vektoren g und d orthogonal zueinander:
Das Skalarprodukt ist also 0.
Setzt man das in die Formel ein
a = g + (-d * 0 * theta) = g dann wirkt in jener Extremstelle ausschließlich die Gravitationskraft, was ja auch richtig sein sollte.
Dennoch "reißt" der Bob in der Simulation einfach ab... Habe es mit verschiedenen Delta-Werten versucht: Stets ist die Geschwindigkeit in Y Richtung einfach zu hoch, sodass der Bob gar nicht hochgezogen wird.
Ich mache also irgendwo was falsch.
Wo und vor allem was?
Hier der Source-Code:
Die Form:
C#-Quellcode
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- Vector2 center = new Vector2(500, 250);
- Vector2 bobPosition = new Vector2(550, 250);
- Vector2 bobVelocity = new Vector2(0, 0);
- IApproximation positionIntegrator;
- IApproximation velocityIntegrator;
- Vector2 gravitationalForce = new Vector2(0, 10);
- private void Form1_Load(object sender, EventArgs e)
- {
- this.Size = new Size(1000, 1000);
- this.DoubleBuffered = true;
- this.Paint += new PaintEventHandler(draw);
- Application.Idle += new EventHandler((a, b) =>
- {
- bobPosition = positionIntegrator.Run();
- Console.WriteLine(velocityIntegrator.Output);
- this.Invalidate();
- });
- positionIntegrator = new RK4(bobPosition, 0.005f);
- velocityIntegrator = new RK4(bobVelocity, 0.005f);
- positionIntegrator.f = pPrime;
- velocityIntegrator.f = pPrimePrime;
- }
- Vector2 pPrime(float dt, Vector2 y)
- {
- return velocityIntegrator.Run();
- }
- Vector2 pPrimePrime(float dt, Vector2 y)
- {
- Vector2 dir = bobPosition - center;
- dir.Normalize();
- Vector2 force = new Vector2(gravitationalForce.X, gravitationalForce.Y);
- force.Normalize();
- float forceMagnitude = gravitationalForce.Length();
- float theta = Vector2.Dot(dir, force);
- dir = -dir;
- Vector2 acceleration = gravitationalForce + dir * theta * (forceMagnitude);
- return acceleration;
- }
- private void draw( object sender, PaintEventArgs e)
- {
- Graphics g = e.Graphics;
- g.FillEllipse(Brushes.Red, center.X - 25f, center.Y - 25f, 50, 50);
- g.FillEllipse(Brushes.Blue, bobPosition.X - 12.5f, bobPosition.Y - 12.5f, 25, 25);
- g.DrawLine(Pens.Black, center.X, center.Y, bobPosition.X, bobPosition.Y);
- }
- }
Hier die numerische Integrator-Klasse:
IApproximation:
RK4:
C#-Quellcode
- public class RK4 : IApproximation
- {
- public RK4(Vector2 _0, float delta)
- {
- Output = _0;
- Delta = delta;
- }
- public override Vector2 Run()
- {
- Vector2 k1 = Delta * f(Time, Output);
- Vector2 k2 = Delta * f(Time + .5f * Delta, Output + .5f * k1);
- Vector2 k3 = Delta * f(Time + .5f * Delta, Output + .5f * k2);
- Vector2 k4 = Delta * f(Time + Delta, Output + k3);
- Output += 1.0f / 6.0f * (k1 + 2 * k2 + 2 * k3 + k4);
- Time += Delta;
- return Output;
- }
- }
Liebe Grüße!
EDIT: Okay, wenigstens eine kleine Besserung.
Benutzt man stattdessen folgende Formel:
a = (1 - |theta|) * g + (-d * |g| * |theta|) reißt er wenigstens nicht ab.
Eine Pendel-Simulation ist das dennoch nicht, eher eine "Sprungfeder" -Simulation...
_
Und Gott alleine weiß alles am allerbesten und besser.
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „φConst“ ()