воскресенье, 17 сентября 2017 г.

НейроКачели

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


Наверное все мы в детстве любили качаться на качелях. Как вы думаете, если ребенка впервые посадить на качели и не показать ему как на них раскачиваться (и не давать соответственно подсмотреть как это делают другие), получится у него их раскачать, сохранять и контролировать скорость раскачивания? В его мозге нет устойчивых взаимосвязей и образов того как ему это сделать. Он начнет пробовать совершать произвольные действия, если качели начнут раскачиваться в мозг пойдет визуальная и вестибулярная обратная связь и по тем действиям, которые он только что предпринимал, начнут формироваться новые нейронные цепочки, связанные с "раскачать качели". Если какие то действия наоборот начнут тормозить раскачавшиеся качели, например ребенок отклонился не в ту сторону - он "запомнит" что так делать не нужно, соответствующие связи будут ослаблены или созданы новые.
Похожим образом работает и искусственная нейросеть, которую мы создадим в нашем сегодняшнем проекте.
Для начала соберем конструкцию. Качели мы построили на базе LEGO Mindstorms EV3, использовав несколько дополнительных деталей из ресурсных наборов. Инструкцию по сборке наиболее сложной части конструкции -  качающихся человечков - в формате LEGO Digital Designer вы можете скачать по ссылке. Остальную часть качелей каждый без труда сможет достроить из тех деталей, которые будут у него под рукой.


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

Посмотрим на качели сбоку. изначально человечки "не знают", в какую сторону им нужно отклоняться (влево или вправо) чтобы качели начали раскачиваться. Хороший способ объяснять вероятности их наклона в ту или иную сторону  используя терминологию спичечных коробков и камушков черного и белого цвета. Пусть у нас есть два коробка, это два нейрона нашей нейронной сети. в каждом из них в случае необученной сети, лежит по 1 камушка каждого цвета. Таким образом  вытащить камушек белого и черного цвета случайным образом можно с вероятностью 50%, соответственно не обученная сеть с равной вероятностью будет отклонять человечков влево и вправо в любой ситуации.
Первый коробок соответствует состоянию когда качели качаются влево, второй - вправо. Если "вытащили" белый камень, человечкам нужно отклониться влево, если черный - вправо. Камень после того как мы его вытащили помещается на место, где он и был.

Понятно, что в самом начале человечки будут дергаться туда-сюда хаотично. Введем блок самообучения. Качество обучения будем оценивать до достигнутой качелями средней скорости без учета знака, по данным гироскопа. Если скорость растет - предпринятая попытка раскачать качели верная, падает - "человечки" ошиблись.

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

В процессе обучения возможна интересная ситуация - неподвижные качели можно раскачать даже неправильными движениями, но только до какого-то предела, если попытки предпринимать и дальше, то они наоборот замедлят раскачивание. В реальной работе робота ситуация действительно проявляется довольно часто, робот раскачивается до какого-то предела (небольшого), но дальше процесс не идет. Дальнейшие попытки раскачать качели приводят к их полной остановке и далее процесс обучение начинается снова, уже в "верном" направлении. И заметьте, это все без вмешательства человека - вполне разумная машина!


Программировать качели мы будем на Python.  Давайте посмотрим код:

# импортируем модуль для работы с железом EV3
from ev3dev.ev3 import *
# импортируем модуль математики
from math import *
# импортируем модуль для работы со временем
from time import *
# импортируем модуль генератора случайных чисел
from random import random
# импортируем модуль многопоточности
import threading

# начальная скорость моторов ("человечков")
speedB = 0
speedC = 0

# текущая средняя скорость движения качелей
moving_average = 0
# предыдущая средняя скорость движения качелей
moving_average_old = 0

# Позиция человечков -100..100
pos = 0

# направление движения качелей
state_gyro = 0

# описание нейрона сети
class brain():
    def __init__(self):
        self.Black = 1
        self.White = 1

# создаем пару нейронов
BrainLeft = brain()
BrainRight = brain()

# объект для отслеживания кнопок на блоке
btn = Button()

# объекты для моторов
B = LargeMotor('outB')
C = LargeMotor('outC')

# объект для работы с гироскопом
gyro = GyroSensor("in4")

# устраняем дрейф гироскопа и ставим его в режим измерения скорости
gyro.mode = "GYRO-RATE"
gyro.mode = "GYRO-ANG"
gyro.mode = "GYRO-RATE"

# человечков - в исходную позицию sleep(1)
B.run_forever(speed_sp=80)
C.run_forever(speed_sp=80)
sleep(3)

B.stop(stop_action="brake")
C.stop(stop_action="brake")
sleep(1)

B.reset()
C.reset()

B.run_to_rel_pos(position_sp=-120, speed_sp=80)
C.run_to_rel_pos(position_sp=-120, speed_sp=80)
while any(C.state): sleep(0.1)

B.stop(stop_action="brake")
C.stop(stop_action="brake")

sleep(1)
B.reset()
C.reset()

# готов к работе!
Sound.speak('Ready').wait()

stop = False

# П-регулятор для управления человечками
def reg():
    while not stop:
        speedB = ((-1*pos)-B.position)*8
        speedC = (pos-C.position)*8

        if(speedB > 900): speedB = 900
        if(speedB < -900): speedB = -900
        if(speedC > 900): speedC = 900
        if(speedC < -900): speedC = -900

        B.run_forever(speed_sp=speedB)
        C.run_forever(speed_sp=speedC)

        sleep(0.01)

# Запускаем регулятор в параллельном потоке
t = threading.Thread(target=reg)
t.daemon = True
t.start()

# Максимальная достигнутая скорость
max_speed = 0

while not stop:

    # вылет по кнопке "назад" на блоке     
    stop = btn.backspace
    
    # скорость по показаниям гироскопа
    state_gyro_speed = gyro.value()
        
    if(state_gyro_speed != 0): 
        # текущее направление движения качелей
        state_gyro = state_gyro_speed/abs(state_gyro_speed)
        if(state_gyro > 0):
            # если влево, и вытащили черный камень
            if(random() <= (BrainLeft.Black/(BrainLeft.Black + BrainLeft.White))): pos = -100
            # если белый 
            else: pos = 100
        else:
            # если вправо, и вытащили черный камень
            if(random() <= (BrainRight.Black/(BrainRight.Black + BrainRight.White))): pos = -100
            # если белый
            else: pos = 100
            
    moving_average_old = moving_average
       
    # ждем перед оценкой
    sleep(0.25)

    moving_average = abs(state_gyro_speed)*0.1 + moving_average*0.9

    if(state_gyro > 0):
        # если скорость не упала при движении влево
        if(moving_average >= moving_average_old): 
            if(pos<0): BrainLeft.Black += 1
            else: BrainLeft.White += 1
        else:
            # если скорость упала при движении влево
            if(pos<0 and BrainLeft.Black > 1): BrainLeft.Black -= 1
            elif(pos>0 and BrainLeft.White > 1): BrainLeft.White -= 1

    elif(state_gyro < 0):
        # если скорость не упала при движении вправо
        if(moving_average >= moving_average_old): 
            if(pos<0): BrainRight.Black += 1
            else: BrainRight.White += 1
        else:
        # если скорость упала при движении вправо
            if(pos<0 and BrainRight.Black > 1): BrainRight.Black -= 1
            elif(pos>0 and BrainRight.White > 1): BrainRight.White -= 1
    # выводим состояние нейронной сети     print("[[ " + str(BrainLeft.Black) + ", " + str(BrainLeft.White) + "][ " + str(BrainRight.Black) + ", " + str(BrainRight.White) + "]]",moving_average)

    # если скорость выросла на 25, фиксируем новый рекорд    
    if moving_average > max_speed + 25:
        print("[[ " + str(BrainLeft.Black) + ", " + str(BrainLeft.White) + "][ " + str(BrainRight.Black) + ", " + str(BrainRight.White) + "]]",moving_average)
        max_speed = moving_average
        # если скорость выросла до 200 - обучение завершено
        if max_speed < 200:
            Sound.speak('New Record')
        else:
            Sound.speak('Learning Complete')

Sound.beep().wait() 
B.stop(stop_action="brake")
C.stop(stop_action="brake")

# завершение работы
Sound.speak('Stop').wait()


print("[[ " + str(BrainLeft.Black) + ", " + str(BrainLeft.White) + "][ " + str(BrainRight.Black) + ", " + str(BrainRight.White) + "]]")

пятница, 7 июля 2017 г.

Немного о футболе роботов WRO gen.III. Часть 5

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


Давайте проследим эволюцию решений, которые нами были использованы с тех пор, как мы начали заниматься футболом роботов:

2014 год:

В этом году мы еще не участвовали в соревнованиях в данной категории, вели подготовительные работы, изучали доступные материалы и экспериментировали.
  • Первая версия нападающего с дриблингом и мощной пиналкой была собрана по мотивам робота команды "Омега", вскоре после этого дриблинг был запрещен и конструкция стала не актуальной.

2015 год:
  • Ориентация на поле с использованием датчика освещенности (поля в те времена были еще с цветными зонами)
  • Построение кратчайшей траектории объезда мяча, с учетом положения на поле
  • Выбор направления удара из 5 возможных (3 цветных поля, 2 белых)
  • Контроль застревания "по компасу"

2016 год:
  • Ориентация на поле с использованием ультразвукового датчика
  • Построение кратчайшей траектории объезда мяча, с учетом положения на поле, наличия бортов и "скатов"
  • Выбор направления удара из 9 возможных (визуально поле делим на 9 зон, матрица 3x3, из каждой зоны свое направление удара по воротам)
  • Контроль застревания "по компасу" и по наличию мяча
  • Взаимодействие роботов с использованием Bluetooth, роботы обмениваются информацией о том, в какой зоне сейчас мяч

2017 год:
  • Ориентация на поле с использованием ультразвукового датчика, энкодеров, датчика освещенности. Робот теперь знает где он с точностью 1-2 см по обоим координатным осям. Накопление информации о перемещениях робота и мяча для использования при построении маршрутов и маневров
  • Пересчет неравномерного распределения показаний компаса в идеальное для построения модели и расчетов в идеальной системе координат
  • Помехоустойчикое чтение датчиков
  • Определение направления на мяч "в градусах". Определение расстояния до мяча с точностью до 3-5 см
  • Построение кратчайшей траектории объезда мяча, с учетом положения на поле, наличия бортов и "скатов", пометки о возможных помехах на пути по факту застревания с корректировкой траектории
  • Выбор направления удара из 180 возможных, направление удара рассчитывается "на лету" с точностью 3-4 градуса в момент захода на мяч и учитывается при построении траектории движения к нему
  • Контроль застревания "по компасу", по наличию мяча, по наличию препятствий, по нагрузке на моторы
  • Взаимодействие роботов с использованием Bluetooth, роботы обмениваются информацией о координатах мяча на поле
  • Повышающий редуктор у нападающего, линейная скорость движения выше в 2 раза
  • Мощная "пиналка" у нападающего
  • Гибкое управление скоростью движения, плавные старты и остановы
  • Генерация роботами в процессе работы лог-файлов в формате srt-субтитров для возможности просмотра поверх снятого видео для анализа и отладки

Мы рассматриваем данные состязания в первую очередь как совокупность отличных задачек, в которых можно применить те навыки, которые были получены командой при работе над хоббийными проектами. Например, работа над такими роботами как NAVIDOZ3R и LEGO Pong позволила нам применить для локализации роботов полученные знания в области тригонометрии, которую до сих пор в школе пока не изучали.


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

Возможностей платформы NXT мы до сих пор не исчерпали, разве что памяти для сложных вычислений стало не хватать. Интересной находкой, реально дающей колоссальные возможности, стало использование приоритезации задач (процессов). Неприятной обнаруженной особенностью - необходимость работы с мьютексами при разделении "железа" между процессами. Почти все команды-соперники перешли на EV3, роботы на основе NXT встречаются все реже. Похоже перехода не избежать и нам.


В этом году уровень команд заметно вырос, игра стала более стремительной, не оставляющей времени "на подумать". Если в прошлом году была всего одна команда, с роботом на самодельных omni-колесах, позволяющих ему без разворотов перемещаться в любых направлениях, то в этом году и остальные команды, ездившие "на мир" в прошлом сезоне привезли оттуда идеи для своих omni-роботов. Решения, предложенные этими командами в итоге оказались очень интересными, не оставляющими шансов для роботов с традиционной конструкцией.


Помните серию "Футбол" из Смешариков? На полях творилась похожая картина. Пока наш нападающий с традиционной конструкцией "думал" и выполнял маневры, стремительные omni-соперники быстрее добирались до мяча и посылали его в сторону узкого борта с нашими воротами. 2-3 точных удара по мячу, которые успевал  за тайм сделать наш нападающий, в те момент когда он все же успевал подобрать мяч, не шли не в какое сравнение с 40-50 попытками забить гол нам. Пусть они были не точные, но теория вероятностей штука упрямая, ширина ворот - 25% от длины узкого борта.


Тем не менее решения, над которыми наша команда работала в этом сезоне не подвели нас, роботы вели себя так, как и планировалось, чем мы очень довольны. Как гласит лозунг WRO футбола, "ценно не то, что вы выиграете или проиграете, а то, как много вы узнаете".

Теперь мы планируем немного отдохнуть и начнем новый сезон наших хоббийных проектов. До скорых встреч!


воскресенье, 21 мая 2017 г.

Управляемый робот-футболист

Давненько не было вестей от нашей команды. Вы думаете что мы забросили роботов? Не дождетесь!) С середины января находимся в режиме планомерной подготовки к ВРО, снова готовимся к футболу роботов. В этом году алгоритмы машин снова переписаны заново и во многом не повторяют логику работы наших футболистов предыдущих поколений.


Учебный процесс тоже не стоял на месте, в нашей копилке теперь вот такой крупнокалиберный арсенал: "Введение в программирование (C++)" от Академии Яндекса, "Программирование на Python", "Python: основы и применение", "Введение в Linux" от Института биоинформатики, "Введение в архитектуру ЭВМ. Элементы операционных систем" от Computer Science Center.


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

Поиграть против своей автономной команды очень интересно и полезно:

  • Зная слабые места своих автономных роботов можно создавать на поле такие игровые ситуации, в которых они проявятся. Это важно для отладки алгоритмов и конструкций.
  • Управляя роботом ты моделируешь в голове работу некого алгоритма, который затем может быть перенесен в программу автономного игрока
  • Это реальный драйв - ты играешь в игру не на экране, а в реальном мире, с полноценной физикой и красивыми текстурами. Обзор 360 градусов и высокое разрешение!


Так как мы находимся в процессе изучения языка Python, то интересной учебной задачей стала реализация такого управляемого робота-оппонента на базе ev3dev. Можно конечно "не заморачиваться" и использовать смартфон и написанное кем-то приложение, но это не наш путь. На борту у EV3 есть Bluetooth, у китайцев на Aliexpress - дешевые блютузные джойстики - почему бы не поуправлять роботом с реальных кнопок и стика? Используя стандартное ПО LEGO EV3 такую связку заставить работать невозможно, ev3dev открывает перед нами такую возможность.

Для начала сам робот. Традиционно подготовили инструкцию по сборке в Lego Digital Designer, скачать можно по ссылке. В конструкции умышленно не использовали механизм удара по мячу, чтобы у начинающих не было соблазна собрать на базе этой инструкции автономного робота.


Чтобы джойстик заработал с EV3, необходимо "спарить" устройства привычным образом, после чего в /dev/input должен появиться новый девайс:

robot@ev3dev:~$ ls /dev/input
by-path  event0  event1  event2

Кроме Bluetooth-джойстика можно использовать беспроводной USB-джойстик, воткнув его USB-приемник в соответствующий порт на роботе. Беспроводная клавиатура с интерфейсом USB или Bluetooth тоже подойдет. Технически роботом можно управлять используя даже беспроводную мышку, но это вероятно не особенно удобно. Главное условие - после подключения устройства оно должно появляться в устройствах ввода, в /dev/input

Для получения данных с HID-устройств мы использовали стандартный модуль Python evdev. Ничего доустанавливать в ev3dev не требуется.

Нашу программу для робота можно скачать по ссылке. Основная фишка управления по сравнению со "смартфонным" - реализация плавного разгона и торможения, что обеспечивает комфортное управление. Выглядит программа следующим образом:

#!/usr/bin/env python3

# Подключаем модуль для управления EV3
from ev3dev.ev3 import *
# Подключаем модуль для чтения данных с HID-устройств
import evdev

# Создаем объект device, измените на ваш /dev/input/event2
device = evdev.InputDevice('/dev/input/event2')

StatusGo = 0
StatusLR = 0

# Целевая скорость, робот наберет ее когда разгонится
speed = 100

# Реальная скорость, с нее робот стартует
real_speedB = 0
real_speedC = 0

speedB = 0
speedC = 0

# Признак зарершения программы (нажат акнопка Start на джойстике)
STOP = False

# Создаем объекты - моторы B и C
B = LargeMotor('outB')
C = LargeMotor('outC')

# Цикл пока не нажата кнопка Start на джойстике
while not STOP:
    # Читаем список событий с джойстика
    gen = device.read()
    try:
       # Для всех событий в списке
       for event in gen:
           # Выделяем те, которые возникли при нажатиях кнопок
           if event.type == evdev.ecodes.EV_KEY:
               # преобразуем такие события в строку myStr
               myStr = str(event)
               
               # если отпущена кнопка "Влево"
               if myStr.find("code 168, type 01, val 00") >= 0:
                   StatusLR = 0
               # если нажата кнопка "Влево"
               if myStr.find("code 168, type 01, val 01") >= 0:
                   StatusLR = -1
               # если удерживается кнопка "Влево"
               if myStr.find("code 168, type 01, val 02") >= 0:
                   StatusLR = -2
               # если отпущена кнопка "Вправо"
               if myStr.find("code 208, type 01, val 00") >= 0:
                   StatusLR = 0
               # если нажата кнопка "Вправо"
               if myStr.find("code 208, type 01, val 01") >= 0:
                   StatusLR = 1
               # если удерживается кнопка "Вправо"
               if myStr.find("code 208, type 01, val 02") >= 0:
                   StatusLR = 2
               # если отпущена кнопка "Вперед"  
               if myStr.find("code 172, type 01, val 00") >= 0:
                   StatusGo = 0
               # если нажата кнопка "Вперед"
               if myStr.find("code 172, type 01, val 01") >= 0:
                   StatusGo = speed*0.75
               # если удерживается кнопка "Вперед"
               if myStr.find("code 172, type 01, val 02") >= 0:
                   StatusGo = speed
               # если отпущена кнопка "Назад"
               if myStr.find("code 114, type 01, val 00") >= 0:
                   StatusGo = 0
               # если нажата кнопка "Назад"
               if myStr.find("code 114, type 01, val 01") >= 0:
                   StatusGo = -1*(speed * 0.75)
               # если удерживается кнопка "Назад"
               if myStr.find("code 114, type 01, val 02") >= 0:
                   #print ("GO BREAK")
                   StatusGo = -1*speed
               # если нажата кнопка "Start"         
               if myStr.find("code 164, type 01, val 02") >= 0:
                   print ("BREAK! STOP PROGRAMM")
                   STOP = True
               # Кнопка - среднее значение скорости
               if myStr.find("code 164, type 01, val 01") >= 0:
                   speed = 75
               # Кнопка нажата - уменьшить скорость
               if myStr.find("code 115, type 01, val 01") >= 0:
                   speed = speed - 5
                   if(speed < 5):
                       speed = 5
               # Кнопка удерживается - уменьшить скорость        
               if myStr.find("code 115, type 01, val 02") >= 0:
                   speed = speed - 1
                   if(speed < 5): 
                       speed = 5
               # Кнопка нажата - увеличить скорость
               if myStr.find("code 113, type 01, val 01") >= 0:
                   speed = speed + 5
                   if(speed > 100): 
                       speed = 100
               # Кнопка удерживается - увеличить скорость
               if myStr.find("code 113, type 01, val 02") >= 0:
                   speed = speed + 1
                   if(speed > 100): 
                       speed = 100

    except IOError:
        pass
    
    # перебрасываем статусы нажатий в мощности моторов  
    speedB = StatusGo
    speedC = StatusGo
    
    # Поворот влево
    if(StatusLR < 0):
        speedB = speedB-(25*abs(StatusLR))
        speedC = speedC+(25*abs(StatusLR))         
    # поворот вправо
    if(StatusLR > 0):
        speedC = speedC-(25*StatusLR)
        speedB = speedB+(25*StatusLR)
    
    # ограничение скорости
    if(speedB > 100):
        speedB = 100
    if(speedC > 100):
        speedC = 100
    if(speedB < -100):
        speedB = -100
    if(speedC < -100):
        speedC = -100

    # плавный разгон и торможение
    if(abs(speedB) > 5 and abs(speedC) > 5):
        real_speedB = real_speedB*0.95 + speedB*0.05
        real_speedC = real_speedC*0.95 + speedC*0.05
    if(speedB == 0 and speedC == 0):
        real_speedB = real_speedB*0.95
        real_speedC = real_speedC*0.95
    if(speedB == 0 and abs(real_speedB) < 5):
        real_speedB = 0
    if(speedC == 0 and abs(real_speedC) < 5):
        real_speedC = 0
    
    # подаем рассчитанные мощности на моторы        
    B.run_forever(speed_sp=real_speedB*9)
    C.run_forever(speed_sp=real_speedC*9)

# останавливаем моторы после вылета из цикла         
B.stop(stop_action="hold")
C.stop(stop_action="hold")

# сигнал завершения программы
Sound.beep()

воскресенье, 19 марта 2017 г.

Хоббийная робототехника как семейное увлечение. Часть 1

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


Все началось осенью 2011 года, когда я привез из командировки своим сыновьям LEGO Mindsorms NXT 2.0. Детям на тот момент было 6 и 4 года. Покупка эта была спонтанная, до того момента я даже не подозревал о существовании таких конструкторов, а у детей из LEGO были только пара наборов серии City. На глаза попалась реклама и, посмотрев на youtube как робот из конструктора собирает кубик Рубика и играет в крестики нолики, я не смог устоять. 

Небольшое отступление по поводу стоимости LEGO Mindstorms, старших наборов Technic и совместимых с ними деталей. На нашем канале Youtube нам часто оставляют комментарии типа "Деньги некуда девать. Наверное это дети зажиточных чинуш". На своем опыте я убедился, что такие наборы LEGO - в долгосрочной перспективе это очень дешево и выгодно. Из дома чудесным образом плавно пропадают коробки с китайскими одноразовыми машинками на пультах, мигающие глазами шагающие страшилища и прочие игрушки в которые играли всего пару раз, в магазинах дети даже у полок с таким наполнением перестают задерживаться. И правда, зачем? Из конструктора можно собрать лучше, каждый день что-то новое, а то, во что наигрались - не пылится - разбирается на детали для новых проектов.

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

Еще одно отступление относительно того, откуда взялся наш канал на Youtube и заблуждения многих подписчиков относительно того, что мы "снимаем видео на публику". Съемкой видео, как наверное и многие родители, я увлекся в попытке запечатлеть уходящие мгновения в жизни подрастающих детей, с целью показать им в будущем какими они были в детстве, да и для себя, чтобы в преклонном возрасте пересматривать эти моменты в кресле-качалке, завернувшись в плед, непременно клетчатый. Видео где-то нужно хранить, HD занимает немало места на выходящих периодически из строя жестких дисках. Неплохой вариант - торрент, пару раз выкачивал свое же видео после краха носителей, но не любое ценное для меня видео будет гарантированно хранить кто-то еще. Облачные сервисы с терабайтными подписками - слишком накладное удовольствие, когда как оказалось под рукой есть бесплатный инструмент хранения видео - Youtube. Поначалу видео выкладывал на канал не публикуя в открытом доступе, но постепенно, по мере того как все больше и больше делился ссылками на ролики, пришло понимание что открытый доступ по-умолчанию - это даже интересно, народ в комментариях делится полезными идеями, ссылками, дает советы - это очень ценно. Да и критика, а она бывает - только мотивирует тренироваться в монтаже, оставлять в кадре только самое интересное, исправлять недочеты. Отсюда и канал настолько неоднороден, на нем кроме роботов и электроники - путешествия, спорт, творчества, да и просто памятные семейные моменты, которые пришедшие к нам посмотреть на роботов могут рассматривать как фильм о фильме о тех, кто этих роботов строит.

Наш первый робот был конечно же собран по "инструкции по быстрому старту". Ни я, ни дети не представляли как его строить, а уж тем более программировать. Решили следовать печатному руководству:


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


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

Самым интересным открытием в то время стал блог Александра Колотова NiNoXT Настоящий кладезь полезной информации, открытой для всех, без каких-либо коммерческих уловок, этот блог притягивал к себе каждой новой статьей так же сильно, как когда то "Огород Еозловского" в "Компьютерре". После таких статей хотелось строить роботов ночи напролет, очень жаль что новых статей в блоге нет уже более двух лет.

Я не бросился сразу же учить своих дошкольников программированию, так как сам не знал как подойти к этому роботу. Пришлось применить методы "тыка" и "проб и ошибок", начав изучать программирование LEGO Mindstorms с целью научить в дальнейшем этому детей. Многие родители сетуют на то, что у них нет "специального образования", поэтому они даже не пытаются заниматься со своими детьми такой сложной наукой как строительство и программирование роботов. Зачастую при этом и педагогического образования у них тоже нет, но поучать детей в бытовых вопросах они очень любят, якобы с высоты своего опыта. Так почему бы не получить опыт в деле, которое точно заинтересует ребенка и не научить его этому или хотя бы заняться с ним совместным досугом?


Не успев построить и десяток роботов мы узнали о соревнованиях, которые проводятся в нашем городе на базе клуба технического творчества. Конечно же дети захотели поучаствовать и мы построили нашего первого "спортивного" робота. Тогда у нашей команды еще не было названия и робота мы назвали "Папай". Робот ездил зигзагами по линии, шатаясь как пьяный морячок из легендарной игры, а еще этого робота детям помогал строить папа, это и определило его название. Удивительно для нас, но на соревнованиях мы встретили других робототехников (! :), которым тоже как и нам нравилось строить роботов. 



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

Следующий сезон прошел в первых попытках освоения детьми программирования роботов. Конечно же, это был графический LEGO-язык, и первые шаги в написании программ были сделаны детьми именно на NXT-G. Параллельно с этим ребята продолжили собирать роботов по готовым инструкциям, это, с одной стороны мотивировало к изучению программирования, с другой - "набивалась" рука на конструировании, приходило понимание того как можно применить те или иные детали.


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

Вскоре последовали новые соревнования, первый в нашем городе "Турнир мобильных роботов" при СГАУ. Именно тогда, в ноябре 2012 года, команда получила название "Карандаш и Самоделкин".


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

Что лучше, корпеть над одной задачей целый сезон, оттачивая робота для участия в конкретной соревновательной дисциплине, чтобы после перейти к задаче новой, вписанной в регламент очередного состязания? Год за годом оттачивать, например, робота, движущегося по линии, не уступающего свои лидерские позиции менее упертым/успешным командам? Серьезная подготовка занимает все время, заниматься параллельно хоббийными проектами сложно и неэффективно. С другой стороны может ну его, этот спорт? Разносторонние знания, полученные при разработке своих проектов, не ограничиваемые какими-то регламентами полет фантазии и набор используемых технологий? Но как не сбиться с намеченного пути, как подбирать задачи так, чтобы они шаг за шагом двигали команду в развитии? В соревновательной робототехники за тебя уже все решено, открываешь регламенты и вперед, а как быть с робототехникой хоббийной?

Вот такие мысли крутились в голове, время неумолимо шло вперед, а роботов строилось все больше и больше...


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

Продолжение следует ...


Самое популярное