Both sides previous revision
Poprzednia wersja
|
|
pl:miw:miw08_mindstormsdesign:labirynt [2008/05/27 00:23] miw |
pl:miw:miw08_mindstormsdesign:labirynt [2019/06/27 15:50] (aktualna) |
| ===== Labirynt ===== |
| {{ :pl:miw:miw08_mindstormsdesign:labirynt.png?200|Labirynt}} |
| Przed przystąpieniem do zadania należy przygotować labirynt (makietę). W celu lepszego sterowania robotem dobrze jest również pozbyć się kleszczy z przodu (patrz budowa robota TriBot). Kleszcze mogą utrudniać poruszanie się robota po planszy. |
| W ramach prezentowanego niżej algorytmu przyjęto: |
| - pola makiety po jakich poruszać się będzie robot są na tyle duże, że robot może się swobodnie obrócić |
| - przyjmujemy budowę robota TriBot bez przednich kleszczy |
| - robot nie wie nic o planszy |
| - w algorytmie przyjęto ruch co określoną długość, w celu uproszczenia za długość kroku przyjęto szerokość jednego pola planszy (patrz rys. Labirynt) |
| - każdej nowej pozycji przypisywany jest numer oraz parametry związane z tą pozycją |
| Opis pozycji robota: |
| {{ :pl:miw:miw08_mindstormsdesign:pomiar.png|Pomiar}} |
| - pozycja robota zostaje opisana przez 8 pomiarów echosondy pobieranych co kąt 45<sup>0</sup>. Otrzymane wyniki są zapisywane w bazie wiedzy robota o planszy. Kolejne pozycje są numerowane. Każda nowa pozycja znajduje się w odległości N cm od pozostałej (gdzie N jest szerokością jednego pola planszy). |
| - Taka struktura danych mogłaby wyglądać następująco: |
| pole(nr_pola,[nr_pomiaru,następne_pole,ultrasonic_value]) |
| * nr_pola - numer pola dla którego przeprowadzane są pomiary |
| * nr_pomiaru - numer przeprowadzanego pomiaru |
| * następne_pole - jest to informacja o polu jakie znajduje się w danym kierunku |
| * utrasonic_value - wartość echosondy w danym kierunku |
| {{ :pl:miw:miw08_mindstormsdesign:pomiar2.png|Przechodzenie do następnego pola}} |
| W ten sposób zdefiniowane pola można łączyć i budować prostą bazę wiedzy o otoczeniu robota. Czarne cyfry na rysunku przedstawiają numery poszukiwań. Pomiary przeprowadzane są co 45<sup>0</sup> więc jest ich 8. Czerwone cyfry oznaczają numery pól. Niebieskie cyfry są przypisanym numerem pola, do którego można się dostać podążając w kierunku pomiaru np. 3. Żółta cyfra 0 oznacza z kolei ścianę (przeszkodę), którą napotkamy w zadanym kierunku. Wartość ściany definiuje pomiar echosondy. Jeżeli odległość jest mniejsza niż ustalona wartość to wówczas przyjmujemy, że jest w tym miejscu ściana lub inna przeszkoda. |
| Poniżej zaprezontowano algorytm, który przy wykorzystaniu takiej postaci wiedzy steruje robotem TriBot. |
| |
| |
| |
| ==== Zapis słowny === |
| - Zbadaj otoczenie. |
| - Spośród zbadanych wartości **ultrasonic_v** wybierz tą, która jest największa i nie ma przypisanego węzła. Obróć się tam, gdzie ona jest. |
| - Jeżeli znaleziono wartość największą to: |
| - Przypisz tej galezi jako nr następnego węzła kolejny wolny nr węzła. |
| - Rusz się do przodu o N cm. |
| - Jeżeli wszyskie pozostałe połaczenia są zablokowane to: |
| - Wybierz kierunek z zaznaczonym węzłem następnym. |
| - Rusz się do przodu o N cm. |
| - Po przejściu do wezła zablokuj dostęp do węzła, z ostatniej pozycji robota. |
| - Idź do (2). |
| - Zbadaj otoczenie dla pomiaru 5 przypisz numer wcześniejszego węzła. |
| |
| |
| ==== Zapis regułowy ==== |
| <code ada> |
| Rule: 1 |
| if listOfAddedNodes.has?(current_node) == false |
| then listOfAddedNodes.add(current_node) and node.add(current_node,[1,0,ultras_v]) |
| then turn = 45 and node.add(current_node,[2,0,ultras_v]) |
| then turn = 45 and node.add(current_node,[3,0,ultras_v]) |
| then turn = 45 and node.add(current_node,[4,0,ultras_v]) |
| then turn = 45 and node.add(current_node,[5,previous_node,ultras_v]) |
| then turn = 45 and node.add(current_node,[6,0,ultras_v]) |
| then turn = 45 and node.add(current_node,[7,0,ultras_v]) |
| then turn = 45 and node.add(current_node,[8,0,ultras_v]) |
| |
| Rule: 2 |
| if listOfAddedNodes.has?(current_node) == true |
| then goTo(Rule 5) |
| |
| Rule: 3 |
| if messure_no in [0;8] |
| then messure_no++ and goTo(Rule 5) |
| |
| Rule: 4 |
| if messure_no not in [0;8] |
| then messure_no := 0 and goTo(Rule 7) |
| |
| Rule: 5 |
| if ultras_v(current_node,messure_no) > X and next_node(current_node,messure_no) == 0 |
| then turn = messure_no*45 |
| and goStepFoward |
| and node_counter++ |
| and node.update(current_node,[messure_no,node_counter,ultras_v]) |
| and current_node = node_counter |
| and goTo(Rule 1) |
| else goTo(Rule 3) |
| |
| Rule: 6 |
| if messure_no in [0;8] |
| then messure_no++ and goTo(Rule 7) |
| else STOP |
| |
| Rule: 7 |
| if ultras_v(current_node,messure_no) > X and next_node(current_node,messure_no) > 0 |
| then turn = messure_no*45 |
| and goStepFoward |
| and current_node = next_node(current_node,messure_no) |
| and node.update(current_node,[messure_no,-1,0]) |
| and goTo(Rule 2) |
| else goTo(Rule 6) |
| |
| </code> |
| |
| ==== Implementacja w Prologu ==== |
| <code prolog> |
| messured_nodes(node_no). |
| node(node_no,messure_no,next_node,ultrasonic_val,messured). |
| current_node(node_no,messure_no). |
| |
| current_messure(number). |
| %---------------------- |
| % dokonywanie pomiarów |
| %---------------------- |
| start :- |
| current_node(X,_), |
| node(X,Y,_,_), |
| messured_nodes(Q), |
| X \= Q, |
| nxt_ultrasonic_sensor(port,Value1), |
| assert(node(X,1,0,Value1), |
| |
| nxt_turn(speed,45), |
| nxt_ultrasonic_sensor(port,Value2), |
| assert(node(X,2,0,Value2), |
| |
| nxt_turn(speed,45), |
| nxt_ultrasonic_sensor(port,Value3), |
| assert(node(X,3,0,Value3), |
| |
| nxt_turn(speed,45), |
| nxt_ultrasonic_sensor(port,Value4), |
| assert(node(X,4,0,Value4), |
| |
| nxt_turn(speed,45), |
| nxt_ultrasonic_sensor(port,Value5), |
| assert(node(X,5,0,Value5), |
| |
| nxt_turn(speed,45), |
| nxt_ultrasonic_sensor(port,Value6), |
| assert(node(X,6,0,Value6), |
| |
| nxt_turn(speed,45), |
| nxt_ultrasonic_sensor(port,Value7), |
| assert(node(X,7,0,Value7), |
| |
| nxt_turn(speed,45), |
| nxt_ultrasonic_sensor(port,Value8), |
| assert(node(X,8,0,Value8) |
| assert(messured_nodes(X)). |
| |
| |
| %--------------------------- |
| % szukanie najlepszej drogi |
| %--------------------------- |
| |
| start :- |
| current_node(X,M), |
| node(X,Y,Next,U), |
| messured_nodes(X), |
| Next = 0, |
| U <= number, % wartość progowa, ponad którą dokonywane jest przeszukiwanie |
| retract(node(X,Y,_,_)), |
| assert(node(X,Y,1000,U), % blokowanie połączenia |
| current_messure(A), |
| B is A + 1, |
| retractall(current_messure(_)), |
| assert(current_messure(B)). |
| |
| start :- |
| current_node(X,M), |
| node(X,Y,Next,U), |
| messured_nodes(X), |
| Next = 0, |
| U > number, % wartość progowa, ponad którą dokonywane jest przeszukiwanie |
| retract(node(X,Y,_,_)), |
| nxt_ultrasonic_sensor(port,Value), |
| assert(node(X,Y,X+1,Value), |
| abs(M-Y,N), |
| nxt_turn(speed,45*N), % przemieszczenie do nowego punktu |
| nxt_go(1), |
| retractall(current_node(X,_)), |
| W is X + 1, |
| assert(current_node(W,1)), |
| assert(current_messure(1)). |
| |
| start :- |
| current_node(X,M), |
| node(X,Y,Next,U), |
| messured_nodes(X), |
| Next > 0, |
| U > number, % wartość progowa, ponad którą dokonywane jest przeszukiwanie |
| current_messure(D), |
| D <= 8, % pominięcie punktu, zwiększenie licznika o 1 |
| B is A + 1, |
| retractall(current_messure(_)), |
| assert(current_messure(B)). |
| |
| start :- |
| current_node(X,M), |
| node(X,Y,Next,U), |
| messured_nodes(X), |
| Next > 0, |
| U > number, % wartość progowa, ponad którą dokonywane jest przeszukiwanie |
| current_messure(D), |
| D > 8, |
| abs(M-Y,N), |
| nxt_turn(speed,45*N), % przejscie do punktu, który już był wcześniej badany |
| nxt_go(1), |
| node(Next,P,X,U2), |
| retractall(current_node(X,_)), |
| assert(current_node(Next,P)), |
| retractall(node(Next,P,_,_)), |
| assert(node(Next,P,1000,U2)). % zablokowanie powrotu do poprzedniego punktu |
| |
| start :- |
| go(0). |
| </code> |
| |
| |
| |
| |
| ==== XTT ==== |
| {{:pl:miw:miw08_mindstormsdesign:labirynt222.png|XTT}} |
| |
| FIXME |
| * przy większych algorytmach pojawia się problem z zapętlaniem |
| * podział na atrybuty, nie jest taki oczywisty, zwłaszcza w przypadku, gdy argumentami jest tablica argumentów |
| * ponadto, nie jest oczywiste jak odczytywać argumenty. W tym algorytmie założyłem, że wszystkie atrybuty są odwzorowaniem jednego rekordu z tablicy atrybutów. Atrybuty zmieniają się w przypadku zwiększenia atrybutu current_node |
| * nie jest jasne wykorzystanie akcji assert i retract. I pobieranie z nich wartości. |