尝试模拟重力时出现奇怪的行为

4

我正在尝试使用C++和GLM模拟牛顿引力。我正在使用GLM向量和在维基百科上找到的这个方程。

我将其翻译为代码:

const static double g_const = 6.67430E-11;
void gravitate(object& obj1,object& obj2) {
    glm::vec2 distance = glm::abs(obj2.position-obj1.position);
    glm::vec2 unitvec = (obj2.position-obj1.position)/distance;
    glm::vec2 force = -g_const*obj1.mass*obj2.mass/(distance*distance)*unitvec;
    obj2.updateForce(force);
}

对象类被结构化为这样
class object {
public:
    double mass;
    glm::vec2 velocity;
    glm::vec2 position;

    object(double massin, glm::vec2 pos) : mass(massin), position(pos) {;}
    object(double massin, glm::vec2 pos, glm::vec2 vel) : mass(massin), position(pos), velocity(vel) {;}

    void updateForce(glm::vec2 force) {
        velocity+=force/mass;
    }

    void updatePos() {
        position+=velocity;
    }

    void printPos(); // Not used in this example
    void printVel(); // Not used in this example
}

主函数运行如下:
int main() {
    object test1(massOfEarth,
        glm::vec2(0, 0),
        glm::vec2(0,0));
    object test2(massOfmoon,
        glm::vec2(distanceFromEarth,
        distanceFromEarth),
        moonInitalVelocity);
    while (true) {
       gravitate(test1,test2);
       test2.updatePos();
    }
}

当我运行它时,输出如下: GIF版本 注意:抱歉帧速率低,这是视频转换为gif的副作用。
有人知道出了什么问题吗?
另外,完整代码在此处可用:https://github.com/ProtoByter/GravityLaw 编辑1:
在物体突然加速点处施加在物体上的y力为3.5079064080620432e+26 N
当其以恒定速度移动时,y力为-2.9308778146655032e+23 N
编辑2:
为澄清起见,我正在使用牛顿万有引力的向量形式,在维基百科上它被定义为矢量量,而glm::distance返回一个double,因此不适合。

1
有人知道这里出了什么问题吗?也许,物理专家可以立即看出这里出了什么问题。对于其他像我这样的蠢货,你能解释一下你期望得到的输出与你实际得到的输出不同吗?通常,我会使用调试器将程序计算的结果与“纸上的数字”(即它应该计算的内容)进行比较。 - Scheff's Cat
我问了我的物理老师,他说我所做的应该是可行的。 - CosmoΓammaByte
当它突然加速时,其值为3.5079064080620432e+26 N。因此,在此之前请尽可能短地暂停您的程序,然后使用单步调试检查计算结果。使用“double”进行计算并不完全像您在实数数学/物理课程中所学的那样。它们最多只是类似的,并且仅适用于少数值(与实数的无限集相比)。对于非常小或非常大的值,您可能会得到奇怪的效果。这是我会考虑的第二个问题。 - Scheff's Cat
2
你正在除以零。在gravitate的第2行中,当两个物体靠近时,distance变为零或接近于零。正如你所知,lim 1/zero -> 一个巨大的数字。另外请注意,你正在使用曼哈顿距离,也许对于你的计算,你应该使用欧几里得距离(在std C++中计算它的函数称为hypot,但我不知道你正在使用的库中是否有相应的函数)。 - Aleksander Bobiński
@CosmoΓammaByte 我猜你的物理老师不是程序员。毫无疑问,你打算写的代码本来可以工作,但你实际上写的代码却不能。你必须找出你打算和实际写的代码之间的差异。这在编程中很正常。 - john
显示剩余2条评论
1个回答

3
您使用的计算两个对象之间距离的函数不正确。 您使用了glm::abs(gentype const &x)函数,该函数只是用于计算x的绝对值,即当x小于0时返回-x,x大于等于时则直接返回其本身。
您可以使用glm::distance(point1, point2)函数来计算点point1和point2之间的距离。
如需更多信息,请查看以下链接: https://glm.g-truc.net/0.9.4/api/a00129.htmlhttps://glm.g-truc.net/0.9.4/api/a00131.html

维基百科称距离必须是一个向量量,glm::distance返回一个双精度浮点数,而维基百科将r定义为|r2-r1|,因此我不知道你的意思。 - CosmoΓammaByte
但奇怪的是,这使它变得更好了。 - CosmoΓammaByte
我建议你先了解一些向量加减的概念,然后你会发现点1 - 点2是一个向量量,无论你是找到向量(点1 - 点2)的大小还是仅仅|点1 - 点2|,这些都是相同的东西。 - Ravi Prakash
glm::distance返回一个双精度值,因此它不是一个向量量。 - CosmoΓammaByte
@CosmoΓammaByte 距离始终是一个大小,而不是一个向量。您误解了维基百科文章中的符号表示法,当一个向量被放置在 | 符号之间时,它表示的是大小,而不是绝对值。 - William Miller
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接