diff --git a/Raporty/route-planning.md b/Raporty/route-planning.md new file mode 100644 index 0000000..fa5d973 --- /dev/null +++ b/Raporty/route-planning.md @@ -0,0 +1,95 @@ +##### Raport przygotowały: Natalia Plitta, Marta Roszak, Kinga Molik, Sara Kowalska + +##### Raportowany okres: 5 kwietnia - 26 kwietnia 2020 + +##### Niniejszy raport poświęcony jest przekazaniu informacji na temat stanu projektu grupowego realizowanego na przedmiot Sztuczna Inteligencja w roku akademickim 2019/2020. + +Ruch agenta został zaimplementowany przy za pomocą algorytmu A* z następującymi warunkami: + +- agent wykonuje: krok do przodu/ obrót w prawo/ obrót w lewo; +- agent nie może wejść na pole "zajęte" przez stolik; +- koszt wejścia na puste pole to 1; +- koszt wejścia na pole z kałużą to 3. + +**** + +Koszt F obliczany jest z sumy kosztu G i kosztu H. + +Koszt H obliczany jest z funkcji: + +``` +def heuristic(current, goal): + dx = abs(current[0] - goal[0]) + dy = abs(current[1] - goal[1]) + return math.sqrt(dx * dx + dy * dy) +``` + +Która oblicza odległość do punku końcowego przy pomocy wzoru Euklidesa. + +Metoda __aStar__, wywoływana przez metodę __goByAStar__, wytycza ścieżkę, którą będzie poruszał się kelner. W pierwszej kolejności sprawdzane jest czy nasz punkt docelowy jest osiągalny. Jeżeli tak to zaczynamy wytyczanie ścieżki. Tworzymy węzły (obiekty klasy __Node__) startowy i końcowy oraz listy pomocnicze 'open' i 'closed'. + +```python +start_node = Node(None, start) +start_node.g = start_node.h = start_node.f = 0 +end_node = Node(None, end) +end_node.g = end_node.h = end_node.f = 0 + +open_list = [] +closed_list = [] +open_list.append(start_node) +``` + +Dopóki lista 'open' ma dostępne pola jest możliwa dalsza droga. Porównujemy koszty F i za każdym razem uaktualniamy obecny punkt, w którym koszt jest najmniejszy. + +Jeżeli nasz obecny węzeł jest węzłem końcowym tzn. osiągnęliśmy nasz cel, metoda zwraca nam ścieżkę zbudowaną z odwróconej listy "kroków" (stanów) do klasy kelner. + +Jeśli nie osiągnęliśmy celu przechodzimy do analizowania sąsiadów obecnej pozycji, najpierw sprawdzamy czy punkt ten jest osiągalny : + +```python +for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0)]: + node_position = (current_node.position[0] + new_position[0],current_node.position[1] + new_position[1]) + if node_position[0] >= (rows - 1) or node_position[0] <= 0 or node_position[1] >= (rows - 1) or node_position[1] <= 0: continue + if node_position in cantwalk: + continue +new_node = Node(current_node, node_position) +children.append(new_node) +``` + +Tworzymy listę 'children'- potencjalnych następnych kroków. + +*Zmienna 'didBreak' pozwala nam na kontynuacje algorytmu bez redundantnego analizowania węzłów.* + +Jeśli nie analizowaliśmy danego węzła, obliczamy dla niego dany koszt G + +- jeśli jest on nieosiągalny - koszt jest zbyt duży do dalszego podążania w tym kierunku; +- jeśli jest to "kałuża" to koszt wynosi 3; +- jeśli jest to "zwykła płytka" koszt wynosi 1. + +Następnie obliczamy koszt H i koszt F (jako sumę G i H) dla danego węzła 'child' i dodajemy go do listy 'open'. + +```python +if child.position in cantwalk: + child.g = current_node.g + 99999 +elif child.position in puddles: + child.g = current_node.g + 3 +else: + child.g = current_node.g + 1 +child.h = heuristic(child.position, end_node.position) +child.f = child.g + child.h +``` + +Kontrolowane jest również czy dany krok nie oddalałby agenta od celu: + +```python +for open_node in open_list: + if child == open_node and child.g > open_node.g: + didBreak = True + break + + if didBreak: + continue + +open_list.append(child) +``` + +Gdy wytyczona zostanie ścieżka, metoda __goByAStar__ przy pomocy dostępnych akcji (__rotateRight__, __rotateLeft__ i __goForward__), "wykonuje" odpowiednie ruchy, zgodne z wytyczoną ścieżką. \ No newline at end of file