AI-2020/route-planning.md

3.1 KiB

Raport Planowanie Ruchu

Definicja pętli głównej strategii przeszukiwania

def astar(self):
    print("finding path to", self.goal)
    fringe = PriorityQueue()
    explored = []
    start = Node((self.x, self.y, self.dir), False, False)
    fringe.put((1, start)) 

Utworzenie kolejki fringe, listy przebytych Node oraz dodanie do kolejki poczatkowego Node.

    while True:
        if fringe.empty():
            return False
        elem = fringe.get()[1]

Jeśli kolejka jest pusta, zwraca False jako wystąpienie błędu. W innym przypadku pobiera pierwszy element z kolejki fringe.

        if self.goaltest(elem.state):
            self.path = []
            while elem.action is not False:
                self.path.insert(0, elem.action)
                elem = elem.parent
            print(self.path)
            return True

Jeśli pobrany element jest celem to za pomocą dodanych pól parent i action tworzona jest lista ruchów do wykonania przez agenta.

        explored.append(elem.state)
        for (akcja, stan) in self.succ(elem.state):
            x = Node(stan, elem, akcja)
            p = self.f(x)

W innym przypadku element ten jest dodany do listy przebytych i otrzymane są jego następniki.

            if not(stan in fringe.queue) and not(stan in explored):
                fringe.put((p, x))
            elif (stan in fringe.queue):
                fringe.queue.remove(elem)
                fringe.put((p, x))

Jeśli następnik będący stanem nie był wcześniej dodany do kolejki to zostaje dodany teraz, jeśli był to jego priorytet jest aktualizowany jeśli jest niższy od wcześniejszego.

Definicja funkcji następnika

def succ(self, state):		        
    s = []
    r = state[2] - 1
    if r == 0: 
        r = 4
    s.append((("rotate", "right"), (state[0], state[1], r)))

    l = state[2] + 1
    if l == 5:
        l = 1
    s.append((("rotate", "left"), (state[0], state[1], l)))
    if self.canWalk(state):
        if state[2] == 1:
            w = state[1] - 1
            s.append((("walk"), (state[0], w, state[2])))
        elif state[2] == 2:
            w = state[0] - 1
            s.append((("walk"), (w, state[1], state[2])))
        elif state[2] == 3:
            w = state[1] + 1
            s.append((("walk"), (state[0], w, state[2])))
        elif state[2] == 4:
            w = state[0] + 1
            s.append((("walk"), (w, state[1], state[2])))
    return s

Funkcja następnika zwraca stany otrzymane poprzez obrót w prawo i lewo, oraz jeśli to możliwe to ruch do przodu.

Definicja przyjętej heurystyki

def f(self, node):
    cost = restaurant.tiles[self.goal[1]][self.goal[0]].cost
    return heuristic((node.state[0], node.state[1]), self.goal) + cost

Przyjęta heurystyka zwraca dystans pomiędzy dwoma punktami w linii prostej do którego jest dodany koszt pola, gdzie pole ma koszt 1 dla zwykłego i koszt 5 dla pola z kałużą.