宇宙飞船推进系统的人工智能:控制力量使飞船在x=0和v=0处着陆。

3

我需要编写AI来控制游戏中的飞船的多个推进喷嘴。

为简单起见:
将空间视为1D。
飞船是一个点,只有1个喷嘴。

规则和问题

xva分别表示飞船的位置、速度和加速度。
F是施加在飞船上的喷流的力。

我知道飞船的质量m,假设m = 1。

以下是摘要:

acceleration = F/m;
v = vOld + acceleration*timestep;
x = xOld + v*timestep;

这个目标是让飞船以0速度降落在特定位置:x=0和v=0。

人工智能可以“加速”或“减速”喷气:

F+=flexibility;
or 
F-=flexibility;

人工智能可以访问当前的xvF。人工智能还可以缓存它。

那么我应该如何编程人工智能呢?

我不太好的解决方案

思路1:最终,x应该等于0。

假设a是一个常数:

(current x) + (current v) * t + 1/2 * a * t * t = 0

t是一个神奇的数字 - 它需要多长时间才能使飞船的x=0。

想法2:最后,v应该等于0。

(current v) + a*t = 0

我将两个想法结合起来:

如果 |x|>=thresholdX --> 使用想法1
如果 |x|~0 --> 使用想法2
介于两者之间 --> 对两个想法加权平均

这里,thresholdX 是另一个魔数。
我使用方程中的 a 来找到适当的 F。(F=ma

这是结果:

enter image description here
由于质量由另一个 AI 近似计算,并且存在一些小的随机外力,因此图形具有噪声。

如果有人问,我可以发布我的 C++ 代码(约 100 行)。


1
使用常量a几乎是不可能的——对于每个x,只有一个可能的v可以允许平稳着陆,而对于每个v,也只有一个x。您需要一个变量加速度a(t) - pingul
@pingul 很棒的想法,谢谢!你能猜出函数 a(t) 的公式应该是什么吗? - javaLover
1
这可能是一个相当棘手的问题。找到解析解(即a(t)的确定形式)很难,因为有无限多个解可以实现最终结果(当x == 0时,v == 0)。一个不太数学化的解决方案可能是使用某些学习算法进行训练或制作一个监管控制系统,但这些也可能很困难。我在这里概述了一种比较简单的方法:http://stackoverflow.com/questions/38870822/how-to-implement-arriving-behavior-with-time-delta/38880776#38880776 - pingul
@pingul 太棒了的链接!你提供的页面中的一个链接(http://natureofcode.com/book/chapter-6-autonomous-agents/)非常好,谢谢! - javaLover
这不是一个解决方案,但为了更好地理解问题,也许你应该在相空间中绘制你的变量,而不是针对时间。例如,你可以创建一个v-x图表,并绘制一个区域,其中你可以在给定最大值a(基本上是火箭的最大推力)的情况下进行安全着陆。 - biziclop
显示剩余2条评论
2个回答

4
首先,你计划降落在一个有质量的物体上,还是只是在空间中的任意点停下来?你的问题说“着陆”,所以我假设前者,这种情况下你需要考虑重力。这应该很容易做到:F_actual = F_engine - F_gravity
其次,在现实生活中你会怎么做?现实中的飞行员希望在到达跑道之前就将飞机“建立”在“滑行坡度”上,并使飞机处于“修整状态”,以便在理想条件下(没有风等)飞机可以自动降落而无需控制输入(我简化了一些,忽略了起落过程等)。
对于火箭,我可能希望将自己置于这样的情况:在离地面安全高度的某个位置,我的下降速率足够使得火箭在发动机以恒定功率运行的情况下自行降落到地面,除了在着陆时关闭发动机外,我不需要额外的输入(实际上,我希望飞行系统允许我在着陆时自动关闭发动机)。
要看看这将如何工作,只需将问题反向运行。从x=0, v=0开始,以a=发动机可以产生的某个恒定和合理加速度,绘制火箭上升时随时间变化的x和v。显然,v=at(一条直线),而x是这些值的总和(一个抛物线)。
那个抛物线就是你的“滑行坡度”。现在,你的问题不再是试图在同时达到x=0v=0(x永远不为负)的情况下着陆,而是“我如何以安全高度撞上滑行坡度?”所以你的逻辑会像这样:
  1. 如果x=0,则关闭发动机。
  2. 否则,如果你在滑行坡度上,则将引擎功率设置为所需的(恒定)减速度。坐下来等待物理学为你做所有艰苦的工作。
  3. 否则,如果x<min_approach_height并且你不在滑行坡度上,则猛烈燃烧以攀登。
  4. 否则,调整发动机功率以达到滑行坡度。
一些注意事项:
  1. “滑降道”并不意味着水平运动。我只是用这个术语来类比固定翼飞机。我的意思是将速度v绘制成对位移x的图形,使恒定的加速度a可以产生轻柔的着陆,而无需其他控制输入。
  2. 你要降落的物体是否有大气层?如果有,你的火箭会有一个终端速度,在这种情况下,逻辑简化为:快速进入大气层以使速度达到滑降道上方的终端速度。等待滑降道。当你接近滑降道时,以恒定功率点火。在触地时关闭引擎。
  3. 到目前为止,我忽略了“近似”的质量和“随机外力”。只要它们不让你偏离滑降道太远,小幅度的功率调整就可以将你带回滑降道。当你下降时,持续进行这些修正。如果你偏离滑降道太远,进行最大推力点火,然后重试。
  4. 顺便说一句,如果没有那些随机因素,这个滑降道方法可以让你用只有两个设置的引擎(恒定减速功率和关闭)轻松着陆。
  5. 我没有解决你的问题,只是把它转化成了另一个问题——但是,解决这个新问题应该会使你的游戏更加逼真(希望提高沉浸感)。此外,这个问题可能比原来的问题简单(见上面的注释2和4)。最后,尽早设定好滑降道,然后只进行小修正调整意味着你的人工智能不必处理极端情况或提供极端的控制输入。

嗯......即使经过编辑,这篇文章还是相当长。我想我应该停在这里......


太棒了!我使用了你的解决方案,它完美地运行了。现在我尝试将这个解决方案扩展到3D,但我卡住了。这里是一个新问题的链接。你可能也能很容易地回答它。感谢你的关注!https://dev59.com/rek6XIcBkEYKwwoYAfGc - javaLover

0
第一步是使用手动控制实现游戏。建立一个带有物理模拟的仿真,并为飞行员添加一些按钮。如果太空船的手动着陆成功,那么就可以开始进行第一个AI原型设计。这通常被实现为单臂赌徒,也就是说,随机生成器计算加速度。用户没有其他选择,只能观看和希望。下一个将手动实现的AI原型使用伪随机生成器。也就是说,爆发在一定范围内但仍然是随机的。问题不在于AI是否能够着陆,而在于AI需要进行10次还是100次试验。减少失败率的最佳实践是使用像OP中的规则这样的启发式方法。这些启发式方法并不适用于每种情况,它们只能改善伪随机生成器。这有点像过程生成。

伪随机生成器的数字应该用于某些系统设置吗?使用哪些数字以及什么公式?你是指像std::mt19937这样的东西吗?我是否必须随机选择种子? - javaLover
AI可以控制F(对飞船的力量)。 AI的第一版是在-100和100之间波动F(真随机生成器)。 飞船将进行随机行走。 AI的第二版是以减少的随机性“在0到10之间生成F,但如果位置x> 0,则给出F = -10”。 AI的第三版进一步减少了随机性。 这被称为伪随机生成器。 它是一个混合系统(启发式加C ++随机生成器)。 - Manuel Rodriguez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接