Академический Документы
Профессиональный Документы
Культура Документы
Экспортирование знаний из OWL-онтологий в классы с помощью языков Python/C++ для непосредственного управления роботом
Экспортирование знаний из OWL-онтологий в классы с помощью языков Python/C++ для непосредственного управления роботом
ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
ВЫСШЕГО ОБРАЗОВАНИЯ
«САНКТ-ПЕТЕРБУРГСКИЙ ПОЛИТЕХНИЧЕСКИЙ
УНИВЕРСИТЕТ ПЕТРА ВЕЛИКОГО»
ИММиТ, кафедра «Мехатроника и роботостроение» при ЦНИИ РТК
Оценка:
Научный руководитель-консультант:
Абросимов Э.А.
Руководитель практики
от ФГАОУ ВО «СПбПУ» Габриель А.С.
Дата:
1
ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ
2
СОДЕРЖАНИЕ
ВВЕДЕНИЕ..............................................................................................................4
ТЕОРЕТИЧЕСКАЯ ЧАСТЬ...................................................................................5
1 OWL-ОНТОЛОГИИ.............................................................................................5
1.1 Язык OWL.....................................................................................................................
1.2 Основные элементы онтологий...................................................................................
1.3 Пример онтологии........................................................................................................
2 ОЗНАКОМЛЕНИЕ С НЕОБХОДИМЫМИ ПРОГРАММНЫМИ
ПРОДУКТАМИ.....................................................................................................11
2.1 Фреймворк Protégé.....................................................................................................
2.1.1 Использование Reasoner........................................................................11
2.2 Фреймворк ROS..........................................................................................................
2.2.1 Робот TurtleBot3.....................................................................................12
2.2.2 Gazebo......................................................................................................13
3 ОБЗОР БИБЛИОТЕК ДЛЯ РАБОТЫ С ОНТОЛОГИЯМИ...........................15
3.1 Cowl (язык программирования C++)........................................................................
3.2 Owlready2 (язык программирования Python)...........................................................
3.3 Выбор библиотеки......................................................................................................
ПРАКТИЧЕСКАЯ ЧАСТЬ...................................................................................18
4 МОДЕЛИРОВАНИЕ ПРОСТЕЙШИХ ЗАДАЧ...............................................18
4.1 Передача в онтологию сведений, на каком из участков находится робот
............................................................................................................................................
4.2 Передача в онтологию информации, обнаружен ли ОИ и если да, то
какой..................................................................................................................................
4.3 Получение из онтологии от Reasoner действий для робота...................................
ЗАКЛЮЧЕНИЕ.....................................................................................................25
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ............................................26
ПРИЛОЖЕНИЕ 1 ЛИСТИНГ КОДА УЗЛА-ПОДПИСЧИКА ROS.................28
ПРИЛОЖЕНИЕ 2 ЛИСТИНГ КОДА УЗЛА-ПУБЛИКАТОРА ROS...............31
3
ВВЕДЕНИЕ
4
ТЕОРЕТИЧЕСКАЯ ЧАСТЬ
1 OWL-ОНТОЛОГИИ
Онтология – способ формального представления понятий, называемых
классами, в некоторой области знаний и свойств, характеризующих эти
понятия. Такой способ представления знаний, как онтология может быть
использован как основа для базы знаний, при создании множества
индивидуальных экземпляров.
Процесс построения онтологии, согласно [1], состоит из создания
следующих блоков:
классов и их свойств (classes, properties);
свойств каждой концепции, описывающих различные
функциональные возможности и атрибуты концепции (слоты
(slots), иногда называемые роли);
ограничения по слотам (также известных как аспекты/грани (slot
facets), иногда называемые ограничения ролей).
Также в [1] названы причины возникновения потребности в разработке
онтологий:
совместное использование людьми или программными агентами
общего понимания структуры информации;
обеспечение возможности использования знаний предметной
области;
создание явных допущений в предметной области;
отделение знаний предметной области от оперативных знаний;
анализ знаний в предметной области.
1.1 Язык OWL
5
Формальная семантика OWL описывает, как получить логические
следствия, имея такую онтологию, то есть получить факты, которые не
представлены в онтологии буквально, но следуют из ее семантики [2].
Язык OWL, ранней версией которого является язык OIL, основывается
на XML, но имеет пару отличий, представленных в [2]:
онтология отличается от схемы XML тем, что это представление
знаний, а не формат сообщений;
доступность инструментов, которые могут рассуждать. Такие
инструменты обеспечивают общую поддержку, делая
строительство онтологии намного более доступным, чем
строительство четкой и работоспособной системы, чтобы
рассуждать в пределах одной XML схемы.
6
Свойства обладают некоторыми характеристиками, отвечающими за
логику онтологии [1].
TransitiveProperty. Если свойство P транзитивно, то справедливо
следующее:
∀ x , y , z ; P ( x , y ) ; P ( y , z ) → P( x , z) (1)
SymmetricProperty. Если свойство P симметрично, то
справедливо следующее:
∀ x , y ; P ( x , y )→ P ( y , x ) (2)
FunctionalProperty. Если свойство P функционально, то
справедливо следующее:
∀ x , y , z ; P ( x , y ) ; P ( x , z ) → y=z (3)
inverseOf. Если свойство P1 помечено, как inverseOf P2, то
справедливо следующее:
∀ x , y ; P 1 ( x , y ) → P 2( y , x ) (4)
InverseFunctionalProperty. Если свойство P обратно
функционально, то справедливо следующее:
∀ x , y , z ; P ( y , x ) ; P ( z , x ) → y=z (5)
1.3 Пример онтологии
8
Рисунок 2 – Экземпляры классов онтологии
Описание классов (все классы также являются непересекающимися)
представлено на рисунке 3.
9
Рисунок 5 – Описание свойств классов онтологии и их характеристики
10
2 ОЗНАКОМЛЕНИЕ С НЕОБХОДИМЫМИ ПРОГРАММНЫМИ
ПРОДУКТАМИ
Для выполнения работы использовались фреймворки Protégé и ROS,
описание которых приведено в подразделах этого раздела. Для установки
фреймворка Protégé был использован Docker.
Docker позволяет сначала «упаковать» приложение со всем его
окружением и зависимостями в контейнер, который может быть развернут на
любой Linux-системе, а также предоставляет набор команд для управления
этими контейнерами.
Это дало возможность использовать Protégé из командной строки.
2.1 Фреймворк Protégé
11
В OWL Reasoner работает на основе концепции “Open World
Reasoning” – OWR. Это рассуждение об открытости мира – категория,
которая обозначает открытость баз знаний, берущая основание на
предположении об открытости мира. Этот фактор выступает в качестве
принципиального отличия таких баз знаний от баз знаний, основанных на
предположении о замкнутости мира.
Так это говорит о возможности получения фактов путем вывода их
логическими рассуждениями.
То есть если какой-то тезис не был явно задан как истинный, нельзя
называть его строго ложным – предполагается же, что правдивость данного
тезиса не была занесена в базу знаний, а потому должна иметь
неопределенность своего значения.
Таким образом создаются явные допущения, что даёт возможность
изменять эти допущения при изменении влияющих на них знаний без ущерба
логике.
2.2 Фреймворк ROS
Операционная система робота (The Robot Operating System – ROS) –
это гибкая структура для написания программного обеспечения робота [5].
Иначе набор инструментов, библиотек и соглашений, направленных на
упрощение задачи создания сложного и надежного поведения роботов на
самых разных роботизированных платформах.
ROS основан на архитектуре графов [6]. Так вся обработка данных
производится в узлах графа, узлы в свою очередь могут получать и
передавать информацию через топики.
Внутри среды можно осуществлять картографирование, навигацию,
тестировать системы компьютерного зрения, строить симуляции и другое.
Всё это осуществляется с использованием различных ROS-ориентированных
пакетов.
Для работы была выбрана версия ROS Melodic, так как она подходит к
версии дистрибутива Ubuntu 18.04 операционной системы Linux.
12
2.2.1 Робот TurtleBot3
TurtleBot3 – один из стандартных платформенных роботов, которых
поддерживает ROS [7]. Это небольшой программируемый мобильный робот
на базе ROS для использования в образовательных целях, исследовательских
работах и прототипировании продуктов.
Основные технологии TurtleBot3 – это SLAM, навигация и
манипуляция, что делает его подходящим для домашних сервисных роботов.
TurtleBot3 может запускать алгоритмы SLAM (одновременной локализации и
картографирования) для построения карты.
Подробную инструкцию по работе с TurtleBot3 можно найти в [7].
TurtleBot3 поддерживает среду разработки моделирования, которая
может быть запрограммирована и разработана с помощью виртуального
робота в процессе моделирования. Для этого существует две среды
разработки: одна использует узел (fake node) с инструментом 3D-
визуализации RViz, а другая – 3D-симулятор робота Gazebo.
Узел fake node подходит для тестирования с моделью робота и
движения, но не поддерживает датчики. Gazebo же отлично подходит для
SLAM и навигации, так как он поддерживает такие датчики, как IMU, LDS и
камеру.
2.2.2 Gazebo
В ходе практической части работы будет использована среда Gazebo.
Это 3D динамический симулятор с возможностью точного и эффективного
моделирования роботов в сложных условиях [8]. Подобно игровым движкам,
Gazebo предлагает физическую симуляцию с гораздо более высокой
степенью точности, набор датчиков и интерфейсов как для пользователей,
так и для программ.
Gazebo может быть использована для:
тестирования алгоритмов робототехники;
проектирования роботов;
13
выполнение регрессионного тестирования с реалистическими
сценариями.
Также Gazebo имеет такие ключевые особенности, как:
несколько физических движков;
богатая библиотека моделей роботов и сред;
большое разнообразие датчиков;
удобные программные и графические интерфейсы.
Подробную инструкцию использования Gazebo можно найти в [8].
14
3 ОБЗОР БИБЛИОТЕК ДЛЯ РАБОТЫ С ОНТОЛОГИЯМИ
Для работы с онтологией посредством команд Protégé необходимо
использовать библиотеки для одного из языков программирования, которые
поддерживает ROS: C++ или Python. Для рассмотрения были предложены
две таких библиотеки на разных языках, ниже будет представлен обзор на
них и выбор той, с которой и будет проводиться работа.
3.1 Cowl (язык программирования C++)
15
3.2 Owlready2 (язык программирования Python)
16
критериев является запуск Reasoner непосредственно из этой библиотеки, без
обращения к Protégé. Таким требованиям удовлетворяет только одна из
рассмотренных библиотек – Owlready2 на Python, которая и будет
использована в практической части работы.
17
ПРАКТИЧЕСКАЯ ЧАСТЬ
TurtleBot3
OI11 Burger
Robot2 TurtleBot3
Area12 Area11 Waffle_pi
Robot1
OI21
Area22
Area21
18
публикуются данные о координатах робота. Для этого открывается
симулятор командой:
$ roslaunch turtlebot3_gazebo turtlebot3_empty_world.launch
Происходит загрузка мира, после чего узел Gazebo начинает
публикацию данных в топик, который можно определить, написав команду:
$ rosnode info gazebo
Из представленного списка топиков найдены топики, принимающие в
качестве сообщения одометрические данные (тип сообщения
nav_msgs/Odometry). Это топики /tb3_0/odom (для Robot1) и /tb3_1/odom (для
Robot2).
Информация о типе данных nav_msgs/Odometry предоставляется по
команде:
$ rosmsg info nav_msgs/Odometry
Нас будет интересовать м часть сообщения:
geometry_msgs/PoseWithCovariance pose
geometry_msgs/Pose pose
geometry_msgs/Point position
float64 x
float64 y
float64 z
Дальше был создан пакет, в котором объявляется узел-подписчик на
топики /tb3_0/odom и /tb3_1/odom.
В директории системы сборки catkin был создан пакет talkers с
зависимостью rospy (использование языка Python). Для того, чтобы узел
запускался из файла, нужно изменить CMakeLists.txt в только что созданном
пакете, добавив:
catkin_install_python(PROGRAMS
scripts/talker.py #Путь файла с кодом
DESTINATION talker)
Далее был написан код узла (см. Приложение 1).
Разбор нужных для этого задания строчек кода:
19
import sys
sys.path.append("/home/kirill")
import owlready2
from owlready2 import *
Данный код импортирует в файл программы библиотеку owlready2, так
как код должен взаимодействовать с онтологией.
onto=get_ontology("file:///home/kirill/data-docker/protege-docker-x11/
workspace/ Ontology_GroupOfRobots.owl").load()
В переменную onto проиcходит импорт онтологии с указанием пути до
неё, по этой переменной будет осуществляться обращение к онтологии.
import roslib
roslib.load_manifest('talkers')
import rospy
from nav_msgs.msg import Odometry
Эта часть кода импортирует библиотеки для связи с ROS, загружает
тип данных Odometry.
def listener():
rospy.init_node('listener', anonymous=True)
rospy.Subscriber("/tb3_0/odom", Odometry, callback1)
rospy.Subscriber("/tb3_1/odom", Odometry, callback2)
rospy.spin()
Код функции, где определяется имя узла, далее идёт команда, которая
считывает сообщение из /tb3_0/odom типа Odometry и передаёт его в
функцию callback(), вызывая её. Следующая команда совершает аналогичные
операции, только принимая значения положения Robot2. Последняя команда
обеспечивает бесконечную работу узла, пока он не будет закрыт вручную.
def callback1(data):
if ((data.pose.pose.position.x > 0)&(data.pose.pose.position.y > 0)):
onto.Robot1.BeInTheArea = [onto.Area11]
elif ((data.pose.pose.position.x <= 0)&(data.pose.pose.position.y > 0)):
20
onto.Robot1.BeInTheArea = [onto.Area12]
elif ((data.pose.pose.position.x <= 0)&(data.pose.pose.position.y <= 0)):
onto.Robot1.BeInTheArea = [onto.Area21]
else:
onto.Robot1.BeInTheArea = [onto.Area22]
onto.save(file = "NewOnto", format = "rdfxml")
Код данной функции определяет положение робота Robot1 по его
координатам. Переменная data.pose.pose.position.x (имя переменной взято из
вывода информации о типе данных nav_msgs/Odometry) хранит в себе
координату x, с y и z – аналогично. Так разбиение по секторам происходит по
принципу: если робот в первой четверти на координатной плоскости, то он на
Area11, на второй – Area12, на третьей – Area21, на четвёртой – Area22.
В конце происходит сохранение онтологии под именем NewOnto.
Функция callback2() аналогична и сделана для робота Robot2.
Изменения в онтологии (принадлежность роботов определенному
сектору) после запуска созданного узла представлены на рисунке 7.
21
В основном теле программы задаётся положение ОИ11 и ОИ21, был
создан индивидуум Nothing, который понадобится при выполнении функций
callback 1 и 2.
if (onto.Robot1.BeInTheArea == onto.OI11.BeInTheArea):
onto.Robot1.Find = [onto.OI11]
elif (onto.Robot1.BeInTheArea == onto.OI21.BeInTheArea):
onto.Robot1.Find = [onto.OI21]
else:
onto.Robot1.Find = [onto.Nothing]
Данный код был добавлен к функции callback1. Он вносит в онтологию
изменения по тому, нашел ли робот Robot1 ОИ11 или ОИ21. Для этого он
проверяет совпадает ли сектор робота с сектором одного из ОИ, при
совпадении передавая в онтологию информацию, что ОИ был найден. Если
же робот покинул сектор с ОИ, либо ещё не находил ОИ, то в онтологии
будет информация о том, что робот не нашёл ничего (как на рисунке 8).
22
Рисунок 9 – Новое положение робота Robot1
24
Данная функция создаёт локальную переменную типа Twist, изменяя её
в зависимости от условия: если найдет ОИ1, то робот Robot1 будет вращаться
быстрее и совершит больше оборотов, чем если будет обнаружен ОИ2. При
этом, если ничего обнаружено не будет, робот не предпримет никаких
действий.
Аналогичная функция написана и для робота Robot2.
Сохранение онтологии в данном случае не требуется, так как не
происходили её изменения.
25
ЗАКЛЮЧЕНИЕ
26
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
27
(дата обращения: 26.06.2021). – Режим доступа: свободный. — Текст:
электронный.
28
ПРИЛОЖЕНИЕ 1 ЛИСТИНГ КОДА УЗЛА-ПОДПИСЧИКА ROS
#!/usr/bin/env python3
#import OWL_files
import sys
sys.path.append("/home/kirill")
import owlready2
#import ROS_files
import roslib
roslib.load_manifest('talkers')
import rospy
#Download ontology
onto=get_ontology("file:///home/kirill/data-docker/protege-docker-x11/
workspace/Ontology_GroupOfRobots.owl").load()
def callback1(data):
onto.Robot1.BeInTheArea = [onto.Area11]
onto.Robot1.BeInTheArea = [onto.Area12]
onto.Robot1.BeInTheArea = [onto.Area21]
else:
onto.Robot1.BeInTheArea = [onto.Area22]
if (onto.Robot1.BeInTheArea == onto.OI11.BeInTheArea):
29
onto.Robot1.Find = [onto.OI11]
onto.Robot1.Find = [onto.OI21]
else:
onto.Robot1.Find = [onto.Nothing]
def callback2(data):
onto.Robot2.BeInTheArea = [onto.Area11]
onto.Robot2.BeInTheArea = [onto.Area12]
onto.Robot2.BeInTheArea = [onto.Area21]
else:
onto.Robot2.BeInTheArea = [onto.Area22]
if (onto.Robot2.BeInTheArea == onto.OI11.BeInTheArea):
onto.Robot2.Find = [onto.OI11]
onto.Robot2.Find = [onto.OI21]
else:
onto.Robot2.Find = [onto.Nothing]
def listener():
rospy.init_node('listener', anonymous=True)
30
rospy.Subscriber("/tb3_1/odom", Odometry, callback2)
rospy.spin()
if __name__ == '__main__':
onto.OI11.BeInTheArea = [onto.Area12]
onto.OI21.BeInTheArea = [onto.Area21]
Nothing = onto.ObjectOfInterest("Nothing")
listener()
31
ПРИЛОЖЕНИЕ 2 ЛИСТИНГ КОДА УЗЛА-ПУБЛИКАТОРА ROS
#!/usr/bin/env python3
#import OWL_files
import sys
sys.path.append("/home/kirill")
import owlready2
#import ROS_files
import roslib
roslib.load_manifest('talkers')
import rospy
#Download ontology
onto=get_ontology("file:///home/kirill/data-docker/protege-docker-x11/
workspace/
NewOnto").load()
def call1():
twist_robot1 = Twist()
if onto.Robot1.Find == [onto.OI11]:
twist_robot1.linear.x = 0.0
twist_robot1.angular.z = 2.0
twist_robot1.linear.x = 0.0
twist_robot1.angular.z = 1.0
else:
twist_robot1.linear.x = 0.0
32
twist_robot1.angular.z = 0.0
return twist_robot1
def call2():
twist_robot2 = Twist()
if onto.Robot2.Find == [onto.OI11]:
twist_robot2.linear.x = 0.0
twist_robot2.angular.z = 2.0
twist_robot2.linear.x = 0.0
twist_robot2.angular.z = 1.0
else:
twist_robot2.linear.x = 0.0
twist_robot2.angular.z = 0.0
return twist_robot2
def writer():
rospy.init_node('writer', anonymous=True)
for i in range(10):
sync_reasoner([onto])
pub1.publish(call1())
pub2.publish(call2())
rospy.sleep(2.0)
if __name__ == '__main__':
writer()
33