AL-2020/route-planning.md

3.6 KiB

Raport 2

Definicja pętli głownej strategi przeszukiwania

Naszą główną funkcją jest funkcja aStar(startField, goalField), przyjmuje ona dwa argumenty: startField - pole z którego wyrusza agent goalField - cel drogi agenta. Zwraca ona ścieżkę z startField do goalField.

Opis

closedSet - lista zawierająca sprawdzane i sprawdzone pola z listy openSet

openSet - lista zawierająca pola do sprawdzenia

path - lista zawierająca pola tworzące ścieżkę do wybranego celu


  • Dodajemy pierwszy element który będziemy sprawdzać do listy openSet: openSet.push(startField);
  • Kolorujemy punkt startowy na zielono: colorGreen(startField, animationFrame);
  • Dopóki lista openSet nie bedzie pusta sprawdzamy jej elementy: while(openSet.length > 0)
  • Wybieramy najbardziej obiecujący element z zbioru openSet:
let winner = 0;
for(let i = 0; i < openSet.length; i++){
    if (openSet[i].f < openSet[winner].f){
        winner = i
    }
}

let current = openSet[winner];
  • Jeśli pole current okaże się naszym celem tworzymy ścieżkę z punktu startowego do naszego celu.
if(current === goalField){
    path = []
    var temp = current;
    path.push(temp);
    while(temp.previous){
    path.push(temp.previous);
    temp = temp.previous
}
  • Następnie kolorujemy tą ścieżkę i kończymy funkcję zwracając ścieżkę path
for(var i = 0; i < path.length; i++){
    animationFrame = colorYellow(path[i], animationFrame);
}
return path;
  • Jeśli pole current nie jest naszym celem, to usuwamy je z listy openSet, dodajemy do listy closedSet oraz kolorujemy je na czerwono.
removeFromSet(openSet, current);
closedSet.push(current);
animationFrame = colorRed(current, animationFrame);
  • Pobieramy sąsiadów pola current: var neighbors = current.neighbors;
  • Dla każdego sąsiada obliczamy koszt dotarcia do niego z punktu początkowego najlepszą ścieżką.
for(var i = 0; i < neighbors.length; i++){
    var neighbor = neighbors[i];
    if(!closedSet.includes(neighbor)){
        var tempG = current.gScore + neighbor.costOfTravel;
        if(openSet.includes(neighbor)){
            if(tempG < neighbor.gScore){
                neighbor.gScore = tempG;
            }
        } else {
            neighbor.g = tempG;
            openSet.push(neighbor);
            animationFrame = colorGreen(neighbor,animationFrame);
        }
  • Po przypisaniu kosztu do sąsiada przypisujemy jego odległość do celu:
    `neighbor.h = getDistance(neighbor, goalField);

  • sumę jego kosztu oraz heurystki: neighbor.f = neighbor.g + neighbor.h; gdzie neighbor.g to koszt dotarcia do danego pola, a neighbor.h to szacowana odległość od danego pola do celu.

  • oraz jego poprzednika: neighbor.previous = current;

Definicja funkcji następnika

Następnik wybierany jest z listy sąsiadów poprzednio wybranych pól. Jest to najbardziej obiecujące pole current, tzn. pole o najmniejszej sumie kosztu przejścia do niego z punktu startowego oraz heurystki.

let winner = 0;
    for(let i = 0; i < openSet.length; i++){
        if (openSet[i].f < openSet[winner].f){
            winner = i
        }
    }
let current = openSet[winner];

Definicja przyjętej heurystyki

Jest to szacowana odległość od sprawdzanego pola do celu. Obliczana jest jako Manhattan Distance, ponieważ w naszym modelu Agent nie może poruszać się po skosie.

distance = |x1 - x2| + |y1 - y2|

Przykładowe działanie implementacji algorytmu A*

https://youtu.be/b5RHlOqqs4Y