Kod programu

Podczas zajęć udało nam się w całości zaimplementować jeden algorytm. Jego założeniem było sprawienie, aby robot przemieszczał się po pomieszczeniu a po zauważeniu przed sobą przeszkody zmieniał kierunek jazdy. Ponadto rozbudowaliśmy robota o sensor dotyku, dzięki czemu mogliśmy dodać warunek stopu programu: po wciśnięciu przycisku robot zatrzymywał się i zamykał połączenie. Pełny kod programu:

:- consult('plnxt.pl').
 
start :-
    nxt_open,
    trigger_create(_,check_touch,[nxt_stop,nxt_close]),
    trigger_create(_,check_distance,[nxt_stop,rotate,nxt_go(300)],inf),
    nxt_go(300).
 
check_distance :-
    nxt_ultrasonic(Distance,force),
    Distance < 20.
 
check_touch :-
    nxt_touch(Value,force),
    Value =:= 1.
 
rotate :-
    Angle is 30 + random(150),
    nxt_rotate(360,Angle).

Załączniki

Zdjęcia Gienka z dodanym czujnikiem dotyku:

Pełny filmik do pobrania

Spostrzeżenia, wnioski, napotkane problemy

Podczas wykonywania ćwiczenia napotkaliśmy kilka problemów, z których większość spowodowana była brakiem doświadczenia w korzystaniu z plnxt. Na szczęście szybko udawało nam się wyłapywać i usuwać błędy tego typu.

Ważne jest, aby przy implementacji algorytmu uwzględnić warunki stopu, gdyż w przeciwnym wypadku możemy stać się świadkami sceny wziętej wprost z „Ucznia Czarnoksiężnika” Goethego, czyli w tym przypadku robota uparcie wykonującego zadane mu zadanie i nie reagującego na polecenie zatrzymania się. Gdy tak się zdarzy, wyjściem może być zrestartowanie xpce, otwarcie połączenia i dopiero wtedy wysłanie polecenia nxt_stop.

Podobnie niezbyt dobrym pomysłem okazało się rekurencyjne tworzenie nieskończonej ilości wątków i otwierania kolejnych połączeń. Tutaj pomógł już tylko sprzętowy restart robota.

nxt_close a sprawa warningów

Innym problemem, pojawiającym się chyba w każdej grupie, było występowanie ostrzeżeń:

Warning: [Thread ID] Thread running „trigger_start(Zdarzenie, Akcja, Licznik)” died on exception: source_sink 'nxt_close' does not exist.

pojawiających się w przypadku, gdy Akcja zawierała w sobie polecenie nxt_close.

Przyczyny występowania tego błędu nie są nam znane, ale po przeanalizowaniu kodu plnxt i reference manual SWI Prologu doszliśmy do wniosku, że powodem zaistnienia tej sytuacji może być błąd w plnxt (lub ewentualnie wbudowany błąd Prologu).

Wywołanie trigger_create(_,check_touch,[nxt_stop,nxt_close]) powoduje w efekcie wywołanie reguły

 trigger_cycle(ID,Event,Action,1) :-
	Event,
	fire(Action),
	retract(threads_trigger(ID)).

Kiedy jedną z akcji jest zamknięcie połączenia, odpalany jest nxt_close, który z kolei zabija wszystkie triggery (trigger_killall). W efekcie retract(threads_trigger(ID)) kończy się niepowodzeniem (nie ma już threads_triggera o zadanym ID), a więc cel wątku jest niespełniony.

Natomiast w SWI-Prolog 5.6.60 Reference Manual: Section 8.1 czytamy:

If a detached thread dies due to failure or exception of the initial goal the thread prints a message using print_message/2.
If such termination is considered normal the code must be wrapped using ignore/1 and/or catch/3 to ensure successful completion.

Update: Wygląda na to, że na chwilę obecną nie da się podlinkować sprawozdania pod osobistą stronę robota.

pl/dydaktyka/piw/2009/sprawozdania/piw20090408-14c.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