Wizualizacja Danych Sensorycznych Wizualizacja sensorów robota
Transkrypt
Wizualizacja Danych Sensorycznych Wizualizacja sensorów robota
Wizualizacja Danych Sensorycznych Wizualizacja sensorów robota klasy line follower Dawid Powązka 163054 13 czerwca 2010 1 Spis treści 1 Opis problemu. 3 2 Harmonogram prac. 3 3 Komunikacja. 3.1 Mikrokontroler. . . . . 3.2 Aplikacja. . . . . . . . 3.3 Suma kontrolna CRC. 3.4 Realizacja sprzętowa. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 5 6 7 4 Wizualizacja czujników. 7 5 Rysowanie trasy robota. 5.1 Napotkane problemy. . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Zrealizowana koncepcja. . . . . . . . . . . . . . . . . . . . . . . . 7 8 8 6 Interfejs graficzny aplikacji 8 7 Diagram klas. 9 8 Schemat przepływu. 9 9 Testy oraz uzyskane wyniki. 9 10 Wnioski. 11 2 1 Opis problemu. Głównym zadaniem projektu jest zaprojektowanie aplikacji graficznej, która w jednoznaczny i przejrzysty sposób będzie obrazowała stan czujników robota line follower. Roboty tego typu mają za zadanie poruszanie się po trasie wyznaczonej poprzez linie. Na świecie rozgrywane są zawody takich robotów, gdzie startują różnorodne konstrukcje, których sterowanie odbywa się na podstawie odpowiednich czujników. Roboty te muszą posiadać sensory koloru, które umożliwiają określenie położenia linii względem robota. Najczęściej stosowane są czarne linie, umieszczone na białym tle. W zależności o konstrukcji i konwencji roboty takie posiadają różną liczbę takich czujników. Zbudowany przeze mnie robot posiada 5 czujników zbudowanych za pomocą reflekcyjnych czujników odbiciowych CNY70. Za pomocą odpowiednich rezystorów czujniki zostały skalibrowane tak, że gdy znajdują się nad czarną linią uzyskujemy stan logicznej 1, a gdy znajdują się nad białym obszarem otrzymujemy logiczne 0. Wizualizacja sprowadza się zatem do pokazywania dwóch stanów czujników. Ponad to, wykorzystywany do testów robot jest platformą mobilną klasy 2.0, co znaczy, że posiada dwa niezależnie napędzane koła. Aplikacja powinna wyświetlać prędkości silników tego robota. Dodatkową udostępnianą funkcją będzie możliwość wyrysowywania trasy przebytej przez robota, jeśli będzie to możliwe. 2 Harmonogram prac. • 1 tydzień: Zapoznanie się ze środowiskiem Qt4. • 1 tydzień: Projekt graficznego wyglądu aplikacji. • 1 tydzień: Ostateczny wybór elementów graficznych oraz ich rozmieszczenia w aplikacji. Gotowy szablon aplikacji. • 1 tydzień: Utworzenie połączeń oraz reakcji pomiędzy poszczególnymi elementami. • Punkt kontrolny: Przedstawienie szkieletowej aplikacji, która symuluje wybrane reakcje na żądania ze strony użytkownika, jak i symuluje pracę czujników. • 1 tydzień: Rozwój modułu komunikacji aplikacji z robotem poprzez port szeregowy. • 1 tydzień: Wstępne testy komunikacji. • 1 tydzień: Weryfikacja i poprawa ewentualnych błędów w komunikacji aplikacji z robotem. Testy ostateczne. • Kamień milowy: działająca aplikacja, poprawnie komunikująca się z robotem. • 1 tydzień: Testy działania aplikacji na prawdziwym robocie. • 1 tydzień: Rozwijanie algorytmu odtwarzającego trasę, którą przejechał robot, na podstawie danych z czujników. 3 • 1 tydzień: Testy algorytmu. Ostatnie cztery punkty harmonogramu zostały przesunięte w czasie o mniej więcej 1 tydzień. Spowodowane to było opoźnieniami w pracach na robotem, który powstawał na zaliczenie innego projektu. 3 Komunikacja. Aby możliwa była wizualizacja pracy czujników należało nawiązać nić porozumienia z robotem. Postanowiono użyć komunikacji przez port szeregowy oraz standardu rs232. Jest to standard rozpowszechniony oraz wiele mikrokontrolerów ma wbudowane moduły do transmisji asynchronicznej. Poniżej przedstawione są przyjęte przeze mnie parametry transmisji, które dla obu urządzeń muszą zostać ustawione jednakowe: • Prędkość transmisji: 2400 bps. • Liczba bitów danych: 8 bitów. • Parzystość: wyłączona. • Kontrola przepływu: wyłączona. • Bity stopu: 1 bit stopu. Poniższe podrozdziały opisują rozwiązania komunikacyjne po stronie mikrokontrolera oraz aplikacji. 3.1 Mikrokontroler. Mikrokontrolerem sterującym robotem jest Atmega8. Posiada on moduł USART do synchronicznej i asynchronicznej transmisji szeregowej. Skonfigurowany on został w drugim trybie pracy. Kod poniżej przedstawia inicjalizację modułu: /* Ustawianie prędkości*/ UBRRH = (unsigned char)(UART_CONST >>8); UBRRL = (unsigned char)UART_CONST ; UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE);//załączenie odbiornika i nadajnika, włączenie prze Niekoniecznym jest ustawianie wymienionych wyżej parametrów transmisji, ponieważ są one przyjmowane jako domyślne. 16- bitowy rejestr UBBR zawiera informacje o prędkości transmisji. Należy wpisać tutaj wartość wyliczoną na podstawie częstotliwości zegara mikrokontrolera F CPU oraz żądanej prędkości F CP U transmisji według wzoru 16ulBAU D −1. Mikrokontroler wysyła dane o czujnikach oraz silnikach na zewnętrzne żądanie. W funkcji obsługi przerwania wysyłane są 4 bajty danych. • 1 bajt: sensory. • 2 bajt: silnik lewy. • 3 bajt: silnik prawy. • 4 bajt: suma kontrolna CRC. 4 Poniższy fragment kodu przedstawia obsługę wysyłania. ISR(USART_RXC_vect) { UDR; unsigned char CRC=0; // odczytanie CRC CRC= Tablica_CRC[CRC^(SENSORY&0b0011111)]; CRC= Tablica_CRC[CRC^LEWY]; CRC= Tablica_CRC[CRC^PRAWY]; // Wysyłanie UART_send_number(SENSORY&0b0011111); UART_send_number(LEWY); UART_send_number(PRAWY); UART_send_number(CRC); } Funkcje wysyłające pochodzą z modułu uart.h, który został napisany na potrzeby innego projektu. Dokumentacja do tego modułu została dołączona do tego sprawozdania. Zastosowane wyrażenie (SEN SORY &0b0011111) ma na celu eliminację dwóch najstarszych bitów, do których nie są podpięte czujniki. 3.2 Aplikacja. W aplikacji do obsługi portu szeregowego użyto modułu MenageSerialPort, który bezpośrednio korzysta z platformy QextSerialPort. Obie platformy są na licencji GPL. W bardzo prosty sposób pomagają obsługiwać port szeregowy. Zaletą tych modułów jest możliwość instalowania na systemach Windowsowych oraz Posixsowych. Przy ustawianiu i korzystaniu z tej biblioteki przydatna była pozycja [1] w bibliografii. Bardzo ważnym elementem jest odpowiednie skonfigurowanie portu. Wykorzystywana biblioteka umożliwia skonfigurowanie portu w dość łatwy sposób. Poniższy kod przedstawia inicjalizację parametrów portu. serialPort->setPort(port); //Port serialPort->setBaudRate(BAUD2400); //BaudRate serialPort->setDataBits(DATA_8); //DataBits serialPort->setParity(PAR_NONE); //Parity serialPort->setStopBits(STOP_1); //StopBits serialPort->setFlowControl(FLOW_OFF); //FlowControl Aplikacja zgłasza żądanie do mikrokntrolera o wysłanie ramki z danymi. W tym celu wysyła ona jeden bajt. Bajt ten zawiera znak ’1’, jednakże mógłby to być dowolny znak lub liczba 8 bitowa. Mikrokontroler w żaden sposób nie wykorzystuje przesyłanych danych. Służą one jedynie do wyzwolenia funkcji obsługującej przerwania od zakończenia odbioru danych. W tym punkcie nie jest wyliczana suma kontrolna CRC. Dane mogą ulec zmianie. Nie będzie to miało wpływu na działanie programu. Odbieranie danych odbywa się na zasadzie przerwania. Dzięki temu nie musimy ciągle świadomie sprawdzać portu. Odbywa się to w klasie MenageSerialPort w wątku. Sprawdzanie polega na czekaniu aż w buforze będą minimum 4 5 bajty danych. Dopiero wtedy dane są ściągane z bufora. Wysyłany jest wtedy sygnał o otrzymaniu nowych danych, który odbiera funkcja realizująca dalsze funkcje. Bezpośrednio po odbiorze sprawdzana jest suma kontrolna CRC. Jeśli CRC się zgadza z tym wysłanym przez mikrokontroler wykonywane są dalsze operacje. Jeśli CRC się różni nie podejmowana jest żadna akcja. W ogółu przypadków urządzenie zewnętrzne proszone jest o ponownie przesłanie paczki z danymi. W naszym przypadku nie jest to odpowiednie rozwiązanie. Po pierwsze dane, które są wysyłane ulegają szybkim zmianą. Druga rzecz związana jest z ograniczeniami czasowymi. Nawet ponownie wysłanie tych samych danych sprawi, że staną się one bezużyteczne. Robot jest w ciągłym ruchu, także zdąży się już przemieścić do przodu. 3.3 Suma kontrolna CRC. Do kontroli poprawności uzyskiwanych danych z mikrokontrolera zastosowano sumę kontrolną CRC. CRC jest to cykliczna suma kontrolna, która jest bardziej niezawodna od zwykłej sumy kontrolnej. CRC otrzymuje się poprzez dzielenie liczby binarnej przez wcześniej określoną wartość. W swoim przykładzie wykorzystałem CRC 8-bitowe oraz specjalnie wygenerowaną tablicę z wartościami CRC. Tworzenie CRC uzyskuje się odczytując odpowiednie liczby z tej tablicy. Indeks z którego należy odczytać daną tworzy się za pomocą operacji XOR bajtu CRC z bajtem danych. Przykład poniżej przedstawia przykładowe liczenie CRC dla 3 danych: unsigned char CRC=0; CRC = Tablica_CRC[CRC^dane1]; CRC = Tablica_CRC[CRC^dane2]; CRC = Tablica_CRC[CRC^dane2]; Tablica poniżej zestawia wyliczone wartości sumy kontrolnej CRC, która została użyta w tym projekcie. unsigned char Tablica_CRC[256]= { 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 }; 6 3.4 Realizacja sprzętowa. Komunikacja pomiędzy robotem a komputerem w pierwszym zamyśle miała się odbywać przez port szeregowy komputera. Szybko zrezygnowano z tego pomysłu, ponieważ kable są z reguły krótkie oraz dosyć ciężkie. Z pewnością uniemożliwiło to by swobodne poruszanie się lekkiego robota. Postanowiono zakupić specjalne moduły do transmisji radiowej. Pierwszy moduł zamontowany został na robocie. Posiada on bezpośrednie wyprowadzenia linii RXD i TXD, które zostały bezpośrednio podłączone do mikrokontrolera. Moduł po stronie komputera podpinany jest do portu USB, jednakże na komputerze emulowany jest wirtualny port szeregowy. W związku z tym komunikacja odbywa się w taki sam sposób jak przez port szeregowy. W testach z wykorzystaniem terminala komunikacja działa w bardzo zadowalający sposób. Jednakże poprzez wykorzystanie projektowanej aplikacji nie udało się nawiązać bezprzewodowej komunikacji. Moduł nie odpowiadał. Prawdopodobnie wystąpił jakiś błąd natury sprzętowej. Biorąc uwagę na względy czasowe wykonania projektu, wykorzystano jeszcze jeden sposób. Wyprowadzenia RXD i TXD modułu konwertującego standard USB na RS232, opratym na chipie FTDI, przedłużono za pomocą przewodów. Rozwiązanie to zaoszczędziło dużo czasu i pozwoliło na dalszą realizację zadania. 4 Wizualizacja czujników. Głównym zadaniem aplikacji jest wizualizacja czujników koloru robota line follower. Aby tego dokonać pobierane są dane z robota w sposób opisany w poprzednim rozdziale. Funkcja wysyłająca wywoływana jest co pewien określony przez użytkownika czas. Realizowane jest z wykorzystaniem klasy QTimer. Co określony interwał czasu uruchamiana jest funkcja Refresh. Wtedy wysyłane jest żądanie o dane do mikrokontrolera. Dane odbierane w funkcji new dataReceived są odpowiednio przetwarzane. Jeśli dane są poprawne, czyli suma kontrolna CRC się zgadza obliczane są odpowiednie stany czujników koloru z liczby zawartej w 1 przesłanym bajcie. Liczba ta określa stan portu do którego podłączone są czujniki. Stan czujnika znajduje się na odpowiednim bicie. Odczytywany jest za pomocą koniunkcji otrzymanej liczby z liczbą, która określa pozycję danego sensora. Jest to 1 przesunięta o odpowiednią liczbę bitów w lewo. Przykładowo dla czujnika trzeciego, czyli środkowego, wyrażenie będzie miało postać: value & 4. Wyrażenie takie przyjmuje tylko wartości 1 lub 0. Drugi i trzeci przesłany bajt oznacza wypełnienie PWMa sterującego silnikami. Są to liczby 8- bitowe. Zamieniane są one na procentowe wypełnienie. Dane uzyskiwane z trzech pierwszych bajtów zapisywane są do klasy Dane. Taka paczka zostaje dodana do listy i poddana przetwarzaniu w celu uzyskania drogi. Dokładnie jest to omówione w rozdziale 5. 5 Rysowanie trasy robota. Dodatkową funkcją udostępnianą użytkownika jest możliwość wyrysowania drogi, którą przebył robot na podstawie danych uzyskiwanych z czujników i silników. Nie jest to zadanie łatwe i jednoznaczne. W dużym stopniu zależy od algorytmu sterowania robota. Poniższe podrozdziały opisują problemy napotkane przy realizacji tego zadania i opis zrealizowanego rysowania. 7 5.1 Napotkane problemy. Początkowym założeniem było zrealizowanie rysowania całej drogi przebytej przez robota w formie małej mapy. Niestety takiego podejścia nie udało się uzyskać z powodów powstałych niepewności i niedokładności. Pierwszym elementem jest sterowanie robota, które realizuje bardzo prymitywny algorytm. Skutkuje to częstym skanowaniem linii oraz częstym skręcaniem. Uzyskujemy bardzo zróżnicowane odczyty z których w jednoznaczny sposób nie można wywnioskować aktualnego ruchu robota. Istotny problem był przy rysowaniu skręcania. Nie posiadamy informacji o ile tak naprawdę zrotował robot. W takim wypadku rysowana droga nie odzwierciedlała w żaden sposób tej rzeczywistej. Powstawały zapętlenia i przekłamania. Pewnym rozwiązaniem tej sytuacji byłoby zastosowanie enkoderów oraz mierzenie drogi przebytej przez każde z kół. Na podstawie tych danych moglibyśmy wywnioskować o jak duży kąt zrotował robot. Rozwiązanie to miało bardzo wiele niedociągnięć wynikających z wielkiego zróżnicowania pomiarów także zrezygnowano z tego pomysłu. 5.2 Zrealizowana koncepcja. Druga bardziej uproszczona koncepcja pozwala na wyrysowywanie pojedynczych ”kawałków”drogi robota. Wyrysowywany jest odcinek prosty, prawy lub lewy łuk świadczący o skręcaniu. W związku z bardzo chaotycznymi odczytami, postanowiłem, że próbki danych od sensorów będą zapisywane i następnie na podstawie większej ilości danych, będzie następowało odtworzenie ruchu robota. Ilość tych próbek może ustalać bezpośrednio sam użytkownik. Algorytm działania jest przedstawiony poniżej: • Obliczana jest pozycja linii na podstawie jednej paczki danych. • Obliczana jest różnica pomiędzy prędkościami silników. • Na podstawie danych oceniany jest ruch robota. • Najbardziej powtarzający się ruch jest zapisywany na listę dopasowań. • Uruchamiane jest rysowanie. Rysowanie zostało zaimplementowane na bazie klasy OknoZRysunkiem, znajdującej się w materiałach do wykładu [2]. Klasa ta została odpowiednio zmodyfikowana. Całość rysowania odbywa się w funkcji paintEvent. Z listy dopasowań ściągany jest pierwszy element oraz wyrysowywany jest odpowiedni kształt. Prosta i łuki są generowane z wcześniej ustalonych punktów. 6 Interfejs graficzny aplikacji Rysunek 1 przedstawia interfejs graficzny aplikacji. Interfejs graficzny został podzielony na pomniejsze sekcje za pomocą grupowania kontrolek. Menu Połączenie służy do wybrania portu na którym ma się odbywać komunikacja oraz przyciski połączenia i rozłączenia. Poniżej okno Komunikat służy do wyświetlania użytkownikowi informacji o stanie i błędach połączenia. Dodatkowo status połączenia jest sygnalizowany na belce statusowej. Grupa Sensory zawiera pięć elementów typu QProgressBar, które służą do 8 Rysunek 1: Interfejs graficzny aplikacji. wizualizacji stanu czujników koloru. Elementy te mogą przyjmować wartości 0 lub 1. Następna grupa przedstawia prędkość silników. Uzyskiwane wartości z mikrokontrolera są z zakresu 0- 255 i są one przeliczane na wartości procentowe, które są wyświetlane. Grupa Wizualizacja zbiera ustawienia odnośnie wizualizowania stanu czujników. Pole Ćzas Interwałuókreśla czas w milisekundach co jaki będzie odświeżany stan czujników. Liczba ustawiona w polu Ilość próbek stanowi ilość uzyskanych odczytów z których będzie przeprowadzone określenie ruchu robota. Dzięki przyciskom Start i Stop użytkownik decyduje o rysowaniu trasy w okienku obok. 7 Diagram klas. Diagram klas został przedstawiony na rysunku 2. Dla zachowania przejrzystości diagramu nie dodawano atrybutów klasy Ui MainWindow. Klasa ta zawiera bardzo dużo elementów i jest generowana automatycznie przez Designera. Natomiast informacje dotyczące klasy QextSerialPort zawarta jest w dokumentacji [1]. 8 Schemat przepływu. Schemat przepływu został przedstawiony na rysunku 3. 9 Testy oraz uzyskane wyniki. Testy przeprowadzone zostały na zbudowanym i opisanym w punkcie 1 robocie. Na podłodze została wyklejona czarną taśmą izolacyjną o szerokości 19mm. Taśma taka stosowana jest zwykle na zawodach line followerów. Na jasnej podłodze czujniki zachowywały się tak jak na białej powierzchni także można było wykleić dużo dłuższy tor. Droga posiada duży odcinek prostej, łagodny łuk oraz kilka 9 Rysunek 2: Diagram klas Rysunek 3: Schemat blokowy 10 ostrzejszych i bliżej siebie położonych. Robot poprawnie przejeżdża tą trasę. Aplikacja działa poprawnie pokazując stany czujników i prędkości. Łatwo można zauważyć, jak szybko i często zmieniają się wartości sensorów. Ważnym parametrem jest ustalenie interwału timera. Za duży czas skutkowałem powolnym odświeżaniem wartości. Bardzo mały czas rzędu 30 ms skutkowałem ciągłym drganiem elementów wizualizacyjnych, przez co odczytanie czegokolwiek staje się trudne. Z punktu dobrego odwzorowania przebywanej drogi konieczne jest uzyskiwanie dużej ilości pomiarów w krótkim czasie. Im większa liczba próbek tym lepsze następowało odwzorowanie. W związku z tym czas interwału powinniśmy ustawić na jak najmniejszy. Rozwiązaniem tego problemu było ustawienie wyświetlania co 10 pomiaru. W ogólnym przypadku decyzję o czasie odświeżania i ilości próbek zostawiono użytkownikowi. 10 Wnioski. Zaimplementowana aplikacja realizuje postawione przed nią założenia. W poprawny sposób pozyskuje dane z mikrokontrolera oraz przetwarza je w należyty sposób kontrolując przy tym różne błędy. Zaprojektowany interfejs graficzny w przejrzysty sposób obrazuje stan czujników koloru oraz prędkości robota. Rysowanie trasy nie zostało zaimplementowane według początkowego pomysłu. Wynikłe podczas realizacji zadania problemy uniemożliwiły powstanie mini mapy trasy poruszającego się robota. Rysowana droga nie pokrywała się z tą rzeczywistą, dlatego zrezygnowano z wyświetlania niepoprawnych rzeczy. Starano się zaprojektować prosty i przejrzysty interfejs użytkownika. Wszystkie kontrolki zostały umieszczone w centralnym oknie. Umożliwiają one głównie obsługę i monitorowanie stanu połączenia oraz wpływ na parametry wizualizacji. W związku z moim zainteresowaniem robotami i zawodami line followerów, w przyszłości planuję rozwijanie mojej aplikacji. Chciałbym aby powstał system kontroli i testowania poprawności algorytmów sterujących. Możliwe mogłoby być również zmiana parametrów ustawień algorytmów, jak i również zatrzymywanie lub zmiana prędkości robota. Usprawniło by to na pewno pracę nad sterowaniem tych robotów. Literatura [1] Dokumentacja platformy QextSerialPort. [2] B. Kreczmer. Materiały do wykładu. 11