太空船动态推进器平衡


14

在我的游戏中,太空飞船是一种由玩家打造的装置,可以在任意位置,任意旋转地安装任意数量的推进器。我目前有一些肮脏的代码可以将船旋转到给定的角度(加速和减速)。

这是一个对称船面对红线指向的示例,被告知向左旋转。

船

但是,正如您想象的那样,取决于玩家将推进器放在何处,有时会出现不希望的线性力影响飞船的情况。在这种情况下,船开始前进。

我正在详细说明是否有可能找到推力器可以施加的最大推力而不引起线速度。(在上述情况下,这将是没有的,因为没有什么可以抵消来自后推力的力,而前推力会互相残杀)。

到目前为止,我想出了一个公式来确定“转弯效率”,例如,相对于线性运动,会引起多少旋转。

a-推进器b的位置矢量b-推进器b的位置矢量v1-推进器a的力v2-推进器b的力

efficiencyDelta = a.cross(v1)/ | v1 | -(a.cross(v1)+ b.cross(v2))/ | v1 + v2 |

,基本上是“ a.cross(v1 * t)/ | v1 |” 应该是转弯效率。然后,我们将其与推进器的转向效率相减,以查看是否值得使用新的推进器。

当我意识到推进器不是应该打开/关闭,而是可以将其推力从0更改为1时出现的。当玩家希望飞船前进时该怎么办。当然,需要平衡旋转/移动的量。

我不是火箭科学家,所以我希望有人可以告诉我,是否甚至可以这样计算每个推进器的油门,并向我推正确的方向。

感谢您抽出宝贵的时间!/金


3
我从同一条路径开始,但是有许多配置,无法同时旋转和平移。那你带走旋转吗?还是您允许翻译?最终,这取决于用户设计飞船。对于我的演示,我伪造了它。相关阅读:gamedev.stackexchange.com/questions/58216/...gamedev.stackexchange.com/questions/40615/...
MichaelHouse

我走了类似的路,最终在此页面上编写了一个演示。在移动推进器时(将其在船上拖动以设置位置和功率),它会绘制三种形状。直觉是您可以将所有可能的运动视为3d空间中的一个点(x,y,旋转),并且限制为0-1是该空间的约束。因此,您最终得到一个包含所有可能运动的3d形状。如果您不希望线速度,请查看该空间中的(x = 0,y = 0)线(在我的演示中Q,W,E,S全部为0)
amitp 2014年

Answers:


7

我将假设您的船体运动正确,否则该分析将不成立。您需要强于效率的东西才能正确解决此问题。

每个推进器都会对船的运动产生两种影响:线性和角度。这些可以独立考虑。如果推进器f在一个方向上产生力dir,并且从质心偏移一个矢量r(不是几何中心或子图形的中心!),那么对线性分量的影响为:

t = f * dir // f is a scalar, dir is unit length

对角速度的影响由扭矩给出:

tau = f * <dir.x, dir.y, 0> CROSS <r.x, r.y, 0> // cross product

t是力矢量(即线性推力)。tau是一个有符号标量,当除以质量惯性矩时,将给出角加速度。重要的是dirr都在同一坐标空间中,即都在局部坐标中或在世界坐标中。

船舶的整体线性加速度由t每个推进器的s 之和除以船舶的质量得出。同样,角加速度也就是转矩除以质量惯性矩(这是另一个标量)之和。如果总扭矩为零,则船舶将不会转弯。同样,如果总推力为零,它也不会移动。召回转矩是一个标量,但推力(“和t”的总和)是一个2D向量。

阐述的重点是,现在我们可以将问题写为 线性程序。首先说我们要我们的船。每个推进器都有一个变量$ x_1,x_2,... $,这是推进器将提供的推进量。一组约束是:

0 <= x_i < fmax_i  //for each i

fmax该推力器的最大力在哪里(这使我们可以更强或更弱)。接下来,我们说两个平等:

0 = Sum_i  x_i * dir_i.x
0 = Sum_i  x_i * dir_i.y

通过说总推力为零(推力是矢量,所以我们只说每个部分为零),我们就编码了这样的约束:我们将不施加线性加速度。

现在我们要我们的船转弯。大概我们想尽快这样做,所以我们想要:

max (Sum_i  x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0>

x_i在满足上述不等式和等式的同时求解,同时使上述总和最大化,将为我们提供所需的推力。大多数编程语言都有一个可用的LP库。只需将上述问题放入其中,它就会产生您的答案。

一个类似的问题将使我们继续前进。假设我们在一个坐标系中重新编写问题,在该坐标系中我们想沿正x方向移动。那么约束是:

0 <= x_i < fmax_i  //for each i
max Sum_i  x_i * dir_i.x
0 = Sum_i  x_i * dir_i.y
0 = (Sum_i  x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0> // as before

由于推进器只能产生单个方向的推力,因此您将能够实现的旋转和线速度的种类将受到限制。这将作为解决方案体现在0 = x_1 = x_2 = ... = x_n,这意味着您永远都将一事无成。为了减轻这种情况,我建议为每位玩家将一对小的,弱的(例如5%或10%)推进器添加到每侧45度的位置。这将为解决方案提供更大的灵活性,因为它们可以用来抵消主推力器的弱次要影响。

最终,对于多达100个推进器,LP的解决方案足够快,可以在每帧完成。但是,由于解决方案不取决于位置或当前状态,因此只要形状发生变化,您就可以为每种合理的控制器输入组合预先计算解决方案(包括添加非推力器,这些推力器会改变惯性矩或船的质量,因为推进器相对于质心位于不同的位置!)。这是24种可能性(即8个方向乘以{左旋转,不旋转,右旋转})。


很好解释!
2014年

1
Sum_i在这种情况下是什么意思?
S.TarıkÇetin17年

1

我的第一个想法是纯粹基于经验的解决方案,即在沙盒环境中模拟钻机以产生不同程度的推力,以了解其行为。可以在确定性解决方案的搜索中平衡许多复杂的数学运算,而无需数字化计算,例如使用牛顿法。例:

推力范围是0到1000,其中1000是ALOT。

步骤1

以信任(0 + 1000)/ 2 = 500进行模拟。结果:太多信任

第2步

现在范围是0到500以信任(0 + 500)/ 2 = 250模拟。结果:太多信任

步骤三

现在范围是0到250用信任模拟(0 + 250)/ 2 = 125结果:信任太少

步骤4

现在范围是125到250用信任模拟(125 + 250)/2=187.5结果信任过多

步骤5 现在的范围是125到187.5信任度模拟(125 + 187.5)/2=156.25结果信任度太低

步骤#6 现在的范围是156.25到187.5,范围低于35的阈值,这意味着该估计值足够好

最终结果=(187.5 + 156.25)/ 2 = 171.875

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.