Войти

Показать полную графическую версию : Выбор значения многозначной функции


Страниц : 1 [2] 3

lxa85
15-07-2012, 21:41
По поводу шаговых двигателей.
FDD. Там червячная передача, да и "платформа" уже имеется.
Дальномер на ней закрепить и все. (габаритные размеры последнего не выяснял)

pva
15-07-2012, 23:33
Beyound, Дисперсия превышена в sqrt(999) раз - просто в формуле ошиблись. И с расстоянием может не расти, если это шум самого датчика или усилителя (пытаемся это выяснить). Если будет расти - это то, что нужно. Изначально по дисперсии планировалось отделить область до и после пика при замере дальности.
FDD »
матричный принтер круче (формата a3 особенно)!

Tonny_Bennet
16-07-2012, 11:11
Стандартная процедура замеры плотности распределения такая (почти как ты описал):
1. записывается сигнал, дофига независимых отсчётов.
2. вещественная ось делится на равные отрезки (чем длинее отрезок - тем глаже, но меньше точек в гистограмме)
3. вычисляется сколько точек попали в каждый отрезок. »

Учитывая что значения строго дискретны у меня и получилось плотность распределения.

Мне понравились расстояния 10 и 15 см, потому что там явный скачок и провал ср-кв. отклонения. В идеале было бы хорошо посмотреть "типичный" сингал и "сильное отклонение от нормы", а расстояние любое от 10 до 30 см. »
Прикрепляю измерения на 10 и 15 см. Частота измерений 200 Гц. Набирал до 3000 событий.

Tonny_Bennet
16-07-2012, 11:14
Дисперсия превышена в sqrt(999) раз - просто в формуле ошиблись »

В том месте где среднее неправильно посчитали?

pva
16-07-2012, 16:56
В том месте где среднее неправильно посчитал »
Среднее вроде везде правильно было.
В общем, немного понятно, почему так прыгает дисперсия. При удалении от пика в низким напряждениям начинается совсем не гауссово поведение.

1. В сигнале присуствует независимая от расстояния периодическая помеха (возможно напряжение питания, но частота слишком низкая, около 20 Гц. Её можно увидеть по повторяющимся пикам на частотной диаграмме.
2. В области низких напряжений (см. quant.png) есть "дыры" (2 шт), в которые не попадают значения. Причём её форма зависит от дальности. Нужно посмотреть, как они ведут себя на разных расстояниях - возможно это тот фактор, который мы ищем. Ещё интересно, что происходит с областью низких напряжений при переходе через пик среднего значения напряжения при приближении к препятствию.

Рекомендации будут такие:
1. определять расстояние не по среднему, а по моде (это точка, где максимальное значение плотности вероятности).
2. Пройтись по всему диапазону, можно снимать по 500 точек, и посмотреть, как ведёт себя область ниже моды. Должно быть хорошо видно на графике плотности (как bitmap.png), квантилей (quant.png), поведение периодической помехи может покажет фурье (fourier.png)
или автокореляция (autocorr.png).


у меня почему-то плотность распределния получилась гораздо симметричней, чем у тебя. Ты накладывал преобразование на данные?

Tonny_Bennet
17-07-2012, 10:19
1. определять расстояние не по среднему, а по моде (это точка, где максимальное значение плотности вероятности). »
Для этого нужно набирать некоторую статистику в момент измерения. У меня начали возникать некоторые проблемы с алгоритмом. Немного позже подробнее расскажу в чём именно.

2. Пройтись по всему диапазону, можно снимать по 500 точек, и посмотреть, как ведёт себя область ниже моды. »
Потребуется некоторое время для измерений.

Tonny_Bennet
17-07-2012, 10:36
у меня почему-то плотность распределния получилась гораздо симметричней, чем у тебя. Ты накладывал преобразование на данные? »
Нет, преобразований не делал

Tonny_Bennet
18-07-2012, 12:26
Столкнулся с проблемой.

Есть экземпляр ком-порта через который происходит обмен данными с модулем. Если я устанавливаю определённой командой автоопрос линии АЦП с заданной частотой, данные из модуля лезут сами. Добавляю обработчик событий ComPort.DataReceived += new SerialDataReceivedEventHandler(ComPort_DataReceived); в котором разбираю строки, пришедшие из порта и записываю данные в экземпляр некоторого класса Adc. Соответственно все расчёты (расстояния и т.д.) я провожу с экземпляром класса Adc. Что бы реализовать систему расчёта расстояния исходя не из текущего значения а из

определять расстояние не по среднему, а по моде (это точка, где максимальное значение плотности вероятности). »

Я решил добавить в класс очередь в которой хранить последние N значений.


public int Value
{
get { return _value; }
set
{
_value = value;
if (_hist_of_value.Count >= 1000)
{
var a = _hist_of_value.Dequeue();
}
_hist_of_value.Enqueue(value);
}
}

private Queue<int> _hist_of_value = new Queue<int>(1000);

public int[] HistValue
{
get
{
return _hist_of_value.ToArray();
}
}


Добавил поле, которое должно вернуть последние значения в виде целочисленного массива.

Написал новую процедуру расчёта расстояния. Она должна построить плотность распределения исходя из последних N измерений и найдя максимальное значение, посчитать и вернуть расстояние.


Dictionary<int, int> chanals = new Dictionary<int, int>();

for (int i = 0; i < adc.HistValue.Length; i++)
{

try
{
chanals[adc.HistValue[i]] += 1;
}
catch (KeyNotFoundException)
{
chanals.Add(adc.HistValue[i], 1);
}

}


При запуску стали возникать ошибки в месте chanals.Add(adc.HistValue[i], 1); " Элемент с тем же ключом уже был добавлен." У меня и сейчас мало предположений почему если нет ключа процедура отработала блок try {} и потом вызвала ошибку. Единственное, что может прийти в голову так это то, что в процедуру подсчёта расстояния передаётся ссылка на объект Adc а не его копия на момент вызова, и за время проверки try {} объект успевает измениться и возникает исключение.

Подскажите пожалуйста в чём может быть проблема.

pva
18-07-2012, 22:02
Судя по коду ты используешь C#. Я в нём начинающий, могу на общих основаниях сказать что исключение может давать adc.HistValue[i], которую ты оба раза вызываешь.

Предлагаю изменить алгоритм таким образом:
1. Собираем статистику N точек (в обычный int[])
2. Сортируем по возрастанию (обычный Array.sort<int>())
3. Теперь задача найти самую длинную "горизонтальную палку" (обычный поиск максимума)
Можно с уверенностью утверждать, что распределение унимодально, и что мода достаточно сосредоточенная, поэтому можно смело отбрасывать "палки" короче какого-то заранее заданного процента от N (надо подобрать на глаз). Этих палок скорее всего не больше 2-х. Можно даже сделать сглаживание: расположить между этими палками, согласно отношению их длин.

Tonny_Bennet
19-07-2012, 00:00
Судя по коду ты используешь C#. Я в нём начинающий, могу на общих основаниях сказать что исключение может давать adc.HistValue[i], которую ты оба раза вызываешь. »
Да это С#.... и по-моему здесь проблема из-за того, что одну переменную изменяют в разных потоках... (по моему чтение из ком-порта это отдельный поток)
У специалистов бы проконсультироваться...

Предлагаю изменить алгоритм таким образом:
1. Собираем статистику N точек (в обычный int[])
2. Сортируем по возрастанию (обычный Array.sort<int>())
3. Теперь задача найти самую длинную "горизонтальную палку" (обычный поиск максимума) »

В принципе по похожему я работал, когда вышеопубликованную гистограмму делал. Но для повышения стройности кода и использования всех прелестей ООП возникло желание запихнуть некоторые вещи в описание класса.... а с желанием появились и ошибки.

Tonny_Bennet
19-07-2012, 15:01
Извратился, пытаясь проверять на оба исключения...


try
{
chanals[adc.HistValue[i]] += 1;
}
catch (KeyNotFoundException)
{
try
{
chanals.Add(adc.HistValue[i], 1);
}
catch(ArgumentException)
{
chanals[adc.HistValue[i]] += 1;
}
}



Периодически всё же возникает то одно то другое исключение. Понять почему оно появляется я не могу :(

ferget
19-07-2012, 17:20
Вы ее в режиме отладки запустите и пошагово пройдите

и посмотрите какие значения

pva
19-07-2012, 21:51
Вы ее в режиме отладки запустите »
В этом случае в ком-порт может вывалиться кака. Лучше записать данные из порта в файл, и запустить отладку на данных из файла. Мой любимый метод: вывалить в файл, загрузить в мат.пакет и изголяться над данными в поисках истины.

По поводу украшения кода: неужели в данном случае код стал проще/быстрее/понятней/надёжней?

Delirium
20-07-2012, 02:12
chanals.Add(adc.HistValue[i], 1); " Элемент с тем же ключом уже был добавлен." »
Что, если проверять перед добавлением, типа
if(chanals.Exists(adc.HistValue[i])) {} Или подобного функционала нет?

ferget
20-07-2012, 08:06
Или подобного функционала нет? »
есть

if(chanals.ContainsKey(adc.HistValue[i])) {}

Tonny_Bennet
20-07-2012, 12:59
В этом случае в ком-порт может вывалиться кака. Лучше записать данные из порта в файл, и запустить отладку на данных из файла. Мой любимый метод: вывалить в файл, загрузить в мат.пакет и изголяться над данными в поисках истины. »

Попробую.

Что, если проверять перед добавлением, типа
Код:
if(chanals.Exists(adc.HistValue[i])) {}
Или подобного функционала нет? »
есть
Код:
if(chanals.ContainsKey(adc.HistValue[i])) {} »

Спасибо за советы. Делал по примеру из MSDN а там был с try {} catch () {}. Переделал на проверку с блоком if. Всё равно периодически возникает Исключение.
Прикрепляю скриншот окна студии.
http://s018.radikal.ru/i519/1207/d0/c67a2d2f4ca0t.jpg (http://radikal.ru/F/s018.radikal.ru/i519/1207/d0/c67a2d2f4ca0.png.html)

ferget
20-07-2012, 14:06
а зачем вы сделали ключом adc.HistValue[i], может лучше сделать ключом i, а adc.HistValue[i] - значением

Tonny_Bennet
20-07-2012, 14:21
а зачем вы сделали ключом adc.HistValue[i], может лучше сделать ключом i, а adc.HistValue[i] - значением »

Это сделано для построения плотности распределения.

В массиве HistValue хранятся последние N значений измерений. К примеру:

0371
0372
0351
0372
0372
0372
0371
0371
0371
0304
0372
0371
0371
0371
0371

И мне нужно посчитать сколько раз из N выпадало 371, сколько раз выпадало 372 и т.д. Поэтому я последовательно перебираю все значения из массива, и если ключ не создан я создаю пару из HistValue[i] и 1, если ключ уже был создан я просто увеличиваю значение на 1. Когда перебор окончен я ищу максимальное значение и узнаю какому ключу это значение соответствует.

ferget
20-07-2012, 14:41
И мне нужно посчитать сколько раз из N выпадало 371, сколько раз выпадало 372 и т.д. Поэтому я последовательно перебираю все значения из массива, и если ключ не создан я создаю пару из HistValue[i] и 1, если ключ уже был создан я просто увеличиваю значение на 1. Когда перебор окончен я ищу максимальное значение и узнаю какому ключу это значение соответствует. »
Спасибо, понятно

Но не понятно, что происходит на скриншоте, выглядит как будто значения в HistValue меняются на ходу

попробуйте создать в функции массив в него скопировать HistValue и работать с этим массивом

Tonny_Bennet
20-07-2012, 15:14
Но не понятно, что происходит на скриншоте, выглядит как будто значения в HistValue меняются на ходу
попробуйте создать в функции массив в него скопировать HistValue и работать с этим массивом »

Скопировал. Вроде работает нормально.

В таком случае получается, что во время вызова процедуры передаётся ссылка на объект а не копия объекта???




© OSzone.net 2001-2012