ДО курс по робототехнике

5 апреля 2013 г.

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

(C)
Эта заметка была написана в продолжение прошлой записи, посвященной производительности 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 не опрашивает блок чаще чем каждую миллисекунду. Т.е. быстрее этого опрашивать датчики никак не получиться. А ваше какое мнение?

Комментариев нет:

Отправить комментарий