При моделировании робототехнических систем в программном комплексе 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.

Далее необходимо удалить ненужные объекты из иерархии сцены, как показано на рисунке 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.

Исходный файл проекта располагается на сервисе 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/
Добавить комментарий