Computersimulation der elastischen Kollision

Ich versuche, die Kollision von 2 Kugeln gleicher Masse zu berechnen, vorausgesetzt, die Kollision ist perfekt elastisch, für eine Computerphysik-Simulation. Anhand der Koordinaten beider Kugeln und ihrer Anfangsgeschwindigkeiten zum Zeitpunkt der Kollision möchte ich die Endgeschwindigkeiten berechnen. Ich habe mich eine Weile im Internet umgesehen und einige verschiedene Websites gefunden, die eine Formel dafür enthalten. Das Problem ist, dass beim Ausführen der Simulation die kinetische Energie nicht richtig erhalten zu sein schien (bei einigen Kollisionen wurde Energie hinzugefügt, die überhaupt keinen Sinn ergibt, bei einigen ging sie verloren). Meine Frage ist also: Stimmt etwas mit dieser Methode nicht? Hier ist Pseudo-Code für die Methode:

function manage_bounce(ball, ball2) {
    dx = ball._x-ball2._x;
    dy = ball._y-ball2._y;
    collisionision_angle = Math.atan2(dy, dx);
    magnitude_1 = Math.sqrt(ball.xspeed*ball.xspeed+ball.yspeed*ball.yspeed);
    magnitude_2 = Math.sqrt(ball2.xspeed*ball2.xspeed+ball2.yspeed*ball2.yspeed);
    direction_1 = Math.atan2(ball.yspeed, ball.xspeed);
    direction_2 = Math.atan2(ball2.yspeed, ball2.xspeed);
    new_xspeed_1 = magnitude_1*Math.cos(direction_1-collisionision_angle);
    new_yspeed_1 = magnitude_1*Math.sin(direction_1-collisionision_angle);
    new_xspeed_2 = magnitude_2*Math.cos(direction_2-collisionision_angle);
    new_yspeed_2 = magnitude_2*Math.sin(direction_2-collisionision_angle);
    final_xspeed_1 = ((ball.mass-ball2.mass)*new_xspeed_1+(ball2.mass+ball2.mass)*new_xspeed_2)/(ball.mass+ball2.mass);
    final_xspeed_2 = ((ball.mass+ball.mass)*new_xspeed_1+(ball2.mass-ball.mass)*new_xspeed_2)/(ball.mass+ball2.mass);
    final_yspeed_1 = new_yspeed_1;
    final_yspeed_2 = new_yspeed_2;
    ball.xspeed = Math.cos(collisionision_angle)*final_xspeed_1+Math.cos(collisionision_angle+Math.PI/2)*final_yspeed_1;
    ball.yspeed = Math.sin(collisionision_angle)*final_xspeed_1+Math.sin(collisionision_angle+Math.PI/2)*final_yspeed_1;
    ball2.xspeed = Math.cos(collisionision_angle)*final_xspeed_2+Math.cos(collisionision_angle+Math.PI/2)*final_yspeed_2;
    ball2.yspeed = Math.sin(collisionision_angle)*final_xspeed_2+Math.sin(collisionision_angle+Math.PI/2)*final_yspeed_2;
}
Wäre Computational Science ein besseres Zuhause für diese Frage?

Antworten (1)

Ich habe Ihren Code mit trigonometrischen Identitäten und der Tatsache, dass die Massen der Kugeln gleich sind, vereinfacht. Ich habe den Code auch so formatiert, dass er wie das Ergebnis einer Rotationsmatrix-Multiplikation aussieht, und Kommentare hinzugefügt, die angeben, was meiner Meinung nach das Ziel jedes Abschnitts ist.

function manage_bounce(ball, ball2) {
    // determine direction of balls with ball2 at origin
    dx = ball._x-ball2._x;
    dy = ball._y-ball2._y;
    collision_angle = Math.atan2(dy, dx);
    c = Math.cos(collision_angle);
    s = Math.sin(collision_angle);

    // Rotate coordinate system by -collision_angle so
    // x-axis aligns with line joining the balls' centers.
    // Recalculate velocity components in new coordinate system.
    new_xspeed_1 =  c*ball.xspeed + s*ball.yspeed;
    new_yspeed_1 = -s*ball.xspeed + c*ball.yspeed;
    new_xspeed_2 =  c*ball_2.xspeed + s*ball_2.yspeed;
    new_yspeed_2 = -s*ball_2.xspeed + c*ball_2.yspeed;

    // Exchange the velocities parallel to collision
    // direction (xspeed) and rotate (+collision_angle)
    // back to original coordinate system.
    ball.xspeed = c*new_xspeed_2 - s*new_yspeed_1;
    ball.yspeed = s*new_xspeed_2 + c*new_yspeed_1;
    ball2.xspeed = c*new_xspeed_1 - s*new_yspeed_2;
    ball2.yspeed = s*new_xspeed_1 + c*new_yspeed_2;
}

Das sieht richtig aus. Da die Massen der Kugeln gleich sind, sollte sich ein Geschwindigkeitsaustausch parallel zur Stoßrichtung ergeben, da dies den Impuls erhält. Kinetische Energie sollte da erhalten bleiben

K = 1 2 M v 1 2 + 1 2 M v 2 2 = ( 1 2 M v 1 X 2 + 1 2 M v 1 j 2 ) + ( 1 2 M v 2 X 2 + 1 2 M v 2 j 2 ) = ( 1 2 M v 2 X 2 + 1 2 M v 1 j 2 ) + ( 1 2 M v 1 X 2 + 1 2 M v 2 j 2 )
vom Wechseln v 1 X Und v 2 X .

Wenn es sich um Pseudocode handelt, versuchen Sie, Ihren tatsächlichen Code auf die gleiche Weise wie ich zu vereinfachen, und prüfen Sie, ob Fehler aufgedeckt werden.

Bearbeiten: zwei weitere mathematische Vereinfachungen:

r = Math.sqrt(dx*dx + dy*dy) // or r = Math.hypot(dx, dy) if available
c = dx/r // cos(collision_angle)
s = dy/r // sin(collision_angle)
Danke schön! Ihre Vereinfachung hat mir geholfen, meinen Fehler zu erkennen.
@chessprogrammer Ich habe eine weitere Änderung nur aus Gründen der Geschwindigkeit und Genauigkeit hinzugefügt. Als Referenz: fgiesen.wordpress.com/2010/10/21/finish-your-derivations-please