Якщо останні півроку ви не просиділи в печері, то однозначно чули про найгучнішу подію у кінематографі останнього часу — прем’єру сьомого епізоду «Зоряні війни». Однак «Пробудження Сили» відбулося не тільки у фільмі, але й у наших головах. Ми в ELEKS багато думали, як би знайти суперсилу, а потім зрозуміли, що насправді нам просто-напросто потрібно було поєднати Kinect 2.0 для Windows із Sphero 2.0. І пересувати предмети за допомогою телепатії стало можливо (ну майже).
Sphero — це невеличкий, розміром з бейсбольний м’яч, керований через bluetooth робот. На його борту — акселерометр, магнітометр, гіроскоп, LED підсвітка, bluetooth-модуль і мотори, які забезпечують його рух. Існує багато Android/iOS програм для керування Sphero. Його можна використовувати не лише як цікаву іграшку, але і як маніпулятор, оскільки є можливість програмного доступу до його датчиків.
Kinect — безконтактний сенсорний ігровий контролер, спочатку представлений для консолі Xbox 360, і значно пізніше для ПК під керуванням ОС Windows. Розроблений фірмою Microsoft. Заснований на додаванні периферійного пристрою до гральної консолі Xbox 360, Kinect дозволяє користувачеві взаємодіяти з нею без допомоги контактного ігрового контролера через усні команди, пози тіла, об’єкти або малюнки.
Використання Kinect
Ви вже знаєте, що Kinect — це дуже круто. Серйозно, він може зробити будь-кого трішки Дартом Вейдером. Але навчитися працювати з ним — ось у чому полягає справжня сила. У Kinect 2.0 передбачене використання лише USB 3.0, оскільки він надсилає таку кількість даних, яку USB 2.0 витримати не здатен. Відповідно, це вимагає також DirectX 11 та драйверів, які підтримують Windows 8 і пізніші версії. Але коли усіх вимог дотримано, до ваших послуг 20 Mb/sec Color data, 13 Mb/sec Depth data, 13 Mb/sec Infrared data, 32 Kb/sec audio та багато інших цікавих можливостей. Круто, правда? Окрім цього, Kinect SDK дозволяє відслідковувати скелети одразу шести людей. Усе це свідчить про те, що Kinect — ідеальний сенсор для створення взаємодії між людиною і технологією.
Чому Sphero? Очевидно, що поява BB-8дуже надихнула нашу команду. І оскільки BB-8 був створений на основі Sphero, який на той час вже був у нас на озброєнні, для нашого експерименту ми обрали саме цю технологію. Ми використали неофіційний .NET SDK, який дозволив нам створити кастомізовану систему контролю Sphero, використовуючи Kinect та Kinect SDK для Windows.
Функціонал Sphero .NET SDK доволі обмежений. Для того, щоб змусити Sphero рухатись в потрібному напрямку, потрібно задати йому вектор руху, що робиться через кут і швидкість. Кінцеві кординати Sphero отримуються з Kinect завдяки JediGestureRecognizer — класу, який ми створили для відслідковування позиції, куди вказує рука «джедая». Для визначення вектора руху Sphero до кінцевих координат, виконується його калькуляція на основі різниць поточної і кінцевої координат. То як же перемістити Sphero з його поточної точки на іншу?
Погляньмо:
Відповідно до ґайдлайнів Microsoft про взаємодію з Kinect, перша річ, яку ви повинні зробити — це визначити фізичну зону взаємодії (PHIZ — physical human interaction zone). Найчастіше Kinect із Windows використовують тоді, коли хочуть створити взаємодію з екраном, відповідно PHIZ створюють навпроти користувача.
Спершу ми думали створити квадратний простір перед людиною і спроектувати його на підлогу. Таким чином, коли людина рухає рукою в повітрі, Sphero відтворює цей рух на підлозі. Але цей концепт здавався нам не дуже природнім, адже коли ви хочете щось пересунути (навіть якщо телепатично), ви як правило, фокусуєте свою руку на предметі, який хочете перемістити.
Отже ми вирішили розташувати PHIZ на підлозі, і це виявилося легше, ніж ми очікували. За основні точки ми взяли голову людини та її активну руку, і за допомогою прямої, що пролягає через точку голови і точку активної руки, ми вирахували точку, спроектовану на підлогу.
Трошки математики
Точка В (голова) має координати (0.26, 1.90, 3.20), лінія М (активна рука) має координати (0.30, 1.40, 2.80). Kinect надсилає координати в метрах. Вісь Y спрямована по вертикалі, вісь Z спрямована від Kinect і показує відстань до об’єкту, розташованого перед ним. Ми повинні знайти спроектовану точку С. С має Y=0.
Щоби вирішити це завдання, ми звернулися до тригонометрії:
Ми використали формулу тангенсу.
Звідси, алгоритм такий:
1. Знайти спроектовану точку для осі ZY згідно вказівок, поданих нижче.
2. Знайти спроектовану точку для осі XZ згідно вказівок, поданих нижче.
Як знайти спроектовану точку з трикутника:
Маючи ці результати, ви можете легко знайти координати спроектованої на підлозі точки.
Далі ми повинні примусити Sphero котитись до цієї точки. У нас вже є обчислений кут і відстань, яку має пройти Sphero. Так само нам дано швидкість переміщення Sphero — 2 м/с. Ми можемо змінити коефіцієнт швидкості, отже, якщо ви встановите коефіцієнт, рівний 0.5, реальна швидкість Sphero буде 1 м/с.
Sphero .NET SDK має функцію, яка дозволяє надсилати команду «Roll (angle, velocity)», що примушує Sphero котитись в цьому напрямку, допоки ви не надішлете команду «Roll(angle, 0)». Для більшої точності управління кулею, ми створили таймер, який дозволяє надсилати команди ґаджету з вказаною частотою.
Щоби краще контролювати Sphero, ми дозволили користувачу змінювати кінцеву точку під час руху. Для цього ми поділили відстань (1) від точки А до точки В на маленькі ітераційні проміжки (dl) — відстані, які Sphero долає між спрацюваннями таймера, не змінюючи напрямку. Під час кожного спрацювання таймера відбувається рекалькуляція кінцевої точки, а також наступної точки, куди докотисься Sphero до наступного спрацювання таймера. Отже, якщо кінцева точка (В) змінюється під час руху Sphero, ґаджет змінює свій напрямок до нової проміжної точки, пов’язаної з новою кінцевою точкою (В’).
Як це виглядає у коді:
//Sphero is in next point Point currentPosition = _nextIntermediaryPoint; SetCurrentPosition(currentPosition); Point destinationPosition = GetDestinationPosition(); //recalculate the Sphero angle (0.0 <= a <= 359.0): double spheroAngle = GetSpheroAngle(currentPosition, destinationPosition); //recalculate distance double realDistance = GetDistance(currentPosition, destinationPosition); if (realDistance >= _iterationDistance) { //Save recalculated sphero angle (for correct stop) _lastAngle = (int)spheroAngle; //Move with recalculated values Roll(_lastAngle, (int)_spheroSpeed); //Recalculate real angle (-180.0 < a <= 180.0) double realAngle = GetAngle(currentPosition, destinationPosition); //Recalculate next intermediary point Point nextPoint = CalculateNextIterationPosition(currentPosition, realAngle, _iterationDistance); SetNextIterationPosition(nextPoint); } else { //Sphero near or on destination point Roll(_lastAngle, 0); }
Як ми відслідковуємо силу
Щоби розпізнавати жести рук, ми використали Body data. Зважаючи на те, що алгоритми, які зчитують людський скелет, були далекими від ідеалу, ми повинні були відфільтровувати потрібні нам дані від шуму, відповідно до формули:
FrameRecived — HandTrackedFrames<= Epsilon
FrameRecived — кількість кадрів, які ми охопили.
HandTrackedFrames — кількість кадрів, коли долоня була відкрита.
Epsilon — стала, що визначає допустиму кількість шуму.
Ця формула допомагає визначити, чи людина тримає відкриту долоню перед собою, бо саме цей жест забезпечує переміщення Sphero. Після ряду тестів ми визначили, що Epsilon дорівнює 3, а кількість кадрів до опрацювання — 8. Це означає, що якщо ми відстежили жест відкритої руки щонайменше на 5 кадрах — сила активна.
Логіку трекання можна знайти тут.
Сило, прибудь!
Для того, аби випробувати свої нові здібності, потрібно створити належні умови. Перш за все облаштуйте сцену дій:
1. Покласти Sphero на підлогу;
2. Встановити коректний кут (задній вогник повинен бути розміщений протилежно до Kinect’у);
3. Встановити швидкість.
Займіть своє місце на сцені, як молодий падаван. Відчуйте силу в собі. Розкрийте свою долоню і сфокусуйте її (а також свої думки) на Sphero. А тепер телепатично переміщайте Sphero за допомогою руки. Для того, щоби зупинити Sphero, стисніть кулак. Якщо ви відчуєте силу знову, перейдіть на інше місце і продовжуйте переміщати Sphero.
Концепт ви можете знайти на GitHub. Нехай буде з вами сила!
Стаття написана у свівавторстві з Олександром Кудіновим. Дякуємо Марті Чавазі за адаптацію з англійської.