我还没有解决所有的方程式,但是这里有一些视觉效果可以帮助我们解决这个问题。它归结为一些几何:
(通过肯尼的汽车图标)
从任何给定的起点和方向,我们都可以绘制两个具有最小转弯半径的圆-一个在左侧,一个在右侧。这些描述了通往我们道路的最紧要点。
我们可以对任何所需的最终位置和方向执行相同的操作。这些圆圈描述了我们道路的最可能的尽头。
现在,问题减少到找到一条路径,该路径将一个起始圆与一个终止圆连接,并沿切线相接。
(这是假设我们不需要在中间的障碍物上寻路,这在问题中没有提到。暴风城的答案进入了如何使用导航图信息解决这些类型的问题。一旦有了节点序列要通过,我们可以将以下方法应用于计划的每个部分。)
如果为简单起见,我们使用直线,则会得到以下内容:
这给了我们极限的情况。通过这种方法找到路径后,您可以人为地增加一个或两个起点和终点的圆,以获得一条不太直接但更平滑的路径,直到两个圆吻在一起为止。
计算这些路径
让我们找出一个转向的案例-说我们从右转开始我们的道路。
我们右转圆的中心是:
startRightCenter = carStart.position + carStart.right * minRadius
我们称这条路径的直线部分的角度(从x轴正方向测量) pathAngle
如果我们从rightCenter
离开转弯圆的点开始绘制矢量(在该点上我们必须面对pathAngle),则该矢量为...
startOffset = minRadius * (-cos(pathAngle), sin(pathAngle))
这意味着我们离开圆的点必须是...
departure = startRightCenter + startOffset
我们重新进入转弯圆的点取决于我们要以左转还是右转为终点:
// To end with a right turn:
reentry = endRightCenter + startOffset
// To end with a left turn: (crossover)
reentry = endLeftCenter - startOffset
现在,如果我们做我们的工作权,连线departure
到reentry
应该垂直于startOffset
:
dot(reentry - departure, startOffset) = 0
求解该方程式将为我们提供正确的角度。(我在这里使用复数,因为从技术上讲,有两个这样的角度,但是其中一个涉及反向驱动,这通常不是我们想要的)
让我们用右转右转案例代替:
dot(endRightCenter + startOffset - startRightCenter - startOffset, startOffset) = 0
dot(endRightCenter - startRightCenter, startOffset) = 0
pathAngle = atan2(endRightCenter - startRightCenter)
交叉的情况更加复杂-这是我还没有算完所有数学的情况。我暂不发布答案,以防在我确定其余详细信息时对您有用。
编辑:目标在最小转弯半径内
事实证明,即使目的地比我们的最小转弯距离更近,这种方法也经常开箱即用。再入圆中的至少一部分结束于转弯半径之外,只要我们不介意它有点像椒盐脆饼一样,就可以找到一条可行的路径...
如果我们不喜欢这样走的路(或者如果不可行-我没有详尽检查每个案例-可能没有不可能的案例),我们总是可以向前或向后行驶,直到找到合适的道路如上图所示,在开始和结束圆圈之间接吻。