Визуальное представление прямой задачи кинематики промышленного робота ABB IRB 140 с помощью CoppeliaSim и Lazarus

от автора

При моделировании робототехнических систем в программном комплексе CoppeliaSim пользователь сталкивается с необходимостью создания настраиваемого пользовательского интерфейса (сustom user interfaces). CoppeliaSim предлагает создание настраиваемого пользовательского интерфейса  с помощью штатного стредства – встроенного плагина Qt.

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

В рамках данной статьи рассмотрим процесс создания пользовательского интерфейса в Lazarus (бесплатный аналог Delphi). В качестве примера возмем модель промышленного робота ABB IRB 140.

Запустим CoppeliaSim и добавим модель робота ABB IRB 140 на сцену. Для этого в обзорщике моделей в дереве robots необходимо выбирать no-mobile и перетащить промышленного робота ABB IRB 140 на сцену. Модель промышленного робота ABB IRB 140 представлена на рисунке 1.

Рисунок 1 – Модель промышленного робота ABB IRB 140
Рисунок 1 – Модель промышленного робота ABB IRB 140

Далее необходимо удалить ненужные объекты из иерархии сцены, как показано на рисунке 2.

Рисунок 2 – Иерархия сцены после удаления ненужных объектов
Рисунок 2 – Иерархия сцены после удаления ненужных объектов

Для всех шарниров (IRB140_joint1…IRB140_joint6) в окне Scene Object Properties во вкладке Joint в поле Mode значение Torque/force mode необходимо изменить на Passive mode.

Далее приступим к разработке управляющего скрипта.

Связь между программами будем осуществлять посредством TCP/IP протокола по 5050 сокету. В качестве клиента будет выступать приложение, созданное в Lazarus, в качестве сервера  – CoppeliaSim.

Клиент на сервер будет передавать информацию в следующем виде:

[FK#J1=0.00,J2=0.00,J3=0.00,J4=0.00,J5=0.00,J6=0.00]

Наш управляющий скрипт для CoppeliaSim:

local socket = require("socket") local server = assert(socket.bind("*", 5050)) local tcp = assert(socket.tcp())  function sysCall_init()      simJoints={}     for i=1,6,1 do         simJoints[i]=sim.getObjectHandle('IRB140_joint'..i)     end end  function sysCall_actuation()  local client = server:accept()      --print("request received")      client:settimeout(10)      local packet, err = client:receive()      if not err then         --print("received from client=",packet)                  cmd=string.sub(packet, 2,3)                 -----------------------------------------------         if string.find(cmd, "FK") then                       i= string.find(packet, "J1=")              j= string.find(packet, ",J2=")              j1=string.sub(packet, i+3, j-1)              j1=string.gsub(j1, ",", ".")              j1=tonumber(j1)                            -------------------------------              i= string.find(packet, "J2=")              j= string.find(packet, ",J3=")              j2=string.sub(packet, i+3, j-1)              j2=string.gsub(j2, ",", ".")              j2=tonumber(j2)               -------------------------------              i= string.find(packet, "J3=")              j= string.find(packet, ",J4=")              j3=string.sub(packet, i+3, j-1)              j3=string.gsub(j3, ",", ".")              j3=tonumber(j3)                 -------------------------------              i= string.find(packet, "J4=")              j= string.find(packet, ",J5=")              j4=string.sub(packet, i+3, j-1)              j4=string.gsub(j4, ",", ".")              j4=tonumber(j4)              -------------------------------              i= string.find(packet, "J5=")              j= string.find(packet, ",J6=")              j5=string.sub(packet, i+3, j-1)              j5=string.gsub(j5, ",", ".")              j5=tonumber(j5)                 -------------------------------              i= string.find(packet, "J6=")              j= string.find(packet, "]")              j6=string.sub(packet, i+3, j-1)              j6=string.gsub(j6, ",", ".")              j6=tonumber(j6)                 -------------------------------              --print("J1=",j1)              --print("J2=",j2)              --print("J3=",j3)              --print("J4=",j4)              --print("J5=",j5)              --print("J6=",j6)              -------------------------------              sim.setJointPosition(simJoints[1],j1)              sim.setJointPosition(simJoints[2],j2)              sim.setJointPosition(simJoints[3],j3)              sim.setJointPosition(simJoints[4],j4)              sim.setJointPosition(simJoints[5],j5)              sim.setJointPosition(simJoints[6],j6)         end          client:send(packet .. "\n")       end      -- print("closing socket")       client:close()  end

С помощью string.gsub в принимаемой строке производим замену всех запятых на точки. Данное действие необходимо из-за русскоязычной локализации Windows.

Далее приступим к созданию клиента.

Узнаем максимальные значения углов поворота осей для промышленного робота ABB IRB 140 из документации на него (либо ищем в интернете). Не забываем, что на сервер мы отправляем значения углов в радианах.

Данная статья подразумевает некоторое умение работы с Delphi/Lazarus и знание их основных компонентов, поэтому опустим эти моменты. Подчеркнем лишь то, что для передачи на сервер мы формируем стоку в следующем виде:

[FK#J1=0.00,J2=0.00,J3=0.00,J4=0.00,J5=0.00,J6=0.00]

В разделе uses подключаем библиотеку WinSock.

В разделе var объявим следующие переменные:

S:TSocket; Addr:TSockAddr; Data:TWSAData; i: integer; b: byte; bfr: TBytes;

В обработчике нажатия кнопки «Старт» пишем следующий код:

procedure TForm1.Button1Click(Sender: TObject); begin  WSAStartup($101, Data); //загружаем WinSock;  Timer1.Enabled:=true; end;

Добавляем на форму компонент таймер TTimer и в обработчике событий таймера OnTimer пишем следующий код:

procedure TForm1.Timer1Timer(Sender: TObject); begin  s:=Socket(AF_INET, SOCK_STREAM,IPPROTO_IP); //создаем сокет  Addr.sin_family:=AF_Inet; //задаем семейство адресов  Addr.sin_port:=HToNS(5050); //задаем номер порта  Addr.sin_addr.S_addr:=Inet_Addr('127.0.0.1'); //задаем IP-адрес  FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0); //заполняем нулями поля  Connect(S,Addr,SizeOf(TSockAddr)); //подключаемся к серверу  st:='[FK#J1='+FloatToStr(j1)+',J2='+FloatToStr(j2)+',J3='+FloatToStr(j3)+',J4='+FloatToStr(j5)+',J5='+FloatToStr(j4)+',J6='+FloatToStr(j6)+']'; //передаваемая строка  bfr:= SysUtils.TEncoding.ASCII.GetBytes(st + chr(13) + chr(10)); // переводим строку в массив байтов  for i:=0 to ((Length(bfr))-1) do //отправляем данные на сервер по одному байту   begin   b:=bfr[i];   Send(S,b,1,0);   end;  Shutdown (s, 1); //завершение соединения  CloseSocket(S); //отключение от сервера  sleep(1); end;

В обработчике нажатия кнопки «Стоп» пишем следующий код:

procedure TForm1.Button2Click(Sender: TObject); begin  Timer1.Enabled:=false;  Shutdown (s, 1); //завершение соединения  CloseSocket(S); //отключение от сервера  WSACleanup(); //выгрузка сетевой библиотеки end;

В нашем случае приложение имеет вид, представленный на рисунке 3.

Рисунок 3 – Созданное в Lazarus приложение
Рисунок 3 – Созданное в Lazarus приложение

Исходный файл проекта располагается на сервисе GitHub по следующей ссылке.

Запускаем симулирование промышленного робота ABB IRB 140 в CoppeliaSim, нажимаем на кнопку «Старт» в окне нашего приложения созданного Lazarus и радуемся результатом – теперь моделью промышленного робота можно управлять.

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

Литература

1. Визуальное представление прямой задачи кинематики промышленного робота ABB IRB 140 с помощью CoppeliaSim и Qt. — Текст : электронный // Habr : [сайт]. — URL: https://habr.com/ru/post/598987/ (дата обращения: 29.01.2022).

2. LuaSocket API documentation. — Текст : электронный // Defold : [сайт]. — URL: https://defold.com/ref/beta/socket/ (дата обращения: 29.01.2022).

3. Использование сокетов в Delphi. Часть первая: стандартные сокеты. — Текст : электронный // Королевство Delphi : [сайт]. — URL: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1021 (дата обращения: 29.01.2022).

4. Фленов, М. Е. Delphi в шутку и всерьез: что умеют хакеры (+CD) / М. Е. Фленов. — СПб : Питер, 2006. — 271 c.

5. Lua 5.3 Руководство. — Текст : электронный // Lua : [сайт]. — URL: https://lua.org.ru/contents_ru.html (дата обращения: 29.01.2022).

6. String Library Tutorial. — Текст : электронный // lua-users wiki : [сайт]. — URL: http://lua-users.org/wiki/StringLibraryTutorial (дата обращения: 29.01.2022).

7. System.SysUtils.TEncoding.GetBytes.
— Текст : электронный // RAD Studio API Documentation : [сайт]. — URL:
https://docwiki.embarcadero.com/Libraries/Sydney/en/System.SysUtils.TEncoding.GetBytes
(дата обращения: 29.01.2022).


ссылка на оригинал статьи https://habr.com/ru/post/648531/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *