将物体从点 a 移动到点 b(二维),该物体只能向前移动并自行旋转

发布于 2024-12-11 08:18:33 字数 1148 浏览 0 评论 0原文

所以我有一艘船,底部有推进器,只能使用这些推进器前进。它还可以绕其中心旋转。它的推进器给它加速,所以它不会以恒定速度移动。我想做的就是告诉它“移动到B点”。

我已经想出了一个解决方案,但它效果不太好,旋转不顺畅,移动不稳,而且最终没有准确地到达应有的位置,所以我必须有很大的误差范围。

这是一个正常的问题吗?如果是,是否有“标准”的方法来做到这一点?这是一个容易的问题吗?我想让它看起来像是船正在利用玩家所拥有的约束(推进器、旋转)自行转向该点。这排除了从 A 点到 B 点的 lerping。是吗?

我希望得到一些帮助来解决这个问题。位置存储在向量中,这是一个二维问题。仅供参考,我提供了我的解决方案,该解决方案基本上是加速船直到并将其旋转到指向该点。我认为我的这个想法的实现是有问题的:

Vector diff = vector_sub(to_point, pos);
float angle = vector_getangle(diff);
float current_angle = vector_getangle(dir);
float angle_diff = rightrange(angle) - rightrange(current_angle);
float len = vector_getlength(diff);

// "Margin of error"
float margin = 15.0;

// Adjust direction, only if we're not stopping the next thing we do (len <= margin)
if ( len > margin && fabs(angle_diff) > 2.0 )
{
    dir = vector_setangle(dir, current_angle + (angle_diff)*delta*(MY_PI) - MY_PI/2);
}
else if ( len > margin )
{
    dir = vector_normalize(diff);
}

// accelerate ship (if needed)
acc.x = acc.y = speed;
acc = vector_setangle(acc, vector_getangle(dir));

if ( len <= margin )
{
    // Player is within margin of error
}

So I have a ship, that has thrusters at the bottom and that can only use these to move forward. It can also rotate itself around its center. Its thrusters gives it acceleration, so it doesn't move at a constant velocity. What I want to do is to tell it "move to point B".

I have come up with a solution but it doesn't work very well and it doesn't rotate smoothly, it moves jerkily and it doesn't end up exactly where it should be, so I have to have a big margin of error.

Is this a normal problem, and if so is there a "standard" way of doing it? Is this an easy problem? I want to make it look like the ship is steering itself to that point, using the constraints (thrusters, rotation) the player has. This excludes just lerping it from point A to B. Or does it?

I'd love some help in solving this problem. Positions are stored in vectors, and it's a 2D problem. Just for reference I'm including my solution, which basically is accelerating the ship until and rotating it to point to the point. I think my implementation of this idea is the problem:

Vector diff = vector_sub(to_point, pos);
float angle = vector_getangle(diff);
float current_angle = vector_getangle(dir);
float angle_diff = rightrange(angle) - rightrange(current_angle);
float len = vector_getlength(diff);

// "Margin of error"
float margin = 15.0;

// Adjust direction, only if we're not stopping the next thing we do (len <= margin)
if ( len > margin && fabs(angle_diff) > 2.0 )
{
    dir = vector_setangle(dir, current_angle + (angle_diff)*delta*(MY_PI) - MY_PI/2);
}
else if ( len > margin )
{
    dir = vector_normalize(diff);
}

// accelerate ship (if needed)
acc.x = acc.y = speed;
acc = vector_setangle(acc, vector_getangle(dir));

if ( len <= margin )
{
    // Player is within margin of error
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

2024-12-18 08:18:34

如果您不是在寻找在线工作的非常通用的解决方案,那么有一个简单的解决方案。我所说的在线是指沿着完整的轨迹不断地重新计算动作。

假设船在开始时处于静止状态,只需将其旋转到目标点(同时仍处于静止状态)。现在,您的飞船可以通过加速 t 秒、在运动中向后旋转(根据您的约束为 0.5 秒)并再减速 t 秒来到达目标。如果当前点和目的地之间的距离为d,那么您需要求解的方程为:

d = 0.5*a*t^2 + 0.5*a*t + 0.5*a*t^2

第一项是加速时行驶的距离。第二项是旋转时行驶的距离(v*t_rotv=a*tt_rot=0.5)。最后一项是减速时行驶的距离。解决上面的 t 问题,你就得到了你的轨迹。

如果船在开始时正在移动,我会首先停止它(只是沿其速度矢量的相反方向旋转,然后减速直到静止)。现在我们知道如何到达目的地了。

离线轨迹计算的问题是不太准确。您很有可能会到达目标附近,但不会完全位于目标之上。


让我们把问题变得更有趣一点:如果没有加速,船就无法旋转。我们将这个加速度矢量称为a_r,它是一个与船的方向成一定角度的矢量(有点像后面有一个一定角度的推进器)。您现在的任务是旋转船舶并沿一定方向加速,以抵消垂直于连接当前位置和目标的矢量的速度分量。我不会尝试离线计算向量,而是采用在线方法。

最简单的方法是添加以下在每个时间间隔计算的算法:

  1. 计算从船舶指向目的地的向量。
  2. 将当前速度矢量分成两个分量:朝向目的地和垂直于目的地。
  3. 如果垂直速度为零,则跳过 4
  4. 开始向垂直矢量方向的负方向旋转。如果已经将视线移开(不是完全相反,而是只是移开视线),也启动主推进器。

这会有点波动,我怀疑过一段时间它也会稳定下来。我必须承认,我不知道如何让它停在目的地。


最后的方法是对船舶的动力学进行建模,并尝试将其线性化。这将是一个非线性系统,因此第二步是必要的。然后将模型转换为离散时间系统。最后应用控制规则使其达到目标点。为此,您可以将状态空间从位置和速度更改为位置误差和(可能)速度误差,最后添加调节控制(一个控制循环,它采用当前状态,并生成一个输入,使得状态变量将趋近于零)。

最后一个在数学部分相当困难,你可能需要学习一些控制工程才能做到这一点。然而,你会得到比上述简单算法更好的结果 - 诚然,这甚至可能不起作用。此外,您现在可以对其应用各种优化规则:最小化达到目标的时间、最小化燃油消耗、最小化行驶距离等。

If you are not looking for a very general solution that works online, then there is a simple solution. What I mean by online is continuously re-calculating the actions along the complete trajectory.

Assuming the ship is at rest at start, simply rotate it towards your target point (while still at rest). Now, your ship can reach the target by accelerating for t seconds, rotating back while in motion (for 0.5 seconds as per your constraint), and decelerating for another t seconds. If the distance between current point and destination is d, then the equation you need to solve is:

d = 0.5*a*t^2 + 0.5*a*t + 0.5*a*t^2

The first term is distance traveled while accelerating. The second term is distance traveled while rotating (v*t_rot, v=a*t, t_rot=0.5). The final term is the distance traveled while decelerating. Solve the above for t, and you have your trajectory.

If the ship is moving at start, I would first stop it (just rotate in opposite direction of its speed vector, and decelerate until at rest). Now we know how to reach destination.

The problem with offline trajectory calculation is that it is not very accurate. There is a good chance that you will end up in the vicinity of the target, but not exactly on top of it.


Let's make the problem a little more interesting: the ship cannot rotate without acceleration. Let's call this acceleration vector a_r, a vector that is at a certain angle against the ship's direction (somewhat like having a thruster at an angle at the back). Your task now is to rotate the ship and accelerate in such a direction that the speed component perpendicular to the vector connecting the current position to the target is canceled out. Instead of trying to calculate the vectors offline, I would go with an online approach with this.

The easiest thing to do would be to add the following algorithm calculated at every time interval:

  1. Calculate the vector pointing from ship to destination.
  2. Split your current speed vector into two components: towards the destination, and perpendicular to it.
  3. If perpendicular speed is zero, skip 4
  4. Start rotating towards the negative of the perpendicular vector's direction. If already looking away from it (not exact opposite, but just looking away), also fire main thruster.

This will oscillate a bit, I suspect it will also stabilize after a while. I must admit, I don't know how I would make it stop at destination.


And the final approach is to model the ship's dynamics, and try to linearize it. It will be a non-linear system, so the second step will be necessary. Then convert the model to a discrete time system. And finally apply a control rule to make it reach target point. For this, you can change your state-space from position and speed to error in position and (maybe) error in speed, and finally add a regulation control (a control loop that takes the current state, and generates an input such that the state variables will approach zero).

This last one is fairly difficult in the maths compartment, and you'd probably need to study control engineering a bit to do it. However, you'll get much better results than the above simplistic algorithm - which admittedly might not even work. In addition, you can now apply various optimization rules to it: minimize time to reach target, minimize fuel consumption, minimize distance traveled, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文