Вся наша команда с нетерпением ожидала доставки долгожданного HoloLens, его пришлось заказывать через знакомых за океаном и держать кулаки, чтоб таможня не заинтересовалось пока не сертифицированным для Европы WiFi. Наконец, в начале сентября, к нам попал заветный овальный футляр. Открываем, заряжаем, надеваем на голову — вот они, ворота в виртуальный мир. Правда у ворот просят пропуск — нужно авторизоваться паролем от Microsoft. Да-да, тем самым, криптостойко длинным, со специальными символами и в разных регистрах. Пока наш первопроходец виртуальных миров, щипая воздух жестом air-tap, набивал на плавающей в пространстве клавиатуре что-то типа Opa, opa #00FF00 ograd@!, у остальных было время призадуматься о том, как же мы этим 3D собираемся управлять.
Проблема
На десктопах, и с некоторыми оговорками на планшетах и мобильниках, у нас есть два типа устройств ввода. Мышь — можно указать любой из миллиона пикселей. Быстро, но неточно. Клавиатура — нажать одну или несколько кнопок из гораздо меньшего ассортимента (< 100), зато работает очень надёжно и даже вслепую. Спецкнопки вроде Escape нажимаются практически без ошибок, не перепутаешь.
У HoloLens аналогом мыши является висящая перед носом точка курсора. Щипок air-tap не столь удобен как клик мышиной кнопки, но помогает прилагаемый однокнопочный контроллер Clicker. Легко выбрать желаемую проецируемую кнопку и дать команду “поехали”, но вот уже с отменой действия есть серьёзные проблемы — катастрофически не хватает Escape. Например, в Galaxy Explorer легко показать на планету и вызвать детальную информацию, но вот попытки вернуться к карте галактики или просто изменить масштаб сильно напоминают пляски с бубном, особенно если смотреть на человека в очках со стороны.
Команды Microsoft рекомендует отдавать голосом, через Cortana, однако вы пробовали делать это хотя-бы впятером в одной комнате? Привет кубиклы и Open Space. При использовании у работающего конвейера, как в нашем случае, мешает внешний шум. Кроме того, глядя на экран, пользователь с мышкой сразу видит доступные кнопки и гиперссылки, а на физической клавиатуре возможные варианты выбора даже можно потрогать. Но вот передо мной микрофон, как, глядя на него, понять какие команды поддерживаются? Не ясно даже на каком языке с ним говорить, не говоря уж о том, что команда у нас интернациональная и родной язык и произношение у каждого свои.
Идея
Так родилась идея прикрутить к HoloLens нунчак от Wii. Две качественные, аппаратные кнопки с антидребезгом, джойстик, плюс, в перспективе, возможность задействовать акселерометр. Устройство компактное, мобильное, прочное и дешёвое. Тем более, что Wii remote опознаётся по Bluetooth как HID устройство ввода, что же может быть проще?
Тут ждало первое разочарование — для подключения контроллер от Nintendo просит PIN, который является записанным наоборот адресом устройства. Например, мой контроллер имеет адрес 00:1E:A9:5D:A6:BC и нужно как-то ввести строку из 5 символов с кодами BC,A6,5D,A9,1E, и в конце завершающий 00. Может кому-то и повезло с адресом контроллера, но у меня все имеющиеся адреса попадали в диапазон непечатных символов.
Нунчак выдаёт данные по шине I2C и с микроконтроллера легко опросить состояние кнопок и акселерометра. Решил передавать данные на HoloLens через Bluefruit EZ-Key — это готовый контроллер HID клавиатуры, способный отсылать произвольную комбинацию до 6-ти одновременно нажатых клавиш.
Получилась такая архитектура:
Ардуино, как же без неё
Логики от микроконтроллера требуется минимум — читай себе данные с I2C, да посылай соответсвующий USB HID код из таблицы. Для чтения нашлась готовая библиотека для Arduino, его и взял, конкретно выбор пал на миниатюрную Arduino Pro Mini на 8MHz с питанием 3,3 В. У нас не массовое производство и для прототипа пойдёт и цена в 10 долларов, даже если с той же работой справится и микроконтроллер за пару копеек.
Собираем на макетке прототип, запускаем на HoloLens Internet Explorer как простейшую замену Notepad и… ура! Заработала! При нажатии кнопок в адресной строке браузера появляются буквы!
Первый COM комом
При отладке кода для Ардуино наступил на грабли — неожиданно Bluefruit перестала отсылать коды, хотя Bluetooth был в порядке и устройство по-прежнему определялось HoloLens как клавиатура. Arduino Mini программируется FTDI-кабелем или другой Ардуино, и при очередной переделке прототипа на Bluefruit не подавалось питание. Arduino же, получила ток с компьютера через кабель программатора, и запустившаяся программа начала честно передавать коды кнопок. 3,3 вольта приложенные к входу обесточенной платы выжгли входной RX-пин последовательного интерфейса на стороне Bluetooth-модуля. И ведь читал же когда-то на Easyelectronics статью почему так делать нельзя!
К счастью, после замены Bluefruit на новую, дальше пошло как по маслу. Схема соединения очень простая — никаких активных элементов, нужно только соединить пины друг с другом.
Для питания оставил кабель нунчака и припаял штекер USB-A. Стабилизатор Arduino преобразует 5 вольт с USB в 3,3, которые питают логику нунчака и Bluefruit EZ-Key. На конец кабеля вынес кнопку Pair от Bluetooth. Что необычно, по инструкции эту кнопку надо соединять с шиной питания, а не с землёй, как все остальные кнопки на Bluefruit.
Программирование и сборка
Исполняемая на Arduino программа очень проста — 20 раз в секунду опрашивать нажатые кнопки, складывать их USB HID коды в буфер (возможны несколько нажатий одновременно) и отсылать по последовательному интерфейсу на Bluetooth-модуль. Единственная особенность — важно правильно указать тип Arduino в IDE. Моя модель работает на 8 MHz, а не на стандартных для Ардуино 16-ти, так что сперва последовательный интерфейс работал на половинной скорости и отдавал данные на 4800 бод вместо ожидаемых 9200.
Все исходники и прочие файлы выложены под MIT-лицензией на GitHub.
Arduino Mini и Bluefroot имеют похожие размеры, и для компактности я спаял их вместе вот в такой бутерброд:
Для изоляции между платами сделана П-образная вставка из пластика, она же защищает экран Bluetooth-модуля от сдавливания. Обрезав кабель, подпаялся к логике нунчака.
В целом получилась достаточно компактная конструкция, даже поместилась внутрь родного корпуса. Пришлось лишь срезать некоторые рёбра жёсткости.
Вся конструкция в сборе. На конце кабеля штекер питания и кнопка соединения Bluetooth.
Unity
С точки зрения HoloLens мой контроллер — простая клавиатура, поддержка которой встроена с начала времён. Не нужно ни внешних зависимостей, ни сторонних библиотек.
Направления джойстика превращаются в ASDW, кнопка «Z» в Enter, а «C» — в Escape.
if (UnityEngine.Input.GetKey(KeyCode.A))
{
// Joystick left
...
}
if (UnityEngine.Input.GetKey(KeyCode.D))
{
// Joystick right
...
}
Такой код очень удобно отлаживать запустив эмулятор HoloLens на десктопе, можно просто нажимать кнопки на клавиатуре и, с точки зрения приложения, нет никакой разницы.
В результае получилось вот что:
Видео снято прямо с очков через встроенную функцию Mixed Reality Capture. Исходники демки тоже на Github.
Что дальше?
Power Bank легко положить в карман и питание от USB не сильно снижает мобильность, однако хочется полностью автономного устройства. Думаю прикрутить литий-ионную банку 18650 и контроллер зарядки от Micro-USB. На Ардуино можно подавать любое напряжение от 3,3 до 8 вольт, так что дополнительная стабилизация не понадобится. Увы, в родной корпус аккумулятор уже не поместится, придётся печатать собственный на 3D-принтере.
В нунчаке есть ещё акселерометр, который у меня пока не задействован. В принципе, с его помощью можно сымитировать мышку, но мы пока не придумали как это толково применить. HoloLens планируется использовать не сидя за столом в спокойном офисе, а на ходу и в шумном складе. У пользователя не получится держать горизонтально руку, точными движениями наклоняя контроллер, а вот чётко распознаваемые нажатия кнопок — самое то.
Может кто-то гениальный изобретёт подходящую для очков систему команд и жестов, но пока что управление клавиатурой и мышкой это то, что хорошо понимают пользователи и хорошо умеют программировать разработчики.
На форуме поддержки народ требует новых жестов и зрелищ, посмотрим что ещё наизобретает Microsoft.
Автор: commanderxo