Lua 基于物理的航天器二维轨迹规划

Lua 基于物理的航天器二维轨迹规划,lua,2d,physics,box2d,Lua,2d,Physics,Box2d,我正在用太空中的飞船做一个2D游戏 为了做到这一点,我使用了LÖVE,它用Lua包装了Box2D。但我相信,任何比我更了解物理学的人都可以回答我的问题——所以伪代码被接受为回答 我的问题是,我不知道如何在2D物理世界上正确移动我的宇宙飞船。更具体地说: 质量m的船舶位于初始位置{x,y}。它的初始速度向量为{vx,vy}(可以是{0,0}) 目标是{xo,yo}中的一个点。船舶必须沿着最短轨道以{vxo,vyo}(或其附近)的速度到达目标 有一个名为update(dt)的函数经常被调用(即每秒调

我正在用太空中的飞船做一个2D游戏

为了做到这一点,我使用了LÖVE,它用Lua包装了Box2D。但我相信,任何比我更了解物理学的人都可以回答我的问题——所以伪代码被接受为回答

我的问题是,我不知道如何在2D物理世界上正确移动我的宇宙飞船。更具体地说:

质量
m
的船舶位于初始位置
{x,y}
。它的初始速度向量为
{vx,vy}
(可以是
{0,0}

目标是
{xo,yo}
中的一个点。船舶必须沿着最短轨道以
{vxo,vyo}
(或其附近)的速度到达目标

有一个名为
update(dt)
的函数经常被调用(即每秒调用30次)。在这个功能中,船舶可以通过对自身施加“脉冲”来修改其位置和轨迹。脉冲的大小是二进制的:您可以在给定的方向上应用它,也可以根本不应用它)。在代码中,它如下所示:

function Ship:update(dt)
  m = self:getMass()
  x,y = self:getPosition()
  vx,vy = self:getLinearVelocity()
  xo,yo = self:getTargetPosition()
  vxo,vyo = self:getTargetVelocity()
  thrust = self:getThrust()

  if(???)
    angle = ???
    self:applyImpulse(math.sin(angle)*thrust, math.cos(angle)*thrust))
  end
end
第一个
表明在某些情况下(我想)最好是“不要冲动”,让船“漂移”。第二部分讲述如何计算给定dt上的脉冲角

我们在太空中,所以我们可以忽略诸如空气摩擦之类的事情

虽然这将是非常好的,我不是找人来为我编码这个;我把代码放在那里,以便清楚地理解我的问题

我需要的是一种策略——一种攻击的方式。我懂一些基础物理,但我不是专家。例如,此问题是否有名称?诸如此类的事情

非常感谢

编辑:Beta为此提供了一个有效的策略,Judge在评论中直接在LÖVE中实施了该策略


编辑2:在谷歌搜索了更多的信息后,我也发现了。它是C++的,但它是我所做的。这可能对任何人提出这个问题都有帮助。

你的角度是相反/相邻的反切线

So角度=内倾角(VY/VX)


不知道你在说什么,想漂移???

以初始速度从当前位置到目的地,然后沿着最短路径和当前速度之间的标准化差施加推力。你实际上不需要这个角度

-- shortest path minus initial velocity
dx,dy = x0 - x - vx, y0 - y - vy

-- normalize the direction vector
magnitude = sqrt(dx*dx + dy*dy)
dx,dy = dx/magnitude, dy/mangitude

-- apply the thrust in the direction we just calculated
self:applyImpulse(thrust*dx, thrust*dy)
注意,这并没有考虑目标速度,因为这会变得非常复杂

我有一个非常小的Lua模块,用于处理二维向量。欢迎您使用它。上述代码将简化为:

d = destination - position - velocity
d:normalize()
d = d * thrust
self:applyImpulse(d.x, d.y)

这叫做运动规划,这不是小事

以下是获得非最佳轨迹的简单方法:

  • 停下来。施加与速度方向相反的推力,直到速度为零。
  • 计算最后一个航段(与第一个航段相反),一个稳定的推力,从静止开始,使船舶到达x0和v0。起点与x0的距离为| v0 | ^2/(2*推力)。
  • 到达起点(然后完成最后一程)。从一个站点到另一个站点是很容易的:朝着它推进,直到走到一半,然后向后推进,直到停下来。 如果你想要一个快速而肮脏的方法来达到最佳轨迹,你可以使用一个迭代的方法:从上面的非最佳方法开始;这只是推力角的时间序列。现在试着对这个序列做一些小的改变,保持一组序列接近目标。拒绝最坏的,尝试最好的——如果你觉得大胆,你可以把它变成一个遗传算法——运气好的话,它会开始拐弯

    如果你想得到确切的答案,可以使用变分法。我会尝试一下,如果我成功了,我会把答案贴在这里

    编辑:下面是一个更简单问题的精确解决方案

    假设我们没有指向任何方向的推力,而是有四个指向{+X,+Y,-X,-Y}方向的固定推力。在任何给定的时间,我们最多发射一个+/-X和一个+/-Y(同时发射+X和-X没有意义)。所以现在X和Y问题是独立的(它们不在原始问题中,因为推力必须在X和Y之间共享)。我们现在必须解决一维问题——并应用它两次

    事实证明,最好的轨迹是先向一个方向推进,然后再向另一个方向推进,而不是再回到第一个方向。(只有当另一个轴的解比你的解需要更长的时间时,滑行才有用,这样你就有时间消磨时间。)首先解决速度问题:假设(WLOG)你的目标速度大于你的初始速度。要达到目标速度,你需要一段持续时间的推力(+)

    T = (Vf - Vi)/a
    
    (我用的是Vf:最终速度,Vi:初始速度,a:推力大小。)

    我们注意到,如果这就是我们所做的,位置就不会正确。实际的最终位置将是

    X = (Vi + Vf)T/2
    
    因此,我们必须对

    D = Xf - X = Xf -(Vi+Vf)T/2
    
    现在,为了使位置正确,我们在前面加一个方向的推力周期,在后面加一个相反方向的相等周期。这将使最终速度不受干扰,但会给我们一些位移。如果第一个周期(和第三个周期)的持续时间是t,那么我们从中得到的位移是

    d = +/-(at^2 + atT)
    
    +/-取决于我们的推力是+then-,还是-then+。假设它是+。 我们求解二次方程:

    t = (-aT + sqrt(a^2 T^2 + 4 a D))/2a
    

    我们完成了。

    你在排放燃料吗?如果你是,你的质量会随着时间而改变

    推力是一种反作用力。它是质量变化率,乘以排气相对于宇宙飞船的速度

    你有外力吗?如果你这样做了,这些需要进入你的冲动计算

    让我们假设一个神奇的推力没有质量被驱逐,没有
    Constant Parameters:
      ExternalForceX   = strength of the external force in the X direction
      ExternalForceY   = id. Y direction
      MassOfShip       = coeficient controlling 
    Variable Parameters:
      ImpulseAngle     = direction of impulse
      ImpulseThrust    = force of thrust
    Formula:
      Vx[new] = (cos(ImpulseAngle) * ImpulseThrust) + ExternalForceX  + (MassOfShip * Vx[current])
      Vy[new] = (sin(ImpulseAngle) * ImpulseThrust) + ExternalForceY  + (MassOfShip * Vy[current])