【问题标题】:How to make sure that the boids avoid walls 100% of the time如何确保 boids 100% 的时间避开墙壁
【发布时间】:2021-05-19 22:42:48
【问题描述】:

我正在尝试进行 boids 模拟。目前,我有一个他们可以四处漫游并且必须避开障碍物的世界。我的障碍物被定义为线,我正在使用线交点来查看它前面是否有任何墙壁,如果有,我会避开它。事实上,direction angle + FOVdirection angle - FOV 有两行。如果这两条线中的任何一条发生碰撞,则 boid 将转身离开。我设置的转向条件是只要这些牵引线的点积的平均值小于direction anglecos,就保持转向。这是代码。

for (auto& boid : boids)
        {
            //finding the tow vectors to + and - fov from the direction angle
            olc::vf2d lessFov = { (-std::cos(boid.DirectionAngle() - boid.collisionFov) * boid.collisionSensoryRange) + boid.position.x,
                (-std::sin(boid.DirectionAngle() - boid.collisionFov) * boid.collisionSensoryRange) + boid.position.y};

            olc::vf2d plusFov = { (-std::cos(boid.DirectionAngle() + boid.collisionFov) * boid.collisionSensoryRange) + boid.position.x,
                (-std::sin(boid.DirectionAngle() + boid.collisionFov) * boid.collisionSensoryRange) + boid.position.y };

            for (auto& obs : map.obstacles)
            {
                olc::vf2d intersectionPoint1{};
                olc::vf2d intersectionPoint2{};

                if (checkLineIntersect(lessFov, boid.position, obs.p1, obs.p2, intersectionPoint1) ||
                    checkLineIntersect(plusFov, boid.position, obs.p1, obs.p2, intersectionPoint2))
                {

                    //This is the problem
                    if (boid.position.dot( (intersectionPoint1 + intersectionPoint2) / 2 ) < std::cos(boid.DirectionAngle()))
                        boid.rotationAngle -= elapsedTime * obstacleAvoidancePriority;
                    else
                        boid.rotationAngle += elapsedTime * obstacleAvoidancePriority;
                }
            }

        }

我几乎对它给我的结果感到满意,只是偶尔会有一些小虫子设法穿过墙壁(这种情况很少见,但确实会发生),例如下图中被困在盒子里的那个.它在外面产卵,但设法进去了。

我想要一种方法来确保机器人永远不会穿过墙壁。谢谢。

编辑:

我刚刚注意到,在这部分代码中,else 子句永远不会执行。这种情况只是我在对点积了解有限的情况下幻想出来的,因为我希望它们不总是朝着同一个方向发展。

//This is the problem
if (boid.position.dot( (intersectionPoint1 + intersectionPoint2) / 2 ) < std::cos(boid.DirectionAngle()))
    boid.rotationAngle -= elapsedTime * obstacleAvoidancePriority;
else
    boid.rotationAngle += elapsedTime * obstacleAvoidancePriority;

这是我尝试的另一种方法。

bool i1 = checkLineIntersect(lessFov, boid.position, obs.p1, obs.p2, intersectionPoint1);
bool i2 = checkLineIntersect(plusFov, boid.position, obs.p1, obs.p2, intersectionPoint2);

if (i1 && !i2)
    boid.rotationAngle += elapsedTime * obstacleAvoidancePriority;
else if(i2 && !i1)
    boid.rotationAngle -= elapsedTime * obstacleAvoidancePriority;
else if(i1 || i2)
    if (i1 > i2)
        boid.rotationAngle += elapsedTime * obstacleAvoidancePriority;
    else
        boid.rotationAngle -= elapsedTime * obstacleAvoidancePriority; 

这个确实给了我“向随机方向转动”的效果,但泄漏的地方更多。

【问题讨论】:

    标签: c++ math collision-detection


    【解决方案1】:

    看起来您正在将点积与cos 进行比较。前者可以有任何值,后者仅限于[-1,+1]。这很可疑。

    此外,虽然boid.DirectionAngle() 没有明确定义,但它似乎是一个绝对角度(相对于坐标系)。因此,cos(boid.DirectionAngle()) 是沿坐标系 x 轴的分量。然而左边的点项是独立于坐标系的。这同样值得怀疑。

    我会建议缩放点积,但数学似乎太错误而无法修复。

    【讨论】:

    • this 问题的第一个答案是从哪里得到这个想法。它用于视野内的碰撞检测,但我认为它也可以在这里工作。
    • @Apple_Banana:该代码中有一个 .normalized,这导致该点积被限制在相同的 [-1,+1] 范围内。
    猜你喜欢
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    相关资源
    最近更新 更多