Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Poprzednia wersja
Nowa wersja
Poprzednia wersja
pl:plnxt:pierwsze_kroki [2009/02/21 19:40]
holownia
pl:plnxt:pierwsze_kroki [2009/09/25 00:39]
holownia
Linia 1: Linia 1:
 ====== Pierwsze kroki ====== ====== Pierwsze kroki ======
  
-===== Test połączenia =====+W tym przewodniku przedstawiono sposób konfiguracji PLNXT oraz przykłady użycia od najprostszych do bardziej skomplikowanych.
  
-==== Otwarcie ​====+Zakłada się, że użytkownik posiada podstawową znajomość języka Prolog i poprawnie skonfigurował system operacyjny do współpracy z modułem komunikacyjnym,​ którego ma zamiar używać. Jeśli nie, proszę wrócić do [[pl:​plnxt:​start#​konfiguracja|opisu konfiguracji]]. 
 + 
 +===== Użyteczność modułów komunikacyjnych ===== 
 + 
 +Obecnie dostępne są 4 moduły, ale moduł //sockets// ma poważne uchybienia i nie nadaje się do użytkowania. 
 + 
 +Moduł //​simulator//​ korzysta z prologowej biblioteki graficznej //xpce//. Umożliwia uruchamianie programów napisanych przy użyciu biblioteki PLNXT bez zestawu Mindstorms NXT. Nie jest w rzeczywistości modułem komunikacyjnym,​ bo jednynie w prymitywny sposób symuluje działanie NXT (jednego lub więcej) przez wyświetlanie stanu silników i możliwość wybierania wartości odczytywanych przez sensory. Mimo swojej prostoty, dzięki możliwości spowolnienia w czasie "​ruchu"​ wirtualnego robota, //​simulator//​ pozwala śledzić działanie nawet bardziej złożonych programów. 
 + 
 +Dwa moduły komunikacyjne //serial// i //​iCommand//​ dostarczają dwóch alternatywnych sposobów kontrolowania prawdziwego robota. //​ICommand//​ ma jednak poważne minusy względem //serial//. Wymaga wirutalnej maszyny javy i zainstalowanej biblioteki javowej o identycznej nazwie iCommand. Biblioteka ta stanowi warstwę pośredniczącą między obsługą portu i PLNXT. Jej uchybieniem jest brak pewnych funkcji: 
 +  * synchroniczne poruszanie silnikami,​ 
 +  * kontrolowanie wielu robotów jednocześnie. 
 + 
 +Zaleca się używanie modułu //​serial//​. 
 + 
 +===== Konfiguracja PLNXT ===== 
 + 
 +W pliku konfiguracyjnym //​plnxt.pl//​ dostępny jest szereg ustawień. 
 + 
 +Należy wybrać moduł komunikacyjny przez odkomentowanie jednej z linii w poniższym bloku: 
 +<code prolog>​ 
 +%%% Choose communication module. 
 +%%% One and only of lines below should be uncommented. 
 +:- use_module(lib/​nxt_actions_serial). 
 +%:- use_module(lib/​nxt_actions_icommand). 
 +%:- use_module(lib/​nxt_actions_simulator). 
 +%:- use_module(lib/​nxt_actions_sockets). 
 +</​code>​ 
 + 
 +Następnie definiuje się roboty, których będzie się używać. Każdemu z nich nadaje się alias. Pierwszy z robotów jest robotem domyślnym, którego można kotrolować z konsoli w głównym wątku SWI-Prolog. 
 + 
 +Definicja każdego robota wygląda następująco:​ 
 +<code prolog>​ 
 +% nxt_goal_definition(Alias,​Device,​Conn_type,​Sync_mode,​Readings,​WheelCircumference,​AxleLenght,​LeftMotor,​RightMotor,​PincerMotor,​ 
 +%       Reverse,​TouchPort,​SoundPort,​LightPort,​UltrasonicPort). 
 +nxt_goal_definition(my_robot,'/​dev/​rfcomm0',​bt,​off,​on_demand,​17.5,​11,'​C','​B','​A',​false,'​S1','​S2','​S3','​S4'​). 
 +</​code>​ 
 + 
 +Znaczenie poszczególnych ustawień:​ 
 +  * Alias - alias robota (słowo //current// nie jest dozwolone). 
 +  * Device - port szeregowy używany do komunikacji. 
 +  * Conn_type - rodzaj połączenia,​ //usb// albo //bt// (bluetooth). 
 +  * Sync_mode - synchronizacja silników (//on// albo //off//). Może być włączona (//on//) jedynie, gdy używany jest moduł //​serial//​. 
 +  * Readings - sposób odczytywania pomiarów sensorów (//cyclic// albo //​on_demand//​). Wyjaśnienie [[pl:​plnxt:​pierwsze_kroki#​odczyt_sensorow|tutaj]]. 
 +  * WheelCircumference - obwód koła w cm. Standardowa opona w zestawie NXT ma obwód 17,5 cm. 
 +  * AxleLength - odległość pomiędzy prawym i lewym kołem w cm. 
 +  * LeftMotor - port, do którego podłączony jest lewy silnik ('​A',​ '​B'​ albo '​C'​). 
 +  * RightMotor - port, do którego podłączony jest prawy silnik ('​A',​ '​B'​ albo '​C'​). 
 +  * PincerMotor - port, do którego podłączony jest dodatkowy silnik ('​A',​ '​B'​ albo '​C'​). 
 +  * Reverse - //true// albo //false//. NIE ZAIMPLEMENTOWANE! 
 +  * TouchPort - port, do którego podłączony jest sensor dotyku ('​S1',​ '​S2',​ '​S3'​ albo '​S4'​). 
 +  * SoundPort - port, do którego podłączony jest sensor dźwięku ('​S1',​ '​S2',​ '​S3'​ albo '​S4'​). 
 +  * LightPort - port, do którego podłączony jest sensor światła ('​S1',​ '​S2',​ '​S3'​ albo '​S4'​). 
 +  * UltrasonicPort - port, do którego podłączony jest sensor odległości ('​S1',​ '​S2',​ '​S3'​ albo '​S4'​). 
 + 
 +==== Odczyt sensorów ==== 
 + 
 +Są dwa podejścia przy wyzwalaniu zdażeń odczytami sensorów. W PLNXT zastosowano tzw. triggery, które cyklicznie sprawdzają prawdziwość pewnego warunku niezbędnego do wyzwolenia akcji. Jeśli użytkownik chce aby robot zatrzymał się przed ścianą, stworzy taki trigger, aby np. po zbliżeniu się do przeszkody na 15 cm, robot stanął. Trigger ten będzie mierzył odległość aż warunek będzie prawdziwy. W przypadku, gdy użytkownik zechce, aby np. po zbliżeniu się do ściany na 60 cm, robot otworzył i zamknął szczypce, a po zbliżeniu na 30 cm odegrał melodyjkę, każda z tych akcji będzie wymagać osobnego triggera. Każdy z nich będzie oddzielnie dokonywał pomiaru odległości,​ a tym samym sensor ultradźwiękowy będzie potrójnie obciążony. W takich przypadkach należy się zastanowić,​ czy nie opłaca się uruchomić wątku, który cyklicznie odczytuje pomiary i zapisuje je, a wywołanie odczytu w programie np. predykatem //​nxt_ultrasonic//​ nie powoduje dokonywania pomiaru, a jedynie jego odczyt spośród zapisanych wartości. Ustawianie w definicji robota opcji //​Readings//​ na //cyclic// spowoduje uruchomienie takiego mechanizmu. Standardowy sposób dokonywania pomiarów tylko wtedy, gdy są wymagane, odbywa się, gdy //​Readings//​ ustawione jest na //​on_demand//​. 
 + 
 +==== Inne moduły niż //serial// ==== 
 + 
 +Jedynie w przypadku używania modułu komunikacyjnego //serial// znaczenie mają opcje Device i Conn_type. Dla innych modułów mogą być ustawione dowolnie. 
 + 
 +**Należy bezwględnie zwrócić uwagę, aby nie ustawiać opcji Sync_mode na //on//, gdy używa się innego modułu niż //​serial//​.** W przeciwnym wypadku PLNXT nie będzie działać poprawnie. 
 + 
 +==== Moduł //​simulator//​ ==== 
 + 
 +Dla ułatwienia obserwacji zdarzeń przy użyciu modułu //​simulator//​ wprowadzono czynnik czasu: 
 +<code prolog>​ 
 +nxt_simulator_time_factor(0.25). 
 +</​code>​ 
 + 
 +Jego ustawienie na wartość 1 powoduje wykonywanie akcji w czasie rzeczywistym. Wartości większe od 1 przyspieszają upływ czasu. Wartości mniejsze od 1 - spowalniają. Np. wartość 0,25 powoduje 4-krotne spowolnienie. 
 + 
 + 
 +===== Sterowanie z konsoli ===== 
 + 
 +==== Test połączenia ==== 
 + 
 +=== Otwarcie połączenia ​===
 <code prolog> <code prolog>
 $ pl $ pl
Linia 10: Linia 88:
 </​code>​ </​code>​
  
-Zwróć uwagę na sygnalizację zawarcia połączenia na wyświetlaczu jednostki centralnej.+Proszę zwrócić uwagę na sygnalizację zawarcia połączenia na wyświetlaczu jednostki centralnej.
  
-==== Wydanie polecenia ​====+=== Wydanie polecenia ===
 Sprawdzenie poziomu baterii (najprostsze polecenie, które korzysta i z zapisu i z odczytu z urządzenia):​ Sprawdzenie poziomu baterii (najprostsze polecenie, które korzysta i z zapisu i z odczytu z urządzenia):​
 <code prolog> <code prolog>
Linia 20: Linia 98:
 Powinien pojawić się poziom baterii, jeżeli nie, mamy problem! Powinien pojawić się poziom baterii, jeżeli nie, mamy problem!
  
-==== Zamknięcie ​====+=== Zamknięcie ===
 <code prolog> <code prolog>
 ?- nxt_close. ?- nxt_close.
 </​code>​ </​code>​
  
-Zwróć uwagę na sygnalizację braku połączenia na wyświetlaczu jednostki centralnej.+Proszę zwrócić uwagę na sygnalizację braku połączenia na wyświetlaczu jednostki centralnej.
  
-===== Praca w powłoce SWIPL =====+==== Praca w powłoce SWIPL ====
  
 Proszę uruchomić powłokę SWIPL i załadować plik plnxt.pl ([plnxt].), a następnie: Proszę uruchomić powłokę SWIPL i załadować plik plnxt.pl ([plnxt].), a następnie:
Linia 46: Linia 124:
   * Zamknąć połączenie:​ nxt_close.   * Zamknąć połączenie:​ nxt_close.
  
-===== Programy w pliku =====+===== Tworzenie programów krok po kroku =====
  
-Większość predykatów ma swoją wersję z opcją '​force'​ (npnxt_go(400,​force).),​ która wymusza natychmiastowe wykonanie polecenia.\\ +Poniższe przykłady prezentują wszystkie mechanizmy dostępne w PLNXTZapoznają ze stosowaniem tego interfejsu od najprostszych przykładów ​do bardziej skomplikowanych
-Brak tej opcji sprawia, że polecenie oczekuje na wykonanie ​do zatrzymania robota.\\ +Wszystkie ​przykłady znajdują się w pliku //​demos/​examples.pl//​.
-To pozwala na pisanie sekwencyjnych programów, jak przykład niżej.+
  
-Proszę skopiować poniższy kod do pliku i załadować ​SWIPL.+==== Otwieranie połączenia ==== 
 + 
 +W definicjach robotów w pliku //​plnxt.pl//​ po to nadawane są aliasy, aby można byłłatwy sposób zadać cel konkretnemu robotowi. 
 + 
 +Najprostszy program otwierający połączenie,​ odczekujący 10 sekund i zamykający je może wyglądać następująco:​
 <code prolog> <code prolog>
-:- consult('​sciezka_do_plnxt.pl'​).+start1 ​:- 
 + nxt_goal(my_robot,​nxt_open),​ 
 + sleep(10),​ 
 + nxt_goal(my_robot,​nxt_close). 
 +</​code>​
  
-start :-+Jeśli //​my_robot//​ jest zdefiniowany jako pierwszy w pliku //​plnxt.pl//,​ jest domyślnym robotem i powyższy program może wyglądać dla niego prościej:​ 
 +<code prolog>​ 
 +start2 ​:-
  nxt_open,  nxt_open,
- nxt_go_cm(400,80), % Jazda 80 cm do przodu z prędkością 400 stopni/​sekundę. + sleep(10),
- nxt_go_cm(-400,​80), % Jazda 80 cm do tyłu z prędkością 400 stopni/​sekundę.+
  nxt_close.  nxt_close.
 +</​code>​
  
-:- start.+Obie wersje różnią się nieznacznie wykonaniem poleceń. Predykat //​nxt_goal//​ tworzy nowy wątek dla jednego ze zdefiniowanych robotów realizujący zadany cel. Sama procedura otwierania połączenia trwa zauważalnie długo (2-3 sekundy). Stąd działanie drugiego programu, które odbywa się w jednym wątku, trwa trochę dłużej, gdyż odczekanie 10 sekund nie jest zrównoleglone z otwieraniem połączenia. 
 + 
 +==== Poruszanie ==== 
 + 
 +Dodajmy do powyższego programu ruch do przodu i do tyłu: 
 +<code prolog>​ 
 +start3 :- 
 + nxt_open,​ 
 + nxt_go_cm(300,​40),​ 
 + nxt_go_cm(-300,40), 
 + sleep(3),​ 
 + nxt_close.
 </​code>​ </​code>​
  
-===== Do czego w takim razie przydaje ​się '​force'?​ =====+Robot przemieszcza ​się 40 cm do przodu z prędkością obrotową kół 300 stopni na sekundę. Po zatrzymaniu wykonuje ruch do tyłu z tą samą prędkością.
  
-Proszę przetestować proste przykłady programów z wykorzystaniem mechanizmu trigger (FIXME dokumentacja).+==== Opcja force ====
  
-==== Przykład 1 ====+W powyższym przykładzie działa mechanizm sekwencjonowania poleceń. Robot czeka z wykonaniem drugiego do zatrzymania. Większość predykatów najwyższej warstwy PLNXT (//​movement//​) może przyjmować opcjonalnie dodatkowy argument //force//. Wymusza on wykonanie polecenia natychmiast,​ bez względu na to czy robot stoi, czy się porusza.
  
 +W przykładzie robot rozpocznie ruch do przodu bez ograniczenia,​ ale natychmiast polecenie się zdeaktualizuje,​ gdyż rozpocznie się wykonywanie następnego:​ wymuszony ruch do tyłu.
 <code prolog> <code prolog>
-:- consult('​sciezka_do_plnxt.pl'​).+start4 ​:- 
 + nxt_open,​ 
 + nxt_go(300), 
 + nxt_go_cm(-300,​40,​force),​ 
 + sleep(3)
 + nxt_close. 
 +</​code>​
  
-start :-+==== Odczyt sensorów ==== 
 + 
 +<code prolog>​ 
 +start5 ​:-
  nxt_open,  nxt_open,
- trigger_create(_,check_distance,[nxt_stop,nxt_close])+ segment5, 
- nxt_go(300).+ segment5, 
 + segment5, 
 + segment5
 + segment5, 
 + nxt_close.
  
-check_distance ​:- +segment5 ​:- 
- nxt_ultrasonic(Distance,​force), + nxt_light(Light),​ 
- Distance ​< 15.+ nxt_ultrasonic(Distance), 
 + nl, 
 + write('​Light:​ '), write(Light),​nl
 + write('​Distance: '), write(Distance),​nl,​ 
 + nxt_go_cm(300,​20).
 </​code>​ </​code>​
-Trigger będzie wyzwolony, gdy check_distance będzie prawdziwe. Wtedy zostanie wykonane zatrzymanie robota i zamknięcie połączenia.\\ 
-Zatem jest to prosty program: robot porusza się do przodu do napotkania przeszkody.\\ 
-Pomiar odległości odbywa się cyklicznie. Bez opcji '​force'​ odbyłby się po zatrzymaniu silników (w tym przypadku "​nigdy"​).\\ 
-Robota czekałoby bolesne spotkanie z przeszkodą. 
  
-==== Przykład 2 ====+Robot porusza się do przodu i co każde 10 cm zatrzymuje się oraz dokonuje pomiaru odległości i natężenia światła. 
 + 
 + 
 +==== Timer ==== 
 + 
 +Timer uruchamia akcję po upływie zadanego czasu. W przykładzie robot poruszą się 80 cm do przodu, 80 cm do tyłu, a następnie zamyka połączenie. W międzyczasie po upływie dwóch sekund od startu otwiera i zamyka szczypce.
  
 <code prolog> <code prolog>
-:- consult('​../​plnxt.pl'​).+start6 ​:- 
 + nxt_open,​ 
 + nxt_go_cm(300,80)
 + timer_create(_,​2,​clap6),​ 
 + nxt_go_cm(-300,​80),​ 
 + nxt_close.
  
-start:-+clap6 :- 
 + nxt_pincer(open,​force),​ 
 + sleep(1),​ 
 + nxt_pincer(close,​force). 
 +</​code>​ 
 + 
 + 
 +==== Trigger ==== 
 + 
 +Trigger sprawdza cyklicznie prawdziwość pewnego warunku, który wzwala akcję. Akcja jest wyzwalana tylko raz. Po zadziałaniu triggera jego wątek zostaje zakończony. 
 + 
 +W przykładzie robot przemieszcza się do przodu, a utworzony trigger sprawdza, czy nie zbliża się przeszkoda (warunek //​check_distance//​). Gdy robot podjedzie na odlełość mniejszą niż 20 cm, zostanie uruchomiona akcja //​obstacle//​ - robot zatrzyma się i zamknie połączenie. 
 + 
 +<code prolog>​ 
 +start7 ​:-
  nxt_open,  nxt_open,
- go_on_buddy+ nxt_go(300)
- trigger_create(_,​pushed,​[nxt_stop,nxt_close]).+ trigger_create(_,​check_distance7,obstacle7).
  
-go_on_buddy ​:- +check_distance7 ​:- 
- nxt_go(200), + nxt_ultrasonic(Value,force), 
-        sleep(1), % Chwila przerwy, żeby jedno klaśnięcie nie zostało rozpoznane jako dwa. + Value < 20.
- trigger_create(_,​clap,​wait_a_second_buddy).+
  
-wait_a_second_buddy ​:-+obstacle7 ​:-
  nxt_stop,  nxt_stop,
-        sleep(1), + nxt_close. 
- trigger_create(_,​clap,​go_on_buddy).+</​code>​
  
-% Sprawdzenie,​ czy natężenie dźwięku przekracza progową wartość. +W następnym przykładzie robot pełni rolę magazynieraDojeżdza do piłki umieszczonej przed nimłapie ją szczypcamiodwraca się i zostawia pod ścianą.
-clap :- +
- nxt_sound(Value,force), +
- Value > 15.+
  
-% Sprawdzenieczy sensor dotyku jest wciśnięty+<code prolog>​ 
-pushed ​:-+start8 :- 
 + nxt_open, 
 + nxt_pincer(open),​ 
 + nxt_go(400),​ 
 + trigger_create(_,​check_ball8,​ball8)
 + 
 +check_ball8 ​:-
  nxt_touch(Value,​force),​  nxt_touch(Value,​force),​
- Value=1.+ Value = 1
 + 
 +ball8 :- 
 + nxt_stop,​ 
 + nxt_pincer(close),​ 
 + nxt_rotate(400,​180),​ 
 + trigger_create(_,​check_distance8,​wall8),​ 
 + nxt_go(400). 
 + 
 +check_distance8 :- 
 + nxt_ultrasonic(Value,​force),​ 
 + Value < 20. 
 + 
 +wall8 :- 
 + nxt_stop,​ 
 + nxt_pincer(open),​ 
 + nxt_go_cm(-400,​20),​ 
 + nxt_pincer(close),​ 
 + sleep(1),​ 
 + nxt_stop,​ 
 + nxt_close.
 </​code>​ </​code>​
  
-Robot jedzie do przodu. Zatrzymuje ​się po klaśnięciuWznawia ruch po ponownym klaśnięciu.\\ +W kolejnym przykładzie robot porusza ​się przypadkowo ​po pomieszczeniu unikając przeszkódProgram przerywa działanie ​po zadaniu celu: //stop9/0//.
-Po wciśnięciu sensora dotyku zatrzymuje się i zamyka połączenie.\\ +
-Proszę odpowiednio dobrać próg natężenia dźwięku.\\ +
-Zbyt niska wartość może spowodować zapętlenie.\\ +
-Zbyt wysoka sprawi, że zamiast klaskać, trzeba będzie solidnie "​puknąć"​ sensor.+
  
 +<code prolog>
 +start9 :-
 + nxt_open,
 + nxt_go(300),​
 + trigger_create(_,​check_distance9,​obstacle9).
  
 +check_distance9 :-
 + nxt_ultrasonic(Value,​force),​
 + Value < 25.
 +
 +obstacle9 :-
 + nxt_stop,
 + nxt_go_cm(-300,​25),​
 + Angle is 110 + random(140),​
 + nxt_rotate(200,​Angle),​
 + nxt_go(300),​
 + trigger_create(_,​check_distance9,​obstacle9).
 +
 +stop9 :-
 + nxt_stop,
 + nxt_close.
 +</​code>​
 +
 +==== Noreturn trigger ====
 +
 +W powyższym przykładzie trigger zatrzymuje robota i wykonywane są kolejne instrukcje. W wątku, w którym utworzony został trigger, nie ma kolejnych instrukcji, więc wątek sam zostaje zakończony. Gdyby były jeszcze jakieś predykaty, które mogłyby kolidować z akcją podejmowaną przez wyzwolony trigger, efekt byłby nieporządany. W takich sytuacjach przydaje się //noreturn trigger//. Zabija on wątek, który go utworzył.
 +
 +W przykładzie robot porusza się po kwadracie w lewo. Po klaśnięciu zaczyna się wycofywać "​klaskając"​.
 +
 +**Uwaga! W zależności od hałasu w miejscu, w którym działa robot, należy odpowiednio dobrać próg natężenia dźwięku rozpoznawanego jako klaśnięcie.**
 +
 +<code prolog>
 +start10 :-
 + nxt_open,
 + trigger_create_noreturn(_,​clap10,​go_backward_clapping10),​
 + segment10.
 +
 +segment10 :-
 + nxt_rotate(300,​-90),​
 + nxt_go_cm(300,​20),​
 + segment10.
 +
 +clap10 :-
 + nxt_sound(Value,​force),​
 + Value > 55.
 +
 +go_backward_clapping10 :-
 + nxt_stop,
 + nxt_go_cm(-300,​40),​
 + nxt_pincer(open,​force),​
 + sleep(1),
 + nxt_pincer(close,​force),​
 + sleep(1),
 + nxt_pincer(open,​force),​
 + sleep(1),
 + nxt_pincer(close,​force),​
 + wait_till(nxt_is_stopped),​
 + nxt_close.
 +</​code>​
 +
 +==== Trigger wielokrotny ====
 +
 +Istnieje możliwość stworzenie triggera, który może wyzwalać akcję więcej niż raz. Należy podać jako czwarty argument liczbę razy. Można też wpisać //inf// (z ang. infinite), co skutkuje uruchomieniem triggera pracującego w nieskończoność (do czasu jego zabicia lub zamknięcia połączenia z robotem).
 +
 +W przykładzie robot porusza się 1 metr do przodu. Na klaśnięcie otwiera i zamyka szczypce. Zamknięcie połączenia następuje po wciśnięciu sensora dotyku.
 +
 +<code prolog>
 +start11 :-
 + nxt_open,
 + trigger_create(_,​nxt_touch(1,​force),​[nxt_stop,​nxt_close]),​
 + trigger_create(_,​clap11,​pincer11,​inf),​
 + nxt_go_cm(250,​100).
 +
 +clap11 :-
 + nxt_sound(Value,​force),​
 + Value > 55.
 +
 +pincer11 :-
 + nxt_pincer(open,​force),​
 + sleep(1),
 + nxt_pincer(close,​force).
 +</​code>​
 +
 +==== nxt_goal ====
 +
 +Poznany w pierwszym przykładzie predykat //​nxt_goal//​ bywa bardzo przydatny. Opcjonalnie trzecim jego argumentem może być opis wątku. W przykładzie robot porusza się po kwadracie wykonując 3 okrążenia. Dzięki zastosowaniu //​nxt_goal//​ realizuje ten ruch w osobnym wątku, a wątek główny nie jest zajęty. Można z konsoli SWI-Prolog wydawać dodatkowe polecenia, np. odczytywać wartości sensorów. Proszę wypróbować predykat //​nxt_threads//,​ który wyświetla listę wątków robota.
 +
 +<code prolog>
 +start12 :-
 + nxt_open,
 + nxt_goal(current,​segment12(12),​square_move).
 +
 +segment12(0) :- nxt_close.
 +
 +segment12(M) :-
 + N is M-1,
 + nxt_rotate(300,​-90),​
 + nxt_go_cm(300,​20),​
 + segment12(N).
 +</​code>​
 +
 +Przykładowe uruchomienie:​
 +<code prolog>
 +2 ?- start12.
 +true.
 +
 +3 ?- nxt_threads.
 +------------------------------------------------------------
 +Thread ID Robot Description
 +------------------------------------------------------------
 +main my_robot console_control
 +2 my_robot square_move
 +3 my_robot trigger(nxt_is_stopped,​ [current_thread(2,​ _G304), thread_send_message(2,​ resume)])
 +------------------------------------------------------------
 +true.
 +
 +4 ?- nxt_light(Value,​force).
 +Value = 25.
 +
 +5 ?- nxt_threads.
 +------------------------------------------------------------
 +Thread ID Robot Description
 +------------------------------------------------------------
 +main my_robot console_control
 +------------------------------------------------------------
 +true.
 +</​code>​
 +
 +Triggery na liście wątków są opisywane następująco:​ //​trigger(zdarzenie_wyzwalające,​akcja)//​. W tym przykładzie widać trigger wyzwalany w momencie zatrzymania robota. To mechanizm sekwencjonowania poleceń i będzie pojawiać się często w listach wątków.
 +
 +==== Obsługa wielu robotów ====
 +
 +Głównym przeznaczeniem predykatu //​nxt_goal//​ jest zadawanie celu wielu robotom jednocześnie.
 +
 +Do uruchomienia przykładu potrzebne są dwa roboty. Oba zdefiniowane w pliku //​plnxt.pl//​! Jeden z nich ma alias //​my_robot//,​ a drugi //joey//. //​My_robot//​ i //joey// jednocześnie rozpoczynają jazdę do przodu. W momencie napotkania ściany przez //​my_robot//​ następuje jego zatrzymanie,​ ale zatrzymuje się również //joey//.
 +
 +<code prolog>
 +start13 :-
 + nxt_goal(my_robot,​go_to_a_wall13),​
 + nxt_goal(joey,​go_joey13).
 +
 +go_to_a_wall13 :-
 + nxt_open,
 + trigger_create(_,​check_distance13,​wall13),​
 + nxt_go(300).
 +
 +go_joey13 :-
 + nxt_open,
 + nxt_go(300).
 +
 +stop_joey13 :-
 + nxt_stop,
 + nxt_close.
 +
 +check_distance13 :-
 + nxt_ultrasonic(Value,​force),​
 + Value < 20.
 +
 +wall13 :-
 + nxt_stop,
 + nxt_goal(joey,​stop_joey13),​
 + nxt_close.
 +</​code>​
pl/plnxt/pierwsze_kroki.txt · ostatnio zmienione: 2019/06/27 15:50 (edycja zewnętrzna)
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0