Показать полную графическую версию : Выбор значения многозначной функции
По поводу шаговых двигателей.
FDD. Там червячная передача, да и "платформа" уже имеется.
Дальномер на ней закрепить и все. (габаритные размеры последнего не выяснял)
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) раз - просто в формуле ошиблись »
В том месте где среднее неправильно посчитали?
В том месте где среднее неправильно посчитал »
Среднее вроде везде правильно было.
В общем, немного понятно, почему так прыгает дисперсия. При удалении от пика в низким напряждениям начинается совсем не гауссово поведение.
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 {} объект успевает измениться и возникает исключение.
Подскажите пожалуйста в чём может быть проблема.
Судя по коду ты используешь 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;
}
}
Периодически всё же возникает то одно то другое исключение. Понять почему оно появляется я не могу :(
Вы ее в режиме отладки запустите и пошагово пройдите
и посмотрите какие значения
Вы ее в режиме отладки запустите »
В этом случае в ком-порт может вывалиться кака. Лучше записать данные из порта в файл, и запустить отладку на данных из файла. Мой любимый метод: вывалить в файл, загрузить в мат.пакет и изголяться над данными в поисках истины.
По поводу украшения кода: неужели в данном случае код стал проще/быстрее/понятней/надёжней?
Delirium
20-07-2012, 02:12
chanals.Add(adc.HistValue[i], 1); " Элемент с тем же ключом уже был добавлен." »
Что, если проверять перед добавлением, типа
if(chanals.Exists(adc.HistValue[i])) {} Или подобного функционала нет?
Или подобного функционала нет? »
есть
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)
а зачем вы сделали ключом 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. Когда перебор окончен я ищу максимальное значение и узнаю какому ключу это значение соответствует.
И мне нужно посчитать сколько раз из N выпадало 371, сколько раз выпадало 372 и т.д. Поэтому я последовательно перебираю все значения из массива, и если ключ не создан я создаю пару из HistValue[i] и 1, если ключ уже был создан я просто увеличиваю значение на 1. Когда перебор окончен я ищу максимальное значение и узнаю какому ключу это значение соответствует. »
Спасибо, понятно
Но не понятно, что происходит на скриншоте, выглядит как будто значения в HistValue меняются на ходу
попробуйте создать в функции массив в него скопировать HistValue и работать с этим массивом
Tonny_Bennet
20-07-2012, 15:14
Но не понятно, что происходит на скриншоте, выглядит как будто значения в HistValue меняются на ходу
попробуйте создать в функции массив в него скопировать HistValue и работать с этим массивом »
Скопировал. Вроде работает нормально.
В таком случае получается, что во время вызова процедуры передаётся ссылка на объект а не копия объекта???
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.