Начнем со среды: программировать роботов сможет каждый

Динамические объекты в C++

Следующей важной особенностью C++ является работа с динамической памятью. В языке С работа с динамической памятью очень проста и использует всего две функции:

  • malloc — резевирует память,
  • free — освобождает память.

Например:


char *string; // задали указатель на строку string = malloc(1000); // получили память … free( string ); // освободили память

1 2 3 4

char*string;// задали указатель на строку

string=malloc(1000);// получили память

free(string);// освободили память

В C++ все намного сложнее. Для работы с динамической памятью вводится понятие динамический объект.

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

Для создания нового объекта используется ключевое слово new.

int *px = new int;

1 int*px=newint;

В этой строке создан новый динамический объект — целое число. Возможно создать объекта любого типа данных: int, float, double, char и т. д. Создадим динамический экземпляр класса:

Base *pBase = new Base;

1 Base*pBase=newBase;

В этой строке мы создали динамический экземпляр класса. Только в этом случае мы должны ссылаться на свойства и методы через знак «->».

pBase->x

1 pBase->x

Когда объект больше не нужен, то он удаляется ключевым словом delete. При использовании оператора delete для указателя, знак * не используется.

delete px; delete pBase;

1 2

delete px;

delete pBase;

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

Создание динамических объектов происходит в конструкторе класса. А где же проиходит их удаление? Для этого в классе есть специальная функция — деструктор.

Индустриальные роботы в современной промышленности

Мировой рынок роботов

Применение индустриальных роботов во всем мире каждый год увеличивается. К 2018 году более 1,3 млн роботов будут введены в эксплуатацию по всему миру. Средний показатель плотности применения роботов в производстве, по данным 2014 года, равен 66 единицам на 10 тыс. работников. В 21 стране этот показатель выше среднего (рис. 1).

В них входит большинство индустриально развитых страх Европы, США, Канада и Азиатский регион (Южная Корея, Япония, Тайвань). Словения занимает в этом списке не последнее место и с показателем 100 роботов на 10 тыс. человек занимает лидирующие позиции по автоматизации производства. Наибольшее применение роботы находят в автомобильной промышленности, где наблюдается более высокая плотность роботизации производства (рис. 2).

Рис. 1. Плотность применения роботов

Рис. 2. Распределение роботов по отраслям

Области применения роботов

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

Робот, благодаря наличию шести степеней свободы, может также делать сложные многоосевые перемещения вдоль необходимой траектории, выполняя, таким образом, любую обработку, которая до этого была возможна только на специализированных станках. Это становится реальным прежде всего вследствие многолетней эволюции индустриальных роботов и контроллеров. Индустриальные роботы стали более точными и жесткими — возможно позиционирование робота с точностью до нескольких сотых долей миллиметра. Совершеннее стали и контроллеры роботов — они позволяют управлять несколькими роботами одновременно, а также интерполировать перемещения робота с дополнительными линейными и поворотными осями. Всё это создало предпосылки для использования роботов в тех отраслях, где до сих пор было возможно применение только специализированных станков с ЧПУ.

Программирование EV3 на Python

Одним из наиболее популярных языков программирования в мире является Python. Он имеет небольшое синтаксическое ядро и объемную стандартную библиотеку функций. В операционной системе Linuх язык программирования Python установлен. При желании можно установить нужный вам текстовый редактор.

На микрокомпьютере EV3 установлена операционная система Linux. Для того, чтобы программировать EV3 на Python нужно установить Linux ev3dev на модуль EV3.

Затем нужно установить образ на карту памяти microCD. Желательно, чтобы класс карты был не менее десяти. Объем карты памяти от двух до тридцати двух гигабайт. Можно также использовать карту памяти microSDHC.

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

Затем нужно настроить соединение с компьютером и можно приступать к работе. Настройки соединения с компьютером нужно описывать отдельно так как они достаточно сложные. Для написания программ нужен еще редактор кода.

В качестве одного из вариантов можно установить редактор кода PyCharm Edu. Есть бесплатная версия с наличием подсказок, проверкой кода и подсвечиванием синтаксиса. Созданный в программе файл можно передать в блок EV3 при помощи программы PuTTY. Эта программа помогает установить SSH соединение операционной системы Windows с микроконтроллером EV3.

Скачать программу PuTTY можнос официального сайта. Есть 32 битная и 64 битная версии программы.

Среда программирования EV3


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

Также в ПО существуют задания по программированию, которые позволяют быстро научиться программировать роботов EV3. Программное обеспечение является пиктографическим. Оно обеспечивает простое и интуитивно понятное визуальное программирование.

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

EV3 является целой платформой, которую можно использовать в игровых и образовательных целях. При помощи платформы Lego Mindstorms EV3 можно обучать основам робототехники, программирования, изучать различные алгоритмы. При этом не нужно иметь знаний схемотехники и различных протоколов.

Webs

Один из крупнейших сервисов с более чем 50 миллионами сайтов. Webs существует с 2001 года, когда он ещё назывался Freewebs и являлся одним из первых бесплатных конструкторов сайтов. В одном из последних обновлений было добавлено множество новых и современных дизайнов, а также полноценная поддержка drag&drop редактора, позволяющего создавать сайты в считанные минуты. Этот процесс призван упростить использование шаблонов, которые доступные здес в большом количестве.

Преимущества

  • Бесплатный тариф.
  • Не нужно беспокоиться о хостинге.
  • Drag&drop редактор.
  • Множество шаблонов.
  • Относительно доступные цены:

Недостатки

  • Неинтуитивный интерфейс.
  • Отсутствие локализации.
  • Часть шаблонов доступна только на платных тарифах.
  • Достаточно ограниченная функциональность, которую нельзя расширить.
  • Дорого обойдётся сайтам для электронной коммерции.
  • В сравнении с другими конструкторами бесплатный тариф весьма ограничен.

SprutCAM для программирования роботов

Стандартные возможности создания программ

Все вышеперечисленные примеры требуют программирования сложных перемещений инструмента и, как следствие, осей робота. При классическом программировании роботов задание перемещений происходит последовательно — от точки к точке. Такой подход очень трудно применить для сложных траекторий, связанных еще и с ориентацией инструмента. Подобное программирование также потребует много времени, в течение которого робот фактически будет занят и не будет задействован в производственном процессе. Многие производители предоставляют возможность создания программ для робота в G­коде или в близком формате, когда программист учитывает лишь координаты центральной точки инструмента и создает программу в обычном декартовом пространстве, а положение фактических осей робота пересчитывается контроллером. В этом случае можно провести аналогию со станками с ЧПУ, которые имеют схожие возможности.

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

Применение CAM­системы для программирования

Логичным выходом из данной ситуации, следуя аналогии с классическими станками, в которых для создания программ обработки сложных форм применяют CAM­системы, является применение CAM для программирования робота. Действительно, создание траектории перемещения инструмента ничем не отличается от создания ее для станка. Разница лишь в том, что, впоследствии движения инструмента должны быть пересчитаны в движения осей робота и дополнительных осей. Этой возможностью обладает далеко не каждая CAM­система.

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

Компания «СПРУТ­Технология» уже более 20 лет занимается разработкой программного обеспечения SprutCAM. Одной из опций данного продукта является возможность      создания программ для промышленных роботов на основе загружаемой 3D­модели изделия.

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

Наборы и конструкторы Ларт

ЛАРТ Сармат Армага

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

ЛАРТ Печенег Батана

Комплект включает плату Ардуино Нано и имеет достаточное количество элементов для разработки и строительства роботов, которых при помощи состава набора можно собрать две разновидности: робот, движущийся по черной линии и робот с датчиком ультразвука. Для программирования применяется текстовая среда Arduino IDE.  Для разных модификаций роботов имеется возможность использования совместимых с Ардуино компонентов, а при помощи дополнительной пластины можно установить большее количество датчиков.

Конструктор Смарт Робо

Готовый конструктор для создания электронного робота на основе Ардуино, в комплект входит необходимое количество элементов, и руководство к сборке. Базовый элемент набора – плата от Keyestudio (100% аналог Ардуино). Полученный робот может быть запрограммирован на движение по линии, возможность объезда препятствий и управление от дистанционного пульта. Все элементы соединяются при помощи быстроразъемных соединителей и не требуют пайки. Доработать и усовершенствовать полученную конструкцию можно добавив на плату дополнительные элементы, совместимые с контроллером Ардуино.

Конструктор Смарт

Серия наборов, которые отличаются по комплектации. Основной компонент – плата Smart Uno – аналог контроллера  Ардуино Уно, не уступающий ему по качественным характеристикам. В зависимости от комплектации (Смарт 10, Смарт 20 и Смарт 30) набор содержит элементы, как для начального уровня проектирования, так и для разработки более сложных проектов. При необходимости возможно подключение других электронных компонентов, совместимых с микроконтроллером.

Смарт Genuino

Серия наборов – Смарт 10 Genuino, Смарт 20 Genuino, Смарт 30 Genuino, которые отличны по количеству деталей в комплекте. Главный базовый компонент – плата Genuino Uno, кроме которой в составе имеются электронные детали, беспаечная макетная плата, провода и руководство по проектированию.  Набор будет интересен как новичкам, так и профессиональным пользователям.

Робоплатформа Robbo (ScratchDuino)

Конструктор предназначен для обучения детей и взрослых основам робототехники и электроники. Управление роботизированным механизмом может осуществляться из различных сред программирования (Scratch, Lazarus, Кумир) или же пульта управления. Базовый компонент – картридж Ардуино. В зависимости от типа комплектации варьируется количество составных элементов.

Неявно генерируемый конструктор по умолчанию

Если ваш класс не имеет других конструкторов, то язык C++ автоматически сгенерирует для вашего класса открытый конструктор по умолчанию. Его иногда называют неявным конструктором (или «неявно сгенерированным конструктором»). Рассмотрим следующий класс:

class Date { private: int m_day = 12; int m_month = 1; int m_year = 2018; };

1 2 3 4 5 6 7

classDate

{

private

intm_day=12;

intm_month=1;

intm_year=2018;

};

У этого класса нет конструктора, поэтому компилятор сгенерирует следующий, идентичен по выполнению, конструктор:


class Date { private: int m_day = 12; int m_month = 1; int m_year = 2018; public: Date() // неявно генерируемый конструктор { } };

1 2 3 4 5 6 7 8 9 10 11 12

classDate

{

private

intm_day=12;

intm_month=1;

intm_year=2018;

public

Date()// неявно генерируемый конструктор

{

}

};

Этот конструктор позволяет создавать объекты класса, но не выполняет их инициализацию и не присваивает значения членам класса.

Хотя вы не можете увидеть неявно сгенерированный конструктор, но его существование можно доказать:

class Date { private: int m_day = 12; int m_month = 1; int m_year = 2018; // Не было предоставлено конструктора, поэтому C++ автоматически создаст открытый конструктор по умолчанию }; int main() { Date date; // вызов неявного конструктора return 0; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

classDate

{

private

intm_day=12;

intm_month=1;

intm_year=2018;

// Не было предоставлено конструктора, поэтому C++ автоматически создаст открытый конструктор по умолчанию

};

intmain()

{

Date date;// вызов неявного конструктора

return;

}

Вышеприведенный код скомпилируется, поскольку в объекте сработает неявный конструктор (который является открытым). Если ваш класс имеет другие конструкторы, то неявно генерируемый конструктор создаваться не будет. Например:

class Date { private: int m_day = 12; int m_month = 1; int m_year = 2018; public: Date(int day, int month, int year) // обычный конструктор (не по умолчанию) { m_day = day; m_month = month; m_year = year; } // Неявный конструктор не создастся, так как мы уже определили свой конструктор }; int main() { Date date; // ошибка: Невозможно создать объект, так как конструктор по умолчанию не существует, и компилятор не сгенерировал неявный конструктор автоматически Date today(14, 10, 2020); // инициализируем объект today return 0; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

classDate

{

private

intm_day=12;

intm_month=1;

intm_year=2018;

public

Date(intday,intmonth,intyear)// обычный конструктор (не по умолчанию)

{

m_day=day;

m_month=month;

m_year=year;

}

// Неявный конструктор не создастся, так как мы уже определили свой конструктор

};

intmain()

{

Date date;// ошибка: Невозможно создать объект, так как конструктор по умолчанию не существует, и компилятор не сгенерировал неявный конструктор автоматически

Date today(14,10,2020);// инициализируем объект today


return;

}

Рекомендуется всегда создавать по крайней мере один конструктор в классе. Это позволит вам контролировать процесс создания объектов вашего класса, и предотвратит возникновение потенциальных проблем после добавления других конструкторов.

Правило: Создавайте хотя бы один конструктор в классе, даже если это пустой конструктор по умолчанию.

Конструкторы с параметрами

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

#include <cassert> class Fraction { private: int m_numerator; int m_denominator; public: Fraction() // конструктор по умолчанию { m_numerator = 0; m_denominator = 1; } // Конструктор с двумя параметрами, один из которых имеет значение по умолчанию Fraction(int numerator, int denominator=1) { assert(denominator != 0); m_numerator = numerator; m_denominator = denominator; } int getNumerator() { return m_numerator; } int getDenominator() { return m_denominator; } double getValue() { return static_cast<double>(m_numerator) / m_denominator; } };

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

#include <cassert>

classFraction

{

private

intm_numerator;

intm_denominator;

public

Fraction()// конструктор по умолчанию

{

m_numerator=;

m_denominator=1;

}

// Конструктор с двумя параметрами, один из которых имеет значение по умолчанию

Fraction(intnumerator,intdenominator=1)

{

assert(denominator!=);

m_numerator=numerator;

m_denominator=denominator;

}

intgetNumerator(){returnm_numerator;}

intgetDenominator(){returnm_denominator;}

doublegetValue(){returnstatic_cast<double>(m_numerator)m_denominator;}

};

Обратите внимание, теперь у нас есть два конструктора: конструктор по умолчанию, который будет вызываться, если мы не предоставим значения, и конструктор с параметрами, который будет вызываться, если мы предоставим значения. Эти два конструктора могут мирно сосуществовать в одном классе благодаря перегрузке функций

Фактически, вы можете определить любое количество конструкторов до тех пор, пока у них будут уникальные параметры (учитывается их количество и тип).

Как использовать конструктор с параметрами? Всё просто! Прямая инициализация:

int a(7); // прямая инициализация Fraction drob(4, 5); // инициализируем напрямую, вызывается конструктор Fraction(int, int)

1 2

inta(7);// прямая инициализация

Fraction drob(4,5);// инициализируем напрямую, вызывается конструктор Fraction(int, int)

Здесь мы инициализировали нашу дробь числами и , результат — !

В C++11 мы также можем использовать uniform-инициализацию:

int a { 7 }; // uniform-инициализация Fraction drob {4, 5}; // uniform-инициализация, вызывается конструктор Fraction(int, int)

1 2

inta{7};// uniform-инициализация

Fractiondrob{4,5};// uniform-инициализация, вызывается конструктор Fraction(int, int)

Мы также можем указать только один параметр для конструктора с параметрами, а второе значение будет значением по умолчанию:

Fraction seven(7); // вызывается конструктор Fraction(int, int), второй параметр использует значение по умолчанию

1 Fraction seven(7);// вызывается конструктор Fraction(int, int), второй параметр использует значение по умолчанию

Значения по умолчанию для конструкторов работают точно так же, как и для любой другой функции, поэтому в вышеприведенном примере, когда мы вызываем , вызывается , второй параметр которого равен (значение по умолчанию).

Правило: Используйте прямую инициализацию или uniform-инициализацию с объектами ваших классов.

Промежуточный итог

Цель достигнута: пылесос разговаривает. Я рад, что не стал городить слишком много сразу всего. Следующий шаг связать распознавание образов с потоком, регулирующим движение, а также попробовать transfer learning.

Искусственный интеллект, тема настолько объемная, что сложно определить, за что взяться в первую очередь. На мой взгляд не существует единой точки входа. Совсем не обязательно начинать с вычисления сложных производных или курсов программирования на Python (хотя и то и другое безусловно полезно). Выбирайте то, что интересно лично вам, и да пребудет с вами сила довести начатое до конца.

P.S. Детали реализации лежат в репозитории. Комментарии и пулл реквесты приветствуются.


С этим читают