Роевое поведение роботов - ФОРУМ ДВ Робот dvrobot.ru
Пятница, 16.11.2018, 04:44
Главная Мой профиль Регистрация Выход
  • НАШ МАГАЗИН
  • Вы вошли как Гость | Группа "Гости"Приветствую Вас, Гость
    [ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
    • Страница 1 из 1
    • 1
    Модератор форума: GRACH, Serg  
    ФОРУМ ДВ Робот dvrobot.ru » DV ROBOT » Библиотека Проектов » Роевое поведение роботов (Проект по исследованию коллективного поведения роботов)
    Роевое поведение роботов
    loriДата: Среда, 29.10.2014, 14:54 | Сообщение # 1
    12 Вольт
    Группа: Пользователи
    Сообщений: 108
    Репутация: 20
    Статус: Offline
    Хочу представить новый проект по исследованию "роевого поведения" роботов.
    Идея проекта зародилась около месяца назад, и состоит в создании небольшого количества (3-10 шт.) роботизированных платформ, использования компьютерного зрения и алгоритмов коллективного поведения роботов.
    Стоят следующие задачи:
    1. собрать из готовых комплектующих несколько не больших робо-платформ на колесах или гусиницах;
    2. для того чтобы роботы отличались друг от друга снабдить каждого своей цветной меткой;
    3. изготовить равномерно залитое одним цветом поле по которому будут кататься роботы;
    4. над полем установить камеру;
    5. с помощью openCV детектировать роботов на поле и по WiFi передавать на них команды управления.
    Это общая идея, а дальше... все зависит от фантазии. Необходимо будет написать несколько сценариев поведения. К примеру: роботов можно будет поделить на две команды и обучить игре в футбол, или теннис, можно играть в сумо, догонялки с роботом, лабиринт, движение по линии, танцы роботов, бои роботов и т.д. и т.п., в общем все что угодно, на сколько фантазии хватит.
    Самое главное что сами платформы будут очень просты и не дороги - управляющий контроллер (600 руб.), драйвер двух моторов (450 руб.), WiFi модуль (3700 руб.), понижающий модуль (130 руб.) аккумуляторы (2 х 450 руб.), два двигателя с колесами и сама платформа (990 руб.), итого 6770 рублей. Остальное есть в наличии: ПК, видео камера. Изготовить поле и метки не составит труда. OpenCV - бесплатная библиотека компьютерного зрения. Все прочее - "прямые ручки", "ясные мозги", "непреодолимое желание" - все это тоже имеется.
    Приобрели две колесные платформы и электронику к ним. Вот как выглядит:


    А это уже в собранном виде:


    Еще одна гусеничная, и комплектующие для самодельной балансирующей платформы заказаны и где то в пути к нам.
    Осталось только написать скетч для Arduino, наладить связь с ПК, написать управляющую программу и создать сценарии поведения роботов.
    Предложения и здоровая критика приветствуются.
    Прикрепления: 3031625.jpg(198.0 Kb) · 0268950.jpg(159.7 Kb)
     
    Trooper_OKДата: Среда, 29.10.2014, 18:59 | Сообщение # 2
    5 Вольт
    Группа: Пользователи
    Сообщений: 52
    Репутация: 20
    Статус: Offline
    как я понимаю самое дорогое - это WiFi шилд... А вы платки на основе Esp8266 не рассматривали ?  WiFi -UART напрямую, копеечная цена и микроразмеры
     
    konstantinДата: Среда, 29.10.2014, 21:34 | Сообщение # 3
    1.5 Вольт
    Группа: Пользователи
    Сообщений: 6
    Репутация: 0
    Статус: Offline
    Сейчас вот тоже подхожу в плотную к колесному роботу заказ уже набран в корзине)) Тема в принципе тоже интересна.
     
    loriДата: Четверг, 30.10.2014, 06:20 | Сообщение # 4
    12 Вольт
    Группа: Пользователи
    Сообщений: 108
    Репутация: 20
    Статус: Offline
    Цитата Trooper_OK ()
    А вы платки на основе Esp8266 не рассматривали ?  WiFi -UART напрямую, копеечная цена и микроразмеры
    Можно ссылочку!?
     
    muveyДата: Четверг, 30.10.2014, 18:47 | Сообщение # 5
    220 Вольт
    Группа: Пользователи
    Сообщений: 303
    Репутация: 1
    Статус: Offline
    lori, http://ru.aliexpress.com/item/ESP8266-serial-WIFI-wireless-transceiver-module/2032176105.html

    Ex nihilo nihil fit
     
    Trooper_OKДата: Четверг, 30.10.2014, 19:29 | Сообщение # 6
    5 Вольт
    Группа: Пользователи
    Сообщений: 52
    Репутация: 20
    Статус: Offline
    Да,они самые. Единственное - они бывают 5 вариантов- есть с встроенной антенной,есть с штекером под антенну, есть так же не совместимые с ардуино.


    http://habrahabr.ru/company/coolrf/blog/235881/
    Прикрепления: 5051926.jpg(44.2 Kb)


    Сообщение отредактировал Trooper_OK - Четверг, 30.10.2014, 19:31
     
    loriДата: Среда, 05.11.2014, 21:19 | Сообщение # 7
    12 Вольт
    Группа: Пользователи
    Сообщений: 108
    Репутация: 20
    Статус: Offline
    Принялись писать программный код для обработки видео.
    Начали с детектирования меток. Для меток придумали следующий способ кодирования: возможны два варианта меток - круглая и квадратная. По периметру метка обведена оранжевым контуром, это первый этап детектирования, как бы сигнал для программы что здесь находится метка. Внутренняя часть метки разделена на две части, нижняя часть белого цвета, будет указывать на заднюю часть бота, верхняя часть, в свою очередь указывает на перед бота, тоже разделена на две части, которые будут закрашены равномерно двумя разными цветами, по этой части будет детектироваться бот (и выдаваться уникальный ID) и одновременно определяться направление в котором данный бот повернут.
    Вот примеры меток:
    Круглая метка.


    Квадратная метка.


    Вот кадры детектирования меток:
    Кадр RGB с детектированными метками (обведены красными кружками)


    Бинарное изображение с детектированными метками (контур выделен красным)


    Как видно, на RGB и бинарном изображении, программа определяет метки по наличию оранжевого цвета, в то же время она еще не умеет определять цвета внутри метки и направление ориентации. Это будут следующие этапы.
    Прикрепления: 8328791.jpg(1.84 Mb) · 7609585.jpg(1.83 Mb) · 3519119.png(557.6 Kb) · 5504760.png(36.7 Kb)


    Сообщение отредактировал lori - Среда, 05.11.2014, 21:24
     
    Trooper_OKДата: Среда, 05.11.2014, 23:20 | Сообщение # 8
    5 Вольт
    Группа: Пользователи
    Сообщений: 52
    Репутация: 20
    Статус: Offline
    Помниться натыкался я давно на проект "умного стола" распознающего фигурки и угол поворота.
    Там использовалась простая веб-камера и чб-формочки "амебного " вида)



    проект открытый, называется    reacTIVision   (вся документация тут http://sourceforge.net/projects/reactivision/)

    Демо презентация 


    вот вариант использования фигурок и наложенных на них миди-семплов

    Прикрепления: 0132492.png(31.2 Kb)


    Сообщение отредактировал Trooper_OK - Среда, 05.11.2014, 23:48
     
    loriДата: Четверг, 13.11.2014, 06:56 | Сообщение # 9
    12 Вольт
    Группа: Пользователи
    Сообщений: 108
    Репутация: 20
    Статус: Offline
    Господа, все, что написано выше, по поводу сборки роботов, удешевления их конструкции и пр. это, конечно замечательно, и этим непременно нужно воспользоваться. Но все это не имеет никакого практического смысла в разрезе проекта вообще и данного блога в частности, если не будет создана управляющая программа для компьютера которая будет управлять bot-ами, а так же отслеживать другие объекты на поле. Без такой программы bot-ы будут просто бесполезными железяками с моторчиками (если конечно не применить их в других проектах). Думаю, что конструкция bot-ов уже достаточно подробно рассмотрена, предложено масса интересных решений в техническом и экономическом аспектах. Предлагаю переключиться на программную часть проекта.
    Наша команда уже начала создавать программу отслеживания и управления. Как уже писалось, программный код создается на C++ в среде программирования Visual Studio 2012, с применением библиотеки компьютерного зрения openCV. Сам проект понемногу развивается, не без учета пожеланий и идей сообщества roboforum - всем огромное спасибо за советы и рекомендации. Надеемся и в дальнейшем получать от форумчан конструктивную критику и дельные советы.
    На сегодняшний день имеем следующее -
    В техническом плане:
    1. собрано несколько bot-ов;
    2. имеется прототип поля по которому роботы будут кататься.
    В программном плане:
    1. написана часть программного кода по распознаванию меток ботов на поле.
    Если кому интересно здесь программный код. Для работы нужна библиотека openCV и подключенная WEB-камера.
    
    Код
    #include "stdafx.h"
    #include "cv.h"
    #include "highgui.h"

    using std::cout;
    using std::endl;
    using namespace cv;

    void FindBot( IplImage& img );
    void FindColor( IplImage& img, int ); // поиск по цвету, int - код цвета
                                // (0 - оранжевый, 1 - красный, 2 - синий, 3 - зеленый, 4 - желтый)
    void Counter( IplImage* img ); // выделение контуров
    void Metka( IplImage& img, int& x, int& y, int& r, int area, int color ); // распознавание метки
    void ConversionThreshold( IplImage* img ); // пороговое преобразование
    void Color( IplImage& img, int& x, int& y, int& r, int area, int color );

    IplImage *playing_field = NULL; // картинка для хранения кадра с камеры
    IplImage* RGBThreshold = NULL; //cvCreateImage( cvGetSize(playing_field), 8, 3 ); // кадр для хранения порогового преобразования

    struct obj {public: char name; CvPoint center; int radius; int area;}; // наименование, центр (x, y) и радиус описанной окружности, площадь фигуры
    obj bot, shape;

    struct bot {public: int ID; CvPoint center; int radius; int vector;};

    int main( int argc, char** argv ) {
        CvCapture *capture = cvCreateCameraCapture( 0 ); // инициализируем камеру
         
        if(capture == NULL) // если камер не обнаружено - выходим
           return 0;

        //cvNamedWindow( "camera", CV_WINDOW_AUTOSIZE ); // Окошко

        while (1) {
           playing_field = cvQueryFrame( capture ); // получаем фрейм из камеры

           if(!playing_field) // если фрейм не получен
              break;

           // Создаем копию кадра
           IplImage* Image = cvCreateImage( cvGetSize(playing_field), 8, 3 ); //кадр для передачи в функции для последовательной обработки
           RGBThreshold = cvCreateImage( cvGetSize(playing_field), 8, 3 ); // кадр для хранения порогового преобразования
            
           cvCopy( playing_field, Image ); // копируем кадр
            
           ConversionThreshold( Image ); // пороговое преобразование
           cvCopy( Image, RGBThreshold ); // копируем кадр порогового перобразования
            
           cvShowImage( "RGB cvThreshold 2", RGBThreshold );
            
           FindBot( *Image ); // поиск ботов в кадре

           cvShowImage( "camera", playing_field );
            
           if(cvWaitKey(1) == 27)
              break; // Если Esc - выходим

           // Освободить ресурсы
           cvReleaseImage( &Image );
           cvReleaseImage( &RGBThreshold );
        }

        // Освободить ресурсы
        cvReleaseCapture( &capture );

        cvDestroyAllWindows(); // закрываем все окна

        return 0;
    }

    // Поиск ботов
    void FindBot( IplImage& Img ) {
        FindColor( Img, 0 ); // выделить цвет
        Counter( &Img ); // выделить контуры
    }

    // Пороговое преобразование
    void ConversionThreshold( IplImage* Image )
    {
        // Кадры для хранения отдельных слоёв BGR-изображений
        IplImage* r = cvCreateImage( cvGetSize(Image), IPL_DEPTH_8U, 1 );
        IplImage* g = cvCreateImage( cvGetSize(Image), IPL_DEPTH_8U, 1 );
        IplImage* b = cvCreateImage( cvGetSize(Image), IPL_DEPTH_8U, 1 );

        cvSplit( Image, b, g, r, 0 ); // разбиваем на слои

    /*   cvAdaptiveThreshold( r, r, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 1 );
        cvAdaptiveThreshold( g, g, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 1 );
        cvAdaptiveThreshold( b, b, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 1 );
    */
        // Выполняем пороговое преобразование
        cvThreshold( r, r, 120, 250, CV_THRESH_BINARY ); // 150 250
        cvThreshold( g, g, 120, 250, CV_THRESH_BINARY );
        cvThreshold( b, b, 120, 250, CV_THRESH_BINARY );

        // Показать результат порового преобразования
        cvShowImage( "R", r );
        cvShowImage( "G", g );
        cvShowImage( "B", b );

        cvMerge(b, g, r, 0, Image); // суммируем результаты

        // Освобождаем ресурсы
        cvReleaseImage( &r );
        cvReleaseImage( &g );
        cvReleaseImage( &b );
    }

    // Поиск меток цвета
    void FindColor( IplImage& Img, int color ) {
        IplImage* Image = cvCreateImage( cvGetSize(&Img), 8, 3 );
        cvCopy(&Img, Image);

        // Теперь необходимо получить доступ ко всем пикселям.
        uchar* ptr1;
        ptr1 = (uchar*) (Image->imageData );

        // Выделить все пиксели удовлетворяющие искомому цвету (BGR)
        for (int i = 0; i < Image->height; i++)
           for (int j = 0; j < Image->width; j++) {
              switch (color) {
              case 0: // черный цвет
                 if (ptr1[j * 3 + i * Image->widthStep] == 0 && // B
                 ptr1[j * 3 + 1 + i * Image->widthStep] == 0 && // G
                 ptr1[j * 3 + 2 + i * Image->widthStep] == 0) { // R
                    ptr1[j * 3 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 255;
                 }
                 else {
                    ptr1[j * 3 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 0;
                 }
                 break;
              case 1: // белый цвет
                 if (ptr1[j * 3 + i * Image->widthStep] > 200 && // B
                 ptr1[j * 3 + 1 + i * Image->widthStep] > 200 && // G
                 ptr1[j * 3 + 2 + i * Image->widthStep] > 200) { // R
                    ptr1[j * 3 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 255;
                 }
                 else {
                    ptr1[j * 3 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 0;
                 }
                 break;
              case 2: // синий цвет
                 if (ptr1[j * 3 + i * Image->widthStep] > 200 && // B
                 ptr1[j * 3 + 1 + i * Image->widthStep] == 0 && // G
                 ptr1[j * 3 + 2 + i * Image->widthStep] == 0) { // R
                    ptr1[j * 3 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 255;
                 }
                 else {
                    ptr1[j * 3 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 0;
                 }
                 break;
              case 3: // красный цвет
                 if (ptr1[j * 3 + i * Image->widthStep] == 0 && // B
                    ptr1[j * 3 + 1 + i * Image->widthStep] == 0 && // G
                    ptr1[j * 3 + 2 + i * Image->widthStep] > 200) { // R
                    ptr1[j * 3 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 255;
                 }
                 else {
                    ptr1[j * 3 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 0;
                 }
                 break;
              case 4: // желтый цвет
                 if (ptr1[j * 3 + i * Image->widthStep] == 0 && // B
                 ptr1[j * 3 + 1 + i * Image->widthStep] > 200 && // G
                 ptr1[j * 3 + 2 + i * Image->widthStep] > 200) { // R
                    ptr1[j * 3 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 255;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 255;
                 }
                 else {
                    ptr1[j * 3 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 1 + i * Image->widthStep] = 0;
                    ptr1[j * 3 + 2 + i * Image->widthStep] = 0;
                 }
                 break;
              }
           }

           cvCopy( Image, &Img );

        // Освободить ресурсы
        cvReleaseImage( &Image );
    }

    // Выделить все найденные объекты
    void Counter( IplImage* img ) {
        IplImage* img_gray = cvCreateImage( cvSize(img->width, img->height), 8, 1 );

        CvSeq* contours = 0;
        CvMemStorage* storage = cvCreateMemStorage(0);
        cvCvtColor( img, img_gray, CV_BGR2GRAY );

        // Поиск контуров
        cvFindContours( img_gray, storage, &contours, sizeof(CvContour),
                    CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
         
        CvSeq* h_next = 0;

        CvPoint2D32f center;
        float radius;

        // Поиск объектов
        for(CvSeq* c = contours; c != NULL; c = c->h_next) {
           if (c != contours) {
              cvMinEnclosingCircle( h_next, ¢er, &radius ); // поиск центра и радиуса объекта
               
              shape.radius = radius;

              if (radius >= 20 && radius < 50) { // ограничить минимальный и максимальный радиус
                 // Координаты центра окружности
                 shape.center.x = center.x;
                 shape.center.y = center.y;

                 if ((shape.center.x - shape.radius > 0 && shape.center.y - shape.radius > 0) && // только если объект полностью в поле кадра
                 (shape.center.x + shape.radius < img->width && shape.center.y + shape.radius < img->height)) {          
                    shape.area = cvContourArea( h_next ); // запомнить площадь объекта

                    for (int color = 1; color < 5; color++) {
                       Metka( *RGBThreshold, shape.center.x, shape.center.y, shape.radius, shape.area, color ); // распознать метку
                    }

                    cvDrawContours( img, h_next, CV_RGB(255,0,0), CV_RGB(0,255,0), 0, 1, CV_AA, cvPoint(0,0) ); // нарисовать контур объекта
                    cvCircle( playing_field, shape.center, shape.radius, CV_RGB(255,0,0), 1, 8, 0 ); // выделить найденный объект в кадре
                 }
              }
           }
           h_next = c;
        }
         
        cvShowImage( "Contours", img );

        // Освободить ресурсы
        cvReleaseMemStorage( &storage );
        cvReleaseImage( &img_gray );
    }

    // Распознать метку
    void Metka( IplImage& img, int& x, int& y, int& r, int area, int color ) {

        IplImage* roii = cvCreateImage( cvGetSize(&img), 8, 3 ); // кадр для ROI
        cvCopy( &img, roii ); // скопировать кадр в ROI

        cvSetImageROI( roii, cvRect(x - r, y - r, r * 2, r * 2) ); // устанавливаем ROI с изображением полученного объекта
        CvPoint  pt1, pt2; pt1.x = x - r; pt1.y = y - r; pt2.x = pt1.x + r * 2; pt2.y = pt1.y + r * 2;
        FindColor( *roii, color ); // выделить цвет

        Color( *roii, x, y, r, area, color ); // пометить найденный цвет на метке

        cvShowImage( "ROI", roii );

        // Освободить ресурсы
        cvResetImageROI( roii ); // сброс ROI
        cvReleaseImage( &roii );
    }

    void Color( IplImage& img, int& x, int& y, int& r, int area, int color )
    {    
        IplImage* img_gray = cvCreateImage( cvGetSize(&img), 8, 1 );
        cvConvertImage( &img, img_gray, CV_BGR2GRAY );
            
        //cvCvtColor( roii, img_gray, CV_BGR2GRAY );
        CvSeq* contours = 0;
        CvMemStorage* storage = cvCreateMemStorage(0);
         
        // Поиск контуров
        cvFindContours( img_gray, storage, &contours, sizeof(CvContour),
                    CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0) );

        CvSeq* h_next = 0;
        CvPoint2D32f center;
        float radius;

        // Выбор цвета выделения
        int red, grin, blu;
        switch (color) {
        case 0:
           red = 0; grin = 255; blu = 255;
           break;
        case 1:
           red = 255; grin = 255; blu = 0;
           break;
        case 2:
           red = 0; grin = 0; blu = 255;
           break;
        case 3:
           red = 255; grin = 0; blu = 0;
           break;
        case 4:
           red = 255; grin = 237; blu = 0;
           break;
        }

        // Поиск меток
        for (CvSeq* c = contours; c != NULL; c = c->h_next) {
           if (c != contours) {
              cvMinEnclosingCircle( h_next, ¢er, &radius ); // поиск центра и радиуса объекта
               
              int rad = radius;

              int are = cvContourArea( h_next );
               
              if ((are < area / 2 && are > area / 10) && // площадь цветовой метки должен быть в 3 раза меньше площади объекта
              ((center.x + rad) < r * 2 && (center.y + rad) < r * 2) && // только если объект полностью в поле ROI
              (center.x - rad > 0 && center.y - rad > 0)) {             
                 // Координаты центра окружности
                 CvPoint p;
                 p.x = (x - r) + center.x;
                 p.y = (y - r) + center.y;

                 cvCircle( playing_field, p, rad, CV_RGB(red, grin, blu), 1, 8, 0 ); // выделить найденный объект в кадре
              }
           }
           h_next = c;
        }
        cvReleaseMemStorage( &storage );
        cvReleaseImage( &img_gray );
    }


    Сообщение отредактировал lori - Четверг, 13.11.2014, 06:59
     
    loriДата: Вторник, 13.01.2015, 15:40 | Сообщение # 10
    12 Вольт
    Группа: Пользователи
    Сообщений: 108
    Репутация: 20
    Статус: Offline
    Всех с Новым Старым Годом!
    Длинные праздники не давали плотно поработать над проектом "Рой роботов".
    Тем не менее очередной шаг сделан! Выкладываю видео с обработкой метки бота и цели. На видео видно как на пустое поле выкладывается метка (в дальнейшем будет расположена сверху бота). Метка сразу определяется (обводится в зеленый кружок), ей присваивается ID, и определяется вектор направления движения бота (красная линия). Затем в поле помещается цель (красная, пластмассовая уточка), она так же сразу детектируется (обводится синим контуром), и определяется вектор направления метки на цель (голубая линия). Таким образом достигнута первая поставленная цель - детектировать метки и цели на игровом поле.
    Следующая задача будет состоять в следующем: когда метка будет помещена на колесный бот, программа должна будет, управляя двигателями бота, совместить вектор направления движения бота и вектор направления метки на цель так, чтобы они совпали в одну линию, а затем начать движение к цели.
    Таким образом мы достигнем второй поставленной цели - заставить ботов двигаться по направлению к цели, но это уже следующий шаг.
    Вот видео детектирования метки и цели:
     
    Trooper_OKДата: Вторник, 13.01.2015, 17:41 | Сообщение # 11
    5 Вольт
    Группа: Пользователи
    Сообщений: 52
    Репутация: 20
    Статус: Offline
    А метка произвольной формы-цвета может быть ? или красное с синей обводкой? Т.Е могуть ли боты ехать к произвольной уже существующей цели расположенной на местности,если ее указать?
     
    loriДата: Вторник, 13.01.2015, 18:10 | Сообщение # 12
    12 Вольт
    Группа: Пользователи
    Сообщений: 108
    Репутация: 20
    Статус: Offline
    Синий цвет обводки не принадлежит цели, этим цветом программа окантовывает детектированную цель показывая, что она определена. Форма и вид цели подгружаются из файла, в дальнейшем можно будет указывать произвольные цели.
     
    ФОРУМ ДВ Робот dvrobot.ru » DV ROBOT » Библиотека Проектов » Роевое поведение роботов (Проект по исследованию коллективного поведения роботов)
    • Страница 1 из 1
    • 1
    Поиск:

    ДВ Робот - Чат