пятница, 21 сентября 2012 г.

Как определить цвет, когда датчик "врет"?

При работе с датчиками цвета разных производителей случаются ситуации, когда датчик не определяет цвет корректно. Например, в тех ситуациях, когда на определение влияет недостаток освещенности или наоборот - слишком много света. Еще такое может случаться, когда механизм движется слишком быстро или нет какого-то фиксированного расстояния до предмета, цвет которого датчик пытается определить - например, когда робот движется по направлению к этому предмету.
Один из способов, победить такое поведение датчика - снять показания с каждой из трех цветовых компонент: красной, зеленой и синей, так чтобы по их значения самостоятельно (собственным алгоритмом) попытаться определить какого же цвета предмет. Такой способ уже был описан вот в этом материале. Но дело в том, что подразумевается, что у нас есть достаточно много времени для определения цвета, производя последовательно 3 или даже 4 (замер освещенности без подсветки вообще), и датчик и предмет неподвижны относительно друг друга. А это не всегда возможно достичь, особенно в условиях робототехнических состязаний - когда время работы робота является критичной величиной.

Определенное преимущество имеют те конструкции, которые используют HiTechnic датчик цвета. Дело в том, что среды программирования Robolab (и NXT-G?) позволяют за одно измерение - попытку определить цвет, помимо определенного цвета, запросить сразу все три составляющие. Причем такое измерение не вносит никаких дополнительных задержек.

Но как оказалось, c NXT датчиком цвета, можно достигнуть таких же результатов. В среде NXT-G для этого нужно использовать специальный блок, устанавливаемый отдельно. Color Range Block можно скачать на специальной страничке (или здесь) сайта известного LEGO-энтузиаста Steve Hassenplug.

Использовать блок очень просто: он имеет всего три выхода, которые позволяют прочитать значение каждого цветового компонента, после замера цвета. Значение каждого компонента - число от 0 до 1023.
Чтобы посмотреть, что вычисление компонент происходит на самом деле быстро, а не видимым глазу переключением от одного источника света к другому, как это было описано выше в статье, можно провести следующий эксперимент.
Результат эксперимента: 10000 итераций выполняется за 6.8 секунды. Т.е. меньше миллисекунды на один замер.

Еще один эксперимент позволит убедиться, что в предыдущем примере компилятор байткода не вносит никакие оптимизации в цикл поскольку он ничего полезного не делает, и что мы имеем действительно с несколькими замерами, а не с буферизированными значениями:
Здесь видно, что преобразование чисел в строки и вывод строк на экран, вносят значительную задержку в работу программы: 5000 итераций выполняются за 11,2 секунды. Т.е. чуть больше двух миллисекунд на одну итерацию. Также, запустив это программу, и меняя цвет под датчиком, цифры на экране тоже будут меняться, что подтверждает актуальность выдаваемых блоком данных.

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

Для языка программирования Not eXactly C, тоже есть подобный инструментарий, позволяющий получить значения цветовых компонент за раз. Делается это с помощью функции ReadSensorColorRaw.
task main() {
    SetSensorColorFull(S3);

    unsigned int rawData[];
    int result = ReadSensorColorRaw(S3, rawData);

    NumOut(8, LCD_LINE1, rawData[INPUT_RED]);
    NumOut(8, LCD_LINE2, rawData[INPUT_GREEN]);
    NumOut(8, LCD_LINE3, rawData[INPUT_BLUE]);

    until(ButtonPressed(BTNCENTER));
}

Данный функционал тоже производит измерения достаточно быстро:
task main() {
    SetSensorColorFull(S3);

    unsigned int rawData[];
    int result;
    
    unsigned long strt = CurrentTick();
    for(int i=0; i<5000; i++) {
        result = ReadSensorColorRaw(S3, rawData);
        NumOut(8, LCD_LINE1, rawData[INPUT_RED]);
        NumOut(8, LCD_LINE2, rawData[INPUT_GREEN]);
        NumOut(8, LCD_LINE3, rawData[INPUT_BLUE]);
    }
    NumOut(8, LCD_LINE5, CurrentTick() - strt);

    until(ButtonPressed(BTNCENTER));
}

Результат работы - 5000 итераций за 6,2 секунды.

Если необходимо сделать за один вызов и определение цвета и получить значения компонент, то можно использовать функцию SysColorSensorRead.

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

  1. А использование дополнительных блоков не является запрещенным на соревнованиях?

    ОтветитьУдалить

Related Posts Plugin for WordPress, Blogger...