【问题标题】:Weird behaivour when trying to simulate gravity尝试模拟重力时的奇怪行为
【发布时间】:2021-03-04 13:21:29
【问题描述】:

我正在尝试用 C++ 和 GLM 模拟牛顿引力。我正在使用 GLM 向量和我在 Wikipedia 上找到的这个等式

我把它翻译成代码:

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
}

main函数是这样运行的:

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 的副产品

有人知道这里出了什么问题吗?

顺便说一句,完整代码可在此处获得:https://github.com/ProtoByter/GravityLaw

编辑 1:

物体突然加速时施加在物体上的 y 力为 3.5079064080620432e+26 N

当它以恒定速度移动时,y 力为 -2.9308778146655032e+23 N

编辑 2:

为了澄清,我使用牛顿万有引力定律的向量形式,在维基百科上,这被定义为向量,而 glm::distance 返回一个双精度因此不适合

【问题讨论】:

  • 有谁知道这里出了什么问题? 也许,物理学专家可以立即看出这里出了什么问题。对于其他傻瓜(比如我),你能解释一下你期望的输出与你得到的相反吗?一般来说,我会使用debugger 来比较程序计算的内容,以将其与“纸上的数字”(即它应该计算的内容)进行比较。
  • 我问了我的物理老师,他说我所做的应该有效
  • 突然加速是3.5079064080620432e+26 N。因此,在此之前尽可能短地暂停您的程序,然后检查single-step debugging 中的计算。 double 的计算并不完全像您在实数的数学/物理课程中学到的那样。它们充其量是相似的,并且仅针对少数几个值(与无限的实数集相比)。对于非常小或非常大的值,您可能会得到奇怪的效果。这是我要搜索的第二个。
  • 我的物理老师......说我所做的应该有效:首先我会搜索实现错误。 (我最近刚刚滚动了 doxygen 人。上下滚动,因为我的代码中对组的引用没有按预期工作。最后,我发现我写的是 Progess 而不是 Progress 不知何故这并不容易发现...)
  • 你除以零。在gravitate 的第 2 行中,当两个对象接近时,distance 变为零或接近零。如您所知 lim 1/zero -> 一个巨大的数字。另请注意,您使用的是曼哈顿距离,也许对于您的计算,您应该使用欧几里得距离(在标准 C++ 中计算它的函数称为 hypot,但我不知道您正在使用的库中的等价物)

标签: c++ simulation physics glm-math


【解决方案1】:

您使用错误的函数来计算两个对象之间的距离, 您使用了 glm::abs(gentype const &x) ,它仅用于计算 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 |所以我不明白你的意思
  • 但奇怪的是这让它变得更好了
  • 只是测试它,如果它完全有效,那么我会将它标记为答案
  • 我会建议你通过一些向量加减法的概念,然后你会发现point1 - point2是一个向量,你是否找到向量的大小(point1 - point2)或只是 |point1 - point2|这些都是一样的。
  • glm::distance 返回一个双精度,因此不是向量
猜你喜欢
  • 2012-05-27
  • 2011-01-16
  • 2013-12-27
  • 1970-01-01
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多