用线性编程约束方向(简单)

时间:2018-09-12 17:30:43

标签: java 2d linear-algebra game-physics

我想制作一个模块化的2D飞船游戏。用户可以使用构建块来创建飞船。块可以是正方形,也可以是不适合网格的其他形状。为了计算应使用用户输入触发的推进器,我使用ojAlgo解决了线性编程问题。用户输入将类似于:[x:1,y:0,z 0]其中a是可以在方向上给出的最大推力,而-1在另一侧是相同的。 Z在这里旋转。

我有两个问题:
首先与我分别计算x和y的方式有关:

final ExpressionsBasedModel tmpModel = new ExpressionsBasedModel();
final Expression expressionX = tmpModel.addExpression("x").weight(1); //This is the user input.
final Expression expressionY = tmpModel.addExpression("y").weight(0).level(0); //Level means lower == 0 and upper == 0
final Expression expressionZ = tmpModel.addExpression("z").weight(0).level(0);

for (int i = 0; i < size; i++) {
    ThrusterBlock thrusterBlock = blockStash.thrusterList.get(i);
    final Variable thrusterVar = Variable.make("th_" + i);
    thrusterVar.lower(0).upper(1);
    tmpModel.addVariable(thrusterVar);

    expressionX.setLinearFactor(thrusterVar, thrusterBlock.displacement.x);
    expressionY.setLinearFactor(thrusterVar, thrusterBlock.displacement.y);
    expressionZ.setLinearFactor(thrusterVar, thrusterBlock.displacement.z); 
    //The thruster displacement is the calculated thrust in the given direction
}

Optimisation.Result tmpResult = tmpModel.maximise(); //To get the maximum weight (& thrust) out.

这是可行的,因为我可以将权重设置为> 0或<0,并且它将为每个推进器返回0到1之间的值。如果布局中有9个推进器,则可能是输出:

OPTIMAL 1.203 @ [1.0, 1.0, 0.0, 0.0, 0.32, 0.32, 1.0, 1.0, 1.0]
[
    0th [x: 0.401, y: 0.0 , z: -0.022]
    1th [x: 0.401, y: 0.0 , z: -0.022]
    2th [x: -0.401, y: 0.0 , z: -0.027]
    3th [x: -0.401, y: 0.0 , z: -0.027]
    4th [x: 0.0, y: 0.401 , z: 0.025]
    5th [x: 0.0, y: -0.401 , z: 0.025]
    6th [x: 0.0, y: -0.401 , z: 0.025]
    7th [x: 0.0, y: 0.401 , z: 0.025]
    8th [x: 0.401, y: 0.0 , z: -0.022]
]

问题是我不能使用该系统对角移动(例如40°),因为

final Expression expressionX = tmpModel.addExpression("x").weight(1);
final Expression expressionY = tmpModel.addExpression("y").weight(1);

不会将方程式约束为1:1的x和y比率,而是找到最有益的解决方案。我在这里不能使用水平,因为我不知道两者的最大推力。 约束x和y以便使用度数的最佳方法是什么?

第二个问题:
当我想让船转弯时,它会转大约45°,然后转回去。而控制系统显示相同的推进器正在点火。我确定我计算力的方式存在问题,但是我在角度计算方面的经验很低。我认为错误可以在这里找到:

public Vector2 getForce(float power, boolean relative){
   float force = maxThrust * power;
   float angle = toRad(this.relativePosition.z) + (relative ? 0 : this.blockCluster.getPos().z);
   //relativePosition.z is the orientation of the block in degree and this.blockCluster.getPos().z is the ship rotation in radians
   temp.x = force * ((float) Math.cos(angle)) * -1;
   temp.y = force * ((float) Math.sin(angle));
   return temp;
}

我认为这与余弦和正弦仅返回90°有关,但我不确定。

最后,任何优化都将受到赞赏,因为它可能会连续运行多个帧。如果计算速度较慢,我将保存计算结果。

感谢您的时间!

ps:从“游戏开发”移植,因为实现比用例更通用。

0 个答案:

没有答案