Popularny post sobal44 Napisano Sierpień 17, 2010 Popularny post Udostępnij Napisano Sierpień 17, 2010 Jak zbudować robota z kamerą? Wiele osób (robotyków amatorów) marzyło na pewno, żeby kiedyś wyposażyć swojego robota w kamerę, analizującą przestrzeń wokół niego. Daje to na pewno wielkie możliwości. Niejeden z nas rezygnuje z tego typu rozwiązań, gdyż trudno jest napisać program, który badał by złożony świat analizy i przetwarzania obrazu. Chciałbym przedstawić w prosty sposób, jak można wyposażyć swojego robota w kamerę dzięki której mógłby: -śledzić różne obiekty -rozpoznawać kolory -rozpoznawać kształty -mierzyć odległość od danego obiektu(bez użycia czujnika odległości) Dzięki programowi RoboRealm jest to bardzo proste!! Program wyposażony jest w łatwe w użyciu menu, z wieloma modułami, dzięki którym można dodać filtry przetwarzania obrazu, przełożyć obraz na ruchy robota itp. Na podstawie kilku przykładów pokażę jak dzięki temu programowi wasz robot będzie mógł widzieć. Program można ściągnąć za darmo ze strony Roborealm.com, wystarczy tylko podać swój mail, na który zostanie wysłany link z programem. Po włączeniu programu klikamy na „options” wybieramy kamerkę, którą chcemy obsłużyć i możemy się bawić w przetwarzanie obrazu. Przykład I. - Wprowadzenie Rozpoznawanie obiektu o danym kolorze: Najłatwiej wybrać obiekt o jasnym intensywnym kolorze, by odróżniał się od obiektów widzianych przez kamerkę. Ja do przykładu wybrałem nakrętkę od tymbarka bo akurat maiłem pod ręką. 🙂 By usunąć pozostałe obiekty nie usuwając nakrętki, użyję do tego celu modułu RBG_Filter z menu Colors. W RGBFilter zaznaczamy kolor, który chcemy odfiltrować i ustawiamy parametry minimalnej intensywności i barwę obiektu, tak aby nasz obiekt był dobrze widziany i odróżniał się od tła. Następnie przydałoby się określić położenie nakrętki w przestrzeni 2D. Do tego celu trzeba wybrać Center_of_Gravity z Analisys, Po tej czynności mamy określone położenie obiektu, jego współrzędne określone są w pikselach.(maksymalne położenie jest określone przez rozdzielczość kamery w moim przypadku to 640x480). Aby na ekranie był widziany obraz bez filtrów w opcjach center_of_gravity należy wybrać z Overlay on naszą kamerkę Po tym procesie moglibyśmy dojść do sterowania robotem, niestety przy oddaleniu obiektu napotykamy na zakłócenia, które uniemożliwiają dokładne określenie położenia. Aby je wyeliminować trzeba zastosować filtr, który je zlikwiduje. Do tego celu wybrałem z menu filters filtr mean, który rozmywa obraz i likwiduje niepożądane obiekty. Teraz wszyscy pewnie myślą , jak sterować robotem, ponieważ informacje z kamery trafiają do komputera, a nie do robota. Jest kilka rozwiązań: -wyposażyć robota w pokładowy komputer, który analizował by obraz i przesyłał dane do mikrokontrolera sterującego napędem, ramieniem, światłami itp. -podłączyć do komputera interfejs bezprzewodowy (bluetooth, lub wirtualny bezprzewodowy port com) a na pokładzie robota zamontować kamerę bezprzewodową i odbiornik radowy. -lub robota podpiąć na kablach do komputera. Pokażę jak w łatwy sposób przesłać informację z komputera do robota przez interfejs RS232. (np. poprzez kabel com, lub korzystać z modułu radiowego mobot) W pierwszej kolejności napiszę skrypt, w którym do jakiejś zmiennej (w moim przypadku do zmiennej LEFT_MOTOR) będę wpisywał, w którą stronę robot ma się poruszyć by widział obiekt zawsze na środku. Następnie zmienna będzie wysyłana przez rs do uC. Do napisania scryptu użyłem VBScript-program z menu Extension,(jest również Cscript-program w którym można pisać w języku C, natomiast miałem z tym problemy więc użyłem VBScript) oto prosty kod : ' określenie środka ekranu srodek_x = GetVariable("IMAGE_WIDTH") / 2 srodek_y = GetVariable("IMAGE_HEIGHT") / 2 'określenie położenia x = GetVariable("COG_X") y = GetVariable("COG_Y") if x > srodek_x then 'jeśli obiekt jest po prawej stronie to: SetVariable "LEFT_MOTOR", "l" 'przypisz zmiennej leftmotor "l" -left else 'jeśli obiekt jest po lewej stronie to: SetVariable "LEFT_MOTOR", "r" 'przypisz zmiennej leftmotor liczbe "r" - right end if Program działa następująco: wcześniej określony środek ekranu jest sprawdzany ze środkiem obiektu. Gdy nasz obiekt jest po prawej stronie, do zmiennej zostaje przypisany znak „l”, jeśli obiekt jest po lewej stronie to znak „r”. By wysyłać naszą zmienną do robota skorzystałem z modułu serial z menu Control/Other, który otwiera terminal. W nim wybieramy parametry transmisji i dodajemy zmienną, która będzie wysyłana. Przykładowy kod do mikrokontrolera w języku „C” do obsługi interfejsu : /* ************************************************************************ Procesor Atmel ATmega16 ************************************************************************ */ #define F_CPU 16000000UL #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/signal.h> #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #define UART_BAUD 57600 // prędkość transmisji bit/s #define UART_CONST 16 unsigned char volatile fodznak = 0; //flaga odebranego znaku //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%55% //------------------------------------------------------------------------------ //------------------------------------- UART ------------------------------------- //------------------------------------------------------------------------------- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //odbieranie znaku z uart na przerwaniu SIGNAL(SIG_UART_RECV) { fodznak = 1; return UDR; unsigned char znak = UDR; } // inicjacja portu szeregowego void UART_init(void) { UCSR1A &= ~(1<<U2X); //kasuje bit u2x w rejestrze ucsra // Ustawianie prędkości UBRR1H = (unsigned char)(UART_CONST >>8); UBRR1L = (unsigned char)UART_CONST ; UCSR1B=0x98;//załączenie odbiornika i nadajnika rxen/txen/rxcie UCSR1C=0x86;//ustawienie ramki danych 8bitow brak parzystosci i 1 bit stopu // załącz odbiornik i nadajnik UCSRB = _BV(RXEN)|_BV(TXEN)|_BV(RXCIE); // ustalenie formatu ramki: 8bit, 2 bity stopu UCSRC = _BV(URSEL)|_BV(USBS)|_BV(UCSZ1)|_BV(UCSZ0); ustawienie 8 bitów danych i 1 bity stopu UCSRC = (1<<URSEL)|(3<<UCSZ0); set frame 8data, 2 bit stop UCSRC = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS); } // wysyła znak void wyslij_znak(unsigned char c) { while ( !( UCSR1A & (1<<UDRE1)) ) ;// albo jeżeli się nie myle to loop_until_bit_is_set(UCSRA,UDRE) UDR1 = c; } void wyslij_slowo(char dana) { unsigned char i; for(i=0; i<8; i++) { wyslij_znak(dana & 0x80 ? '1' : '0'); dana<<=1; } } //------------------------------------------------------------------------------------ int main(void) // program główny { UART_init(); sei(); while(1) // pętla nieskończona { if(fodznak==1) {fodznak=0; switch (znak) { case 'l': skrec_w_lewo(); break; case 'r': skrec_w_prawo(); break; } } } } Przykład II Mierzenie odległości: Tak jak w przykładzie pierwszym najłatwiej rozpoznawać obiekty o intensywnej barwie, które nie występują w obserwowanym środowisku. W tym przypadku jak i w poprzednim trzeba odfiltrować niechciane kolory., przy pomocy modułów: -mean -RGB_Filetr Należy wybrać także moduł Center of gravity, w którym skorzystamy ze zmiennej zawartej w tym module, określającej wielkość obiektu „COG_BOX_SIZE”. Mierzenie odległości będzie polegało na prostej zasadzie: im obiekt jest bliżej tym jest większy. Moglibyśmy po prostu tą zmienna wysłać i powierzyć liczenie odległości mikrokontrolerowi. Pisząc prosty skrypt powierzymy to zadanie komputerowi. W tym przykładzie skorzystam z modułu, który dodaje zmienną Variable/Set_Vaiable. Dodajemy zmienną „ODL” która będzie przechowywać odległość od obiektu. Również skorzystam z Display/Display_Variables, który wyświetla zmienną na ekranie. Dodajemy zmienne, które mają być wyświetlone: „CG_BOX_SIZE” , „ODL”. Po przetestowaniu działania, widzimy że odległość od rozmiaru obiektu jest funkcją nie linową, trudno jest określić jej wzór. Ja ułatwię sobie zadanie i określę rozmiar od kilku odległości [200,150,100,50]. Oddalając przedmiot na dany dystans, spisujemy zmienną „COG_BOX_SIZE” Dla butelki po napoju „Mountain Dew” wyniki są następujące 200cm – size 96 150cm – size 128 100cm – size 186 50cm - size 366 I po napisaniu prostego skryptu, możemy określić odległość. ' rozmiaru obiektu size = GetVariable("COG_BOX_SIZE") if size > 96 then SetVariable "ODL", 200 if size > 128 then SetVariable "ODL", 150 if size > 186 then SetVariable "ODL", 100 if size > 366 then SetVariable "ODL", 50 Mój przykład jest bardzo niedokładny, ukazuje tylko czy butelka jest blisko czy daleko, ale przy większej liczbie pomiarów możemy uzyskać sensowną rozdzielczość. Przykład III Rozpoznawanie sygnalizacji świetlnej: Przykład powstał ze względu na duże zainteresowanie tematem :”Zawody - jazda robotem po mieście”. Tym przykładem chciałem pokazać, że to wcale nie jest takie trudne. Dużo osób wypowiadało się na ten temat, ale nikt nie pokazał jak to zrobić. Na podstawie kilku zdjęć przesłanych przez Daniel93, stworzyłem krótki program, który rozpoznaje jaki kolor świeci się aktualnie na sygnalizacji. Do tego celu skorzystałem z wcześniej poznanych już modułów: -RBGFilter do odfiltrowania barwy czerwonej i zielonej -mean do zlikwidowania zakłóceń -Set_variable do dodania nowej zmiennej „kolor” -VBScript do napisania skryptu -Display_Variables do wyświetlenia zmiennej „kolor” -Color_Statistics z menu Analysis Dzięki temu nowemu modułowi mamy do dyspozycji mnóstwo zmiennych, opisujących aktualny obraz - zwłaszcza występowanie kolorów R/G/B(czewrony/zielony/niebieski) Na podstawie tych danych powstał skrypt r = GetVariable("MEDIAN_COLOR_R") g = GetVariable("MEDIAN_COLOR_G") if r > g then SetVariable("kolor"), "R" else SetVariable("kolor"), "G" end if Program do zmiennej „kolor” przypisuje kod ascii określający kolor przeważający na aktualnej klatce. (r-red, g-green) A oto rezultaty: Widać w tym przykładzie małe błędy wykonania makiety: -po pierwsze kamera widzi światła znajdujące się naprzeciw -po drugie dioda zielona nie jest tak samo jasna jak pozostałe 9 Cytuj Link do komentarza Share on other sites More sharing options...
Zuk Sierpień 17, 2010 Udostępnij Sierpień 17, 2010 Teraz wszyscy pewnie myślą, jak sterować robotem, ponieważ informacje z kamery trafiają do komputera, a nie do robota. Myślałem, że robot będzie autonomiczny... Ale i tak artykuł ciekawy. Brakuje mi bibliografii, a w tym linków do wykorzystywanych programów z zaznaczeniem formy ich dystrybucji (płatny, freeware, demo...) Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Sierpień 17, 2010 Udostępnij Sierpień 17, 2010 Ciekawe podejście do tematu, bawiłem się właśnie wersją trial (bo żadnej innej chyba tam nie ma?), całkiem sporo możliwości 😉 Cytuj Link do komentarza Share on other sites More sharing options...
Daniel93 Sierpień 18, 2010 Udostępnij Sierpień 18, 2010 Jasność diód postaram się poprawić, ale refleksy od nakretki i sygnalizator z drugiej drogi na razie zostawię dla utrudnienia 🙂 Wydaje mi się, że lepiej by było jeśli analizie nie było by poddane całe zdjęcie, ale wcześniej żeby był odfiltrowany fragment z sygnalizatorem algorytmami z tematu o zawodach robotów jeżdżących po makiecie miasta. Ale mimo to efekty są na prawdę nie złe 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
MaRo88PL Sierpień 18, 2010 Udostępnij Sierpień 18, 2010 U mnie niestety jest problem z podłączeniem programu z kamerką. Kamerkę mam zainstalowaną poprawnie, program też. W opcjach programu po wyborze kamerki wyskakuje Error: Could not connect to 'ZSMC USB PC Camera (ZS0211)'. Err Code: Failed to render streams! (RENDER_STREAM) Is your video camera/device plugged in? Cytuj Link do komentarza Share on other sites More sharing options...
Sabre Sierpień 18, 2010 Udostępnij Sierpień 18, 2010 MaRo88PL, nie tylko ty masz taki problem. Tu jest dokładnie to samo opisane. Cytuj Link do komentarza Share on other sites More sharing options...
nilsen86 Wrzesień 2, 2010 Udostępnij Wrzesień 2, 2010 Witam, chce podłączyć pod komputer moduł z przekaźnikami sterowany z rs232, całość ma współpracować z programem RoboRealm. Mam pytanie, w programie RoboRealm w zakładce controls jaki rodzaj sterowania mam wybrać? Program napisze w Visual Basic, tylko tutaj też mam pytanie, jakiej komendy w VB trzeba użyć do sterowania portem rs232, np. program ma działać w taki sposób: jeżeli zielony kolor pojawi się na ekranie załącza się przekaźnik. z góry dziękuje i przepraszam za niefachowe słownictwo, gdyż jestem początkujący w tych sprawach. 😕 Cytuj Link do komentarza Share on other sites More sharing options...
mactro Wrzesień 5, 2010 Udostępnij Wrzesień 5, 2010 W module z przekaźnikami musisz mieć mikrokontroler, który będzie odczytywał komendy przesyłane przez rs232. Musisz też ustalić sobie jakiś "protokół" komunikacji, np. komenda 'L' załącza jeden przekaźnik, a 'R' inny. Jak napisać to w VB nie mam pojęcia, bo nigdy nie pisałem w tym języku, ale jeżeli korzystasz z Visual Studio, to poszukaj gotowych komponentów do obsługi portu szeregowego. Cytuj Link do komentarza Share on other sites More sharing options...
kiper Październik 4, 2010 Udostępnij Październik 4, 2010 Witam. Napisałem krótki programik w c w zakładce CScript program. Narazie miał on w okienku DOS'a wyświetlac położenie obiektu śledzonego, później był by rozwijany w miare moich potrzeb, lecz niestety, programik się kompiluje i niby działa, ale faktycznie się okno dosa nawet nie wyświetla. Może ktoś pomóc co jest nie tak ? bo sam już niewiem, już tyle sposobów próbowałem. W Dev-cpp normalnie się kompiluje i wyświetla okienko dosa. Chyba że nie jestem uświadomiony, że nie można wywołać okienka żadnego ani dosa z pod tego programu. Oto program: #include "stdio.h" #include "stdlib.h" int main() { int cogX, cogY; cogX = 1;//GetVariable("COG_X"); cogY = 2;//GetVariable("COG_Y"); printf("x =", cogX, "y =", cogY); system("pause"); return 0; } Cytuj Link do komentarza Share on other sites More sharing options...
wsowa Październik 5, 2010 Udostępnij Październik 5, 2010 Żeby zbudować robota z kamerą nie trzeba w cale wyświetlać okna DOSa. Cytuj Link do komentarza Share on other sites More sharing options...
kiper Październik 5, 2010 Udostępnij Październik 5, 2010 Z tym że ja nie buduje robota, i musze wyświetlic odpowiednio przerobione dane z tego programu na monitorze, tylko że no niestety niedziała. Ktoś ma jakiś pomysł ? Cytuj Link do komentarza Share on other sites More sharing options...
Logon Październik 5, 2010 Udostępnij Październik 5, 2010 Kiper chodzi Ci o coś takiego? #include <cstdlib> #include <iostream> using namespace std; int main(int argc, char *argv[]) { int punkt_X, punkt_Y; punkt_X=1; punkt_Y=2; cout <<"Punkt X wynosi: "<< punkt_X << "\nNatomiast punkt Y wynosi: " << punkt_Y<< endl; system("PAUSE"); return EXIT_SUCCESS; } Ps: Wybacz że w C++ ale C jeszcze nie znam 😋 Edit: A tu masz w C poprawione #include "stdio.h" #include "stdlib.h" int main() { int cogX, cogY; cogX = 1;//GetVariable("COG_X"); cogY = 2;//GetVariable("COG_Y"); printf("x = %d\n", cogX); printf( "y = %d\n", cogY); system("pause"); return 0; } Brakowało Ci po prostu "%d" bez którego nic się nie wyświetli. By wyświetlić y = %d\n", cogY przeniosłem do kolejnej linijki inaczej się nie chciało pojawić 🙂 Edit2: \n przenosi do nowej linijki WYŚWIETLANY tekst, co ułatwia czytanie tekstu gdzy go wyśietlimy Cytuj Link do komentarza Share on other sites More sharing options...
sobal44 Październik 6, 2010 Autor tematu Udostępnij Październik 6, 2010 a po co ty chcesz żeby współrzędne wyświetlały sie w okienku dosowym ?? Cytuj Link do komentarza Share on other sites More sharing options...
kiper Październik 6, 2010 Udostępnij Październik 6, 2010 Logon, Dzięki, ale to dalej się nie chcę skompilować i uruchomić w roborealm. sobal44, Mam jeszcze jakieś półtora tygodnia na zrobienie strzelnicy laserowej, no i musze odpowiednio przerobione dane ze współrzędnych wyświetlić na kompie jako punkty, no ale jak niemogę nawet samych współrzędnych wyświetlić to na razie stoję. Cytuj Link do komentarza Share on other sites More sharing options...
Logon Październik 6, 2010 Udostępnij Październik 6, 2010 Zmień może kompilator? Ja używam ogólnie Dev-C++ i jak widać C też skompilował :] No dobra a dlaczego nie chce się skompilować? Masz tam listę możliwych błędów w kodzie? Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!