Камера для лего майндстормс

Обновлено: 29.04.2024

Звезда активна
Звезда активна
Звезда активна
Звезда активна
Звезда активна

С помощью веб-камеры и образовательного набора конструктора LEGO MINDSTORMS Education EV3 (45544) вполне можно сделать робота, отслеживающего двигающийся объект. Робот сможет не только поворачивать камеру в сторону объекта, но и выдерживать определённую дистанцию до него, т.е. подъехать поближе, если объект удаляется от камеры, или отъехать подальше, если объект приближается. О том, как это сделать поговорим в этой статье.

Слежение за объектом на EV3

Подготовка

Итак, давайте разбираться по порядку, что нам понадобится. Кроме самого набора LEGO MINDSTORMS Education EV3 (45544), нам нужна самая простая веб-камера с USB-подключением, не тяжёлая, которую вы сможете закрепить на роботе. Разрешение роли не играет, т.к. мощности EV3 всё равно не хватит на обработку больших изображений.

Чтобы EV3 смог работать с веб-камерой мы будем использовать альтернативную прошивку leJOS, вместо стандартной. О том, что такое leJOS, как подготовить загрузочную SD-карту и как программировать, используя leJOS, можете прочитать в статье «Программируем робота LEGO Mindstorms EV3 на Java». Обработку изображений, полученных с камеры, мы будем делать с помощью библиотеки компьютерного зрения OpenCV, которая появилась в составе leJOS в версии 0.9.1, поэтому эту версию и будем использовать.

После того как вы подготовили модуль EV3 для работы с leJOS, желательно проверить работает ли веб-камера с EV3 с помощью простых примеров, которые вы можете найти в статье «Программируем робота LEGO Mindstorms EV3 на Java» в разделе «Использование веб-камеры в leJOS EV3 для захвата изображения». Если камера работает, можно идти дальше.

Конструкцию робота можете придумать свою или использовать моего «Исследователя EV3», главное, чтобы робот смог не только поворачивать камеру в сторону объекта, но и двигаться к нему или от него. Конструкцию поворачивающейся рамки, к которой крепится камера, измените в зависимости от формы вашей камеры. Мне удалось закрепить камеру только с помощью деталей конструктора, но вы можете использовать резинки, верёвки и другие приспособления. Главное, чтобы камера держалась на рамке прочно и не болталась. Кстати, как робот работает можно посмотреть на видео:

Вот инструкция для сборки «Исследователя EV3»:

Исследователь EV3

Инструкция для сборки робота исследователя EV3 из базового образовательного набора конструктора LEGO Mindstorms Education EV3 (45544).

В версии 2: рамка закреплена прочнее и не отваливается.

После того как робот готов, можно переходить к программированию. Я сразу дам текст программы с комментариями, а ниже дам пояснения, как она работает и какие команды понимает.

Описание работы программы

После запуска программы, если всё в порядке, на экране появляются следующие надписи:

Первая строчка говорит о том, что камера готова. Следующая запись приглашает выбрать режим работы: нормальный или отладка. Следующие 2 строчки – подсказки. В этот момент программа ждёт вашего решения. Вы можете остановить программу, нажав Esc на модуле EV3 или нажать кнопку «вверх», чтобы выбрать нормальный режим, или кнопку «вниз» - для отладки.

Перед тем как выбрать режим подставьте к камере объект, который вы будете отслеживать. При этом старайтесь, чтобы объект был освещён так же, как и при дальнейшем отслеживании. Это не обязательно должен быть шарик. Главное, чтобы объект был яркого насыщенного цвета. Лучше всего использовать синий или зелёный цвета.

Затем нажмите кнопку вниз или вверх, в зависимости от выбранного режима, и робот возьмёт пробу цвета. На самом деле проба берётся 7 раз с небольшим интервалом времени, и конечный цвет будет вычислен как среднее арифметическое от этих 7-ми проб. Это позволяет снизить зависимость от мерцаний и подстройки баланса белого. На экране появится надпись:

Здесь робот сообщает, какой цвет получен с камеры в цветовой модели HSV. Первая цифра – это цветовой тон (Hue), вторая – насыщенность (Saturation) и третья – значение или яркость (Value). Цветовой тон как раз и определяет цвет. В OpenCV он может принимать значения от 0 до 179, см. рисунок ниже.

Шкала цветового тона в цветовой модели HSV в OpenCV

Именно по цветовому тону робот пытается определить название цвета и высвечивает вопрос Is it blue? (Это синий?). Отвечать на него конечно не нужно, это робот сомневается:)

Насыщенность и яркость могут быть в пределах от 0 до 255. Чем меньше насыщенность, тем ближе к белому или серому будет цвет, чем меньше яркость – тем ближе к чёрному. Из чего мы можем сделать вывод, что чем больше значения насыщенности и яркости, тем проще будет определять цвет и отслеживать объект.

Дальше программа будет работать по-разному в зависимости от режима. Режим отладки отличается от нормального режима тем, что вы сможете видеть то, что видит камера через браузер. Конечно, это замедляет работу программы, но зато вы сможете оценить, как происходит работа с изображением. Подробнее об отладке поговорим чуть ниже, а сейчас посмотрим, что будет, если выбрать нормальный режим.

После взятия пробы, действия программы по-простому можно описать так: программа будет в цикле брать кадры с камеры, искать на них объекты такого же цвета, что и цвет пробы, с небольшим допуском, и двигать робота так, чтобы отслеживаемый объект был примерно в центре кадра и был примерно нужного размера. В каждой итерации на экране отрисовывается окружность на экране EV3, в том месте где на кадре обнаружен объект и того размера который удалось определить. Как только робот теряет объект, он останавливается и ждёт, пока объект появится снова.

К сожалению, все описанные действия микрокомпьютер EV3 делает медленно, и о плавности движений робота можно забыть, т.к. идёт большая задержка при обработке изображения. Поэтому моя программа двигает робота пошагово, на это можно обратить внимание на видео: нашли объект на кадре – крутим моторы робота на один шаг (т.е. угол), ищем объект снова и опять двигаем робота на один шаг, и так далее. Пока робот двигается, брать пробы не имеет смысла, т.к. это заведомо будут устаревшие сведения.

Чтобы остановить программу, нажмите и чуть подержите кнопку Esc.

Поиск объекта с помощью OpenCV

Здесь нужно сделать остановку и отдельно написать, как же я буду искать объект на изображениях, полученных с камеры. Делается это очень просто: мы будем искать на изображении пятно определённого цвета – это и будет наш объект.

Если расписывать в деталях, то делается это так. Сначала переводим полученную с камеры картинку в формат HSV с помощью функции cvtColor. В этом формате легче найти заданный цвет, ведь он определяется всего одной цифрой в интервале от 0 до 179, см. выше.

Затем ищем на картинке интересующий нас интервал цвета в кадре. Дело в том, что тот цвет, который изначально запомнил робот, может меняться в зависимости от освещения и теней, падающих на объект. Кроме того шарик, как его видит камера, покрашен неоднородно: светлее посередине и темнее к краям. Именно поэтому в программе мы используем интервал. Однако интервал не должен быть слишком большим, иначе у нас будет много ошибок.

Интервал ищется с помощью функции inRange. В результате работы функции получается чёрно белая картинка, где белыми точками обозначены точки, цвет которых попал в заданный интервал, а чёрными – все остальные.

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

Вот собственно и всё. У найденного контура я могу узнать центр и размер. И, в зависимости от того, где этот контур, т.е. объект, расположен на картинке, я могу сделать вывод, куда нужно поворачивать камеру и двигать робота.

Для улучшения работы этого алгоритма лучше использовать размытие (функция blur) и поиск окружностей (функция minEnclosingCircle), но они замедляют поиск объектов. Поэтому в коде программы они закомментированы. Вы можете попробовать, как работает программа с ними, просто убрав комментарии.

Режим отладки

С нормальным режимом разобрались, теперь напишу, как работает программа в режиме отладки. Когда вы нажали кнопку «Вниз» при выборе режима – вы запустили режим отладки. В этот момент робот точно так же возьмёт пробу цвета, а затем появится следующая надпись:

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

Откройте его с помощью браузера Chrome или Firefox. Как только вы откроете созданный файл, робот оживёт, а в браузере появится потоковое видео с камеры, где будет обведён найденный контур:

Найденный шарик с помощью библиотеки OpenCV

Картинка, как видите, маленькая. Размером всего 160x120. Поверьте, даже с таким небольшим размером вы почувствуете тормоза. Однако такого размера вполне хватает для отслеживания объекта. В браузере вы можете увеличить масштаб, чтобы в картинку не нужно было вглядываться. Вот как это выглядит в масштабе 200%:

Поиск объекта с помощью OpenCV

Одна красная линия обводит найденный с помощью библиотеки OpenCV контур, а вторая - это окружность, диаметр которой равен наибольшему размеру контура с центром в центре контура.

На экране EV3 в это время пишется следующий текст:

В верхней строке, как вы можете догадаться – радиус найденного объекта, а в нижней строке – режим отладки. Всего их 4: contour, mask, source и none. Если во время отладки вы будете нажимать на кнопку Enter на модуле EV3, вы будете переключать режим отладки. По умолчанию – это contour (контур). В этом режиме отображается видео с камеры, и сверху рисуются линии контура и окружность, про которые написано выше.

Следующий режим – mask. В этом режиме вы увидите результат работы функции inRange библиотеки OpenCV.

Результат поиска интервала цветов функцией inRange

Следующий режим – source – это видео, полученное с камеры без обработки, см. картинку ниже.

Изображение, полученное с веб-камеры и переданное из EV3 в браузер

Режим – none – это режим, в котором картинки в браузер не отправляются. Этот режим работает так, как будто отладки нет.

Итак, я написал все мысли, которые у меня были по поводу эксперимента с отслеживанием объекта с помощью библиотеки OpenCV.

При разработке этого эксперимента я использовал следующие статьи и исходники:

камера Pixy для Lego Mindstorms

Если вы выбирали камеру для робота, то наверняка слышали о Pixy. Это популярная система машинного зрения для Arduino и Raspberry Pi. А теперь и для Lego Mindstorms. 30 сентября Charmed Labs анонсировала новую версию продукта.

Видеокамера Pixy производства Charmed Labs предоставляет простую возможность реализации элементов машинного зрения. Тысячи камер были проданы по всему миру после успешно проведенной компании на Kickstarter в начале 2014 года.

В отличие от большинства камер, Pixy выполняет обработку изображения на своем борту, освобождая мощности микроконтроллера для других задач. Вы можете быстро «научить» Pixy обнаруживать новые объекты почти также просто, как считать сигнал нажатия кнопки. Встроенные в его прошивку алгоритмы способны обнаруживать и отслеживать сотни объектов одновременно.

Стандартная версия Pixy поддерживает многие микроконтроллеры, в том числе популярную платформу Arduino, а также одноплатные компьютеры Raspberry Pi и BeagleBone Black.

Новая видеокамера Pixy LEGO подключается напрямую к контроллеру Lego Mindstorms NXT или EV3 с помощью прилагаемого кабеля и интегрируется в программную среду Lego.

Вы часто хотите, чтобы ваш легоробот догнал мяч или подобрал объект. Но это очень трудно реализовать без правильного датчика. Pixy дает роботу возможность выполнения этих видов задач, потому что видит объекты в окружающей среде,

— говорит президент Charmed Labs Рич Легранд.

Теперь интеграция камеры Pixy с Lego стала проста. Порядок установки описан на wiki-странице проекта. Р анее, чтобы «подружить» легоробота с Pixi CMUcam5, необходимо было преодолеть сложности, в том числе был необходим адаптер UART.

Charmed Labs — небольшая компания, расположенная в городе Остин штата Техас (США), специализирующаяся на предоставлении передовых встраиваемых решений для образовательных целей.

Lego-OpenCV

Давно мечтали подключить к блоку EV3 камеру и подарить легороботу машинное зрение? Установка нового релиза Lejos EV3 0.9.1 подарит вам эту возможность.

Блог проекта Lejos сообщает, что их новый релиз прошивки для EV3 поддерживает мощную библиотеку для обработки изображений OpenCV 2.4, включающую функции распознавания лиц, слежение за объектом и другие.

Lejos — альтернативная прошивка для программируемых блоков Lego. Это виртуальная Java-машина для EV3. Lejos предоставляет возможность использовать объектно-ориентированный язык Java и это открывает бОльшие по сравнению со штатной средой программирования возможности: массивы, рекурсии и прочее. Lejos является open-source проектом.

В отличие от предлагаемого компанией Charmed Labs способа наделения легороботов компьютерным зрением с помощью камеры Pixy, у которой для обработки изображений используется свой процессор, Lejos дарит возможность подключить обычную вэб-камеру к USB-порту программируемого блока EV3. Списка поддерживаемых камер нет, но можно найти некоторую информацию об успешных экспериментах на форуме Lejos.

Кроме того новая версия Lejos позволяет объединить EV3-блоки и другие устройства в сеть PAN (Personal Area Network), позволяя устройствам взаимодействовать друг с другом, подключать дополнительные библиотеки.

Lego — самый популярный робототехнический конструктор, но функции компьютерного зрения в штатном программном обеспечении не реализованы. В состав программного обеспечения для конструкторов некоторых других производителей библиотеки машинного зрения включены. Например, Fischertechnik Robotics TXT Discovery set, ТРИК, у которых камера в комплекте.

В 2015 году на Всероссийской Робототехнической Олимпиаде в Иннополисе в творческой категории было несколько роботов из конструктора Lego Mindstorms, использующих библиотеки компьютерного зрения, однако у всех они исполнялись не на программируемом блоке Lego, а на ноутбуке, а роботы получали сигналы от компьютера уже с результатами программ распознавания образов. Новинка позволяет подключить библиотеку OpenCV к самому Ev3.

UPD 20.11.2015:

Яков Кириленко, директор по развитию ООО «КиберТех Лабс», компании-разработчика конструктора ТРИК, прокомментировал появление компьютерного зрения на Lego Mindstorms:

Кстати, а вы пробовали разобраться, что именно там «поддержали» в лехосе и как? Подсказка: еще долго ждать даже примитивные алгоритмы, но шанс на них есть. Даже NXTCam, скорее всего, удастся полностью заменить, но от opencv придется отказаться.
В Лего (EV3) компьютерного зрения нет, сравниваться не с чем. Ну с нашей высоты полета, хотя о «продуктовых» фичах на основе примитивных алгоритмов можно порассуждать.
На EV3 возможны минимальные алгоритмы (те, что у нас (речь о ТРИКе — прим. ред.) «в поставке» с 2014 г, а в прошивке даже раньше), но с сильным загрублением, с потерей точности. То есть сделать на USB-камере датчик цвета MxN или «датчик линии» можно попробовать, должно получиться.
Есть отдельно NXTCam, интересная вещь, но малопопулярная. Ее время не настало пока, но может и не начаться. К EV3 можно легко подключить смартфон вместо камеры и такие попытки были, а продукта («переходника») пока нет. Железка там простая, но с софтом сложнее. Как вариант, такой продукт (датчик-переходник на телефон) может родить Техникс, договорившись с WRO о новых правилах 2017, в которых бы использование и доработка алгоритмов обработки видео были бы частью задачи.

Upd. 23.06.2016:

Пример использование библиотеки OpenCV на EV3 показал пользователь YouTube Алексей Валуев. На видео продемонстрирован робот, собранный из образовательного набора Lego Mindstorms Education EV3 (арт.45544) и веб-камеры. Робот следит за цветным шариком и выдерживает определенное расстояние до него. К сожалению, микрокомпьютер EV3 с библиотекой OpenCV работает медленно, при обработке изображения идет задержка, тем не менее робота удалось запрограммировать на выполнение интересной учебной задачи с использование библиотеки компьютерного зрения. Опыт использования библиотеки Open CV на EV3 для слежения за объектом описан в статье.

Звезда активна
Звезда активна
Звезда активна
Звезда активна
Звезда активна

Используя конструктор LEGO MINDSTORMS EV3 и веб-камеру, вы сможете провести эксперимент по обнаружению лиц в помещении. Для эксперимента подойдёт любой колёсный робот EV3, который умеет вращаться на месте, и на который вы сможете закрепить веб камеру. Робот будет сканировать помещение, поворачиваясь вокруг, а, увидев лица, будет останавливаться и дёргаться столько раз, сколько лиц увидел.

Обнаружение лица на EV3

Подготовка к эксперименту

Для управления роботом мы будем использовать альтернативную прошивку leJOS. Поэтому первое, что нам необходимо сделать – это подготовить SD-карту. Какую взять SD-карту и как установить на неё leJOS подробно описано в статье «Программируем робота LEGO Mindstorms EV3 на Java». Протестировать работает ли ваша камера с EV3, вы можете с помощью простых примеров, описанных в той же статье в разделе «Использование веб-камеры в leJOS EV3 для захвата изображения». Для обнаружения лиц на кадрах, полученных с камеры, будем использовать библиотеку компьютерного зрения OpenCV, которая появилась в leJOS только в версии 0.9.1. Поэтому нам нужна именно эта версия leJOS.

Теперь что касается робота. Будем считать, что простой колёсный робот у вас уже собран. Я буду использовать своего «Исследователя EV3», собранного из образовательного набора LEGO MINDSTORMS Education EV3 (45544). Вот инструкция для сборки «Исследователя EV3»:

Исследователь EV3

Инструкция для сборки робота исследователя EV3 из базового образовательного набора конструктора LEGO Mindstorms Education EV3 (45544).

В версии 2: рамка закреплена прочнее и не отваливается.

Закрепите камеру на роботе и подключите её к модулю EV3 с помощью USB-кабеля. Как выглядит и работает мой готовый робот, вы можете посмотреть на видео:

Как создать проект в Eclipse и как запустить программу, написано в статье «Программируем робота LEGO Mindstorms EV3 на Java». Поэтому здесь я просто приведу код программы, а ниже дам подробные объяснения.

Описание работы программы

После запуска программы, если всё в порядке, на экране появляются следующие надписи:

Обнаружение лиц с помощью OpenCV

Теперь давайте чуть подробнее поговорим о том, как происходит обнаружение лиц на кадрах, полученных с камеры, в нашей программе. Дело в том, что в библиотеке OpenCV, которую мы используем, есть класс CascadeClassifier (каскадный классификатор), который способен находить на изображении определённые объекты, используя признаки Хаара (Альфред Хаар - венгерский математик) или признаки LBP (Local Binary Pattern). Чтобы каскадный классификатор знал, какие объекты нужно искать его тренируют с помощью нескольких сотен простых изображений целевых объектов (например, лиц или машин) одинакового размера, называемых положительными примерами, и произвольных картинок такого же размера, называемых негативными примерами (подробности читайте в официальной документации здесь и здесь). Но в нашем эксперименте мы не будем заниматься тренировкой, а воспользуемся уже готовыми натренированными каскадными классификаторами.

Готовые настройки каскадных классификаторов вы можете найти в папке data в архиве с библиотекой OpenCV (скачать OpenCV можно здесь). Тут есть настройки для поиска лиц в анфас и в профиль, кошачих мордочек, глаз, автомобильных номеров и др. Я для эксперимента выбрал файл lbpcascade_frontalface.xml для обнаружения лиц в анфас, но ничего не мешает вам провести свои эксперименты и поискать, например, лица в профиль или кошачьи мордочки. Для этого закачайте в модуль EV3 в папку с программами нужный файл с помощью центра управления (EV3 Control Center) и поменяйте в программе строчку «String classifierFileName = "lbpcascade_frontalface.xml";» указав здесь необходимое имя файла.

Ещё вам нужно знать, что тренировка и определение объектов с помощью признаков LBP происходит намного быстрее, чем с помощью признаков Хаар.

Итак, после того как мы создали экземпляр класса CascadeClassifier, загрузив настройки из файла lbpcascade_frontalface.xml, нам достаточно вызывать функцию detectMultiScale для каждого изображения полученного с камеры, чтобы найти на нём лица. А дальше уже мы можем по-разному управлять нашим роботом в зависимости от результата.

Кстати, чтобы хоть как-то повысить скорость получения изображения с камеры, я сделал это в отдельном потоке. Так работает немного быстрее. Но, если вы хотите получать видео в основном потоке, откомментируйте строку

и закомментируйте строки

Режим отладки

Теперь расскажу о режиме отладки. Чтобы в него перейти, нужно после запуска программы нажать клавишу вверх на модуле EV3. После этого на экране EV3 появится следующая надпись:

После этого вы можете подключиться к EV3 с помощью вашего браузера. Сначала убедитесь, что ваш EV3 подключен к компьютеру через Bluetooth. Затем сделайте текстовый файл с расширением .html, напишите в нём следующий текст

и откройте этот файл в браузере Chrome, Firefox или Microsoft Edge. Как только вы это сделаете, робот начнёт поворачиваться на месте, а в браузере будет отображаться видео, полученное с камеры. Картинка маленькая, но этого вполне достаточно, чтобы обнаружить на ней лицо.

Обнаружение лица на EV3

На экране в это время будет написано следующее:

Как вы уже поняли, здесь написано количество найденных лиц и режим отладки. Нажимая на центральную кнопку модуля EV3, вы можете переключать режим отладки. Кроме режима faces, в котором отображаются картинка с камеры и рамки, вокруг найденных лиц, есть ещё режимы gray, source и none. В режиме gray вы увидите картинку, переведённую в оттенки серого, а именно на картинке такого формата библиотека OpenCV ищет объекты. В режиме source – картинка, полученная с камеры без изменений. В режиме none – изображение не передаётся в браузер.

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

Yes! We are now carrying CMUcam 5, or know as Pixy! It can detect purple dinosaur :) The camera is designed to be added onto robots outfitted. But, the question is: How to get Lego plus Pixy linked together? Welcome to this How-to!


Mindstorms Wires Explained

Let's begin by exploring all the nitty-gritty details of the standard Mindstorms wire. Lego uses semi-proprietary wires RJ12 variant in its Mindstorms’ Intelligent Brick access and connections methods.

Mindstorms wires are essentially proprietary RJ12 connectors with off-center tabs:


Inside the Mindstorms Wire


  1. The blue wire is the SDA (serial data) wire, one-half of a two-wire data transfer protocol called I2C. EV3 can transmit sensor data and commands through the I2C bus;
  2. Yellow is the SCL (serial clock) wire, the other half of the protocol;
  3. Green is power, typically delivering either 3.3 or 5V from the EV3' battery pack. You can use this wire to power electronics circuitry and add-on modules;
  4. Red is ground. Creating a circuit with this ground and the power pin yields 5V;
  5. Black is also ground. A circuit with this ground and the power pin yields 3.3v;
  6. White is analog, transmitting analog sensor signal back to the EV3 Intelligent Brick.

Now we need to understand the Pixy cradle and servos pinout.

Pixy can be interfaced to several protocols — I2C, Serial, and SPI — plus it controls two servos for pan-tilt functionality.

To connect Pixy with Lego we will need it: Ribbon Crimp Connector — 10-pin (2x5, Female)


And here is how to connect Pixy and Lego:





The video — Making homebrewed Cable Lego x Pixy




Running Pixy PID code

Here is the working chase code provided by Pixy’s Charmed Lab:


Run PixyMon to Configure Pixy For Lego Capability


Are you Curious about Pixy?

This latest CMUcam version of the embedded camera is an image sensor with a powerful processor that you can program by only send the information you’re looking for so your microcontroller isn’t overwhelmed by data from the image sensor. The Pixy CMUCam also exports its information in a variety of useful ways — UART serial, SPI, I2C, digital out, or analog out — so your microcontroller can communicate easily while still doing other tasks. It’s so unobtrusive that you can even hook up multiple Pixy CMUCams to one microcontroller! Superb!

The Pixy CMUCam5 also uses hue and saturation as its primary means of image detection — rather than the normal RGB. This means that lighting or exposure won’t affect the Pixy CMUCam’s detection of an item — which is a frustrating problem with many image sensors. It’s also a vast improvement over previous versions of the Pixy CMUCam, adding increased flexibility when it comes to lighting and exposure changes.

It can also remember seven different color signatures, find hundreds of objects at the same time, and is super fast — processing at 50 frames a second.

Finally, the Pixy CMUCam is also teachable so you can set it up to only send you images that you’ve specifically told it to look for. It’s easy and fast and has an open source application called PixyMon.

Each Pixy CMUcam5 Sensor comes with a 6-pin-to-10-pin IDC cable and mounting tabs and screws.

Читайте также: