Python 正确实施墙跟随转向行为 介绍
一段时间以来,我一直在尝试实施Craig Reynold所描述的“墙跟随”转向行为。这种行为基本上可以归结为网站上的描述: 为了实现墙跟踪,我们首先预测车辆的 根据当前速度在未来短时间内定位 (黑点)。此未来位置投影到上最近的点 “墙”(红点)。从该墙点沿墙向外移动 通过所需偏移距离的法线(红线)生成目标 点(红色圆圈) 链接页面上有一个Java小程序显示了上述内容,但对于那些(大多数人)在查看时遇到困难的人,请参见下面的.gifPython 正确实施墙跟随转向行为 介绍,python,python-2.7,boids,Python,Python 2.7,Boids,一段时间以来,我一直在尝试实施Craig Reynold所描述的“墙跟随”转向行为。这种行为基本上可以归结为网站上的描述: 为了实现墙跟踪,我们首先预测车辆的 根据当前速度在未来短时间内定位 (黑点)。此未来位置投影到上最近的点 “墙”(红点)。从该墙点沿墙向外移动 通过所需偏移距离的法线(红线)生成目标 点(红色圆圈) 链接页面上有一个Java小程序显示了上述内容,但对于那些(大多数人)在查看时遇到困难的人,请参见下面的.gif 我已经非常接近了,但由于某些原因,我的版本仍然有点偏离。我的
我已经非常接近了,但由于某些原因,我的版本仍然有点偏离。我的boid似乎无法选择下一个最近的墙像素,这会导致投影目标点的抖动移动。这个问题非常严重,以至于boid有时几乎可以赶上目标点,而不需要预测新的目标点。请参阅下面的.gif进行比较 要简要描述boid在我的实现中如何操作,请执行以下操作:
followWall()
followWall()
中,如果boid的成员变量hasHitWall
为False,它将检查boid前面的点是否落在墙像素上(boid在其中移动的环境是黑白像素的网格,其中黑=墙)hasHitWall
设置为True,并收集所有连接的墙“边缘像素”,并将其存储在boid中名为currentEdgePixels
的列表中hasHitWall
为真,boid将通过迭代currentEdgePixels
并找到距离其位置最短的一个来找到最近的边缘像素。然后,它将拉动该墙像素的法线,并沿法线向量投影一个设定距离的点。这就成为了“指导点”
seek()
行为转向点(在Craig Reynold的描述中称为目标点)hasHitWall
保持为真,boid将继续在currentEdgePixels
中找到最近的边缘像素并向其搜索我的上述行为代码可以在下面找到。但是,首先对一些常见元素进行一些简要说明:
pixelGrid
:此参数是表示图像行的列表列表。表示行的列表中的每个元素都包含1或0,具体取决于该行/列位置的像素颜色是白色还是黑色
getNormalizedVectorFromOrigin()
:此函数返回一个元组,表示[-1,1]范围内单位圆上的向量。如果将向量(或点)传递到未规范化向量超出[-1,1]范围的函数中,则在返回之前,生成的向量将减小到适合的范围内。例:(1.7675,-1.7675)的向量将变成(0.707,-0.707)
跟随墙():
def followWall(self, pixelGrid, screenSize):
if (not self.hasHitWall):
wallCollisionPixel = self.detectWall(pixelGrid, screenSize)
if (wallCollisionPixel):
self.hasHitWall = True
self.currentEdgePixels = utils.findAllEdgePixels(wallCollisionPixel, pixelGrid, screenSize)
elif (self.hasHitWall):
wallPixel = self.findClosestEdgePixel(pixelGrid, screenSize)
wallPixelNormal = utils.getEdgePixelNormal(wallPixel, pixelGrid, screenSize)
steeringPointDistance = 30
steeringPoint = (int(round(wallPixel[0] + (wallPixelNormal[0] * steeringPointDistance), 0)), int(round(wallPixel[1] + (wallPixelNormal[1] * steeringPointDistance), 0)))
self.seekPoint = steeringPoint
self.seek(steeringPoint, 1)
def findClosestEdgePixel(self, pixelGrid, screenSize):
futureDistance = 20
normalizedVelocity = utils.getNormalizedVectorFromOrigin(self.velocity.get())
futurePosition = (int(round(self.position.x + (normalizedVelocity[0] * futureDistance), 0)), int(round(self.position.y + (normalizedVelocity[1] * futureDistance), 0)))
closestEdgePixel = self.currentEdgePixels[0]
for edgePixel in self.currentEdgePixels:
if (utils.getDistance(futurePosition, edgePixel) < utils.getDistance(futurePosition, closestEdgePixel)):
closestEdgePixel = edgePixel
return closestEdgePixel
def getDistance(point1, point2):
return math.sqrt(((point2[0] - point1[0]) ** 2) + ((point2[1] - point1[1]) ** 2))
findClosestEdgePixel():
def followWall(self, pixelGrid, screenSize):
if (not self.hasHitWall):
wallCollisionPixel = self.detectWall(pixelGrid, screenSize)
if (wallCollisionPixel):
self.hasHitWall = True
self.currentEdgePixels = utils.findAllEdgePixels(wallCollisionPixel, pixelGrid, screenSize)
elif (self.hasHitWall):
wallPixel = self.findClosestEdgePixel(pixelGrid, screenSize)
wallPixelNormal = utils.getEdgePixelNormal(wallPixel, pixelGrid, screenSize)
steeringPointDistance = 30
steeringPoint = (int(round(wallPixel[0] + (wallPixelNormal[0] * steeringPointDistance), 0)), int(round(wallPixel[1] + (wallPixelNormal[1] * steeringPointDistance), 0)))
self.seekPoint = steeringPoint
self.seek(steeringPoint, 1)
def findClosestEdgePixel(self, pixelGrid, screenSize):
futureDistance = 20
normalizedVelocity = utils.getNormalizedVectorFromOrigin(self.velocity.get())
futurePosition = (int(round(self.position.x + (normalizedVelocity[0] * futureDistance), 0)), int(round(self.position.y + (normalizedVelocity[1] * futureDistance), 0)))
closestEdgePixel = self.currentEdgePixels[0]
for edgePixel in self.currentEdgePixels:
if (utils.getDistance(futurePosition, edgePixel) < utils.getDistance(futurePosition, closestEdgePixel)):
closestEdgePixel = edgePixel
return closestEdgePixel
def getDistance(point1, point2):
return math.sqrt(((point2[0] - point1[0]) ** 2) + ((point2[1] - point1[1]) ** 2))
结束 如果有人想知道如何让我的实现更好地工作,或者指出我的代码中可能导致问题的缺陷,我将不胜感激。如果您认为有更好的方法来实现这种特定的转向行为,我也非常乐意听到您的建议 请让我知道,如果我可以提供任何更多的信息或代码位。事先非常感谢