我正在尝试对定向越野进行A *搜索以获得最佳路线。输入是两个文件 - 一个用于解释地形的图像文件和一个用于定义高程的文本文件。我根据预先设定的值计算地形难度,以定义地形穿越的速度。我还根据坡度定义了高程难度(向下坡度给出了更快的速度,反之亦然)。
地形和高程数据存储在矩阵中(列表列表)。因此,输入是与地图上的点相同的索引。提供了两个输入 - 例如:
start = [230,327]
end = [241,347]
问题是我的代码不断重新访问已访问的队列中已存在的节点。节点定义如下:
class Node:
def __init__(self,value,parent,start=[],goal=[]):
self.children = []
self.parent = parent
self.value = value
self.timeToGoal = 0.0000
self.timeTravelled = 0.0000
if parent:
timeToParent = self.parent.timeTravelled
[parentX, parentY] = parent.value
[currentX, currentY] = self.value
xDiff = abs(currentX - parentX)
yDiff = abs(currentX - parentX)
distance = 12.7627
if xDiff == 0 and yDiff != 0:
distance = 10.29
elif xDiff != 0 and yDiff == 0:
distance = 7.55
# distanceFromParent = math.sqrt(((currentX - parentX) ** 2) - (currentY - parentY) ** 2)
speedFromParent = 1.388 * calculateTerrainDifficulty( terrainMap[currentX][currentY]) * calculateElevationDifficulty(elevationMap[parentX][parentY], elevationMap[currentX][currentY], distance)
timeTravelledFromParent = 0
if speedFromParent != 0:
timeTravelledFromParent = distance / speedFromParent
else:
"Error: Speed from Parent Cannot Be Zero"
self.timeTravelled = timeToParent + timeTravelledFromParent
self.path = parent.path[:]
self.path.append(value)
self.start = parent.start
self.goal = parent.goal
else:
self.path = [value]
self.start = start
self.goal = goal
def GetTime(self):
pass
def CreateChildren(self):
pass
我还使用SubNode类来定义函数,时间被定义为自我+毕达哥拉斯斜边距离目标的时间:
class SubNode(Node):
def __init__(self, value, parent, start=[], goal=[]):
super(SubNode, self).__init__(value, parent, start, goal)
self.timeToGoal = self.GetTime()
def GetTime(self):
if self.value == self.goal:
return 0
[currentX, currentY] = self.value
[targetX, targetY] = self.goal
parentTime = 0
if self.parent:
parentTime = self.timeTravelled
heuristicTime = 99999.99
# Pythagorean Hypotenuse - Straight-line Distance
distance = math.sqrt(((int(currentX) - int(targetX)) ** 2) + (int(currentY)- int(targetY)) ** 2)
speed = 1.38 * calculateTerrainDifficulty(terrainMap[currentX][currentY])
if speed != 0:
heuristicTime = distance / speed
heuristicTime=heuristicTime+parentTime
return heuristicTime
def CreateChildren(self):
if not self.children:
dirs = [-1, 0, 1]
[xVal, yVal] = self.value
for xDir in dirs:
newXVal = xVal + xDir
if newXVal < 0 or newXVal > 394: continue
for yDir in dirs:
newYVal = yVal + yDir
if ((xVal == newXVal) and (yVal == newYVal)) or (newYVal < 0 or newYVal > 499) or (
calculateTerrainDifficulty(terrainMap[newXVal][newYVal]) == 0):
continue
child = SubNode([newXVal, newYVal], self)
self.children.append(child)
A *搜索类定义如下。您可以看到我已经将条件放在那里以确保不再重新访问节点,当我在那里放置打印时,我可以看到条件被多次满足。
class AStarSearch:
def __init__(self, start, goal):
self.path = []
self.visitedQueue = []
self.priorityQueue = PriorityQueue()
self.start = start
self.goal = goal
def Search(self):
startNode = SubNode(self.start, 0, self.start, self.goal)
count = 0
self.priorityQueue.put((0, count, startNode))
while (not self.path and self.priorityQueue.qsize()):
closestChild = self.priorityQueue.get()[2]e
closestChild.CreateChildren()
self.visitedQueue.append(closestChild.value)
for child in closestChild.children:
if child.value not in self.visitedQueue:
count += 1
if not child.timeToGoal:
self.path = child.path
break
self.priorityQueue.put((child.timeToGoal, child.value, child))
if not self.path:
print("Not possible to reach goal")
return self.path
由于某种原因,我的程序不断重新访问某些节点(正如我打印访问队列时从输出中看到的那样。我怎样才能避免这种情况?
[[230,327],[231,326],[229,326],[231,325],[231,328],[229,328], [231,327] ,[229,327], [231,327] ,[229,327],[229,325],[231,324],[230,323],[231,329] ],[229,329],[231,327],[229,327],[229,324],[231,330],[231,323],[229,330],[229,331]]
我面临的另一个问题是:
TypeError: unorderable types: SubNode() < SubNode()
有没有办法在不改变python的优先级队列使用的情况下克服这个问题?
答案 0 :(得分:2)
您需要在nearestChild而不是其子项上添加测试:
closestChild = self.priorityQueue.get()[2]e
if closesChild.value not in self.visitedQueue:
closestChild.CreateChildren()
self.visitedQueue.append(closestChild.value)
否则,您可以说访问n1
,然后n2
,同时链接到节点n3
。 n3
中添加了priorityqueue
两次,因此会弹出两次,然后再添加两次visitedQueue
。
条件if child.value not in self.visitedQueue:
对于加速(通过保持较小的优先级队列)非常有用,但不是必需的(因为在展开它们时,priorityQueue
中的不必要对象将被丢弃)。
关于您收到的错误:PriorityQueue
不支持自定义排序,这是优先级队列所需的,因此您必须自定义排序。有一个example here。显然,您的_get_priority
函数需要返回timeTravelled
而不是item[1]
编辑3 :我们(tobias_k和我)首先说你需要为__eq__
实现SubNode
函数,以便python知道它们中的两个是否相等,但是事实并非如此,因为您只在self.visitedQueue中存储值。