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:miw:2009:nxt_api_demo [2009/08/05 13:51]
jsi08
pl:miw:2009:nxt_api_demo [2019/06/27 15:50] (aktualna)
Linia 46: Linia 46:
  
 **Uwaga!** **Uwaga!**
-Początkowa próba wykorzystania wbudowanego w biblotece predykatu //​nxt_motor(Motor,​Speed,​angle(Angle))//​ nie przyniosła oczekiwanego rezultatu. Obroty silników o ustalony kąt były zdecydowanie nieprecyzyjne i pozostawiały bardzo dużo do życzenia jeżeli chodzi o jakikolwiek determinizm. Ratunkiem w ów sytuacji okazał się predykat nxt_motor_get_rotations(Motor,​Rot_count). ​+Początkowa próba wykorzystania wbudowanego w biblotece predykatu //​nxt_motor(Motor,​Speed,​angle(Angle))//​ nie przyniosła oczekiwanego rezultatu. Obroty silników o ustalony kąt były zdecydowanie nieprecyzyjne i pozostawiały bardzo dużo do życzenia jeżeli chodzi o jakikolwiek determinizm. Ratunkiem w ów sytuacji okazał się predykat ​//nxt_motor_get_rotations(Motor,​Rot_count)//
 Umożliwił on zaimplementowanie prostego regulatora P. Jak wiadomo, zdecydowanie najlepiej budować serwomechanizmy w oparciu o regulator typu PD. Jednakże w tej sytuacji lekko zmodyfikowane P okazało się wystarczające. Pobierając dane o pozycji silnika, wypracowywane jest odpowiednie sterowanie. Umożliwił on zaimplementowanie prostego regulatora P. Jak wiadomo, zdecydowanie najlepiej budować serwomechanizmy w oparciu o regulator typu PD. Jednakże w tej sytuacji lekko zmodyfikowane P okazało się wystarczające. Pobierając dane o pozycji silnika, wypracowywane jest odpowiednie sterowanie.
  
Linia 205: Linia 205:
 </​code>​ </​code>​
  
-=== Uzupełnienie ===+=== Uzupełnienie ​i uwagi===
  
-  * Wykorzystywany kod regulatora ​P:+  * Wykorzystywany kod regulatora ​dwupołożeniowego:
  
 <code prolog> <code prolog>
Linia 222: Linia 222:
  
 ==== Czujniki ==== ==== Czujniki ====
 +
 +Konstrukcja robota wykorzystuje 3 czujniki: świetlny, ultrasoniczny i dotykowy. W oprogramowaniu wykorzystywane są jedynie 2 z nich. Przeznaczeniem obu jest odczytywanie rozmieszczenia kolorowych kwadratów na kostce. Wykorzystywane są do tego predykaty odpowiadające za obroty. Oto kody odpowiadające za poszczególne czynności:
 +
 +  * Pozycjonowanie - jest to podstawowy obrót ramienia mający na celu dokładną kalibrację. Wykonywany jest tylko raz.
 +<code prolog>
 +pozycjonuj :- 
 +  repeat,
 +  nxt_motor('​B',​-150),​
 +  nxt_touch(V,​force),​
 +  V==1,  ​
 +  nxt_motor('​B',​0),​
 +  nxt_motor_reset_position('​B',​absolute),​
 +  sleep(0.1).
 +</​code>​
 +
 +  * Obrót ramienia - jest to predykat odpowiadający za ruch ramienia z czujnikiem światła. Podobnie jak w przypadku pozostałych silników również tutaj potrzebna jest regulacja. Predykat ten przyjmuje niewiadomą '​Z',​ która jest wartością zadaną oraz 2 (lub tylko 1) niewiadome '​T',​ które są dolną i górną granicą tolerancji położenia.
 +
 +<code prolog>
 +obrot_ramienia(Z,​T) :- obrot_ramienia(Z,​T,​T). ​
 +obrot_ramienia(Z,​T1,​T2) :-
 +  retract(wolny),​
 +  repeat,
 +  nxt_motor_get_rotations('​B',​R), ​
 +  P is (Z-R)*2,
 +  dwupolozeniowy(P,​P2,​5),​
 +  nxt_motor('​B',​P2),​
 +  R =< Z+T1, % tolerancja roznicy polozenia
 +  R >= Z-T2,
 +  nxt_motor('​B',​0),​
 +  assert(wolny),​
 +  sleep(0.2).
 +</​code> ​
 +
 +  * Odczyt ściany - poniższe predykaty odpowiadają za odczytanie jednej ściany oraz zamianę odczytanych wartości na kolory. Granice kolorów są niestety bardzo zmienne w zależności od oświetlenia.
 +
 +<code prolog>
 +czytaj_sciane(sciana(V1b,​V2b,​V3b,​V4b,​V5b,​V6b,​V7b,​V8b,​V9b)) :- 
 +  wait_till(nxt_is_stopped),​
 +  obrot_ramienia(155,​0),​
 +  nxt_light(V1a),​ kolor(V1a,​V1b),​
 +  obrot_ramienia(187,​0), ​
 +  nxt_light(V2a),​ kolor(V2a,​V2b), ​
 +  rl, wait_till(nxt_is_stopped),​
 +  nxt_light(V3a),​ kolor(V3a,​V3b), ​
 +  rl, wait_till(nxt_is_stopped),​
 +  nxt_light(V4a),​ kolor(V4a,​V4b), ​
 +  rl, wait_till(nxt_is_stopped),​
 +  nxt_light(V5a),​ kolor(V5a,​V5b), ​
 +  rl,
 +  obrot_ramienia(177,​0),​ wait_till(nxt_is_stopped),​
 +  dopelnienie_do_45,​wait_till(nxt_is_stopped),​
 +  nxt_light(V6a),​ kolor(V6a,​V6b), ​
 +  al,​wait_till(nxt_is_stopped),​
 +  nxt_light(V7a),​ kolor(V7a,​V7b), ​
 +  al,​wait_till(nxt_is_stopped),​
 +  nxt_light(V8a),​ kolor(V8a,​V8b), ​
 +  al,​wait_till(nxt_is_stopped),​
 +  nxt_light(V9a),​ kolor(V9a,​V9b), ​
 +  dopelnienie_do_90,​rl,​rl,​
 +  obrot_ramienia(54,​4).
 +
 +kolor(X,Y) :- X =< 20, Y=w. % biały
 +kolor(X,Y) :- X >= 21, X =< 30, Y=y. % żółty
 +kolor(X,Y) :- X >= 31, X =< 37, Y=g. % zielony
 +kolor(X,Y) :- X >= 38, X =< 44, Y=r. % czerwony
 +kolor(X,Y) :- X >= 45, X =< 49, Y=o. % pomarańczowy
 +kolor(X,Y) :- X >= 50, Y=b. % niebieski
 +</​code>​
 +
 +  * Ostani predykat łączy wszystkie pozostałe i odpowiada za całościowe zbadanie kostki.
 +
 +<code prolog>
 +badaj(cube(V1,​ V2, V3, V4, V5, V6,
 +  V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, 
 +  V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, 
 +  V29, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V40, 
 +  V41, V42, V43, V44, V45, V46, V47, V48, V49, 
 +  V50, V51, V52, V53, V54)) :- 
 +  pozycjonuj,
 +  obrot_ramienia(54,​4),​
 +  nxt_light_LED(activate),​
 +  % czytanie ścian normalne
 +  odczyt(V1, ​ V2,  V3,  V4,  V6,  V7,  V8,  V9,  V10, 
 +    V11, V12, V13, V15, V16, V18, V19, V20, V21, 
 +    V22, V23, V24, V25, V27, V28, V30, V31, V32, 
 +    V33, V34, V36, V38, V39, V40, V41, V42, V43, 
 +    V44, V45, V46, V47, V48, V49, V51, V52, V53),
 +  % ściana czytana do góry nogami
 +  czytaj_sciane(sciana(V5,​V29,​V17,​V14,​V26,​V37,​V54,​V35,​V50)),​
 +  rl,​f,​rl. ​
 + 
 +odczyt(V1, ​ V2,  V3,  V4,  V6,  V7,  V8,  V9,  V10, 
 +  V11, V12, V13, V15, V16, V18, V19, V20, V21, 
 +  V22, V23, V24, V25, V27, V28, V30, V31, V32, 
 +  V33, V34, V36, V38, V39, V40, V41, V42, V43, 
 +  V44, V45, V46, V47, V48, V49, V51, V52, V53) :-
 +  czytaj_sciane(sciana(V3,​V9,​V21,​V27,​V15,​V40,​V32,​V44,​V36)),​
 +  f,
 +  czytaj_sciane(sciana(V1,​V10,​V7,​V13,​V16,​V41,​V47,​V39,​V49)),​
 +  f,
 +  czytaj_sciane(sciana(V6,​V24,​V12,​V18,​V30,​V46,​V34,​V42,​V38)),​
 +  f,
 +  czytaj_sciane(sciana(V4,​V19,​V22,​V28,​V25,​V43,​V51,​V45,​V53)),​
 +  rr,f,
 +  czytaj_sciane(sciana(V2,​V11,​V23,​V20,​V8,​V48,​V33,​V52,​V31)),​
 +  f,f.
 +</​code>​
 +
 +=== Uzupełnienie i uwagi ===
 +
 +  * Niestety odczytanie kolorów z użyciem tego predykatu jest bardzo trudne. Wynika to z problemów z wciąż ograniczoną precyzją ruchów ramienia i przede wszystkim słabym odczytem kolorów, które nie różnią się znacząco pod względem luminancji (a to ona jest badana). Potencjalnie są 2 możliwości rozwiązania tego problemu. Pierwszym jest zastosowanie czujnika HiTechnic. Drugim jest zmiana kolorów na kostce rubika i poszukanie odpowiednich,​ rozróżnialnych barw.
 +
 +  * Podczas pisania predykatów natknąłem się na osobliwy problem związany z czymś innym niż mój program. Otóż początkowo predykat '​badaj'​ zawierał w sobie całość ciała predykatu '​odczyt'​. Co zresztą wydaje się czytelniejsze. Niestety podczas próby odczytu 50 koloru, program bez przyczyny się zawieszał. Rozbicie tego samego na 2 predylaty rozwiązało sprawę.
  
 ===== Algorytm ===== ===== Algorytm =====
-===== Realizacja ===== + 
-====== Sprawozdanie ====== +Posiadając już konstrukcję oraz komplet czynności, które powinien wykonywać robot, nie pozostało nic innego jak zajęcie się algorytmem. Jak wiadomo, ułożenie kostki Rubika, nie jest problemem trywialnym. W związku z tym, należy się również liczyć ze sporą złożonością tego typu programu. Wykorzystałem zatem istniejący program **Cube Solver II**, który rozwiązuje problem kostki Rubika ({{:​pl:​miw:​2009:​miw09_nxt_api_demo:​cube_solver_ii.tar.gz|Cube Solver II}}). 
-====== Prezentacja ====== + 
-====== Materiały ======+Zarys wykorzystywanych metod oraz samego algorytmu poszukiwań można znaleźć na tej stronie: [[http://​www.amzi.com/​articles/​rubik.htm|"​Solving Rubik'​s Cube. Prolog in action"​]]. 
 + 
 +Z wiadomych powodów, by skorzystać z potencjału tego programu musiałem go znacząco przerobić. Dodałem możliwość analizy kostki, podanie jej kolorów ręcznie oraz uruchomienie wykonywania algorytmu. 
 + 
 +{{:​pl:​miw:​2009:​miw09_nxt_api_demo:​nxt_rubik.pl|NXT_CUBE_SOLVER}} 
 + 
 +Niestety i tutaj pojawiły się spore problemy. Sam program jest bardziej ideowy, niż praktyczny. Stąd trafiają się nierozwiązywalne przez niego konfiguracje kostki. Ponadto znajdywane przez niego rozwiązania zazwyczaj wymagają około 500 ruchów (sic!), a co przy ograniczonej prędkości i precyzji, okazuje się bardzo problematyczne. Według tego co pisze wikipedia na temat optymalności rozwiązania ([[http://​en.wikipedia.org/​wiki/​Optimal_solutions_for_Rubik%27s_Cube|Optimal solutions for Rubik'​s Cube]]), możliwe jest zaimplementowanie algorytmu, który będzie wymagać nie więcej niż 22 standardowych ruchów (czyli szacunkowo jakichś 60 czynności dla twistera). 
 + 
 +===== Obsługa i uruchomienie ​===== 
 + 
 +Po poskładaniu robota, podstawową czynnością jest przygotowanie komunikacji. Należy włączyć brick, Bluetooth w bricku i na komputerze, a w dalszej kolejności przejść [[https://​ai.ia.agh.edu.pl/​wiki/​plnxt:​conf_serial|opis konfiguracji]]. Kolejnym krokiem jest przygotowanie i umieszczenie w tym samym katalogu co plik nxt_rubik.pl,​ plików z biblioteki PlNXT. Następnie należy włączyć interpreter prologa i skonsultować plik nxt_rubik.pl.  
 + 
 +Sam program uruchamia się predykatem '​go.'​. Zostaną wyświetlone 4 opcje: auto, ręcznie, ułóż oraz wyjdź. Ostatnia nie wymaga chyba wyjaśnień. 
 +  - **Auto** - powoduje próbę automatycznego odczytania pól kostki. 
 +  - **Recznie** - powoduje oczekiwanie na ręczne podanie rozkładu pól kostki. Podaje się kolejno rzędami od góry (według zaprezentowanego w programie przykładu). Poszczególne pola mogą mieć dowolną nazwę (ale konsekwentną) i oddziela się je dowolnymi białymi znakami (enter, spacja). 
 +  - **Uloz** - jak sama nazwa wskazuje. Wykonywany jest algorytm, a następnie wykonywane są ruchy na kostce. Aktualizowany jest procent wykonanych ruchów.  
 + 
 +Ponadto można wykonywać pojedyńcze ruchy wpisując f,rr,rl,mr lub ml.  
 + 
 +**Uwaga!** Należy pamiętać by platforma robota, na której kostka się znajduje, była ustawiona w możliwie najbardziej równoległej do chwytaka pozycji pozycji.  
 + 
 +===== Podsumowanie ​===== 
 + 
 +  * **Problemy** - Niestety większość problemów, które wyniknęły podczas realizacji tego projektu, jest spowodowanych niedoskonałością biblioteki. Oryginalny program do obsługi Titled Twistera są zdecydowanie szybsze i precyzyjniejsze,​ czego nie da się do końca tłumaczyć wadą kodu w prologu. Dodatkowo mechanizmy, które w założeniu powinny ułatwiać pracę z biblioteką,​ okazały się mało (a w zasadzie w ogóle!) nieprecyzyjne. Wymieniam tutaj najbardziej rażące problemy z biblioteką:​ 
 + 
 +  - Predykat //​nxt_motor(Motor,​Speed,​angle(Angle))//​ - nie sprawdza przy jakimkolwiek obciążeniu. Zachowana jest jedynie prędkość. Natomiast kąt obrotu ZNACZĄCO odbiega od tego zadanego. 
 +  - Predykat //​nxt_motor(Motor,​Speed,​time(Time))//​ - sens tego predykatu sam w sobie jest dziwny. Kąt obrotu całkowicie zależy od obciążenia. 
 +  - Predykat //​nxt_ultrasonic(Value)//​ - w ogóle nie działa. Z niewiadomego powodu wyświetlany jest błąd bez wskazówek co może być przyczyną. 
 +  - System triggerów - generalnie funkcjonuje,​ ale kompletnie nie nadaje się do niczego co wymaga chociażby odrobiny prędkości,​ a co za tym idzie - precyzji. Początkowa próba sprzężenia pomiaru pozycji z prędkością silnika, nie dała sensownych rezultatów. Niską prędkość w stosunku do zwykłego "​sekwencyjnego"​ rozwiązania widać bardzo na podstawie chociażby samego wyświetlania. 
 +  - Ogólna prędkość działania - PlNXT wydaje się strasznie utykać pod względem szybkości komunikacji z silnikami. Wystarczy chociażby spojrzeć na oryginalny program Titled Twistera i to jak szybko jest wykonywany.  
 + 
 +  * **To do**: 
 +  - zastosowanie czujnika kolorów HiTech 
 +  - napisanie DOBREGO algorytmu 
 + 
 + 
 +====== Materiały ​i linki====== 
 + 
 +Pomocne strony: 
 + 
 +  * [[http://​www.tiltedtwister.com/​index.html|Titled Twister]] 
 +  * [[http://​www.amzi.com/​articles/​rubik.htm|"​Solving Rubik'​s Cube.Prolog In Action"​]] 
 +  * [[http://​kostka-rubika.web.iq.pl/​wstep_wprowadzenie.html|Kostka Rubika - rozwiązywanie]] 
 +  * [[http://​en.wikipedia.org/​wiki/​Optimal_solutions_for_Rubik%27s_Cube|Optimal solutions for Rubik'​s Cube]] 
 + 
 +Materiały:​ 
 +  * {{:​pl:​miw:​2009:​miw09_nxt_api_demo:​nxt_rubik.pl| NXT CUBE SOLVER}} 
 +  * {{:​pl:​miw:​2009:​miw09_nxt_api_demo:​cube_solver_ii.tar.gz|Cube Solver II}}
pl/miw/2009/nxt_api_demo.1249473069.txt.gz · ostatnio zmienione: 2019/06/27 15:58 (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