球之间的碰撞解决后,动量不守恒 [英] The momentum is not conserved after collision resolution between balls

查看:253
本文介绍了球之间的碰撞解决后,动量不守恒的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在球之间的碰撞分辨率上有问题. 其实碰撞反应非常逼真,但动量却不守恒,为什么?

I have a problem in collision resolution between balls. Actually collision responses are very realistic but the momentum is not conserved, why?

我使用基于此文档的算法: http://www.vobarian.com/collisions /2dcollisions2.pdf .

I use an algorithm based on this document: http://www.vobarian.com/collisions/2dcollisions2.pdf.

在Java代码中,我的算法是:

In Java code my algorithm is:

/**
* Resolve the collision creating new velocities according to physical laws. 
*/
public void resolveCollisionWith(Ball ball) {
    //First resolve intersection for calculate correct new velocities.
    resolveIntersectionWith(ball);

    //Unit normal vector uN is the unit-vector that links the two centers.
    Vector uN = mPosition.subtraction(ball.getPosition()).normalize();

    //Unit tangent vector uT is the unit-vector normal to uN. It's tangent to both the    two balls.
    Vector uT = new Vector(-uN.getY(), uN.getX());

    //Project the two balls velocities onto the collision axis(uT and uN vectors).
    double v1n = uN.dot(mVelocity), v1t = uT.dot(mVelocity);
    double v2n = uN.dot(ball.getVelocity()), v2t = uT.dot(ball.getVelocity());

    //Calculate the post collision normal velocities (tangent velocities don't change).
    double v1nPost = (v1n*(mMass-ball.getMass()) + 2*ball.getMass()*v2n)/(mMass+ball.getMass());
    double v2nPost = (v2n*(ball.getMass()-mMass) + 2*mMass*v1n)/(mMass+ball.getMass());

    //Convert scalar velocities to vectors.
    Vector postV1N = uN.multiplication(v1nPost), postV1T = uT.multiplication(v1t);
    Vector postV2N = uN.multiplication(v2nPost), postV2T = uT.multiplication(v2t);

    //Change the balls velocities.
    mVelocity.set(postV1N.addition(postV1T));
    ball.getVelocity().set(postV2N.addition(postV2T));
}

 /**
 * When two balls collide can occur an intersection(the distance between the centers
 * is less than the sum of the radii) that dephases the response. 
 * The method fix this situation bringing back the two ball according to their mass.
 */
private void resolveIntersectionWith(Ball ball){
    Vector n = mPosition.subtraction(ball.getPosition());
    // How much the distance between centers is less than the radii's sum.
    double offset = getRadius() + ball.getRadius() - n.length();
    n.normalize();
    n.multiply(offset);
    // Bring back the two ball according to their mass.
    mPosition.add(n.multiplication(ball.getMass() * 1.0 / (mMass + ball.getMass())));
    ball.getPosition().subtract(n.multiplication(mMass * 1.0 / (mMass + ball.getMass())));
}

 /**
 * Normalizes and returns this vector.
 */
 // ***INSIDE VECTOR CLASS***
public Vector normalize() {
    //Avoid division by zero.
    if (mX != 0 || mY != 0) {
        double lenght = length();
        mX /= lenght;
        mY /= lenght;
    }
    return this;
}

谢谢!

推荐答案

假设精确的数学运算,方程式本身将逆转动量.因此,自然的怀疑是浮点错误.在正常情况下,误差会很小,尽管它们仍会随着时间累积.但是,除以小数可以放大误差.

The equations themselves will converse momentum, assuming exact math. So the natural suspect is floating point errors. Under normal circumstances, the errors will be very small, though they can still accumulate over time. However, division by small numbers can magnify the errors.

当对非常小的向量进行归一化时,由于每个分量的划分中的放大误差,您可能最终得到其幅值不接近1的东西.反过来,这将大大改变势头.实际上,尽管我假设您会注意到这种情况,但是您编写代码的方式可能会给您带来无限性或NaN.

When you normalize a very small vector, you may end up with something whos magnitude is not close to 1, thanks to magnified errors in the division of each component. This in turn will change the momentum greatly. In fact, the way your code is written could give you infinities or NaNs, though I assume you would have noticed if that were the case.

实际上,在某些情况下,您甚至根本不对向量进行归一化(当两个分量都完全为0时).但是您仍然盲目地使用伪造的向量.

In fact, in some cases you don't even normalize the vector at all (when both of the components are exactly 0). But you still blindly continue with the bogus vector.

我刚刚注意到您的向量是可变的.我强烈建议您改为使其不可变.它简化了代码,并缩小了因缺少副本而导致的错误的范围.

I just noticed your vectors are mutable. I'd highly recommend making them immutable instead. It simplifies the code and reduces the scope for bugs from missing copies.

这篇关于球之间的碰撞解决后,动量不守恒的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆