| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Замерить реакцию человека |
| Автор: MYL 17.12.2006, 15:36 | ||||
| Моя цель - написать программу, которая позволит определить реакцию человека. На экране появляется красный круг. Человек сликает на него - цвет меняется с красного на зелёный. Программа замеряет то время, которое потребовалось человеку, чтобы нажатать на круг. Я залез на Delphi Russian Knowledge Base from Vit Version 2.3, и нашёл раздел "Как реализовать сверхточный таймер?" Но мне всё равно непонятно, как это применить в моей ситуации. Привожу выдержку из заметки: Windows is not a real time operating system so it is not really able to reliably achieve high accuracy timing without using a device driver. The best I have been able to get is a few nanoseconds using QueryPerformanceCounter. This is the procedure I use:
To get improved accuracy do this a little while before using Wait()
|
| Автор: gambit 17.12.2006, 20:15 |
| А я не понимаю зачем тебе нужен такой геморой со сверх точным таймером. запускаеш таймер и как только пользлватель произвел действия останавливаеш его. |
| Автор: 000denmoroz000 17.12.2006, 21:03 | ||||||
| MYL, объявляешь переменную count: count:Int64; ставишь на форму таймер, ставишь интревал 100 и Enabled - false. на событие Timer1.timer пишешь:
При нажатии на круг:
При повторном нажатии:
Уменьшая интревал - добавишь точности. |
| Автор: gambit 17.12.2006, 21:13 |
| 000denmoroz000, Правельно именно это я и имел ввиду. |
| Автор: Alexeis 18.12.2006, 14:40 |
| В этом случае, лучше воспользоваться мультимедийным таймером. Не уверен, что точности обычного таймера будет достаточно. Обычный таймер работает с погрешностью 10мс, согласитесь если время реакции может быть менее 100 мс, то не такая уж высокая точность. Или оставить как есть используя QueryPerformanceCounter После изменения цвета засечь текущее значение счетчика, после нажатия на кнопку засечь во второй раз. Посчитать их разницу и разделить это все на значение QueryPerformanceFrequency. Полученная величина будет измеряться в секундах. |
| Автор: x77 18.12.2006, 14:47 | ||
а зачем здесь вообще таймер?
собственно, всё. в момент показа засекаем время, в момент клика засекаем время. имеем разницу (EndTime - StartTime) с точностью до миллисекунд. а таймер тут не нужен в принципе. |
| Автор: Alexeis 18.12.2006, 15:17 |
| г.м. чет сомневаюсь, что до мс. Наверняка значение обновляется по тому же системному таймеру, т.е. с периодом 10мс. Впрочем утверждать не берусь ... |
| Автор: x77 18.12.2006, 15:23 |
| alexeis1, вместо Time можно юзать GetTickCount. не суть важно. важно, что замерить кол-во времени можно и без таймера, и отработка по педальному клику будет всяко быстрее (точнее), чем отлов по таймеру. |
| Автор: Alexeis 18.12.2006, 15:24 | ||
Да конечно же с точностью до 10мс! Вот лог чтения милисекунд функцией Time
Комментарии думаю излишни. Добавлено @ 15:27 Он тоже дает с точностью 10 мс. Это я точно проверял. Так что лучше QueryPerformanceCounter думаю не найти. Он самый точный! |
| Автор: Snowy 18.12.2006, 15:31 |
| А нужна ли такая точность? ИМХО 1/100 секунды - достаточная точность для измерения человека |
| Автор: Alexeis 18.12.2006, 16:41 | ||
Кто хочет пусть проверит свою
Но я один раз выдал 90мс, естественно +- 10мс. Т.е. с точностью хуже 10%. Решайте сами достаточна ли вам такая точность. Мне кажется, что нет. Думаю отдельные геймеры выдадут и 60мс. |
| Автор: MYL 18.12.2006, 19:13 | ||||||||
| Я понимаю, как работать с GetTickCount, но как работает QueryPerformanceCounter? Нажимаем на кнопку, через некоторое время появляется красный круг
Человек сликает на круг, мы меняем цвет на зелёный и пишем
Но если я вместо GetTickCount буду использовать QueryPerformanceCounter, то получу какие-то странные цифры, которые мне ни о чём не говорят. К примеру Нажимаем на кнопку, через некоторое время появляется красный круг
Человек сликает на круг, мы меняем цвет на зелёный и пишем
И два полученных результата не равны между собой, более того, если GetTickCount даёт похожий на правду результат, то QueryPerformanceCounter выдаёт совершенно непонятные цифры. В общем, как правильно использовать QueryPerformanceCounter? |
| Автор: _hunter 18.12.2006, 19:50 |
| MYL, а MSDN почитать (или по форуму поискать)? выяснилось бы что QueryPerformanceCounter() отдает время в "тиках". "размер" тика отдает QueryPerformanceFrequency() |
| Автор: MYL 18.12.2006, 23:33 |
| The QueryPerformanceFrequency function retrieves the frequency of the high-resolution performance counter, if one exists. BOOL QueryPerformanceFrequency( LARGE_INTEGER *lpFrequency // address of current frequency ); Parameters lpFrequency Points to a variable that the function sets, in counts per second, to the current performance-counter frequency. If the installed hardware does not support a high-resolution performance counter, this parameter can be to zero. В общем, что ставить в скобках QueryPerformanceFrequency ? |
| Автор: MYL 18.12.2006, 23:57 | ||||
А, вроде понял надо написать
У меня ещё вопрос. А если мою программу будут запускать на совершенно разных машинах, то будут ли результаты одинаковыми, если, допустим, у всех людей реакция будет одинаковая? То есть, предположим, два варианта: 1. У человека Celeron 333 и десять запущенных приложений 2. У человека Intel Core Если у двух человек одинаковая реакция, то будут ли на этих двух машинах одинаковые результаты? В самом первом моём сообщении - пример из Delphi Russian Knowledge Base from Vit Version 2.3. Насколько я понимаю, там считают WaitCal, чтобы избежать разницы? То есть мне надо считать
Или я ошибаюсь? |
| Автор: Alexeis 19.12.2006, 01:17 |
| Разница будет только в точности измерений, но в данном случае это не существенно. |
| Автор: cardinal 19.12.2006, 02:25 |
| Если надо сверхточное время замерить, как ты говоришь, то тебе скорее вообще в раздел "программирование контроллеров" потому, что сверхточного времени в многопоточной системе а ля Windows, которая к тому же стоит на разных машинах быть не может... |
| Автор: W4FhLF 19.12.2006, 13:05 | ||
Правильно рассуждаешь. Потери на многопоточности и как результат неточность измерений могут дел натворить таких, что получатся далеко не объективные результаты. Хотя опять же при грамотном выполнении задачи и на Celeron и на Core Duo результаты будут довольно точными. Но если накладывать реальные условия(т.е. могут быть запущены 10 приложений или ещё что другое), то конечно весь этот тест не стоит ничего. Что касается точности GetTickCount то её вполне достаточно, тем более, если учитывать что два её срабатывания как раз укладываются во время прохождения импульса от сетчатки до мозга и от мозга до пальца составляет ~20 мс, прошу заметить, что это только лишь время движения импульсов и только лишь в том случае, если человек полностью сосредоточен на задаче. |
| Автор: Alexeis 19.12.2006, 13:31 |
Я же протестировал! При 90мкс погрешность больше 10%. Может для вас этого и достаточно, но для более менее серьезных исследований сомневаюсь! И еще, установите приоритет программе Real Time. Так чтобы ее как можно меньше прерывали другие программы. Это серьезно может повлиять на точность. |
| Автор: W4FhLF 19.12.2006, 14:45 | ||
alexeis1
Ну во-первых, где это у нас речь шла о 90мкс? Во-вторых, суть Вашего теста мне не ясна, чтобы измерить точность GetTickCount Вы использую другую функцию(Sleep), которая может давать чудовищные для данного случая погрешности. Или я неправильно понял сути? В-третьих, кто определил серьёзность исследований? Вы? При серьёзных исследованиях используются отдельные аппратные таймеры или по-крайней мере комплексы, которые работают в реальнои режиме процессора + учитывается масса других факторов, о которых здесь и небыло упомянуто. В-четвертых, ненужно придираться к отрывкам, я не одной лишь цитируемой фразой ограничился в своих рассуждениях, читайте и вникайте целиком в ответ. Прошу заметить, что я не настаиваю на её использовании и не говорю, что она безупречна, я лишь сказал, само собой, если есть возможность использова более точные средства, то это нужно делать, но опять же, повторяю, многозадачность может свести всю точность на нет. |
| Автор: MYL 19.12.2006, 14:47 | ||||||
Как? Добавлено @ 14:53
Может быть, такие программы уже существуют? Но где их взять?
Ничего серьёзного, но боюсь, что мою программку может запустить на разных машинах более 1 тысячи человек (без шуток). И я боюсь, что везде результаты могут быть разными. Вот поэтому я и спрашиваю... Добавлено @ 14:57 и у меня нет времени изучать ни MSDN, ни контроллеры, ни системы в реальном времени.... Мне бы её как-нибудь написать, чтобы потом не было стыдно... Вот и вся задача! |
| Автор: W4FhLF 19.12.2006, 15:01 |
| Повысить приоритет ты конечно можешь, но это съест кучу времени у других процессов, ощутишь ли ты при этом значительную прибавку в точности сказать сложно. В остальном конечно использую связку QueryPerformanceCounter/QueryPerformanceFrequency, ничего лучше не придумаешь. |
| Автор: Alexeis 19.12.2006, 15:09 | ||
http://forum.vingrad.ru/index.php?showtopic=127774&unread=1&kw=%E2%F0%E5%EC%FF-%F2%E0%E9%EC%E5%F0-%F2%EE%F7%ED%EE%F1%F2%FC-drkb-%F0%E5%E0%EA%F6%E8%FF&st=15&hl=#
Жмешь на кнопку через неопределенное время (от 1 до 5ти секунд) меняется цвет круглишка, сразу после этого считывается количество тиков, после повторного нажатия на кнопку число тиков замеряется еще раз. Разница выводится на экран. |
| Автор: W4FhLF 19.12.2006, 15:17 |
| Ну наверно всё-таки не мкс, а мс. Так, ну понял. А как Ваш тест характеризует точность данной функции? |
| Автор: Alexeis 19.12.2006, 15:22 | ||
| MYL, SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) Добавлено @ 15:26 Ага их самых.
Нет он служит для оценки реакции человека. Сопоставима ли она с точностью GetTickCount(); 90мс сопоставимо с 10мс имхо. |
| Автор: W4FhLF 19.12.2006, 15:33 | ||
Ну вот, а о чём тогда спор? Я ведь изначально сказал, что достаточно этой функции. |
| Автор: Alexeis 19.12.2006, 15:42 |
| Звиняюсь не с точностью а с погрешностью 10мс это же погрешность... |