Перейти к содержимому

Фотография

Программирование на квадрокоптере AR.Drone


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 187

#101
erbol

erbol
  • Читатель
  • 361 сообщений
Используем пакет OpenCV для нахождения параметров прямых на картинке. Преобразование Хафа

В OpenCV для этого имеется функция

CVAPI(CvSeq*) cvHoughLines2( CvArr* image, void* line_storage, int method,
double rho, double theta, int threshold,
double param1 CV_DEFAULT(0), double param2 CV_DEFAULT(0));

— нахождение линий на двоичном изображении, используя преобразование Хафа

image — 8-битное двоичное изображение (в случае вероятностного метода изображение будет модифицироваться)
line_storage — хранилище памяти для сохранения найденных линий (можно использовать матрицу 1xЧисло_линий CvMat)
method — метод:
#define CV_HOUGH_STANDARD 0
#define CV_HOUGH_PROBABILISTIC 1
#define CV_HOUGH_MULTI_SCALE 2


CV_HOUGH_STANDARD — классический вариант трансформации Хафа. Каждая линия представляется двумя числами типа float (rho, theta), где rho — дистанция между точкой (0,0) и линией, а theta — угол между осью x и нормалью к линии (т.е. матрица должна иметь тип of CV_32FC2)
CV_HOUGH_PROBABILISTIC — вероятностный метод трансформации Хафа (более эффективен с случае изображений с несколькими длинными линейными сегментами). Возвращает сегменты линии, которые представляются точками начала и конца (т.е. матрица должна иметь тип of CV_32SC4)
CV_HOUGH_MULTI_SCALE — масштабный вариант классической трансформации Хафа. Линии представлены так же, как и в CV_HOUGH_STANDARD

Вероятностное преобразование Хафа (Probabilistic Hough Transform)
заключается в том, что для нахождения объекта достаточно провести преобразование Хафа только для части (a) точек исходного изображения, 0% <= a <= 100%. То есть сначала провести выделение «контрольных» точек с изображения, и для него провести преобразование Хафа.


rho — разрешение по дистанции
theta — разрешение по углу (в радианах)
threshold — пороговый параметр. Линия возвращается, если аккумулирующий параметр больше порогового значения.
param1 — первый параметр (в зависимости от метода трансфрмации:
CV_HOUGH_STANDARD — 0 — не используется
CV_HOUGH_PROBABILISTIC — минимальная длина линии
CV_HOUGH_MULTI_SCALE — делитель разрешения по дистанции (rho/param1))
param2 — второй параметр (в зависимости от метода трансфрмации:
CV_HOUGH_STANDARD — 0 — не используется
CV_HOUGH_PROBABILISTIC — максимальный промежуток между сегментами линии, лежащими на одной линии, чтобы считать их одним сегментом (объединить их вместе)
CV_HOUGH_MULTI_SCALE — делитель разрешения по углу (theta/param1))

если line_storage — указатель на хранилище памяти, то функция вернёт указатель на первый элемент последовательности, содержащей найденные линии.

Example


//
// нахождение линий на изображении, 
// с использованием преобразования Хафа cvHoughLines2()
//
// модифицированный пример samples\c\houghlines.c
//
// http://robocraft.ru
//

#include <cv.h>
#include <highgui.h>
#include <math.h>

int main(int argc, char* argv[]) 
{
        IplImage* src = 0;
        IplImage* dst=0;
        IplImage* color_dst=0;

        // имя картинки задаётся первым параметром
        char* filename = argc >= 2 ? argv[1] : "Image0.jpg";
        // получаем картинку (в градациях серого)
        src = cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE);

        if( !src ){
                printf("[!] Error: cant load image: %s \n", filename);
                return -1;
        }

        printf("[i] image: %s\n", filename);


        // хранилище памяти для хранения найденных линий
        CvMemStorage* storage = cvCreateMemStorage(0);
        CvSeq* lines = 0;
        int i = 0;


        dst = cvCreateImage( cvGetSize(src), 8, 1 );
        color_dst = cvCreateImage( cvGetSize(src), 8, 3 );

        // детектирование границ
        cvCanny( src, dst, 50, 200, 3 );

        // конвертируем в цветное изображение
        cvCvtColor( dst, color_dst, CV_GRAY2BGR );

        // нахождение линий
        lines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 50, 50, 10 );

        // нарисуем найденные линии
        for( i = 0; i < lines->total; i++ ){
                CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
                cvLine( color_dst, line[0], line[1], CV_RGB(255,0,0), 3, CV_AA, 0 );
        }

        // показываем
        cvNamedWindow( "Source", 1 );
        cvShowImage( "Source", src );

        cvNamedWindow( "Hough", 1 );
        cvShowImage( "Hough", color_dst );

        // ждём нажатия клавиши
        cvWaitKey(0);

        // освобождаем ресурсы
        cvReleaseMemStorage(&storage);
        cvReleaseImage(&src);
        cvReleaseImage(&dst);
        cvReleaseImage(&color_dst);
        cvDestroyAllWindows();
        return 0;
} 

http://robocraft.ru/...vision/502.html

#102
erbol

erbol
  • Читатель
  • 361 сообщений
Через 10 лет нейроинтерфейсы "отменят" инвалидность

Пентагон надеется вернуть к нормальной жизни как минимум 2000 военнослужащих, которые потеряли руки и ноги с 2000 года.

В DARPA считают мышечные нейроинтерфейсы очень перспективными и активно работают над соответствующими технологиями, которые позволят обеспечить надежное и долговременное соединение протеза с нервной системой человека. Кроме того, в перспективе подобные нейроинтерфейсы могут использоваться и здоровыми солдатами – для управления специальной техникой и оборудованием.

В частности речь идет об особом типе периферийного интерфейса TMR, который разработали в Реабилитационном институте Чикаго (RIC). Этот нейроинтерфейс обеспечивает повторную иннервацию мышц, причем в качестве замены ампутированной части тела выступает искусственно созданный механоэлектронный протез. TMR не только позволяет управлять протезом, как собственной рукой или ногой, но и возвращает чувствительность, правда теперь в роли осязательных датчиков выступают не рецепторы в коже, а сенсоры в искусственном покрытии протеза.

Работа в рамках TMR продолжится до 2016 года. Судя по всему, через 10 лет универсальный периферийный нейроинтерфейс будет готов для массового использования.

http://rnd.cnews.ru/...13/06/04/530921



#103
erbol

erbol
  • Читатель
  • 361 сообщений
Смысл параметров функции cvHoughLines2

Параметры rho и theta функции cvHoughLines2, используются при создании аккумуляторной матрицы. Определяют число элементов матрицы.

Из всех параметров функции самым важным для нахождения линий на рисунке является параметр threshold.

threshold — пороговый параметр. Линия возвращается, если аккумулирующий параметр больше порогового значения. Изменяя его значение изменяем чувствительность функции к линиям отображенным на рисунке

С помощью алгоритма Canny можно искать границы (контуры) предметов изображенных на рисунке.

Если на рисунке провести линию, то ее контуром будет прямоугольник. Вот так

Сам рисунок

Изображение

Результат , после обработки функцией cvCanny

Изображение

В данном случае интенсивность пиксела меняется сверху и снизу от прямой , поэтому Canny рисует две линии, сверху и снизу от исходной линии.

Если исходная картинка такая

Изображение

то после обработки функцией cvCanny получим

Изображение

#104
erbol

erbol
  • Читатель
  • 361 сообщений
Стартовал конкурс видеопрезентаций -http://robots.croc.r...tail.php?ID=880.

Видеопрезентации всех прошедших на следующий конкурсный этап участников можно посмотреть на канале в Youtube. Кто был самым артистичным и изобретательным в демонстрации возможностей своего летающего робота — определится путем открытого голосования. Голосами считаются комментарии с текстом «+1» (комментарии с другим текстом, а также отметки «Нравится» НЕ учитываются), оставленные под каждой отдельной видеопрезентацией. Участник, чья видеопрезентация наберет наибольшее количество комментариев «+1», получит приз — планшетный компьютер ASUS VivoTab!

Мне понравилась команда Robodem.



#105
erbol

erbol
  • Читатель
  • 361 сообщений
Обустройство полигона в квартире

Купил монтажную термическую ленту для мебели, белого цвета (35 тенге за метр). К линолеуму буду ее клеить с помощью двухстороннего скотча.

Думаю получится.

С помощью функции cvHoughLines2 буду определять угол линии и крайние точки. Параметры линии буду использовать для корректировки направления носа вертолета и смещения в поперечной к линии плоскости

Как только дошли до края линии, поворот на 180 градусов и движение в обратном направлении.

#106
erbol

erbol
  • Читатель
  • 361 сообщений
Обработка черно-белого видео с вертикальной камеры. Для переключения канала видеопотока используем метод setCamera(int channel). Этот метод определен в классе ARDrone

void ARDrone::setCamera(int channel)
{
// Enable mutex lock
if (mutexCommand) pthread_mutex_lock(mutexCommand);

// AR.Drone 2.0
if (version.major == ARDRONE_VERSION_2) {
sockCommand.sendf("AT*CONFIG_IDS=%d,\"%s\",\"%s\",\"%s\"\r", seq++, ARDRONE_SESSION_ID, ARDRONE_PROFILE_ID, ARDRONE_APPLOCATION_ID);
sockCommand.sendf("AT*CONFIG=%d,\"video:video_channel\",\"%d\"\r", seq++, channel % 2);
}
// AR.Drone 1.0
else {
sockCommand.sendf("AT*CONFIG=%d,\"video:video_channel\",\"%d\"\r", seq++, channel % 4);
}

// Disable mutex lock
if (mutexCommand) pthread_mutex_unlock(mutexCommand);

msleep(100);
}

При использовании данного метода используются операции остатка от целочисленного деления - %

5 % 4 = 1
8 % 8 = 0
6 % 8 = 6

и так далее

И также используется операция преинкремента

http://www.linkex.ru/java/inc-dec.php

// Change camera
static int mode = 0;
if (KEY_PUSH('C')) ardrone.setCamera(++mode%4);
Для работы нам необходим код на C++ реализующий класс ardrone который умеет работать с несколькими потоками одновременно , обрабатывать видеосигнал с вертолета с помощью библиотеки OpenCV

Под классом ardrone имеется в виду набор функций реализующий управление AR.Drone и обрабатывающий навигационные данные получаемые с вертолета

Создал новый проект в VS2008, скопировал туда файлы с определениями класса. В свойствах проекта задал расположение папок с заголовочными файлами нужных библиотек, в этих файлах описаны структуры данных и функции определенные в библиотеках

Задал расположение папок где находятся файлы используемых библиотек.

Четыре свойства

1. Дополнительные каталоги включения - D:\3rdparty\pthread\include;D:\3rdparty\opencv\include;D:\3rdparty\ffmpeg\include
2. Дополнительные каталоги библиотек - D:\3rdparty\opencv\lib\vs2008;D:\3rdparty\pthread\lib;D:\3rdparty\ffmpeg\lib
3. Дополнительные зависимости -
wsock32.lib
wininet.lib
opencv_calib3d249.lib
opencv_contrib249.lib
opencv_core249.lib
opencv_features2d249.lib
opencv_flann249.lib
opencv_highgui249.lib
opencv_imgproc249.lib
opencv_legacy249.lib
opencv_ml249.lib
opencv_objdetect249.lib
opencv_photo249.lib
opencv_softcascade249.lib
opencv_stitching249.lib
opencv_superres249.lib
opencv_video249.lib
opencv_videostab249.lib
avcodec.lib
avdevice.lib
avfilter.lib
avformat.lib
avutil.lib
swresample.lib
swscale.lib
pthreadVC2.lib
4. Определения препроцессора -
WIN32;NDEBUG;_CONSOLE;__STDC_CONSTANT_MACROS;

#107
erbol

erbol
  • Читатель
  • 361 сообщений
Первый вопрос - Как соотносятся между собой длина реальной линии, находящейся на определенном расстоянии от точки наблюдения и количество пикселов отображающих эту линию на картинке видео ?

Ответ - Соотносятся пропорционально. То есть a = k*a1. Где к - коэффициент, а1 - длина линии в единицах длины, а - длина линии в пикселах на изображении

Вроде бы все логично. Но это только на первый взгляд. На самом деле длина линии в пикселах на картинке соответствует ее угловому размеру. Допустим вся картинка имеет угловой размер 60 градусов и ширину в пикселах 480. Если длина линии в пикселах равна 48, то угловой размер линии равен 6 градусам.

Второй вопрос - Как соотносятся между собой длина реальной линии и угол под которым она видна из точки наблюдения ?

Изображение

Точка наблюдения находится в вершине А треугольника. Катету b - соответствует длина линии, катету a - расстояние до линии из точки наблюдения (нормаль к линии из точки наблюдения)

Угол А равен арктангенсу отношения катета b к катету a

A = arctg (b/a)

Вот график функции арктангенса

Изображение

Видно, что график на интервале от 0 до бесконечности имеет три части различные по своему поведению. Два линейных участка и один криволинейный.

Если известна длина линии и угловой размер то можно определить расстояние до линии

a = b/tg(A)

#108
erbol

erbol
  • Читатель
  • 361 сообщений
Как результат cvHoughLine2 возвращает список состоящий из пар значений угол/длина нормали

Где "угол" это угол между нормалью и осью Х. Нормаль проводится к обнаруженной на картинке прямой из начала координат. Начало координат находится в верхнем левом углу картинки

Угол меняется от 0 до 180 градусов. Повернув линию относительно ее любой точки на 180 градусов получим все возможные ее положения на плоскости.

То есть шкала углов имеет "особую точку", в которой угол меняется от 180 градусов до нуля

Постановка задачи.

Пусть на картинке изображены две параллельные линии. Горизонтально или вертикально. Надо найти расстояние между ними.

#109
erbol

erbol
  • Читатель
  • 361 сообщений
Видеопрезентация № 2. Сапешко Виктор Иосифович



#110
erbol

erbol
  • Читатель
  • 361 сообщений
Чтобы лететь вдоль линии летчик-робот должен контролировать угол вертолета по отношению к линии и расстояние до линии.

Также он должен уметь распознавать конец линии для совершения поворота на 180 градусов и полета в обратном направлении

Кроме того он должен уметь совершать изменение курса и движение поперечно курсу для того чтобы переместить вертолет параллельно линии недалеко от ее оси

Постановка. Пусть на полу имеется белая полоса. Нужно летать вдоль нее

Решение. Циклически анализируем изображение получаемое с вертикальной видеокамеры. Ищем на нем контуры белой полосы. Вычисляем наклон линий относительно оси вертолета и положение полосы на изображении

Если наклон превышает 10 градусов, то поворачиваемся вокруг вертикальной оси. Если расстояние от оси белой полосы до центра картинки превышает четверть ширины картинки то перемещаемся в нужную сторону


Изображение

Если полоса находится слева от центра картинки, то проверяем истинность условия

if (w - d) > w/4 vy = 0.5

где d это х - координата центра полосы, w - полуширина картинки

Если полоса находится справа от центра картинки, то проверяем истинность условия

if (d - w) > w/4 vy = -0.5

В случае если условия истинны то задаем вектор скорости в направлении Х, направленный к центру картинки, для того чтобы вертолет сместился в сторону полосы



if (erbol1) {
if (d > w) {
// двигаемся влево
if ((d - w) > w/4) vy = 0.5
}
else
{
// двигаемся вправо
if ((w - d) > w/4) vy = -0.5
}
}


#111
erbol

erbol
  • Читатель
  • 361 сообщений
Визуализация данных получаемых с сенсоров вертолета (скорость, высота, заряд аккумулятора) , а также вычисление вектора перемещения и его визуализация

Изображение

Вот картинка с изображением полученная с вертолета и на нее выводятся данные с сенсоров

Хочу еще сделать окно в которое будет выводится информация в виде векторов мгновенной скорости и текущего значения вектора перемещения

#112
erbol

erbol
  • Читатель
  • 361 сообщений
Изображение

#113
erbol

erbol
  • Читатель
  • 361 сообщений
Для того чтобы отобразить графически вектор скорости нужно задать пропорцию между значением скорости и длиной линии в пикселах на рисунке

Пусть максимальная скорость drone 2 м/сек, а максимальная длина вектора скорости на рисунке - 100 пикселов, то есть чтобы получить длину вектора нужно значение скорости умножить на 50

Пусть к примеру скорость равна 0.70 м/сек, тогда длина вектора будет равна 35 пикселов

1. Чертим оси системы координат с центром в точке CvPoint li = cvPoint( width/4 , height/2);
2. Получаем текущее значение скорости в проекциях на ось X и Y, переводим их в пикселы. Находим координату конца вектора скорости. К координатам центра системы добавляем значения скоростей
3. Чертим вектор на рисунке

Чертим оси системы координат

IplImage* vectors = cvCreate( cvGetSize(image), IPL_DEPTH_8U, 3 );

Ширина окна - 640 пикселов
Высота окна - 360 пикселов

Координаты 2 точек линий осей

1 ось X, 1 точка : X0 - 30, Y0 - 180
1 ось X, 2 точка : X1 - 290, Y0 - 180

2 ось X, 1 точка : X0 - 350, Y0 - 180
2 ось X, 2 точка : X1 - 610, Y0 - 180

1 ось Y, 1 точка : X0 - 160, Y0 - 35
1 ось Y, 2 точка : X1 - 160, Y0 - 325

2 ось Y, 1 точка : X0 - 480, Y0 - 35
2 ось Y, 2 точка : X1 - 480, Y0 - 325

Изображение

Получилась вот такая картинка в окне

Изображение

Код такой

CvPoint li = cvPoint(  30 , height/2);
CvPoint li1 = cvPoint(  290 , height/2);
cvLine( vectors, li, li1, CV_RGB(255,0,0), 1, CV_AA, 0 );
cvShowImage( "Vectors", vectors );

li = cvPoint(  160 , 35);
li1 = cvPoint(  160 , 325);
cvLine( vectors, li, li1, CV_RGB(255,0,0), 1, CV_AA, 0 );
cvShowImage( "Vectors", vectors );

li = cvPoint(  350 , 180);
li1 = cvPoint(  610 , 180);
cvLine( vectors, li, li1, CV_RGB(255,0,0), 1, CV_AA, 0 );
cvShowImage( "Vectors", vectors );

li = cvPoint(  480 , 35);
li1 = cvPoint(  480 , 325);
cvLine( vectors, li, li1, CV_RGB(255,0,0), 1, CV_AA, 0 );
cvShowImage( "Vectors", vectors );


#114
erbol

erbol
  • Читатель
  • 361 сообщений
Получил точный вектор ускорения drone с помощью структуры данных phys_measures

Три вектора ускорения по осям связанным с вертолетом. Ось х направленна вдоль горизонтальной камеры

То есть чтобы получить ускорение относительно неподвижной системы координат надо знать углы Эйлера


double ARDrone::getAccel(double *Ax, double *Ay, double *Az)
{

    // Get the data
    if (mutexNavdata) pthread_mutex_lock(mutexNavdata);
    double A_x =  navdata.phys_measures.phys_accs[0]/10;
    double A_y = -navdata.phys_measures.phys_accs[1]/10;
    double A_z = -navdata.phys_measures.phys_accs[2]/10;
    double A = sqrt(A_x*A_x + A_y*A_y + A_z*A_z);
    if (mutexNavdata) pthread_mutex_unlock(mutexNavdata);

    // Velocities
    if (Ax) *Ax = A_x;
    if (Ay) *Ay = A_y;
    if (Az) *Az = A_z;

    return A;
}



#115
erbol

erbol
  • Читатель
  • 361 сообщений
Ускорение получаемое с помощью phys_measures.phys_accs имеет размерность см/сек^2

Проверить это можно очень просто, ставим drone на горизонтальную поверхность и считываем значение phys_measures.phys_accs[2], это элемент массива соответствует ускорению по оси Z. Он равен примерно 1000, если разделить на 100 , то получим 10 м/сек^2 - ускорение свободного падения.

Это соответствует силе которая всегда действует на тело в состоянии покоя на поверхности Земли.

Чтобы скомпенсировать проекцию ускорения оси Z на оси X и Y нужно найти величину этой проекции. Она будет зависеть от угла между осью вертикальным направлением от Земли и осями вертолета X и Y

Для оси X проекция будет равна - cos(M_PI/2 - angle_pitch)*g, где g - ускорение свободного падения, angle_pitch- угол Эйлера для оси Х вертолета

Для оси Y проекция будет равна - cos(M_PI/2 - angle_roll)*g, где g - ускорение свободного падения, angle_roll- угол Эйлера для оси Y вертолета

Сообщение отредактировал erbol: 01.07.2013, 09:38:33


#116
Nigrum cygnum

Nigrum cygnum
  • В доску свой
  • 1 201 сообщений
Похоже на монолог или блог автора по работе :)
Тема интересная, когда то мог пойти по этой дорожке, но выбрал другое. Завидую вас, люблю всё это дело)
Кстати, на гиф анимации машинка классная!
  • 0

#117
erbol

erbol
  • Читатель
  • 361 сообщений
Навигационные данные которые можно получать с борта AR.Drone представляют из себя набор структур. Эти структуры описаны в том смысле, что известны их имена , имена полей в этих структурах и типы данных полей

Для получения информации о данных гироскопа и акселерометра используются три структуры NAVDATA_RAW_MEASURES , NAVDATA_PHYS_MEASURES и NAVDATA_GYROS_OFFSETS

Я попробовал использовать поле-матрицу phys_accs[3] в структуре NAVDATA_PHYS_MEASURES

Получаем три значения

phys_measures.phys_accs[0] - ускорение вертолета по оси X
phys_measures.phys_accs[1] - ускорение вертолета по оси Y
phys_measures.phys_accs[2] - ускорение вертолета по оси Z

Ускорения получаем в единицах см/сек^2

Когда вертолет стоит на горизонтальной площадке, ускорения по осям X и Y равны приблизительно нулю, а ускорение по оси Z примерно равно 1000 см/сек^2

При вращении вертолета относительно продольной и поперечной оси значения ускорений по оси X и Y меняются приблизительно по косинусу угла осями X , Y и вектором силы тяжести. Я ввел соответствующую поправку чтобы компенсировать влияние проекции силы тяжести на оси, получилось так

Ay = Ay*10 - cos(M_PI/2 - angle_roll)*g
Ax = Ax*10 - cos(M_PI/2 - angle_pitch)*g

Но полной компенсации добиться не удалось. Составил график ускорение - угол, для неподвижного вертолета относительно оси Y. Получилась приблизительно линейная зависимость

Изображение

Сообщение отредактировал erbol: 02.07.2013, 14:54:38


#118
erbol

erbol
  • Читатель
  • 361 сообщений


#119
erbol

erbol
  • Читатель
  • 361 сообщений
AR.Drone получил новую "прошивку" от фирмы Parrot. Версия 2.4.1

В отличии от версии 2.3.3 данные с датчика скорости от вертикальной видеокамеры более точные. И работать начинает датчик скорости только в полете. У версии 2.3.3 скорость движения вертолета можно было определять перемещая вертолет в руках.

Теперь нужно запустить двигатели и только тогда можно получить данные о скорости от структуры navdata.demo.vx

#120
erbol

erbol
  • Читатель
  • 361 сообщений
В версии 2.4.1 алгоритм измерения скорости drone с помощью вертикальной видеокамеры стал точнее

Для моего drone удалось путем подбора найти выражение для вектора перемещения


if (vx>0) {
sx = sx + (vx-vx*0.08)*time;// m
}
else
{
sx = sx + vx*time;
}

if (vy>0) {
sy = sy + (vy-vy*0.10)*time;// m
}
else
{
sy = sy + vy*time;
}



То есть ноль скорости по оси имеет сдвиг в сторону положительной скорости

time - интервал времени получения данных о скорости,


Количество пользователей, читающих эту тему: 2

пользователей: 0, неизвестных прохожих: 2, скрытых пользователей: 0

Размещение рекламы на сайте     Предложения о сотрудничестве     Служба поддержки пользователей

© 2011-2022 vse.kz. При любом использовании материалов Форума ссылка на vse.kz обязательна.