c# - 负加速度恒加速度运动
问题描述
我在 Unity 上制作运动过程。
我想做一个将对象移动到指定位置的过程,但正如标题所示,我希望对象不仅可以移动,而且还希望它的速度衰减达到预定距离。
如果加速度是负的,我就不能很好地处理它。具体来说,我想在初始速度为 10 时到达一个位置而不返回,如图 gif 所示。
我使用恒定加速度运动公式中的“s=v0t+1/2at^2”来找到加速度“a”,但这似乎还不够。
如果您能帮助我,我将不胜感激。
public class Test : MonoBehaviour
{
public float t;
public float initSpd;
public Transform t1, t2;
IEnumerator Start()
{
var p = t1.position;
while (true) {
t1.position = p;
var v0t = initSpd * t;
var distance = Vector2.Distance(t1.position, t2.position);
var direction = (t2.position - t1.position).normalized;
var a = (2 * (distance - v0t)) / (t * t);
var v = initSpd;
// update
yield return Utils.Coroutine.WhileForSeconds(t, () =>
{
t1.Translate(direction * v * Time.deltaTime);
v += a * Time.deltaTime;
});
}
}
}
解决方案
您要计算的数学a
是正确的,但您提出的问题无法让您满意。
正如你所说,在恒定加速度下,位置是时间的二次函数,所以它被描述为
s = b t^2 + c t + d
对于一些常数b, c, d
。的值d
已经由初始位置固定。的值c
已经由初始速度固定。只剩下一个自由参数,当你求解 时s(finalTime) = goalPosition
,你无法控制得到的抛物线是否超过目标。
您可以增加多项式次数,但总会有一些初始速度太大而导致超调。
本质上,您有一个最佳控制/轨迹优化问题,例如
minimize: integral(acceleration(t)^2) from t = 0 to T
subject to: x(0) given
v(0) given
x(T) given
x(t) <= x(T) for all t in [0, T] (assuming x(0) < x(T))
正如您所说的问题,没有优化目标,但是您需要对加速度进行成本或约束,否则您可以获得无限加速度的解决方案(例如,在第一个时间步中加速非常困难,然后滑行到目标恒定速度)。
不平等使它变得复杂。如果您想要一个连续时间分析解决方案,那么 Pontryagin 的原理将是解决它的锤子,但可能会有更简单的技巧。如果您将时间离散化并让加速度为分段常数,那么这是一个简单的凸优化问题。
如果您愿意放宽“永不超调”和“恰好在这个时间到达”的约束,那么非常简单的解决方案,可以更好地适应更复杂的场景,如外力,是使用像 PD 控制器这样的反馈控制律:
a = kp * vectorToGoal - kd * velocityVector,
其中kp
和kd
是手动调整的正常数,并且在每一帧中都重新评估该表达式。您可以调整kp
并kd
最大限度地减少典型场景中的过冲。
或者,您可以做大多数游戏所做的事情 - 让速度瞬间改变 :)
推荐阅读
- jquery - 如何在 localhost 中使用 AJAX url
- java - java中的字母数字排序
- python - 使用 Python / Pandas 和可能的正则表达式从全名列表中提取姓氏
- mysql - Mysql - 在特定日期记录中查找缺失的月份
- ios - iOS 上的 Firebase 不返回新添加的条目
- javascript - Google Chrome、JQuery 和带有键的无法解释的事件行为
- google-cloud-datastore - Google Cloud Datastore、Python 客户端、add_filter 不返回任何结果
- javascript - 基于javascript中时间戳的范围之间的“随机”数
- javascript - 使用 Firebase 反应 Redux
- javascript - 通过 javaScript 显示动态饼图(只显示 for 循环中的最后一个)