Showing posts with label Prolog. Show all posts
Showing posts with label Prolog. Show all posts

2014-03-31

A MSc Thesis Study: A Planning Module for a ROS-Based Ubiquitous Robot Control System

I have recently finished my master's degree research project, which I did at the Robotics lab of the Control Systems Technology Section, Department of Mechanical Engineering, of Eindhoven University of Technology. However, I was a master student of Technical Artificial Intelligence at Utrecht University. My thesis is titled "A Planning Module for a ROS-Based Ubiquitous Robot Control System". My project involved a combination of automated planning, the Semantic Web and robotic technologies. In this blog post, I present my thesis work in a summarized way.

The life expectancy of people is increasing, therefore more professional caregivers are required to take care of the elderly. This results in more expensive health care. A desire for assistive technologies in health care is therefore growing to provide the caregivers to work in a more efficient way. Such assistive technologies are researched and developed at the robotics lab of Eindhoven University of Technology (TU/e) in the form of service robots.

An example of such a service robot is the Autonomous Mate for IntelliGent Operations (AMIGO) robot developed at the robotics lab of the TU/e. A picture of this robot can be seen in the figure below. It is a mobile robot with two arms. It could use its arms, for example, to pick up a drink for a patient and then hand it to the patient.


Research efforts are made to combine these robots with intelligent environments. An example of this is the research project described in my thesis. The idea is to have several service robots in an environment, such as a health care institution, and to have them controlled by a central control system. Therefore, a ubiquitous robotic framework for multi-robot planning and control is proposed. This framework integrates with existing design efforts of the open-source robotics community. The main focus of my research project is on the planning module of the proposed system.

For such a multi-robot control system, a planning module is needed to provide for flexibility. The system needs to be flexible so that it can be used in various different environments and with different types of robots. This planning module handles the planning and scheduling of multiple tasks for the robots in an intelligent way. Therefore, the field of automated planning for robotic systems is analyzed first in my thesis. This is followed by a literature study on subjects ranging from automated planning, to Semantic Web and robotic technologies, such that all fields of ubiquitous robotics are covered. Based on the analysis and the literature study requirements are formed for the system. These requirements are then used to create the design of the framework. Furthermore, a prototype of the framework is implemented and experiments are performed with this prototype. The results of these experiments are evaluated. The thesis also includes a comparison between the proposed system and other similar planning systems as part of the discussion after the evaluation.

The design of the framework includes technologies such as Robot Operating System (ROS), Semantic Web Ontology languages (OWL and OWL-S), RoboEarth Cloud Engine (Rapyuta), and MIndiGolog, as they are innovative, provide genericness and integrate well with each other. MIndiGolog is a high-level agent programming language for multi-agent systems, and is based on situation calculus, a logic formalism designed for representing and reasoning about dynamic domains. MIndiGolog can reason over world states and transitions between states. In the proposed system, robots are also required to have a robot-type description available, which describes the specific robot capabilities of each connected robot, so that the planner can select the right robot for specific tasks. The planner searches for plans to accomplish user-given tasks.

The programming languages Python and Prolog are used to implement the prototype of the framework. PySWIP is used to query Prolog rules in Python. The prototype includes an executive layer, a planning layer and an ontology layer. The figure below displays these three layers. My thesis focuses on the planning layer.


Several qualitative tests and an experiment with real robots are performed with the implemented prototype. The tests are performed to validate the functionality of the planning module of the system. The experiment describes a use case in which robots need to help with a cocktail party. In this use case, the robots need to take orders from guests, bring drinks to the guests, find empty drinks, and clean up empty glasses. The performed experiment however only includes the subtask of detecting empty drinks, due to limited time and resources. The robots need to navigate to the location where they expect empty drinks to be found and then perceive the empty drink.

The picture below shows the experiment. As can be seen, two service robots stand in the middle of a room. The robots need to drive to a location where they expect empty drinks to be found and then perceive this drink. The planning module needs to select the closest robot to go to the closest drink. A video of the experiment is available online.


The results of both the tests and the experiment are successful, as the tests performed as expected and the robots navigated to the nearest location where they expect empty drinks to be found in the experiment. There were however some performance issues with the communication interface of the system, including latency and bandwidth issues. Based on the results, the proposed framework is evaluated as a feasible approach to a ubiquitous robotic system for multi-robot planning and control.

2013-12-09

Rewriting the Univ-Operator (=..) in Prolog

While I was working on my research project, I stumbled on this three year old question on stackoverflow, and I got inspired by it to do an attempt at rewriting the univ-operator in Prolog.

I found one source claiming that the univ-operator was once written as a predicate with the name univ, but I could not find how this predicate was written. After searching around, I also could not find anyone who rewrote the univ-operator back into a Prolog predicate. So I saw this as an exercise for me, and tried to do it myself.

First, I explain what Prolog and the univ-operator are. Then I show how I implemented the univ-predicate, and finally, I show that my predicate works and discuss the matter further.


1. Preliminaries

1.1 Prolog

Prolog is a declarative programming language, and has its roots in First-Order Logic. The logic of Prolog programs is expressed in terms of relations, represented as facts and rules. A computation is initiated by running a query over these relations. The word arity is used to denote the number of arguments in a term. Also, www.learnprolognow.org/ is a good place to start if you want to learn Prolog.

1.2 The Univ-Operator

The univ-operator, written in Prolog as =.. (an equality sign followed by two dots), is an infix-operator that converts between a term and a list. The functionality of this operator is best shown with an example.

Here are some examples of using the univ-operator:

?- a =.. X.
X = [a].

?- f(x,y) =.. L.
L = [f, x, y].

?- Term =.. [f, x, y].
Term = f(x, y).

?- '=..'(f(x,y),L).
L = [f, x, y].



2. Implementation

I use SWI-Prolog for the implementation. The following code is what I came up with:


If you ever use this code, I would appreciate it if you gave me credit for it.

I will now explain the code per predicate.

2.1 univ

The univ-predicate has two arguments: a term and a list. Depending on which arguments are atomic and which are variable, the predicate shows slightly different behavior. First the number of arguments are count. Then either a new term is created with functor name/arity, where F is the name and N is arity, or the name and arity are retrieved from an already existing term. Next, either the arguments are filled into the new empty term, or the arguments are retracted from an already existing term. And finally, a cut is placed to prevent backtracking for multiple solutions. Only one solution (the first) is the right one, and any other attempt on getting more solutions will result in an infinite loop. Theoretically speaking, my countArgs-predicate can count up to infinity. This is also the predicate I am discussing next.

2.2 countArgs

This is a very simple predicate which counts the number of items in a list. If however both arguments of the countArgs-predicate are variable, then there are infinite solutions (every non-negative number can be unified with No in this case, and Args can be a list of any size). If only "Args" is variable, then a list with No unbounded arguments is created.

2.3 fillInArgs

The fillInArgs-predicate, as mentioned above, either fills a new empty term with give arguments, or retracts the arguments from an already existing term. It uses the arg-predicate to fill in or retrieve the arguments. It also counts the number of arguments, this needs to match the count done by countArgs so that all arguments are filled into the term.


3. Evaluation

The implentation works. The following example shows the functionality of my predicate is the same as the univ-operator:

?- univ(f(x,y),L).
L = [f, x, y].

?- univ(f(x,y),[f|Args]).
Args = [x, y].

?- univ(Term,[f,x,y]).
Term = f(x, y).


Now, this predicate can probably be improved in some ways. Perhaps it can be improved by combining the countArgs-predicate and the fillInArgs-predicate, but I see no need to do it for now. Maybe I will try that later, maybe I leave it as an exercise for you. Feel free to give the solution in the comments if you find one.

It could also be interesting to do a benchmark to see which is faster, my univ-predicate or the original univ-operator. It should not be too hard to do this, since Prolog has this nice built-in predicate statistics/2, but I did not want to do this right now. Maybe I will do it later.

Further more, is this predicate really useful? Why not use the operator? Well, it provides more freedom, you can learn from it, and adapt it. Maybe you only need part of univ's functionality, you can rewrite my univ-predicate to get only the part that you need. Maybe you need the univ-funtionality twice in succession, and it is better to rewrite it into a new single predicate. Maybe it does not improve that much on performance (but I have not benchmarked it (yet), so I do not know this), but I think it is a good practice to often try to find ways to improve the performance of your code, or your code in general.

Feel free to join the discussion.