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

Программный комплекс CoppeliaSim позволяет строить разнообразные графики.

Начиная с версии 4.2.0 разработчики исключили из программы "графопостроитель" – графический интерфейс для построения графиков. Теперь все графики строятся скриптингом. Обосновывая это тем, что это позволяет гораздо более гибко и точно управлять графиками.

Построим график траектории движения мобильного робота pioneer p3dx. Для этого на панели меню выберем Add --> Graph. Доступ к его основным свойствам и их настройка осуществляются в диалоговом окне графика. Про объект Graph можно почитать ТУТ.

Добавим на сцену модель робота pioneer p3dx. Для этого в обзорщике моделей в дереве robots выберем mobile и перетащим робота pioneer p3dx на сцену.

Рисунок 1 – Робот pioneer p3dx

Если сейчас нажать на кнопку Play (Старт сцены), то робот поедет в прямом направлении, логика его работы содержится в прикреплённом скрипте.

Отредактируем скрипт таким образом, чтобы вместо прямолинейного движения робот осуществлял круговое. Для этого в функции sysCall_actuation() скорость правого колеса увеличим в два раза.

vRight=v0*2

Убедимся в круговой траектории движения мобильного робота запустив симуляцию.

Далее в скрипте содержащего логику работы мобильного робота в функции sysCall_init() добавим следующий код:

graph=sim.getObjectHandle('Graph')
objectHandle=sim.getObjectHandle('Pioneer_p3dx')
objectPosX=sim.addGraphStream(graph,'x','m',1)
objectPosY=sim.addGraphStream(graph,'y','m',1)
sim.addGraphCurve(graph,'object pos x/y',2,{objectPosX,objectPosY},{0,0},'m by m')

Где 'Graph' и 'Pioneer_p3dx' это имена объектов из иерархии сцены.

В теле скрипта добавим функцию sysCall_sensing().

function sysCall_sensing()
    
end

В функции sysCall_sensing() добавим следующий код:

pos=sim.getObjectPosition(objectHandle,-1)
sim.setGraphStreamValue(graph,objectPosX,pos[1])
sim.setGraphStreamValue(graph,objectPosY,pos[2])

Очистим график после окончания процесса симулирования. Для этого  в функции sysCall_cleanup() добавим следующую строку:

sim.resetGraph(graph)

И запустим процесс симулирования.

Рисунок 2 – График траектории движения

Точность позиционирования обусловлена влиянием физики на нашего мобильного робота.

Одним из самых интересных графиков – пространственная кривая движения механизма.

Приведем скрипт к первоначальному виду, оставив лишь увеличенную в два раза скорость правого колеса.

Далее в скрипте содержащую логику работы мобильного робота в функции  sysCall_init() добавим следующий код:

graph=sim.getObjectHandle('Graph')
base=sim.getObjectHandle('Pioneer_p3dx')
x=sim.addGraphStream(graph, 'x', 'm')

Строить будем зависимость x от времени t.

Добавим функцию sysCall_sensing().

function sysCall_sensing()
    
end

В функции sysCall_sensing() добавим следующий код:

p=sim.getObjectPosition(base,-1)
sim.setGraphStreamValue(graph, x, p[1])

Очистим график после окончания процесса симулирования. Для этого  в функцию очистки  sysCall_cleanup() добавим следующую строку:

sim.resetGraph(graph)

И запустим процесс симулирования.

Рисунок 3 – График зависимости x от времени t

Добавим вторую зависимость у от времени t.

Для этого в функции инициализации sysCall_init() добавим следующую строку:

y=sim.addGraphStream(graph, 'y', 'm')

В функции sysCall_sensing()добавим следующую строку:

sim.setGraphStreamValue(graph, y, p[2])

p[3] - это соответственно координата z.

Запустим процесс симулирования. Получим график изображенный на рисунке 4.

Рисунок 4 – График зависимости x, y от времени t

Из-за того что кривые одного цвета из графика сложно понять где какая переменная. Поэтому введем следующие изменения в описании переменных в функции sysCall_init():

x=sim.addGraphStream(graph, 'x', 'm', 0, {1,0,0})
y=sim.addGraphStream(graph, 'y', 'm', 0, {0,1,0})

Где {1,0,0} и {0,1,0} это значение цвета в RGB формате.

Запустим процесс симулирования. Получим график изображенный на рисунке 5.

Рисунок 5 – График зависимости x, y от времени t

Для построения графика зависимости скорости от времени создадим пользовательский интерфейс.

CoppeliaSim предлагает создание настраиваемого пользовательского интерфейса (сustom user interfaces) с помощью встроенного плагина Qt. При создании пользовательского интерфейса используется специальный XML синтаксис. Начиная с версии 4.2.0 разработчики полностью исключили возможность создания пользовательского интерфейса с помощью "OpenGl-based custom UI".

Пример синтаксиса плагина Qt наиболее хорошо отображен в учебной сцене customUI.ttt находящейся в корне папки scenes в месте установки программы.

В общем удалим и снова добавим на сцену модель робота pioneer p3dx.

Нам потребуется написать немного кода.

В функции sysCall_init() значение переменой v0=2 изменим на ноль:

v0=0

В конце функции sysCall_init() добавим следующий код:

xml = '<ui title="Speed" closeable="false" resizeable="false" activate="false">'..[[
<hslider minimum="0" maximum="1000" on-change="speedChange_callback" id="1"/>
</ui>
]]
ui=simUI.create(xml)

В функции sysCall_cleanup() добавим следующую строку:

simUI.destroy(ui)

В теле скрипта вставим следующую функцию:

function speedChange_callback(ui,id,newVal)
    v0=newVal*2/1000
end

Запустим симулирование. Теперь скоростью робота можно управлять.

Рисунок 6 – Симулирование робота pioneer p3dx

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

Приведем скрипт к первоначальному виду.

Далее в функции sysCall_init() удалим переменную v0=2 и инициализируем следующие переменные:

vl=0
vr=0

В конце тела функции sysCall_init() вставим следующий код:

xml = '<ui title="Speed" closeable="false" resizeable="false" activate="false">'..[[
<hslider minimum="0" maximum="1000" on-change="speedChange_callbackL" id="1"/>
<hslider minimum="0" maximum="1000" on-change="speedChange_callbackR" id="2"/>
</ui>
]]
ui=simUI.create(xml)

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

function speedChange_callbackL(ui,id,newVal)
    vl=newVal*2/1000
end

function speedChange_callbackR(ui,id,newVal)
    vr=newVal*2/1000
end

В функции sysCall_cleanup() добавим следующую строку:

simUI.destroy(ui) 

В функции sysCall_actuation() переменной vLeft и переменной vRight присвоим vl и vr соответственно вместо v0 .

vLeft=vl
vRight=vr

Запустим процесс симулирования.

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

Построим график зависимости скорости от времени.

В функции  sysCall_init() добавим следующий код:

graph=sim.getObjectHandle('Graph')
joint1Vel=sim.addGraphStream(graph,'joint 1 velocity','deg/s',0,{1,0,0})
joint2Vel=sim.addGraphStream(graph,'joint 2 velocity','deg/s',0,{0,1,0})

Добавим функцию sysCall_sensing().

function sysCall_sensing()
    
end

В функции sysCall_sensing() добавим следующий код:

sim.setGraphStreamValue(graph,joint1Vel,180*sim.getJointVelocity(motorLeft)/math.pi)
sim.setGraphStreamValue(graph,joint2Vel,180*sim.getJointVelocity(motorRight)/math.pi)

Очистим график после окончания процесса симулирования. Для этого  в функцию  sysCall_cleanup() добавим следующую строчку.

sim.resetGraph(graph)

Запустим процесс симулирования, поерзаем ползунками. Получим график изображенный на рисунке 7.

Рисунок 7 – График зависимости скорости от времени

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