Встречайте! Мы выпустили на улицу роботов третьего поколения — модель R3 уже можно встретить в Москве, Иннополисе и США. До конца года мы планируем произвести больше сотни таких роботов, и в дальнейшем будем расширять флот за счёт них.
Меня зовут Алексей, я работаю в Yandex Self-Driving Group: несу ответственность за разработку железа трёх (с половиной) поколений роботов Яндекса. В этой статье я не только коротко расскажу про новое поколение, но и поделюсь историей создания роботов-курьеров. Вы сможете взглянуть их глазами на велосипедиста, узнаете, как собрать прототип из фанеры и трёх гироскутеров, а также почему мы выбрали менее дальнобойные лидары. Всё это я дополню роликами и фотографиями разных этапов разработки. Поехали!
Чем третье поколение отличается от первого
Первого робота мы показали миру 7 ноября 2019 года. С тех пор мы доставляли заказы и в снег, и в дождь, и в бурю, и под солнцем Дубая, и по широким тротуарам Огайо, и по узким, иногда ремонтируемым, улицам Москвы. Итого на данный момент мы разработали, изготовили и обкатали три с половиной поколения роботов: R1, R1.5, R2 и R3. Весь накопленный опыт создания и эксплуатации первых поколений мы использовали в третьем. Сейчас поясню, чем роботы R3 отличаются от предыдущих.
Робот стал больше и вместительнее. Теперь мы можем перевозить до 20 кг полезного груза в отсеке объёмом 60 л — это шесть пицц диаметром 40 см и три двухлитровые бутылки Кока-Колы. В роботов второго поколения помещалось только пять пицц, а первое поколение возило только пиццу диаметром 35 см.
Начиная со второго поколения, крышка робота открывается и закрывается автоматически: для этого достаточно нажать кнопку в приложении. Робот третьего поколения научился обнаруживать попытки пользователя закрыть крышку рукой и помогать ему в этом. Грузовой отсек запирается на замок и открывается только из приложения и только для получателя заказа.
Конструкцию робота мы разработали сами, а производство деталей и сборку доверили российским подрядчикам. Стандартные компоненты — чипы, элементную базу, разъёмы, жёсткие диски, процессоры, — конечно, покупаем. Радары и колёса тоже покупные, как и лидары — но именно их мы вскоре поменяем на свои. В первом поколении роботов доля покупных компонентов была больше: мы стремились переиспользовать всё что только можно, чтобы ускорить появление прототипа. Во втором мы разработали и обкатали часть модулей, в третьем случилась еще одна большая итерация разработки электроники.
Роботы первого поколения работали 3,5 часа без подзарядки. Потом мы проапгрейдили первое поколение, установив процессоры ARM (читайте про это ниже), и время работы увеличилось до 7 часов. R2 за счёт оптимизации электроники работали 10 часов. А третье может ездить 8 часов, зато батарейку можно заменить за несколько секунд — робот сразу же поедет доставлять дальше. Чтобы обеспечить горячую замену, мы оборудовали робота резервной несъёмной батареей небольшой ёмкости. Оба аккумулятора по нашему ТЗ собирает российская компания из покупных ячеек. Корпус — наш.
Вот как происходит замена:
У роботов первого поколения была жёсткая подвеска без амортизаторов, с балансирами на передних двух осях. Теперь все оси — на независимых рессорах, а балансиры переехали назад: опыт и эксперименты показали, что так робот едет лучше. «Мягкую» подвеску мы испытали ещё на R2 — и с этим продакшен-опытом за плечами спроектировали подвеску R3. В разделе про разработку я ещё вернусь к тому, как мы тестировали новую подвеску.
Роботам третьего поколения мы поставили лидар, у которого 64 луча (в R1 было 16) и большой угол зрения по вертикали. Чтобы лучше задействовать большое поле зрения, мы перенесли лидар в переднюю часть робота. А чтобы раньше замечать машины, когда робот пересекает пешеходные переходы, в рамках апгрейда R1 мы расположили ещё два радара по бокам. Радары позволяют детектировать движущиеся объекты и быстро оценивать скорость их приближения. Ещё мы поставили дополнительные камеры со всех сторон (у первого поколения была только одна камера). А на R3 заменили объективы на фишай для увеличения поля зрения и охвата в 360 градусов.
Начиная со второго поколения мы используем ультразвуковые сенсоры собственной разработки. У первого были обычные парктроники. С наших сенсоров мы можем снять больше данных, полезных для езды в разных условиях, — с покупными сенсорами это было невозможно. В R3 мы увеличили их количество и оптимизировали конструкцию сенсоров.
Теперь ориентироваться в окружающем мире роботам помогает два радара, один лидар, пять камер, акселерометр и GNSS. Функциональную безопасность обеспечивают девять ультразвуковых сенсоров.
Вот как выглядит лидарное облако с нашего робота:
Масса пустого робота — 70 кг, максимальная скорость — 8 км/ч. У робота шесть ведущих мотор-колёс. Передняя ось на независимой рессорной подвеске, а задние две — на рессорно-балансирной (как у КАМАЗа, например). Минимальный дорожный просвет при полной загрузке — 100 мм.
Мы не сразу пришли к такой конструкции робота. Первые два поколения позволили собрать информацию при езде в боевых условиях и уточнить требования к платформе. Каждое следующее поколение проектировалось с учётом опыта, полученного при эксплуатации предыдущих. Ниже я расскажу, как это было.
Три поколения роботов-курьеров, слева направо: R1, R2, R3
Мы начали разработку робота-курьера в июне 2019 года. С помощью первого поколения мы хотели как можно скорее проверить, насколько софт, разработанный для большого беспилотного автомобиля, будет применим для управления роботом-курьером на городских тротуарах. Большой беспилотник на тот момент уже умел ездить без водителя по дорогам общего пользования.
Прототип старались делать из покупных компонентов, по возможности не разрабатывая ничего своего. Ведь мы тогда не знали, каким должен быть робот, поэтому тратить ресурсы на разработку «того — не знаю что» in-house было нецелесообразно.
Всё, о чём я расскажу ниже, было бы невозможно, если бы у нас не было Инженерного центра. Это волшебное место на юге Москвы, где идеи становятся реальностью. Команда центра — увлечённые своим делом люди с большим опытом из разных индустрий, которые могут полностью разобрать и собрать любую машину, хоть беспилотную, хоть гоночную. У команды есть все необходимые инструменты и оборудование, чтобы быстро производить опытные серии деталей. Это сильно сокращает цикл разработки, когда нужно делать несколько итераций. Все роботы, которые есть у нас сейчас (полторы сотни) — собраны здесь.
Мы сформулировали первоначальные требования к шасси нашего робота. Соответствие этих требований действительности предстояло проверить в реальных условиях, поэтому мы стремились как можно быстрее получить работающий прототип.
Затем мы провели мозговой штурм и исследование известных конструкций шасси. В нашей команде были ребята с опытом проектирования и постройки роботов и автомобилей, поэтому вариантов было придумано и рассмотрено очень много. После обсуждений и споров выбрали рабочий вариант: шестиколёсное шасси на мотор-колёсах, все колёса ведущие.
Итак, для первого прототипа мы взяли 8-дюймовые колёса и драйвера от гироскутеров, разработческую плату Nucleo и собрали из фанерки и алюминиевых профилей прототип шестиколёсного шасси, управляемый с пульта. Прошивку для драйверов модифицировали под свои задачи, а команды управления рассылали через Nucleo. Внимательный читатель заметит на картинке ниже VoltaBox из моего прошлого проекта, который пошёл в дело в качестве пятивольтового DC/DC-преобразователя.
К девборде подключён Wi-Fi адаптер, в который мы слали команды с ноутбука. На ноутбуке был запущен Python-скрипт, преобразующий команды с Bluetooth-джойстика. Мы до сих пор иногда используем этот скрипт для того, чтобы обкатать какие-то новые низкоуровневые хардварные фишки робота.
Платформа была собрана и подготовлена к тестам примерно за два дня одним инженером-конструктором и одним embedded-инженером. А менеджер (я) стоял рядом и держал болгарку.
Большая Красная Кнопка для выключения системы была расположена на самом прототипе, поэтому во время первых тестов я сидел сверху и на всякий случай держал руку где-то рядом с ней. И при первом же тесте на земле это пригодилось: драйвера от гироскутеров оказались слишком умными и при определённом сочетании команд управления платформа начинала неконтролируемо вращаться на месте. Интересно, что на тестах подвешенной платформы, которые мы делали до запуска на полу, мы такого поведения не заметили.
Вот один из первых проездов на платформе:
В целом платформа доказала, что пригодна для использования в прототипе: она была достаточно грузоподъёмной и быстрой. Но тесты показали, что жёстко закреплённые колёса нам не подходят: на неровностях шасси начинало поворачивать непредсказуемо, из-за того что не все колёса касаются земли. Мы добавили балансирную подвеску передних двух осей и дополнительно загрузили среднюю ось с помощью пружин, чтобы робот поворачивал преимущественно вокруг центра средней оси — это необходимо для качественного управления из беспилотного софта. Мы также тестировали на прототипе активное управление качалками с помощью актуаторов. Они не показали себя эффективными, поэтому мы отказались от них в пользу более простой схемы.
Шасси с актуаторами. Потом на их место поставили пружины, работающие на растяжение
После тестов конструкторский отдел приступил к разработке робота, которого можно было бы испытывать на улице. Серийность предполагалась до 10 штук. Технологиями производства были выбраны вакуумная формовка пластика, резка и гибка листового металла. Некоторые детали были напечатаны на 3D-принтере, отфрезерованы на ЧПУ и выточены на токарном станке. Вся разработка конструктива происходила внутри команды. Большинство деталей изготовили в России внешние подрядчики.
Главной задачей MVP было доказать возможность применения нашей беспилотной технологии в принципиально новом формате робота-курьера. Поэтому важно было использовать готовые знакомые нам компоненты, чтобы как можно быстрее проверять гипотезы. Для этого мы выбрали тот лидар, который ставим по бокам нашего беспилотного автомобиля. У нас уже были обученные под него модели и мы надеялись, что они сразу же взлетят на роботе и не потребуется долго собирать новые датасеты. Максимальная дальность действия этого лидара — 100 метров, у него 16 лучей, которые обращаются на 360 градусов вокруг вертикальной оси, сканируя пространство. Из-за особенностей работы оптимально было его поставить в заднюю часть робота.
Кроме детекции объектов, лидар используется для определения положения робота в пространстве — локализации. Алгоритм совмещает полученные с помощью лидара точки с сохранённой в памяти трёхмерной картой и ищет наилучшее совпадение. Для этого лидар должен видеть статические объекты вокруг робота на 360 градусов — здания, столбы, остановки, мусорные корзины. Вертикальный угол обзора нашего лидара был относительно небольшой — 30 градусов — поэтому для надёжности локализации лидар на роботе был установлен строго вертикально.
Чтобы улучшить ближние детекции, мы добавили в переднюю часть робота два парктроника. Сначала мы использовали готовые парктроники. Как и любые стандартные, они пищали, когда видели препятствие, и робот мог напугать пешеходов. Поэтому мы вытащили пищалку из блока управления. Кроме того, нам пришлось хакнуть протокол связи между блоками управления и индикации — иначе в принципе не удавалось пользоваться парктроником: изначально он не предназначался для того, чтобы считывать с него данные в электронном виде.
На первых порах мы просто смотрели на дистанцию на парктрониках и по определённому порогу замедлялись, а потом останавливались. Из-за особенностей работы софта верхнего уровня — там использовалась велосипедная модель движения, — мы не могли разворачиваться на месте. Это нельзя было исправить без вложения значительных ресурсов разработчиков для реализации новой, «танковой», модели движения робота. Поэтому мы сделали на нижнем уровне разворот на месте в случае, когда робот упирался в препятствия парктрониками. Разворачивались в сторону до тех пор, пока не переставали видеть препятствие, затем вступали в действие алгоритмы беспилотника, и мы строили плавную траекторию. В итоге мы успешно и красиво объезжали препятствие. Танковая модель была реализована для серийного робота, а реакция на парктроники перенесена на верхний уровень.
Кроме этого, в первом роботе была установлена камера, но она использовалась только для записи видео во время тестовых проездов.
В беспилотном автомобиле установлена серьёзная серверная x86-платформа с двумя процессорами и тремя видеокартами. Конечно, мы не могли себе позволить возить такое в роботе из-за массы, габаритов и энергопотребления. Нужно было масштабировать эту платформу под ограниченные ресурсы.
Из-за того, что весь софт тогда был написан под x86, мы не стали на этом этапе рассматривать ARM-based embedded решения. Переезд на ARM стоил бы дорого по времени и ресурсам, поэтому, забегая вперёд, скажу, что переезжали мы уже в следующем поколении, когда доказали принципиальную возможность передвижения под управлением беспилотного софта.
Сначала мы хотели взять ноутбук для VR-игр, который игроки носят за спиной. Но оказалось, что таких на тот момент больше не производили. Мы решили собрать свою платформу. Взяли mini-ITX материнку, одну видеокарту, самый мощный на тот момент десктопный процессор и попробовали со всем этим взлететь. Получилось.
Кроме вычислителя, и нижнего уровня управления, на борту прописались Ethernet-роутер MikroTik, модуль GeoHub, который был разработан ранее для беспилотника (это Embedded Linux железка, которая отвечает за получение GNSS-сигнала и акселерометр), два модуля связности (LTE+Wi-Fi) — тоже от беспилотника, блоки питания, аккумулятор.
Сравните эту схему со схемой R3 (в конце поста). Тут всего один компонент зелёного цвета — это модуль, разработанный нами ранее для беспилотного автомобиля. Мы старались по максимуму переиспользовать готовые компоненты, чтобы ускорить проверку гипотез.
Масштабирование и адаптация софта
Основной задачей было выключить всё ненужное и не выключать ничего нужного. Чтобы разобраться, что нужно, а что не нужно, я ходил по командам разработчиков и задавал много вопросов занятым большим беспилотником людям, много экспериментировал. Для экспериментов мы собрали прототип без внешней обшивки и приклеили на него монитор с тачскрином для удобства.
Вот как происходила первая автономная доставка воды спикеру на одном из наших внутренних мероприятий:
За четыре месяца нам удалось с нуля спроектировать, собрать и запустить в городе прототип, который можно было показать всему миру, а также масштабировать софт под весьма ограниченные ресурсы и другую платформу. Мы почти не трогали код, в основном меняли конфиги. В этой конфигурации мы собрали ещё несколько роботов, которые выехали в город — около нашего офиса на Льва Толстого и в Сколково, — и совершили первые коммерческие доставки. Кстати, если вам интересно узнать про развитие нашего проекта в коммерческом плане, то 4 декабря об этом будет рассказывать Паша Воробьёв в треке Product на конференции YaTalks.
В наследство от большого беспилотника роботу досталась плавность движений и продуманность траекторий. Конечно, после успешных первых проездов появилась выделенная software-команда, которая стала оптимизировать алгоритмы и код уже специально для робота и проделала за эти два года огромную работу. Но это другая история.
Первые роботы на x86 жили от батарейки около трёх часов. Даже на тестах приходилось постоянно думать об оставшемся уровне заряда и планировать всё так, чтобы его хватило. Для работы в продакшене необходимо было жить не менее 8 часов (смену). Замеры энергопотребления показали, что большую часть заряда потребляет вычислитель, причём даже когда робот просто стоит на месте. Переход на ARM сулил значительный выигрыш в энергопотреблении, но мы знали, что это будет непросто.
Внушительная кодовая база, библиотеки, инструменты разработки, инфраструктура — всё было заточено под x86. Поэтому мы знали, что переезд на ARM будет сложной и ресурсоёмкой задачей. Нужно было оптимизировать работу софта под новую архитектуру, соблюдая при этом совместимость с большим беспилотником, ведь у нас одна кодовая база. После того, как код под ARM для робота был готов, он всё ещё жил в отдельной ветке. Её мёрж в dev занял в итоге около месяца.
Инфраструктура тоже сначала не была предназначена для новой платформы. На x86-код собирался прямо на роботе. На ARM мы такого себе позволить уже не могли, поэтому пришлось научиться собирать код в облаке, а потом привозить его на робота в виде бинарей.
А потом и Apple, посмотрев на наш успех, решили переехать на ARM!
Чтобы ускорить получение робота с большим временем жизни и обкатать новую вычислительную платформу, мы решили разделить разработку нового шасси (R2, о котором ниже) и переезд на ARM. Мы взяли платформу R1 и на её основе разработали робота R1.5 и комплект для апгрейда R1 в R1.5 с ARM-based вычислителем.
В прототипах мы соединяли компоненты проводами по месту. В R1.5 мы сделали первую итерацию по улучшению проводки робота. В том числе, разработали специальную плату расширения для Nucleo, к которой можно подключать все периферийные устройства с помощью разъёмов, а также вынесли на неё модуль акселерометра, чтобы получить возможность замкнуть обратную связь по акселерометру на нижнем уровне и избавиться от громоздкого для робота GeoHub.
Также для этого поколения мы разработали плату PMU, Power Management Unit. Она позволила мониторить токи и напряжения на каждой ветке, а также программно контролировать питание каждой из них. Иногда это позволяло удалённо перезагружать подвисшие периферийные устройства.
3D-модель Power Management Unit
Мы заменили покупные контроллеры колёс от гироскутеров на свои собственные. На наших контроллерах удалось достичь более высокого КПД колёс. Ещё мы изменили интерфейс UART на более надёжный и привычный для нас CAN и заложили хороший фундамент для будущих разработок, поддержав энкодер и контроль температуры двигателя. Потом мы смогли использовать наш контроллер двигателя для других задач.
Два минорных поколения MotorControl. Найдите 10 отличий
В первых поколениях роботов мы использовали батарейки от электровелосипеда. Чтобы оптимизировать компоновку робота и получить обратную связь (заряд, здоровье, нагрузка) от батарейки, мы заказали батарейку по собственному ТЗ у одного российского производителя. Наши батарейки стали более ёмкими и научились отдавать обратную связь по CAN.
В первом поколении у нас была одна IP-камера. В R1.5 мы увеличили их число до четырёх, изменили интерфейс на GMSL (как в большом беспилотнике). Камеры расположили по всем сторонам робота. Теперь мы стали видеть всё. Также добавили радары, чтобы издалека обнаруживать приближающиеся автомобили во время пересечения пешеходных переходов.
Время работы новой платформы от одного заряда увеличилось более чем вдвое. Мы переоборудовали роботов R1 и собрали ещё пару десятков R1.5, которые были основными рабочими лошадками в российских локациях в Москве и Иннополисе до середины 2021 года, после чего их постепенно заменили на роботов следующего поколения.
Продолжение в следующем посте