Use inheritance for my first program (python)

Who is the intruder ?

Setting up the program

Welcome to this first Ontologenius tutorial. In this tutorial, we will take over the Ontologenius API using an OntologyManipulator. This is the most important thing you need to know to use Ontologenius in a simple way. We will also see how to launch Ontologenius by configuring it according to our needs.

To illustrate the different objectives of this tutorial, we will develop a mini-game that will consist of finding the intruder among a list of words. However, finding only the intruder is a much too simple problem. That's why we will also try to find the reason why one word is the intruder among the others.

In this part, we will code the bases of our program from which we will be able to write the more algorithmic part. Before that, I invite you to create a new package that we will call "ontologenius_tutorial" and which will contain only one source file that we will name "intruder.py" in the scripts folder. To be sure that your new package will be well configured to use Ontologenius, we advise you to follow this guide. Do not forget to make it executable with:

chmod +x intruder.py

Now we are ready! Let's open our file and start coding:

#!/usr/bin/env python

import rospy
from std_msgs.msg import String

from ontologenius import OntologyManipulator

_onto = None
_names = []
_start = False

def say(text):
print('[SAY]' + text)

def summarize(words):
to_say = 'on '
for word in words:
to_say = to_say + word + ' '
return to_say

def wordCallback(msg):
global _start
global _names

if msg.data == 'start' :
_start = True
elif not msg.data in _names:
_names.insert(1, msg.data)

Take a break here, we have already written a lot. We will go over all this in detail to better understand what we have done.

import rospy

rospy is a convenience package that imports the most common public pieces of the ROS system.

from std_msgs.msg import String

This imports the ROS String message, which resides in the std_msgs ROS package. We use it to create a topic on which we will send the words from which our program will have to find the intruder.

from ontologenius import OntologyManipulator

This imports what we call an ontology manipulator. This class is just an object to access all API ROS abstraction classes so that you can query and manage Ontologenius. You can find the documentation for this object on the left panel.

_onto = None

As explained above, the ontology manipulator contains several objects to abstract ROS services. The set of services work in a connected mode which allows to greatly save in execution time but which makes the program less robust. For the lack of robustness, each Ontologenius client takes care of everything for you by implementing recovery mechanisms. As for the connected mode, this means that the connection is established at the creation of the object and is broken only at its destruction. So we understand that it is better to avoid creating several ontology manipulators but it is better to create a single instance for our entire program. For convenience, we create here a global variable which will be our ontologyManipulator but in more common use we suggest you define it in a class.

_names = []

This list will allow us to store the different words on which we will perform our search for the intruder.

_start = False

This is our synchronization variable. This variable will be False as long as we continue to collect words and we will put it in the True state as long as we wish to start the search for the intruder.

def say(text):

Here, the say function is just an on-screen display, but you can customize it to use a TTS for example.

def summarize(words):

Here, the summarize function concatenates several words in a single string. We created this function just to make our main function more readable.

def wordCallback(msg):

Here we have the callback function of our input topic. This topic thus receives strings which will be the words from which our program will have to find the intruder. Inside the function, we can see that we use the word "start" as a synchronization word that will launch our reasoning. The different words of "start" are then stored in the list _names pending processing. To add security, line 27 verifies that the word is not already present in the _names list to avoid duplicates.



We have everything we need to start writing the main function to retrieve the list of words to work on and start the reasoning although we do not have it yet.

def main():
global _names
global _start
global _onto

rospy.init_node('intruder')

_onto = OntologyManipulator()
_onto.close()

rospy.Subscriber("intruder/input", String, wordCallback)
rate = rospy.Rate(100)
while not rospy.is_shutdown():

_start = False

say('Let\'s play!')

while (not rospy.is_shutdown()) and (_start == False):
rate.sleep()

say(summarize(_names))

#
# We will find the intruder here
#

_names = []

if __name__ == "__main__":
main()

Now, let's break the code down.

rospy.init_node('intruder')

Initialize a ROS node. This node is not mandatory to use Ontologenius in python but we need it for the ROS subscriber we create after.

_onto = OntologyManipulator()

We finally come back to using Ontologenius! We create here our first ontology manipulator, what a great day ... This manipulator is unique to fully enjoy the benefits of connected services.

_onto.close()

The close function link all the concepts loaded from files and the Internet. Before closing an ontology, exploration requests are not allowed.

_onto.actions.fadd('path/to/may/file.owl');
# OR
_onto.actions.add('http://path/to/my/file.owl');
_onto.close();

For the moment, we are going to consider that the ontological file we are going to work on is provided in the Ontologenius launcher. We will configure it in the next part of the tutorial. It is also possible to load files directly from the program (as above) but in doing so it makes our code less reusable.

rospy.Subscriber("intruder/input", String, wordCallback)

We initialise our subscriber to the topic 'intruder/input'. We also link this topic to our callback function.

while not rospy.is_shutdown():

Just our almost infinite loop. Escaping with a Ctrl + C.

_start = False

say('Let\'s play!')

We initialize the synchronization variable and inform the user that the program is ready to listen to the words.

while (not rospy.is_shutdown()) and (_start == False):

rate.sleep() avoids unnecessary use of the processor.

We only wait for the synchronisation...

say(summarize(_names))

We recall the words on which we will make the reasoning. It is just as a result of this that we will implement our reasoning.

_names = []

Our loop is over, we can erase the words we used and start over!

Now, you just have to compile that before going on to the following. Even if we are working with python, this command must be executed at least once to inform ROS of the presence of the executable.

catkin_make

Do not forget that this command must be done in your workspace