首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >人工智能避障

人工智能避障
EN

Code Review用户
提问于 2018-11-06 07:32:35
回答 2查看 364关注 0票数 5

我正在制作的人工智能非常简单,但是对于它正在做的事情来说,它可能有点效率太低了。下图显示了各种算术运算和数学运算之间的速度差异。sincos,特别是atan都是低效的。它在C++中进行了测试,但仍应符合JavaScript的要求。

能用更有效的数学达到同样的结果吗?

海图源

代码语言:javascript
复制
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

let targetX = 50;
let targetY = 50;

let obstacleX = 150;
let obstacleY = 50;

let aiX = 250;
let aiY = 51;

function loop() {
    // Distance between the vector points
    let disTargetX = targetX - aiX;
    let disTargetY = targetY - aiY;
    
    let disObstacleX = obstacleX - aiX;
    let disObstacleY = obstacleY - aiY;

    // Moves to target by default
    const angleTarget = Math.atan2(disTargetY, disTargetX);
    let moveAngle = angleTarget;

    // If near obstacle, adjust course and try to avoid it
    if (Math.sqrt(disObstacleX * disObstacleX + disObstacleY * disObstacleY) < 60) {
        const angleObstacle = Math.atan2(disObstacleY, disObstacleX);
        moveAngle += angleTarget - angleObstacle;
    }

    // Move the vector to desired location
    aiX += Math.cos(moveAngle);
    aiY += Math.sin(moveAngle);

    //Drawing
    ctx.clearRect(0, 0, 600, 200);

    ctx.beginPath();
    ctx.fillStyle = "teal";
    ctx.arc(aiX, aiY, 10, 0, Math.PI * 2, true);
    ctx.fill();

    ctx.beginPath();
    ctx.fillStyle = "purple";
    ctx.arc(obstacleX, obstacleY, 10, 0, Math.PI * 2, true);
    ctx.fill();
    
    ctx.rect(targetX - 20, targetY - 20,40,40);
    ctx.stroke();

    requestAnimationFrame(loop);
}

requestAnimationFrame(loop);
代码语言:javascript
复制
<canvas id="canvas" width="600" height="200"></canvas>
EN

回答 2

Code Review用户

发布于 2019-01-03 17:09:59

您可能知道这一点,但是在JavaScript中表示浮点数很难避免舍入错误。

你确定你的数学计算是正确的吗?具体来说,当从angleObstacle中减去moveAngle时,真的应该添加angleTarget吗?我试图对其进行更改,以便在发生这种情况时不会添加angleTarget。它似乎允许绿色圆圈避免与障碍物圆圈相撞。我不知道为什么速度会变..。可能是因为随弧tan或其他sin函数的指数变化。

代码语言:javascript
复制
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const targetX = 50;
const targetY = 50;

const obstacleX = 150;
const obstacleY = 50;

let aiX = 250;
let aiY = 51;

function loop() {
    // Distance between the vector points
    const disTargetX = targetX - aiX;
    const disTargetY = targetY - aiY;
    
    const disObstacleX = obstacleX - aiX;
    const disObstacleY = obstacleY - aiY;

    // Moves to target by default
    const angleTarget = Math.atan2(disTargetY, disTargetX);
    let moveAngle = angleTarget;

    // If near obstacle, adjust course and try to avoid it
    if (Math.sqrt(disObstacleX * disObstacleX + disObstacleY * disObstacleY) < 60) {
        const angleObstacle = Math.atan2(disObstacleY, disObstacleX);
        moveAngle += /*angleTarget -*/angleObstacle;
    }

    // Move the vector to desired location
    aiX += Math.cos(moveAngle);
    aiY += Math.sin(moveAngle);

    //Drawing
    ctx.clearRect(0, 0, 600, 200);

    ctx.beginPath();
    ctx.fillStyle = "teal";
    ctx.arc(aiX, aiY, 10, 0, Math.PI * 2, true);
    ctx.fill();

    ctx.beginPath();
    ctx.fillStyle = "purple";
    ctx.arc(obstacleX, obstacleY, 10, 0, Math.PI * 2, true);
    ctx.fill();
    
    ctx.rect(targetX - 20, targetY - 20,40,40);
    ctx.stroke();
    
    if (aiX > 50) {
        requestAnimationFrame(loop);
    }
}

requestAnimationFrame(loop);
代码语言:javascript
复制
<canvas id="canvas" width="600" height="200"></canvas>

其他审查要点

在上面的代码片段中,您会注意到对于函数中没有重新分配的变量的许多声明,let已经被const取代了,例如targetXtargetYobstacleXobstacleYdisTargetXdisTargetY。这样就避免了任何无意的重新分配。

此外,原始代码将永远循环。我在上面的代码段中添加了一个条件,即aiX > 50,它需要为true才能再次调用该函数(通过requestAnimationFrame)。这避免了不必要的处理。

票数 2
EN

Code Review用户

发布于 2018-11-08 10:48:06

AFAIK,三角函数在(非基于图的)动态运动中是不可避免的.根据您想要完成的任务,网格或基于图形的移动可能是一种选择,尽管图遍历和路径查找可能是它自己的蠕虫。

一个更简单的解决方案可能是预先计算几百个值的正弦/余弦/arctangent,并将它们存储在TypedArray中,在这里您可以直接查找它们。既然你没有做科学计算,这可能就足够了。不过,您可能希望运行一些基准测试来比较这两种解决方案。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/207037

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档