воскресенье, 16 сентября 2012 г.

Скорость опроса сенсоров

Эта заметка была написана в продолжение прошлой записи, посвященной производительности NXT блока. Поскольку в той заметке рассматривался аспект производительности самого блока, то, конечно, хотелось получить также данные, показывающие как производительность зависит от типа датчика, ответственного в тот или иной момент за основную работу робота.
Иными словами хотелось бы получить число, как часто мы можем опрашивать тот или иной датчик, поскольку от этого будет зависеть насколько быстро робот сможет реагировать на изменение в окружающей среде.

Итак, сначала надо определиться с методикой определения частоты опроса датчика.
Предлагается такой алгоритм:
  1. Инициализируем датчик
  2. Запоминаем текущее значение таймера (или сбрасываем таймер в ноль)
  3. Делаем N итераций цикла, который делает только одно действие - опрашивает датчик
  4. После завершения цикла запоминаем новое значение таймера, а точнее на сколько он изменился с шага 2.
В результате, поделив количество итераций на время, которое они заняли, станет известно сколько итераций выполниться за 1 секунду.

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

Также нужно выбрать "подопытные" датчики. Имеет смысл посмотреть на три разных: на световой, как представителя аналоговых сенсоров, на датчик расстояния, представителя цифровых устройств, и на енкодеры - датчики встроенные в двигатели и подсчитывающие то, на сколько поворачивается ось двигателя.

Чтобы было, с чем сравнивать, тестирование датчиков производиться в трех средах: NXT-G, NXC и Python.

Что же получилось?

NXT-G
Получились вот такие три программы для замера частоты опроса трех датчиков:





Они выдали вот такие результаты:

датчиккол-во итерацийвремя в мс.итераций в секунду
световой1000053291876
расстояния1000079381259
енкодеры1000043832281

Все результаты, кроме датчика расстояния, вполне ожидаемые. А вот датчик расстояния повел себя довольно странно. Дело в том, что этот датчик имеет вполне вычисляемую скорость работы, которая ограничена скоростью звука. В прошлый раз (это уже было описано здесь) замеры для среды NXT-G показали, что с ее помощью подготавливается такой байткод, который не может опрашивать датчик быстрее чем 17 раз в секунду. В этот раз измерения показывают, что ничто не мешает опрашивать датчик даже каждую миллисекунду. Отличия от прошлого раза - версия NXT-G и версия FW. Если кто-то еще проведет такой же тест и подтвердит высокую скорость работы, то это будет указывать, что новая версия NXT-G привносит определенные изменения в процесс работы с данным датчиком, что, несомненно, следует учитывать в программах.

NXC
Все три программы строились по одному и тому же шаблону:
task main() {
    SetSensorLight(IN_4);
    
    Wait(500);
    
    int tmp;
    long strt = CurrentTick();
    
    for(int i=0;i <10000;i++) {
        tmp = SensorValue(IN_4);
    }
    
    NumOut(12,LCD_LINE4, CurrentTick()-strt);
    
    until(ButtonPressed(BTNCENTER, false) > 0);
}

Естественно, в случае других датчиков инициализация и получение значений выполнялись по другому.

Результаты получились следующие:

датчиккол-во итерацийвремя в мс.итераций в секунду
световой1000011238904
расстояния10002201345
енкодеры1000011089025

Как видно, язык NXC генерирует вполне ожидаемый код - он эффективнее, чем код полученный в среде NXT-G, и логичнее работает с ультразвуковым сенсором.
Единственное, что может заметить пытливый взгляд это расхождение с результатами, декларируемым тестом PerformanceChk2, рассматриваемом в прошлой заметке.

Действительно, автор теста заявлял предельную производительность блока, как 5200 простейших операций в секунду. В результатах теста выше, видно что сенсоры опрашиваются с гораздо большей частотой.

Чтобы разобраться с этим феноменом, давайте сами скомпилируем PerformanceChk2.nxc и запустим его на блоке. Вот, что получается:

int+-12406
long+-14388
int *11061
long *12330
int /11848
long /13140
int <<3454
long <<3551
empty7894
tick/tacho22388
arrays10960
i++25380
asm inc25380

Т.е. получается, что на новом FW производительность блока в целом значительно возросла больше, чем в два раза.

Python
Опять же, все три программы будут во многом идентичны - будут отличаться инициализацией и способом получения данных:
import nxt.locator
from nxt.sensor import *
from time import clock,sleep
 
ITERATIONS = 1000
 
b = nxt.locator.find_one_brick()
 
sens = Ultrasonic(b, PORT_4)
sleep(0.5)
 
print "US testing..."
StartTime = clock()
 
i = 0
while i < ITERATIONS:
    tmp = sens.get_distance()
    i = i+1
 
total = clock()-StartTime
 
print "Time of execution: ",total
Результаты:

датчиккол-во итерацийвремя в мс.итераций в секунду
световой1000010063993
расстояния10009883101
енкодеры1000010049995

Здесь сенсор расстояния работает опять же медленнее, чем остальные. Но гораздо быстрее, чем в NXC. Стоит заглянуть во внутреннюю реализацию класса, чтобы посмотреть не выполняет ли он асинхронные запросы к датчику, используя время от времени закешированное значение. Показания других сенсоров показывают интересную особенность общения программы на Python c NXT блоком - очень похоже на то, что Python не опрашивает блок чаще чем каждую миллисекунду. Т.е. быстрее этого опрашивать датчики никак не получиться. А ваше какое мнение?

3 комментария:

  1. Сразу возникает несколько вопросов по методу тестирования:
    - сколько разрядов имеет таймер? Не происходит ли его переполнения во время теста?
    - хотелось бы увидеть код NXC именно для теста UltraSonic'а - если не ошибаюсь, то на NXC можно задать различные варианты работы: LowSpeed с I2C-устройствами, работа с RAW или с показаниями датчика и т.д.
    - при тестах используется всегда один таймер или разные? В NXT-G и RoboLab можно выбрать один из трех таймеров (что наводит на мысль, что их всего в Mindstorms NXT 3 штуки). Так вот, одинаковые ли они, или разные? У них может быть разная разрядность, некоторые из них может быть нельзя использовать одновременно с ШИМ-ом (который используется для управления двигателями).

    ОтветитьУдалить
    Ответы
    1. Разрядность таймеров - скорее всего 32, так как в справке к NXT-G указан диапазон значений, генерируемый блоком 0...4294967296, то есть 2 в 32 степени. Вопрос с переполнением отпадает, так как даже при частоте 32 МГц для переполнения таймера потребуется более 134 секунд.

      Удалить
    2. 1. для US датчика я использую получение калиброванных (scaled) значений через SensorUS(). Программу посмотреть здесь: http://pastebin.com/dEK250TJ

      2. Скриншотах NXT-G программ видно, что таймеры одни и те же.

      Удалить

Related Posts Plugin for WordPress, Blogger...