Сегодня был последний (а для меня и первый) день
летней школы конференции
GraphiCon. Конференцию в этом году организует
наша лаборатория, и я в ней участвую в качестве волонтёра (на самом деле, я ещё и соавтор одной из статей :).
Я послушал пару докладов, но больше всего меня заинтересовал мастер-класс от
лаборатории "Сенсорика", посвящённый управлению мобильными роботами. Первая часть была скучной, пока они рассказывали про свой проект, что они используют роботов в образовательных целях, и поэтому так важно управлять роботами через Интернет. Например, студенты во Владивостоке могут управлять роботом в Москве, следя за его действиями через видеотрансляцию.
Но потом начало становиться веселее, когда они стали раскрывать API. Расскажу, что представляет собой робот: это жёлтый чемодан с 2 управляющими колёсами и ещё одним для устойчивости. В чемодане лежит ноут и ещё какое-то железо. Также имеется пара сенсоров. Я так и не понял, что они собой представляют - но похожи на простейшие лазерные сканеры. У ноута есть свой IP-адрес, на который можно слать команды через Python-интерфейс. Соответственно, пользователь может это делать в режиме командной строки.
Сначала рассказали, как получать данные с сенсоров, но это не особо интересно. Но вот когда показали API для движения колёс, стало веселее. Тут разумно сказать, почему у робота два управляющих колеса. Это довольно простая система: если двигать их с одинаковыми скоростями, то робот поедет вперёд; если с одинаковыми по модулю, но противоположными по знаку - он будет вертеться на месте. Промежуточные положения дают другие траектории. Соответственно, есть команды типа (названия не помню) robot.rotate{Left,Right}Wheel(angle).
В зале было около 30 компов, и сначала призывали народ управлять роботом по очереди. Но со временем всё перемешалось, и большинство забило, поэтому бороться за "руль" стали несколько групп. Мы довольно быстро сообразили написать следующее (за синтаксис не ручаюсь, я плохой питонист):
while 1: robot.rotateLeftWheel(100); robot.rotateRightWheel(-100);
что должно было заставить робот бесконечно вращаться, и это нам, видимо, удалось.
Постепенно стала поступать информация о том, как это дело реализовано. Оказывается, все команды скидываются в очередь. Если очередь слишком длинная, то новые команды тупо дискардятся. Таким образом, мы с нашим циклом забили очередь, и остальные, видимо, в неё могли "втиснуться" лишь с нулевой вероятностью.
После нескольких экспериментов с функцией random, мы решили реализовать мою идею с "качелями": чтобы робот ездил туда-сюда. Попутно мы также узнали, что если команды поступают роботу слишком часто, то он как-то блокируется, поэтому пришлось также вставить задержку:
while 1: robot.rotateLeftWheel(100*sin(t)); robot.rotateRightWheel(100*sin(t)); t += 0.1; sleep(100);
Но мастер-класс уже заканчивался; возможно, наши команды вконец забили очередь, или мы не угадали с задержками и масштабом, или нужно было инициализировать переменную, но качелей мы так и не увидели. Зато получили интересный опыт программирования роботов, которое, кстати, иногда признаётся родительской задачей компьютерного зрения.