NXT Cases

Autorzy:

  • Bartosz Beza (bartekbeza@gmail.com)
  • Błażej Biesiada (bejo@student.agh.edu.pl)

Temat:

  • Problem wież Hanoi

1. WSTĘP

  • Wieże Hanoi – problem polegający na odbudowaniu, z zachowaniem kształtu, wieży z krążków o różnych średnicach (popularna dziecięca zabawka), przy czym podczas przekładania wolno się posługiwać buforem, reprezentowanym w tym przypadku przez dodatkowy słupek, jednak przy ogólnym założeniu, że nie można kłaść krążka o większej średnicy na mniejszy ani przekładać kilku krążków jednocześnie. Jest to przykład zadania, którego złożoność obliczeniowa wzrasta niezwykle szybko w miarę zwiększania parametru wejściowego, tj. liczby elementów wieży.
  • Przed przystąpieniem do realizacji projektu postawiliśmy sobie na celu pewne założenia - w poszukiwaniu ciekawych przypadków użycia biblioteki PlNXT postanowiliśmy odejść od popularnego robota TriBot i zaprojektować zupełnie nową konstrukcję. Kolejnym założeniem naszego projektu było użycie w nim klocków z tylko jednego zestawu LEGO Mindstorms NXT. Ostatnią i prawdopodobnie najistotniejszą kwestią było, aby logika sterująca robotem realizowała problem, który można łatwo i wydajnie rozwiązać za pomocą języka Prolog. Z połączenia tych wszystkich założeń zrodził się pomysł zbudowania robota-ramienia przenoszącego wieże Hanoi. Zadanie to okazało się w praktyce dość trudne w realizacji z powodu bardzo ograniczonej ilości klocków dostępnych w jednym zestawie Mindstorms NXT oraz stosunkowo dużej wadze silników. W dalszej części projektu opisujemy, w jaki sposób poradziliśmy sobie ze wszystkimi tymi problemami. Projektu niestety nie udało się w pełni zakończyć. Pomimo iż wszystkie elementy (robot, kod, krążki) są już gotowe to przetestowanie działania całości okazało się niemożliwe ze względu bug-i w bibliotece PlNXT, które napotkaliśmy w trakcie prób testowania robota. Pojawił się problem z obracaniem pojedynczych silników o żądaną liczbę stopni.

2. OPIS ROBOTA

Widok całego robota

  1. Chwytak – narzędzie przeznaczone do chwytania krążków Hanoi, zostało zintegrowane z sensorem dotyku. Wykrywa krążki pod chwytakiem, a następnie zaciska się w okół krążka.
  2. System podnoszenia chwytaka – ze względu na ograniczoną ilość klocków należało wymyślić jakieś niestandardowe rozwiązanie. Jest to system kół zębatych podłączonych do jednego z silników. Obracając jednym z kół zębatych jest podnoszona platforma z chwytakiem, co ważne jest ona zawsze nachylona pod takim samym kątem do podłoża.
  3. System obracania ramienia – głównym elementem, na którym znajduje się reszta robota, jest duże koło zębate. Dla jak największej precyzji zastosowaliśmy odpowiednie przełożenia kół zębatych oraz tak zwanego “ślimaka” aby ramie nie mogło się poruszać z powodu czynników zewnętrznych. Widok chwytaka
  4. Sensor dotyku – został umieszczony zaraz nad samym chwytakiem. Samo dotknięcie jest przekazywane przez oś, która również służy do sterowania chwytakiem.
  5. System chwytający – został zbudowany z czterech małych ramion, które są zakończone gumowymi elementami. Gumowe elementy są elastyczne oraz giętkie. Zastosowaliśmy je aby chwycony krążek nie wyślizgiwał się z uchwytu. Ramiona są obracane przez system zębatek – każde oddzielnie ale są tak zsynchronizowane aby zawsze wszystkie były w tym samym położeniu względem środka chwytaka. Konstrukcja bardzo dobrze się spisuje i bez problemu utrzymuje krążki.

3. DZIAŁANIE ROBOTA

Robot

Podczas testów poszczególnych modułów robota okazało się iż wszystkie poza system podnoszenia platformy z chwytakiem działają bez zarzutu. Duża waga górnej platformy powoduje niestabilność konstrukcji i co za tym idzie małą precyzje w ruchach robota w pionie. Problem ten został rozwiązany poprzez zastosowanie sensora dotyku w chwytaku (robot nie musi już precyzyjnie pozycjonować chwytaka w pionie). Innym rozwiązaniem problemu byłoby użycie części (drugiego „największego” koła zębatego) z kolejnego zestawu NXT, jednak takie rozwiązanie wykraczało poza pierwotne założenia naszego projektu zakładające użycie tylko jednego zestawu NXT.

4. IMPLEMENTACJA DZIAŁANIA W PlNXT

%
%	AGH Kraków, 2009
%
%	Podstawy Inżynierii Wiedzy - PROJEKT
%	NXT Cases: Problem wieży Hanoi
%	
%	Autorzy: Bartosz Beza, Błażej Biesiada
%
 
:- consult('plnxt.pl').
 
:- dynamic(current_rod/1). %jedna z 3 pozycji (left,center,right) w ktorej znajduje sie ramie robota
:- dynamic(current_squeeze/1). %aktualny poziom zacisku chwytaka
:- dynamic(neutral_squeeze/1). %chwytak w pozycji luznej
 
 
start :-
	assert(current_rod(center)),
	nxt_open,
	nxt_motor_get_rotations('A',Squeeze_val), %sprawdzenie aktualnej pozycji silnika chwytaka
	assert(current_squeeze(Squeeze_val)),
	assert(neutral_squeeze(Squeeze_val)),
	move_disk(4,left,right,center).
 
stop :-
	nxt_close.
 
 
%%%%%%%%% Logika rozwiazujaca problem wiez hanoi: %%%%%%%%%
 
%%move_disk(N,Left,Right,Center)
%
% Przenosi N krazkow ze stosu Left na stos Right przy pomocy stosu Center.
 
move_disk(1,Left,Right,_) :- 
	current_rod(Cur_rod),
	move_arm_from_to(Cur_rod,Left),
	pick_disk,
	current_rod(Cur_rod),
	move_arm_from_to(Cur_rod,Right),
	drop_disk.
move_disk(N,Left,Right,Center) :- 
	N>1, 
	M is N-1, 
	move_disk(M,Left,Center,Right), 
	move_disk(1,Left,Right,_), 
	move_disk(M,Center,Right,Left).
 
 
%%%%%%%%% Kontrola robota: %%%%%%%%%
 
%% pick_disk
%
% Opuszcza ramie robota dopoki sensor dotyky nie zostanie nacisniety, natepnie zaciska chwytak
% i podnosi ramie do pozycji poczatkowej.
 
pick_disk :-
	nxt_motor_get_rotations('B',Start_count),
	nxt_motor('B', 50),
	wait_till(nxt_touch_is_pressed),
	nxt_motor('B', 0),
	squeeze,
	nxt_motor_get_rotations('B',End_count),
	Back_count is Start_count - End_count,
	nxt_motor('B', -50, Back_count),
	wait_till(not(nxt_motor_is_moving('B'))).
 
 
%% squeeze
%
% Stopniowo zaciska chwytak na krazku, badajac za kazda iteracja o ile poruszyl sie silnik, tak
% dlugo az nie bedzie mozliwe dlasze zaciskanie chwytaka.
 
squeeze :-
	current_squeeze(Squeeze_val),
	retract(current_squeeze(Squeeze_val)),
	squeeze(50,50),
	nxt_motor_get_rotations('A',End_count),
	assert(current_squeeze(End_count)).
squeeze(Speed,Diff) :-
	Diff >= Speed,
	nxt_motor_get_rotations('A',Start_count),
	nxt_motor('A', Speed, Speed),
	nxt_motor_get_rotations('A',End_count),
	wait_till(not(nxt_motor_is_moving('A'))),
	Diff_new is End_count-Start_count+10, %10 jest stala aby wyeliminowac blad pomiarowy
	squeeze(Speed,Diff_new).
squeeze(Speed,Diff) :-
	Diff < Speed.
 
 
%% drop_disk
%
% Opuszcza ramie robota dopoki sensor dotyky nie zostanie nacisniety, natepnie uwalnia krazek
% z chwytaka i podnosi ramie do pozycji poczatkowej.
 
drop_disk :-
	nxt_motor_get_rotations('B',Start_count),
	nxt_motor('B', 50),
	wait_till(nxt_touch_is_pressed),
	nxt_motor('B', 0),
	release,
	nxt_motor_get_rotations('B',End_count),
	Back_count is Start_count - End_count,
	nxt_motor('B', -50, Back_count),
	wait_till(not(nxt_motor_is_moving('B'))).
 
 
%% release
%
% Uwalnia krazek z chwytaka, wracajac do pozycji neutralnej.
 
release :-
	neutral_squeeze(Squeeze_val1),
	current_squeeze(Squeeze_val2),
	Rotations is Squeeze_val1 - Squeeze_val2,
	nxt_motor('A', 50, Rotations),
	wait_till(not(nxt_motor_is_moving('A'))).
 
 
%% move_arm_from_to(Cur_rod,Rod)
%
% Porusza ramieniem robota znad stosu Cur_rod do stosu Rod.
 
move_arm_from_to(Cur_rod,Rod) :-
	write(Rod),
	move_arm_to(Rod),
	retract(current_rod(Cur_rod)),
	assert(current_rod(Rod)),
	write(Rod),
	wait_till(not(nxt_motor_is_moving('C'))),
	write(Rod).
 
 
%% move_arm_to(Rod)
%
% Predykat pomocniczy, porusza ramieniem robota z aktualnego stosu do stosu Rod.
 
move_arm_to(center) :-
	current_rod(left),
	nxt_motor('C', 200, 1000).
move_arm_to(center) :-
	current_rod(right),
	nxt_motor('C', -200, 1000).
move_arm_to(center).
move_arm_to(left) :-
	current_rod(center),
	nxt_motor('C', -200, 1000).
move_arm_to(left) :-
	current_rod(right),
	nxt_motor('C', -200, 2*1000).
move_arm_to(left).
move_arm_to(right) :-
	current_rod(left),
	nxt_motor('C', 200, 2*1000).
move_arm_to(right) :-
	current_rod(center),
	nxt_motor('C', -200, 1000).
move_arm_to(right).
 
 
%% nxt_touch_is_pressed
%
% Predykat pomocniczy, do wygodnego oczekiwania w kodzie na nacisniecie przycisku sensora dotyku.
 
nxt_touch_is_pressed :-
	nxt_actions_touch_sensor('S1',Value),
	Value = 1.
pl/miw/2009/piw09_nxtcases_2.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