Ответ
 
Опции темы Поиск в этой теме
Старый 12.05.2016, 09:59   #1
RobotControlTechnologies
Новичок
 
Регистрация: 11.05.2016
Сообщения: 5
Сказал Спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении
Сообщение Runtime программирование промышленного робота на RCML



Под runtime программированием в этой статье понимается процесс создания исполняемой программы для контроллера робота (далее просто робота) на внешнем контроллере. Процесс исполнения роботом созданной программы в таком случае, происходит итерационно, путем передачи ему минимальной исполняемой команды или пакета команд. Другими словами, при runtime программировании, исполняемая программа передаётся роботу порционно, при этом робот не обладает, не хранит и не знает заранее всю исполняемую программу. Такой подход позволяет создать абстрактную параметризованную исполняемую программу, которая формируется внешним устройством «на ходу», т.е. runtime.

Далее описание и реальный пример того, как работает runtime программирование.

Программа для робота также может содержать примитивную управляющую логику (ветвления, циклы), простые математические операции, а также команды по управлению периферией – аналоговыми и цифровыми входами/выходами. В предлагаемом подходе runtime программирования, в качестве внешнего контроллера используется обычный ПК, на котором могут быть использованы мощные средства программирования дающие необходимый уровень абстракции (ООП и прочие парадигмы) и инструменты, обеспечивающие скорость и легкость разработки сложной логики (высокоуровневые языки программирования). На роботе же остается только логика критичная к скорости реакции, для исполнения которой нужна надежность промышленного контроллера, например, оперативная и адекватная реакция на внештатную ситуацию. Управление же периферией, подключенной к роботу, попросту «проксируется» самим роботом на ПК, позволяя ПО с ПК включать или выключать соответствующие сигналы на роботе. Это чем-то похоже на управление «ножками» на Arduino.



Как отмечалось ранее, runtime программирование позволяет передавать роботу программу порционно – частями. Обычно за один раз передается набор состояний выходных сигналов и небольшое число точек или вообще только одна точка. Таким образом траектория перемещений TCP, выполняемая роботом, может строиться динамически и отдельные её части могут принадлежать как разным технологическим процессам, так и даже разным роботам (подключенным к одному внешнему контроллеру), если работает группа роботов, т.е. возникают предпосылки для динамического замещения роботов в технологическом процессе.

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

В качестве примера, рассмотрим создание программы робота в runtime режиме, обеспечивающей технологический процесс написания объявления маркером.

Результат:

ВНИМАНИЕ! Видео не является рекламой, вакансия закрыта. Статья написана после того, как видео потеряло свою актуальность, для того, чтобы продемонстрировать предлагаемый подход программирования.

Написанный текст:
Код:
ПРИВЕТ, ЛЮДИ! НАМ НУЖЕН
РАЗРАБОТЧИК.ДЛЯ СОЗДАНИЯ ВЕБ
ИНТЕРФЕЙСА СИСТЕМЫ НАШИХ
ЗНАНИЙ. ТАК МЫ СМОЖЕМ ПЕРЕНЯТЬ 
ОТ ВАС ГУМАНОЙДОВ ЗНАНИЯ.

И НАКОНЕЦ-ТО МЫ СМОЖЕМ 
ЗАХВАТИТЬ УЛУЧШИТЬ ЭТОТ МИР

ПОДРОБНЕЕ: HTTP://ROBOTCT.COM/HI
  ИСКРЕННЕ ВАШ SKYNET =^-^=
Для написания этого текста потребовалось передать роботу более 1700 точек.

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


Если писать программу подобный образом, то это было бы минимум 1700 операторов - строк кода, по оператору на точку. А что если бы потом потребовалось изменить текст или высоту букв, или расстояние между ними? Править все 1700 точек-строк? Это противоречит духу автоматизации!

Итак, приступим к решению…

Имеем робота FANUC LR Mate 200iD с котроллером R-30i серии B cabinet. У робота предварительно настроена TCP на конце маркера и координатная система рабочего стола, поэтому мы можем отправлять координаты, напрямую не заботясь о преобразовании координат из координатной системы стола в координатную систему робота.

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

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

Чтобы написать текст нам потребуется вызвать последовательность функций, рисующих буквы в такой же последовательности, в которой они (буквы) указаны в тексте. RCML имеет скудный инструментарий для работы со строками, поэтому сделаем внешний скрипт на Python, который будет генерировать программу на RCML – по сути генерировать только последовательность вызовов функций соответствующих последовательности букв.

Весь код доступен в репозитории на GitHub: rct_paint_words

Рассмотрим подробнее выходной файл, исполнение начинается с функции main():

Пример выходного файла на языке RCML:
Код:
include "chars.rcml"
function main(){
  try {
//Задействование робота
    @fr = robot_fanuc;
    system.echo("Start move programn");
//Предварительная настройка окружения робота, координатная система, нагрузка, скорость
    @fr->set_real_di("speed", SPEED);
    @fr->set_real_di("cnt", CNT);
    @fr->startProgram(UFRAME, UTOOL, PAYLOAD);

    system.echo("preparen");
    @fr->prepare();
    system.echo("start drawn");
//Сгенерированный, на Python, участок
    @fr->draw_r_P(0, 0);
    @fr->draw_P(1, 0);
    @fr->draw_r_I(2, 0);
    @fr->draw_B(3, 0);
    @fr->draw_E(4, 0);
    @fr->draw_T(5, 0);
    @fr->draw_Comm(6, 0);

    @fr->draw_r_L(8, 0);
    @fr->draw_r_Yu(9, 0);
    @fr->draw_r_D(10, 0);
    @fr->draw_r_I(11, 0);
    @fr->draw_Exclamation(12, 0);

    @fr->draw_H(14, 0);
    @fr->draw_A(15, 0);
    @fr->draw_M(16, 0);

    @fr->draw_H(18, 0);
    @fr->draw_r_U(19, 0);
    @fr->draw_r_Je(20, 0);
    @fr->draw_E(21, 0);
    @fr->draw_H(22, 0);

    @fr->draw_P(0, 1);
    @fr->draw_A(1, 1);
    @fr->draw_r_Z(2, 1);
    @fr->draw_P(3, 1);
    @fr->draw_A(4, 1);
    @fr->draw_r_B(5, 1);
    @fr->draw_O(6, 1);
    @fr->draw_T(7, 1);
    @fr->draw_r_Che(8, 1);
    @fr->draw_r_I(9, 1);
    @fr->draw_K(10, 1);
    @fr->draw_Dot(11, 1);
    @fr->draw_r_D(12, 1);
    @fr->draw_r_L(13, 1);
    @fr->draw_r_Ya(14, 1);

    @fr->draw_C(16, 1);
    @fr->draw_O(17, 1);
    @fr->draw_r_Z(18, 1);
    @fr->draw_r_D(19, 1);
    @fr->draw_A(20, 1);
    @fr->draw_H(21, 1);
    @fr->draw_r_I(22, 1);
    @fr->draw_r_Ya(23, 1);

    @fr->draw_B(25, 1);
    @fr->draw_E(26, 1);
    @fr->draw_r_B(27, 1);

    @fr->draw_r_I(0, 2);
    @fr->draw_H(1, 2);
    @fr->draw_T(2, 2);
    @fr->draw_E(3, 2);
    @fr->draw_P(4, 2);
    @fr->draw_r_F(5, 2);
    @fr->draw_E(6, 2);
    @fr->draw_r_Ii(7, 2);
    @fr->draw_C(8, 2);
    @fr->draw_A(9, 2);

    @fr->draw_C(11, 2);
    @fr->draw_r_I(12, 2);
    @fr->draw_C(13, 2);
    @fr->draw_T(14, 2);
    @fr->draw_E(15, 2);
    @fr->draw_M(16, 2);
    @fr->draw_r_y(17, 2);

    @fr->draw_H(19, 2);
    @fr->draw_A(20, 2);
    @fr->draw_r_Sha(21, 2);
    @fr->draw_r_I(22, 2);
    @fr->draw_X(23, 2);

    @fr->draw_r_Z(0, 3);
    @fr->draw_H(1, 3);
    @fr->draw_A(2, 3);
    @fr->draw_H(3, 3);
    @fr->draw_r_I(4, 3);
    @fr->draw_r_Ii(5, 3);
    @fr->draw_Dot(6, 3);

    @fr->draw_T(8, 3);
    @fr->draw_A(9, 3);
    @fr->draw_K(10, 3);

    @fr->draw_M(12, 3);
    @fr->draw_r_y(13, 3);

    @fr->draw_C(15, 3);
    @fr->draw_M(16, 3);
    @fr->draw_O(17, 3);
    @fr->draw_r_Je(18, 3);
    @fr->draw_E(19, 3);
    @fr->draw_M(20, 3);

    @fr->draw_r_P(22, 3);
    @fr->draw_E(23, 3);
    @fr->draw_P(24, 3);
    @fr->draw_E(25, 3);
    @fr->draw_H(26, 3);
    @fr->draw_r_Ya(27, 3);
    @fr->draw_T(28, 3);
    @fr->draw_soft_sign(29, 3);

    @fr->draw_O(0, 4);
    @fr->draw_T(1, 4);

    @fr->draw_B(3, 4);
    @fr->draw_A(4, 4);
    @fr->draw_C(5, 4);

    @fr->draw_r_Ge(7, 4);
    @fr->draw_r_U(8, 4);
    @fr->draw_M(9, 4);
    @fr->draw_A(10, 4);
    @fr->draw_H(11, 4);
    @fr->draw_O(12, 4);
    @fr->draw_r_Ii(13, 4);
    @fr->draw_r_D(14, 4);
    @fr->draw_O(15, 4);
    @fr->draw_B(16, 4);

    @fr->draw_r_Z(18, 4);
    @fr->draw_H(19, 4);
    @fr->draw_A(20, 4);
    @fr->draw_H(21, 4);
    @fr->draw_r_I(22, 4);
    @fr->draw_r_Ya(23, 4);
    @fr->draw_Dot(24, 4);

//Изменение ориентации маркера, чтобы роботу было проще дотянуться до края стола
    @fr->set_real_di("speed", 10); 
    @fr->rotateMarker();
    @fr->set_real_di("speed", SPEED); 

    @fr->draw_r_I(0, 6);

    @fr->draw_H(2, 6);
    @fr->draw_A(3, 6);
    @fr->draw_K(4, 6);
    @fr->draw_O(5, 6);
    @fr->draw_H(6, 6);
    @fr->draw_E(7, 6);
    @fr->draw_r_Ce(8, 6);
    @fr->draw_Minus(9, 6);
    @fr->draw_T(10, 6);
    @fr->draw_O(11, 6);

    @fr->draw_M(13, 6);
    @fr->draw_r_y(14, 6);

    @fr->draw_C(16, 6);
    @fr->draw_M(17, 6);
    @fr->draw_O(18, 6);
    @fr->draw_r_Je(19, 6);
    @fr->draw_E(20, 6);
    @fr->draw_M(21, 6);

    @fr->draw_r_Z(0, 7);
    @fr->draw_A(1, 7);
    @fr->draw_X(2, 7);
    @fr->draw_B(3, 7);
    @fr->draw_A(4, 7);
    @fr->draw_T(5, 7);
    @fr->draw_r_I(6, 7);
    @fr->draw_T(7, 7);
    @fr->draw_soft_sign(8, 7);

    @fr->draw_r_U(10, 7);
    @fr->draw_r_L(11, 7);
    @fr->draw_r_U(12, 7);
    @fr->draw_r_Che(13, 7);
    @fr->draw_r_Sha(14, 7);
    @fr->draw_r_I(15, 7);
    @fr->draw_T(16, 7);
    @fr->draw_soft_sign(17, 7);

    @fr->draw_r_aE(19, 7);
    @fr->draw_T(20, 7);
    @fr->draw_O(21, 7);
    @fr->draw_T(22, 7);

    @fr->draw_M(24, 7);
    @fr->draw_r_I(25, 7);
    @fr->draw_P(26, 7);

    @fr->draw_r_P(0, 9);
    @fr->draw_O(1, 9);
    @fr->draw_r_D(2, 9);
    @fr->draw_P(3, 9);
    @fr->draw_O(4, 9);
    @fr->draw_r_B(5, 9);
    @fr->draw_H(6, 9);
    @fr->draw_E(7, 9);
    @fr->draw_E(8, 9);
    @fr->draw_two_dots(9, 9);

    @fr->draw_H(11, 9);
    @fr->draw_T(12, 9);
    @fr->draw_T(13, 9);
    @fr->draw_P(14, 9);
    @fr->draw_two_dots(15, 9);
    @fr->draw_Slash(16, 9);
    @fr->draw_Slash(17, 9);
    @fr->draw_R(18, 9);
    @fr->draw_O(19, 9);
    @fr->draw_B(20, 9);
    @fr->draw_O(21, 9);
    @fr->draw_T(22, 9);
    @fr->draw_C(23, 9);
    @fr->draw_T(24, 9);
    @fr->draw_Dot(25, 9);
    @fr->draw_C(26, 9);
    @fr->draw_O(27, 9);
    @fr->draw_M(28, 9);
    @fr->draw_Slash(29, 9);
    @fr->draw_H(30, 9);
    @fr->draw_I(31, 9);

    @fr->draw_r_I(2, 10);
    @fr->draw_C(3, 10);
    @fr->draw_K(4, 10);
    @fr->draw_P(5, 10);
    @fr->draw_E(6, 10);
    @fr->draw_H(7, 10);
    @fr->draw_H(8, 10);
    @fr->draw_E(9, 10);

    @fr->draw_B(11, 10);
    @fr->draw_A(12, 10);
    @fr->draw_r_Sha(13, 10);

    @fr->draw_S(15, 10);
    @fr->draw_K(16, 10);
    @fr->draw_Y(17, 10);
    @fr->draw_N(18, 10);
    @fr->draw_E(19, 10);
    @fr->draw_T(20, 10);

    @fr->draw_Equal(22, 10);
    @fr->draw_Roof(23, 10);
    @fr->draw_Minus(24, 10);
    @fr->draw_Roof(25, 10);
    @fr->draw_Equal(26, 10);
// Конец сгенерированного участка
    @fr->stopProgram();
    @fr->go_home();
  } catch(E){
    system.echo("Exception catched!");
    return E;
  }
  return 0;
}
Рассмотрим код отрисовки буквы на примере буквы А:
Код:
function robot_fanuc::draw_A(x_cell,y_cell){
  
  //Постановка маркера в точку, координаты точки 5% по Х и 95% по Y в рамке буквы
  robot->setPoint(x_cell, y_cell, 5, 95); 
  //Ведем линию
  robot->movePoint(x_cell, y_cell, 50, 5);
  //Ведем вторую линию
  robot->movePoint(x_cell, y_cell, 95, 95);
  //Получили "крышу" /

  //Переносим маркер с отрывом от стола для отрисовки палочки
  robot->setPoint(x_cell, y_cell, 35, 50);
  //Рисуем палочку
  robot->movePoint(x_cell, y_cell, 65, 50);

  //отрываем маркер от доски для перехода к следующей букве
  robot->marker_up();
}
Функции перемещения маркера в точку с отрывом или без, тоже очень просты:
Код:
//Перемещение в точку с отрывом маркера или установка точки для начала рисования
function robot_fanuc::setPoint(x_cell, y_cell, x_percent, y_precent){
  //вычисляем абсолютные координаты
  x = calculate_absolute_coords_x(x_cell, x_percent);
  y = calculate_absolute_coords_y(y_cell, y_precent);
  
  robot->marker_up(); // отрываем маркер от стола
  robot->marker_move(x,y); // перемещаем
  robot->marker_down(); // ставим маркер на стол
}

//Перемещение в точку без отрыва маркера/рисование
function robot_fanuc::movePoint(x_cell, y_cell, x_percent, y_precent){
  x = calculate_absolute_coords_x(x_cell, x_percent);
  y = calculate_absolute_coords_y(y_cell, y_precent);
  
  // тут все понятно :)
  robot->marker_move(x,y);
}
Функции marker_up, marker_down, marker_move содержат лишь код передачи роботу изменившейся части координаты точки TCP (Z или XY)
Код:
function robot_fanuc::marker_up(){
  robot->set_real_di("z", SAFE_Z);
  er = robot->sendMoveSignal();
  if (er != 0){
    system.echo("error marker upn");
    throw er;
  }
}

function robot_fanuc::marker_down(){ 
  robot->set_real_di("z", START_Z);
  er = robot->sendMoveSignal();
  if (er != 0){
    system.echo("error marker downn");
    throw er;
  }
}

function robot_fanuc::marker_move(x,y){
  robot->set_real_di("x", x);
  robot->set_real_di("y", y);
  er = robot->sendMoveSignal();
  if (er != 0){
    system.echo("error marker moven");
    throw er;
  }
}
Все константы конфигурации, в том числе размер букв, их количество в строке и пр. были вынесены в отдельный файл chars_config.rcml.

Файл конфигурации chars_config.rcml:
Код:
define CHAR_HEIGHT_MM 50      // Высота символов в мм
define CHAR_WIDTH_PERCENT 60  // Ширина символов в процентах от высоты

define SAFE_Z -20  // Безопасное положение наконечника маркера по оси z
define START_Z 0   // Рабочее положение наконечника маркера по оси z

// Границы рабочей зоны
define BORDER_Y 120
define BORDER_X 75

// Сигналы ON/OFF
define ON  1
define OFF 0

// Паузы между отправкой сигналов мс 
define _SIGNAL_PAUSE_MILLISEC 50
define _OFF_PAUSE_MILLISEC 200

// Углы Эйлера начального положения маркера – углы ориентации инструмента
define START_W -179.707  // Крен
define START_P -2.500    // Тангаж
define START_R 103.269   // Рыскание

// Углы Эйлера после поворота маркера
define SECOND_W -179.704  // Крен
define SECOND_P -2.514    // Тангаж
define SECOND_R -14.699   // Рыскание

define CHAR_OFFSET_MM 4  // Отступ между буквами

define UFRAME 4     // Номер стола
define UTOOL 2      // Номер инструмента
define PAYLOAD 4    // Номер нагрузки
define SPEED 100    // Скорость
define CNT 0        // Параметр сглаженности перемещения
define ROTATE_SPEED // Скорость при повороте

define HOME_PNS 4  // Номер PNS программы перехода в домашнюю позицию
В итоге суммарно мы получили примерно 300 строк высокоуровневого кода, на проектирование и написание которого ушло не более 2 часов.

Если бы данная задача решалась «в лоб» онлайн программированием по точкам, то на это бы ушло более 9 часов (примерно по 20-25 сек на точку, с учетом того, что точек более 1700 шт.). В этом случае страдания разработчика трудно представить , особенно когда выяснилось бы, что он забыл про отступы между буквами, или ошибся с высотой букв и текст не влез, и теперь придется начинать всё с начала.

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

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

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

Однако данный подход следует использовать с осторожностью. В продемонстрированной вариации (с передачей одной точки за раз) runtime подход имеет существенное ограничение – некорректное понимание роботом инструкции сглаживания перемещения (CNT) или её игнорирование, т.к. при передаче всегда одной-текущей точки робот ничего не знает о следующей и не может просчитать сглаженную траекторию обхода текущей точки.

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

Надеюсь, статья оказалась Вам полезной.
С радостью отвечу на Ваши вопросы.
RobotControlTechnologies вне форума   Ответить с цитированием
Старый 12.05.2016, 20:06   #2
lexx905
Гуру
 
Регистрация: 11.11.2015
Сообщения: 119
Сказал Спасибо: 0
Сказали Спасибо 7 раз(а) в 7 сообщении
По умолчанию

красавцы!!!!!
lexx905 вне форума   Ответить с цитированием
Старый 13.05.2016, 14:32   #3
Kirill_Kolobov
Бывалый
 
Регистрация: 04.03.2016
Сообщения: 21
Сказал Спасибо: 2
Сказали Спасибо 0 раз(а) в 0 сообщении
По умолчанию

хорошая работа. молодцы!

а какое прикладное применение?
Kirill_Kolobov вне форума   Ответить с цитированием
Старый 14.05.2016, 11:53   #4
RobotControlTechnologies
Новичок
 
Регистрация: 11.05.2016
Сообщения: 5
Сказал Спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении
По умолчанию

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

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

2. в технологии плазменной 3д наплавки на сварочном комплексе каф. сварки пермского национально-исследовательского политехнического университета. там с помощью сварочного аппарата (дуговая сварка или плазмотрон) путем наплавки производится изготовление роботом изделия из металла. по сути робот работает, как 3д-принтер, то по металлу. за счет большой досягаемости робота можно производить большие изделия, не требовательные к точности изготовления. точность плавает в порядках нескольких миллиметров для изделий размерами порядка 20х20х20 см. если изделие ещё больше, то точность «плывет» сильнее. изделие потом конечно отправляется на доработку на станке, но разовое изготовление чего-то уникального или небольшой партии получается дешевым. и тут тоже потребовалась адаптивность, т.к. физика процессов очень сложная, первые слои металла выкладываются с одним шагом, последующие с другим, причем шаг для очередного слоя очень сильно меняется от характера самого металла и размера изделия (чем меньше изделие, тем меньше оно успевает остыть и нижние слои начинают спекаться). и тут приходиться тоже просчитывать траекторию на ходу, причем стандартные решения по получению траекторий из 3д моделей не подошли, т.к. не учитывают сложную физику термодинамических процессов. этот проект на следующей неделе сдаем в эксплуатацию. хотели с этим комплексом совместно со сварщиками приехать на металлообработку-2016, но не успеваем изготовить стенд.
RobotControlTechnologies вне форума   Ответить с цитированием
Старый 06.06.2016, 15:35   #5
Андрей Косцов
Гуру
 
Регистрация: 24.06.2015
Сообщения: 76
Сказал Спасибо: 11
Сказали Спасибо 11 раз(а) в 10 сообщении
По умолчанию

Ваш робот же в This is Хорошо был :3
Андрей Косцов вне форума   Ответить с цитированием
cказали "Спасибо" Андрей Косцов за это сообщение:
Старый 06.06.2016, 15:54   #6
RobotControlTechnologies
Новичок
 
Регистрация: 11.05.2016
Сообщения: 5
Сказал Спасибо: 1
Сказали Спасибо 0 раз(а) в 0 сообщении
По умолчанию

Да, действительно, это так.

Если быть точнее в выпуск #503 c 7:59

RobotControlTechnologies вне форума   Ответить с цитированием
Старый 27.07.2016, 20:49   #7
lexx905
Гуру
 
Регистрация: 11.11.2015
Сообщения: 119
Сказал Спасибо: 0
Сказали Спасибо 7 раз(а) в 7 сообщении
По умолчанию

lexx905 вне форума   Ответить с цитированием
Ответ
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +2, время: 16:44.

vBulletin v3.6.2, Copyright ©2000-2024, Jelsoft Enterprises Ltd.
Русский перевод: zCarot, Vovan & Co