miércoles, 8 de febrero de 2012

Tutorial Servicios Web Semanticos

Tutorial

En este tutorial aprenderemos como hacer un servicio web compuesto que recomienda robots para una determinada tarea, y a marcarlo semánticamente

Herramientas:



Nuestro primer paso será crear la Ontología que representa a los robots. Algunos de los conceptos básicos de una Ontología son las clases, las instancias y las propiedades, estas ultimas se dividen en propiedades de objetos y propiedades de datos; si tratamos de relacionar estos conceptos con el mundo de la programación orientada a objetos podemos ver las clases de una Ontología como clases de la programación, las propiedades de objetos como atributos que son punteros a otros objetos, las propiedades de datos como atributos de tipos de datos primitivos (String, int, float, etc.) y las instancias como instancias de una clase (Objetos)

Abrimos Protégé y creamos un nuevo proyecto tipo OWL / RDF Files


Luego nos pedirá una URI que será la dirección donde estará almacenada la Ontología, en este caso la guardaremos en glassfish por lo que la dirección será localhost


Luego nos pedirá seleccionar un lenguaje, seleccionaremos OWL DL y luego le damos finish

En la pestaña OWL Classes creamos las clases, en OWL toda clase extiende de la clase Thing, los botones encerrados en el recuadro rojo de la imagen siguiente son en orden de izquierda a derecha: Crear una nueva subclase (Una clase que hereda de la clase que se encuentre seleccionada), crear clase hermana (Una clase que esta en el mismo nivel de jerarquía que la que esté seleccionada) y borrar clase


Así creamos diferentes clases que extienden de Robot: Androide, Zoomorfico, Poliarticulado, Movil e Hibrido; y una clase Dispositivo de la cual extienden: Comunicación, Energía, Extremidades, Motor, Sensor y Transporte, de cada una de ellas podemos crear mas subclases y así sucesivamente hasta crear una Ontología bien definida, para ver el funcionamiento del sistema de recomendación y la creación de los servicios web es suficiente con llegar hasta el nivel de jerarquía que se muestra en la imagen


Notemos que un Robot Híbrido puede ser cualquier combinación de los demás robots, por lo cual podemos modelar este hecho de tal forma que Híbrido extienda de todas sus clases hermanas, para esto diremos que tiene como superclases a Androide, Zoomorfico, Robot, Movil y Poliarticulado, nos aseguramos de cambiar a la vista de Propiedades (recuadro azul) y damos clic en agregar una clase (recuadro rojo) y luego seleccionamos toda las clases mencionadas anteriormente


Luego procederemos a crear las propiedades, a la clase robot le adicionaremos una propiedad de objeto llamada "dispositivos" y podrá contener todas las instancias de la clase dispositivos que tiene un robot. Como las clases Zoomorfico, Androide, etc. heredan de la clase Robot, también heredan sus propiedades, así que cualquier robot tendrá dispositivos. En el campo de Propiedades y Restricciones agregaremos una nueva propiedad de Objeto (recuadro rojo); notemos que para esta propiedad el dominio es la clase Robot y el rango es la clase Dispositivo.


En una Ontología podemos crear condiciones y restricciones, por ejemplo, podemos asumir que un robot dentro de sus dispositivos tiene que tener al menos uno de Energía, uno de Comunicación y un Motor. Para crear esta restricción seleccionamos la clase Robot y nos aseguramos de tener activada la vista lógica (recuadro azul), luego damos clic en el botón crear nueva restricción (recuadro rojo), seleccionamos la propiedad sobre la cual haremos la restriccion, en ese caso dispositivos, luego el tipo de restricciones, en este caso "SomeValuesFrom" y en el campo Filler tenemos varias herramientas para crear una expresión lógica, seleccionaremos el botón "Insert class" (recuadro verde) y seleccionamos la clase Comunicación:


Luego en el campo Filler presionamos el botón "and" (recuadro rojo) y luego insertamos una nueva clase, hasta crear la expresion que se muestra en la imagen


Así logramos crear una expresión lógica que obliga a que un Robot tenga al menos una fuente de Energía, un dispositivo de Comunicación y un Motor. Así podemos crear una serie de restricciones en cada uno de los subniveles de la jerarquía. Por ejemplo, podemos decir que un robot Móvil tiene que tener un GPS y un dispositivo de Transporte, además de la restricción heredada de la clase Robot, por lo que se vería algo como:


Crearemos propiedades de datos para cada uno de los dispositivos, vamos a la clase Wifi y creamos una nueva propiedad de datos (recuadro rojo), la cual llamaremos distancia, su rango es int (recuadro azul) y marcaremos la opción Functional (recuadro verde) la cual significa que esta propiedad podrá tener un único valor


Así crearemos una propiedad para cada uno de los dispositivos que indique alguna medición representable como un tipo de dato numérico.
Una vez terminada nuestra Ontología, guardamos el proyecto en File -> Save Project, seleccionaremos la ruta para guardar el proyecto (.pprj) y la Ontología (.owl)


Luego montaremos el archivo .owl al servidor de Glassfish, generalmente la carpeta del servidor es Carpeta del usuario -> .netbeans -> version -> config -> GF3 -> domain1 -> docroot . Allí crearemos una carpeta llamada Ontologías y pegaremos el archivo Robot.owl. 

Ahora crearemos un archivo wsdl en NotePad++ por cada uno de los tres servicios atómicos. Estos se dividirán así:
  • El primer servicio recibe un Array de Dispositivos y devuelve un objeto de la clase Paquete, el cual tiene dos atributos: Un Array de Robots y un array de Dispositivos, será el encargado de consultar en las Ontologías cuales instancias de la clase Robot tienen los dispositivos requeridos y devolverá dicha lista, notemos que no importa si la distancia del Wifi de un Robot A es 50m y dentro de mis requisitos está un Wifi de 80m, este servicio solo obtiene los robots que tengan los dispositivos sin importar sus propiedades de datos. El Paquete devuelto tiene como atributos el Array de robots obtenidos y el Array de dispositivos requeridos, los mismos que se ingresaron como parametro de entrada.
  • El segundo servicio recibirá una clase Paquete y devolverá una clase paquete. Este servicio será el encargado de eliminar los demás dispositivos que no nos interesan para poder aplicar el algoritmo de la correlación de Pearson en el tercer servicio, ya que este necesita que los objetos a comparar tengan las mismas características en común, es decir, si requerimos un robot con Wifi, Brazo y un Motor y encontramos un Robot con Wifi, Motor, Brazo y Bluetooth debemos ocultar el ultimo dispositivo para trabajar con los que son necesarios. Así que este servicio eliminará los dispositivos que no son necesarios.
  • El tercer servicio recibirá un Paquete y devolverá un Array de Robots, Aplicará la correlación de Pearson comparando cada robot con los valores de los dispositivos dados y luego los ordenará, dando así lugar a un Array con los robots que cumplen las caracteristicas solicitadas ordenados de forma tal que el primero es el que mas se parece al requerido.
Un buen tutorial sobre wsdl y servicios web es: http://www.ibm.com/developerworks/ssa/webservices/tutorials/ws-understand-web-services2/index.html

Aqui tenemos el .wsdl y el .xsd del primer servicio

DepuracionService.wsdl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
    name="DepuracionService"
    targetNamespace="http://localhost:8080/Depuracion/DepuracionService"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://localhost:8080/Depuracion/DepuracionService"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsdl:types>
        <xsd:schema>
  <xsd:import namespace="http://localhost:8080/Depuracion/DepuracionService"
  schemaLocation="DepuracionServiceXSD.xsd"/>
 </xsd:schema>
    </wsdl:types>
    <wsdl:message name="DispositivosMessage">
        <wsdl:part element="tns:ArrayDispositivos" name="DispositivosPart"/>
    </wsdl:message>
    <wsdl:message name="PaqueteMessage">
        <wsdl:part element="tns:Paquete" name="PaquetePart"/>
    </wsdl:message>
    <wsdl:portType name="DepuracionServicePortType">
        <wsdl:operation name="DepuracionServiceOperation">
            <wsdl:input message="tns:DispositivosMessage"/>
            <wsdl:output message="tns:PaqueteMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="DepuracionServicePortBinding" 
 type="tns:DepuracionServicePortType">
        <soap:binding style="document" 
  transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="DepuracionServiceOperation">
            <soap:operation soapAction=""/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
 </wsdl:binding> 
    <wsdl:service name="DepuracionService">
        <wsdl:port binding="tns:DepuracionServicePortBinding" 
  name="DepuracionServicePort">
            <soap:address 
   location="http://localhost:8080/Depuracion/DepuracionService"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>
DepuracionServiceXSD.xsd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<xs:schema version="1.0" 
targetNamespace="http://localhost:8080/Depuracion/DepuracionService" 
xmlns:tns="http://localhost:8080/Depuracion/DepuracionService" 
xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="DispositivoType">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="nombreDispositivo" type="xs:string"/>
   <xs:element name="valorDispositivo" type="xs:int"/>  
  </xs:sequence>
 </xs:complexType>
</xs:element>
  
<xs:element name="RobotsType">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="nombre" type="xs:string"/>
   <xs:element ref="tns:ArrayDispositivos"/>
  </xs:sequence>
 </xs:complexType>
</xs:element>
  
<xs:element name="ArrayDispositivos">
  <xs:complexType>
    <xs:sequence minOccurs="0" maxOccurs="unbounded"> 
  <xs:element ref="tns:DispositivoType"/>
 </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="ArrayRobots">
  <xs:complexType>
    <xs:sequence minOccurs="0" maxOccurs="unbounded"> 
  <xs:element ref="tns:RobotsType"/>
 </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="Paquete">
 <xs:complexType> 
  <xs:sequence>
   <xs:element ref="tns:ArrayDispositivos"/>
   <xs:element ref="tns:ArrayRobots"/>
  </xs:sequence>
 </xs:complexType>
</xs:element>

</xs:schema>


Aqui tenemos el .wsdl y el .xsd del segundo servicio

ModificarCaracteristicasService.wsdl


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wsdl:definitions
    name="ModificarCaracteristicasService"
    targetNamespace="http://localhost:8080/ModificarCaracteristicas
 /ModificarCaracteristicasService"
 xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://localhost:8080/ModificarCaracteristicas
 /ModificarCaracteristicasService"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata">
    <wsdl:types>
        <xsd:schema>
  <xsd:import namespace="http://localhost:8080/ModificarCaracteristicas
  /ModificarCaracteristicasService" 
  schemaLocation="ModificarCaracteristicasServiceXSD.xsd"/>
 </xsd:schema>
    </wsdl:types>
    <wsdl:message name="PaqueteInputMessage">
        <wsdl:part element="tns:Paquete" name="PaqueteInputPart"/>
    </wsdl:message>
    <wsdl:message name="PaqueteOutputMessage">
        <wsdl:part element="tns:Paquete" name="PaqueteOutputPart"/>
    </wsdl:message>
    <wsdl:portType name="ModificarCaracteristicasServicePortType">
        <wsdl:operation name="ModificarCaracteristicasServiceOperation">
            <wsdl:input message="tns:PaqueteInputMessage"/>
   <wsdl:output message="tns:PaqueteOutputMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="ModificarCaracteristicasServicePortBinding" 
 type="tns:ModificarCaracteristicasServicePortType">
        <soap:binding style="document" 
  transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="ModificarCaracteristicasServiceOperation">
            <soap:operation soapAction=""/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
 </wsdl:binding> 
    <wsdl:service name="ModificarCaracteristicasService">
        <wsdl:port binding="tns:ModificarCaracteristicasServicePortBinding" 
  name="ModificarCaracteristicasServicePort">
            <soap:address 
   location="http://localhost:8080/ModificarCaracteristicas
   /ModificarCaracteristicasService"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

ModificarCaracteristicasServiceXSD.xsd


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<xs:schema version="1.0" 
targetNamespace="http://localhost:8080/ModificarCaracteristicas
/ModificarCaracteristicasService" 
xmlns:tns="http://localhost:8080/ModificarCaracteristicas
/ModificarCaracteristicasService" 
xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="DispositivoType">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="nombreDispositivo" type="xs:string"/>
   <xs:element name="valorDispositivo" type="xs:int"/>  
  </xs:sequence>
 </xs:complexType>
</xs:element>
  
<xs:element name="RobotsType">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="nombre" type="xs:string"/>
   <xs:element ref="tns:ArrayDispositivos"/>
  </xs:sequence>
 </xs:complexType>
</xs:element>
  
<xs:element name="ArrayDispositivos">
  <xs:complexType>
    <xs:sequence minOccurs="0" maxOccurs="unbounded"> 
  <xs:element ref="tns:DispositivoType"/>
 </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="ArrayRobots">
  <xs:complexType>
    <xs:sequence minOccurs="0" maxOccurs="unbounded"> 
  <xs:element ref="tns:RobotsType"/>
 </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="Paquete">
 <xs:complexType>
  <xs:sequence> 
   <xs:element ref="tns:ArrayDispositivos"/>
   <xs:element ref="tns:ArrayRobots"/>
  </xs:sequence>
 </xs:complexType>
</xs:element>

</xs:schema>

Aqui tenemos el .wsdl y el .xsd del tercer servicio

MejorRobot.wsl


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wsdl:definitions
    name="MejorRobotService"
    targetNamespace="http://localhost:8080/MejorRobot/MejorRobotService"
 xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://localhost:8080/MejorRobot/MejorRobotService"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata">
    <wsdl:types>
        <xsd:schema>
   <xsd:import namespace="http://localhost:8080/MejorRobot/MejorRobotService" 
   schemaLocation="MejorRobotXSD.xsd"/>
  </xsd:schema>
    </wsdl:types>
    <wsdl:message name="PaqueteMessage">
        <wsdl:part element="tns:Paquete" name="PaquetePart"/>
    </wsdl:message>
    <wsdl:message name="MejorRobotMessage">
        <wsdl:part element="tns:ArrayRobots" name="MejorRobotPart"/>
    </wsdl:message>
    <wsdl:portType name="MejorRobotPortType">
        <wsdl:operation name="MejorRobotOperation">
            <wsdl:input message="tns:PaqueteMessage"/>
   <wsdl:output message="tns:MejorRobotMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="MejorRobotPortBinding" type="tns:MejorRobotPortType">
        <soap:binding style="document" 
  transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="MejorRobotOperation">
            <soap:operation soapAction=""/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
 </wsdl:binding> 
    <wsdl:service name="MejorRobotService">
        <wsdl:port binding="tns:MejorRobotPortBinding" name="MejorRobotPort">
            <soap:address 
   location="http://localhost:8080/MejorRobot/MejorRobotService"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>



MejorRobotXSD.xsd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<xs:schema version="1.0" 
targetNamespace="http://localhost:8080/MejorRobot/MejorRobotService" 
xmlns:tns="http://localhost:8080/MejorRobot/MejorRobotService" 
xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="DispositivoType">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="nombreDispositivo" type="xs:string"/>
   <xs:element name="valorDispositivo" type="xs:int"/>  
  </xs:sequence>
 </xs:complexType>
</xs:element>
  
<xs:element name="RobotsType">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="nombre" type="xs:string"/>
   <xs:element ref="tns:ArrayDispositivos"/>
  </xs:sequence>
 </xs:complexType>
</xs:element>
  
<xs:element name="ArrayDispositivos">
  <xs:complexType>
    <xs:sequence minOccurs="0" maxOccurs="unbounded"> 
  <xs:element ref="tns:DispositivoType"/>
 </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="ArrayRobots">
  <xs:complexType>
    <xs:sequence minOccurs="0" maxOccurs="unbounded"> 
  <xs:element ref="tns:RobotsType"/>
 </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="Paquete">
 <xs:complexType>
  <xs:sequence> 
   <xs:element ref="tns:ArrayDispositivos"/>
   <xs:element ref="tns:ArrayRobots"/>
  </xs:sequence>
 </xs:complexType>
</xs:element>

</xs:schema>

Ahora crearemos en Netbeans tres proyectos diferentes para cada uno de los proyectos, el poryecto debe ser tipo Java Web -> Web Application


El proyecto lo llamaremos "Depuracion", Luego en el proyecto crearemos un nuevo servicio a partir del WSDL, para ellos vamos a file -> new File, seleccionamos Web Services y luego Web Service from WSDL


Llamaremos al servicio "DepuracionService", seleccionamos un paquete donde se crearán las clases definidas en el .xsd y la direccion del wsdl



Creamos un nuevo paquete llamado "clases" y una clase llamada Main, la cual tendrá el siguiente código:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package clases;

import com.hp.hpl.jena.ontology.DatatypeProperty;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
import java.util.ArrayList;
import java.util.List;
import localhost._8080.depuracion.depuracionservice.ArrayDispositivos;
import localhost._8080.depuracion.depuracionservice.ArrayRobots;
import localhost._8080.depuracion.depuracionservice.DispositivoType;
import localhost._8080.depuracion.depuracionservice.Paquete;
import localhost._8080.depuracion.depuracionservice.RobotsType;

public class Main {

    private static final String NS = 
            "http://localhost:8080/Ontologias/robot.owl#";
    private static final String ruta = 
            "http://localhost:8080/Ontologias/robot.owl#";
    private OntModel model;

    public Main() {
        model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null);
        model.read(ruta, "RDF/XML");
    }

    private static boolean estanTodos(List<DispositivoType> req, 
            List<Statement> prop) {
        for (int i = 0; i < req.size(); i++) {
            boolean esta = false;
            for (int j = 0; j < prop.size(); j++) {
                if (req.get(i).getNombreDispositivo().equals(
                        getTipoDisp(prop.get(j).getObject().asResource()))) {
                    esta = true;
                    break;
                }
            }
            if (esta == false) {
                return false;
            }
        }
        return true;
    }
    
    private static String getTipoDisp(Resource r) {
        return r.getPropertyResourceValue(null).getLocalName();
    }

    private List<DispositivoType> toDispositivos(List<Statement> propiedades) {
        List<DispositivoType> disp = new ArrayList<DispositivoType>();
        for (int i = 0; i < propiedades.size() - 1; i++) {
            Resource objeto = propiedades.get(i).getObject().asResource();
            List<Statement> prop = objeto.listProperties().toList();
            for (int j = 0; j < prop.size() - 1; j++) {
                if (!prop.get(j).getPredicate().getLocalName().
                        equals("nombre")) {
                    DispositivoType d = new DispositivoType();
                    d.setNombreDispositivo(getTipoDisp(objeto));
                    d.setValorDispositivo(prop.get(j).getLiteral().getInt());
                    disp.add(d);
                }
            }
        }
        return disp;
    }

    public Paquete ejecutar(ArrayDispositivos aDisp) {
        List<DispositivoType> dispReq = aDisp.getDispositivoType();
        Paquete paq = new Paquete();
        OntClass claseRaiz = model.getOntClass(NS + "Robot");
        List<RobotsType> robots = new ArrayList<RobotsType>();
        for (ExtendedIterator<OntClass> i = claseRaiz.listSubClasses(); 
                i.hasNext();) {
            OntClass clase = i.next();
            List<Individual> objetos = model.listIndividuals(clase).toList();
            for (int j = 0; j < objetos.size(); j++) {
                Individual robot = objetos.get(j);
                List<Statement> propiedades = robot.listProperties().toList();
                if (estanTodos(dispReq, propiedades)) {
                    RobotsType r = new RobotsType();
                    r.setNombre(robot.getLocalName());
                    ArrayDispositivos dd = new ArrayDispositivos();
                    dd.getDispositivoType().addAll(toDispositivos(propiedades));
                    r.setArrayDispositivos(dd);
                    robots.add(r);
                }
            }
        }
        paq.setArrayDispositivos(aDisp);
        ArrayRobots aRob = new ArrayRobots();
        aRob.getRobotsType().addAll(robots);
        paq.setArrayRobots(aRob);
        return paq;
    }}


Jena es una API que nos permite extraer la información de una Ontología y utilizarla en Java.
Un tutorial sobre Jena se encuentra en: http://jena.sourceforge.net/ontology/index.html

Básicamente lo que hacemos es obtener la clase raíz de la Ontología, en este caso la clase Robot, se recorre las subclases y se obtienen las instancias de cada una de estas, luego podemos proceder a obtener las propiedades que cada instancia tiene y así comparar cada Robot con las condiciones dadas obteniendo los que cumplan con los requerimientos necesarios.
Este proyecto requiere importar la librería de Jena, por lo cual creamos una libreria en netbeans y agregamos todos los .jar que se encuentran en la carpeta lib del archivo descargado de Jena.



El código de la clase DepuracionService.java quedaría como sigue:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package services;

import clases.Main;
import javax.jws.WebService;

@WebService(serviceName = "DepuracionService", 
        portName = "DepuracionServicePort", 
        endpointInterface = "localhost._8080.depuracion.depuracionservice."
        + "DepuracionServicePortType", 
        targetNamespace = "http://localhost:8080/Depuracion/DepuracionService", 
        wsdlLocation = "WEB-INF/wsdl/DepuracionService/DepuracionService.wsdl")
public class DepuracionService {

    public localhost._8080.depuracion.depuracionservice.Paquete 
            depuracionServiceOperation(localhost._8080.depuracion.
                    depuracionservice.ArrayDispositivos dispositivosPart) {
        return new Main().ejecutar(dispositivosPart);
    }}


Similarmente crearemos otros dos proyectos, el segundo servicio llamado "ModificarCaracteristicas" y un servicio llamada "ModificarCaracteristicasService", el código de la clase Main.java y ModificarCaracteristicasService.java de se muestran a continuación


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package clases;

import java.util.ArrayList;
import java.util.List;
import localhost._8080.modificarcaracteristicas.
        modificarcaracteristicasservice.*;

public class Main {

    public static Paquete depurar(Paquete paquete) {
        List<RobotsType> robots = paquete.getArrayRobots().getRobotsType();
        List<DispositivoType> disps = paquete.getArrayDispositivos().
                getDispositivoType();
        for (int i = 0; i < robots.size(); i++) {
            RobotsType robot = robots.get(i);
            List<DispositivoType> dispR = robot.getArrayDispositivos().
                    getDispositivoType();
            List<DispositivoType> dispN = new ArrayList<DispositivoType>();
            for (int j = 0; j < disps.size(); j++) {
                for (int k = 0; k < dispR.size(); k++) {
                    if (dispR.get(k).getNombreDispositivo().equals(disps.get(j).
                            getNombreDispositivo())) {
                        dispN.add(dispR.get(k));
                        break;
                    }
                }
            }
            dispR.clear();
            dispR.addAll(dispN);
        }
        return paquete;
    }}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package services;

import clases.Main;
import javax.jws.WebService;

@WebService(serviceName = "ModificarCaracteristicasService", 
        portName = "ModificarCaracteristicasServicePort", 
        endpointInterface = "localhost._8080.modificarcaracteristicas.modifi"
        + "carcaracteristicasservice.ModificarCaracteristicasServicePortType", 
        targetNamespace = "http://localhost:8080/ModificarCaracteristicas"
        + "/ModificarCaracteristicasService", 
        wsdlLocation = "WEB-INF/wsdl/ModificarCaracteristicasService"
        + "/ModificarCaracteristicasService.wsdl")
public class ModificarCaracteristicasService {

    public localhost._8080.modificarcaracteristicas.
            modificarcaracteristicasservice.Paquete 
            modificarCaracteristicasServiceOperation(localhost._8080.
                    modificarcaracteristicas.modificarcaracteristicasservice.
                    Paquete paqueteInputPart) {
        return Main.depurar(paqueteInputPart);
    }
    }



El tercer servicio lo llamamos "MejorRobot", a continuacion el codigo de la clase Main.java y de MejorRobotService.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package clases;

import java.util.ArrayList;
import localhost._8080.mejorrobot.mejorrobotservice.Paquete;
import localhost._8080.mejorrobot.mejorrobotservice.RobotsType;
import java.util.List;
import localhost._8080.mejorrobot.mejorrobotservice.ArrayDispositivos;
import localhost._8080.mejorrobot.mejorrobotservice.ArrayRobots;
import localhost._8080.mejorrobot.mejorrobotservice.DispositivoType;

public class Main {

    private Paquete paquete;

    public Main(Paquete paquete) {
        this.paquete = paquete;
    }

    private double pearson(RobotsType robot, List<DispositivoType> disps) {
        List<DispositivoType> dispRobot = robot.getArrayDispositivos().
                getDispositivoType();
        int n = disps.size();
        double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0, sumY2 = 0,
                xA = 0, yA = 0;
        for (int i = 0; i < n; i++) {
            xA = dispRobot.get(i).getValorDispositivo();
            yA = disps.get(i).getValorDispositivo();
            sumX += xA;
            sumY += yA;
            sumXY += xA * yA;
            sumX2 += xA * xA;
            sumY2 += yA * yA;
        }
        return (n * sumXY - sumX * sumY) / ((Math.sqrt(n * sumX2 - sumX * sumX))
                * Math.sqrt(n * sumY2 - sumY * sumY));
    }

    public ArrayRobots getPearson() {
        List<RobotsType> robots = paquete.getArrayRobots().getRobotsType();
        List<DispositivoType> disp = paquete.getArrayDispositivos()
                .getDispositivoType();
        List<RobotPearson> robotsPer = new ArrayList<RobotPearson>();
        for (int i = 0; i < robots.size(); i++) {
            robotsPer.add(new RobotPearson(robots.get(i),
                    pearson(robots.get(i), disp)));
        }
        ordenarArray(robotsPer);
        ArrayRobots array = new ArrayRobots();
        List<RobotsType> robotsO = new ArrayList<RobotsType>();
        for (int i = 0; i < robotsPer.size(); i++) {
            robotsO.add(robotsPer.get(i).getRobot());
        }
        array.getRobotsType().addAll(robotsO);
        return array;
    }

    private void ordenarArray(List<RobotPearson> robots) {
        for (int i = 0; i < robots.size(); i++) {
            for (int j = i; j < robots.size(); j++) {
                if (robots.get(i).getPearson() < robots.get(j).getPearson()) {
                    RobotPearson aux = robots.get(i);
                    robots.set(i, robots.get(j));
                    robots.set(j, aux);
                }
            }
        }
    }}

class RobotPearson {

    private RobotsType robot;
    private double pearson;

    public RobotPearson(RobotsType robot, double pearson) {
        this.robot = robot;
        this.pearson = pearson;
    }

    public RobotsType getRobot() {
        return robot;
    }

    public void setRobot(RobotsType robot) {
        this.robot = robot;
    }

    public double getPearson() {
        return pearson;
    }

    public void setPearson(double pearson) {
        this.pearson = pearson;
    }}




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package services;

import clases.Main;
import javax.jws.WebService;

@WebService(serviceName = "MejorRobotService",
        portName = "MejorRobotPort", 
        endpointInterface = "localhost._8080.mejorrobot.mejorrobotservice."
        + "MejorRobotPortType", 
        targetNamespace = "http://localhost:8080/MejorRobot/MejorRobotService", 
        wsdlLocation = "WEB-INF/wsdl/MejorRobotService/MejorRobot.wsdl")
public class MejorRobotService {

    public localhost._8080.mejorrobot.mejorrobotservice.ArrayRobots
            mejorRobotOperation(localhost._8080.mejorrobot.mejorrobotservice.
                    Paquete paquetePart) {
        return new Main(paquetePart).getPearson();
    }
    }



Asi tenemos los tres servicios atomicos programados, damos en cada uno clic derecho -> Deploy para ponerlos a correr en GlassFish


Luego procederemos a marcar cada uno de los servicios atómicos y a la composición del servicio web

Abrimos Protege y realizamos los pasos mencionados anteriormente.


Hacemos click en el botón que está dentro del marco rojo e importamos nuestra ontología de dominio.


Si señalamos la pestaña OWLClasses, podremos ver cada una de las clases de nuestra ontología importada.

Luego iremos menú en barra, señalamos project/configure y seleccionamos owlstab; de ésta manera estaremos importando el plug-in de owl-s editor para Protégé y a su vez la ontología para describir servicios web OWL-S.

Al realizar los pasos anteriores tendremos la siguiente vista en nuestro Protégé.



Para realizar el marcado semántico a nuestros servicios web, creamos una nueva instancia de la clase Process declarada en la ontología OWL-S como subclase de ServiceModel.


Observemos el marco rojo, con ese botón crearemos la instacia, luego aparecerá el cuadro que en la anterior imágen tiene como título Choose a Class. En este cuadro seleccionamos Atomic Process.

Luego creamos una nueva instancia de hasInput y tendrémos la siguiente vista.


Luego de darle un identificador a la entrada, especificamos su tipo de dato haciendo click en el botón amarillo con el símbolo de suma.


En nuestro caso señalamos la clase ArrayDispositivos, indicando que el servicio recibe una entrada de este tipo.

Para especificar las salidas, hacemos este mismo proceso pero creando una instancia de hasOutput.

Ahora, supondremos que hemos creado 3 procesos atómicos y crearémos un nuevo process pero señalaremos esta vez Composite Process, para indicar que este es compuesto.


Para realizar este paso es necesario tener instalado el software Graphviz para visualizar un esquema del servicio compuesto. Uno de los botones que tiene forma de rombo rosado, tiene una letra 'S', con este botón crearémos un sequence, ya que nuestro servicio compuesto se comporta como una secuencia.
Creamos varios Perform con el botón que tiene la 'P', un perform por cada atomic process.


Al crear un perform, en la pestaña properties, le damos un nombre al perform y seleccionamos el atomic process correspondiente.

En la siguiente imágen veremos como se especifica que la salida de un atomic process es exactamente la misma entrada del siguiente proceso.


Luego de realizar estos pasos con cada perform, nuestro esquema será de la siguiente manera.


Luego crearemos nuestro grounding, creando una instancia de WsdlGrounding, al crearla, aparecerá un recuadro rojo enmarcando a supportedBy, en la cual se debe especificar el servicio al cual se le está haciendo el grounding. Por el momento no será importante.
Crearemos una instancia de hasAtomicProcessGrounding y allí especificaremos todo acerca de la ubicación de ciertos elementos en el wsdl de cada servicio.
Vamos a tomar como ejemplo el servicio web ModificarCaracteristicasService. El wsdl en nuestro caso está ubicado en nuestro localhost, accediendo a él con la siguiente dirección: http://localhost:8080/ModificarCaracteristicas/ModificarCaracteristicasService?WSDL

Observemos ahora la siguiente imágen.


Cada elemento del wsdl será especificado utilizando la dirección de este último añadiendo # y el nombre del elemento en el wsdl.

Ejemplo: http://localhost:8080/ModificarCaracteristicas/ModificarCaracteristicasService?WSDL#Paquete

De esta manera estaríamos especificando, en este caso, que las salidas de el servicio son de tipo Paquete.

Posteriormente crearemos el serviceProfile, creando una instancia.


En este definiremos las entradas del servicio compuesto y las salidas, indicaremos el procesos que tiene, damos el servicio al cual pertenece, y de manera opcional darémos una breve descripción del servicio en texto.

Luego creamos una instancia de Service e indicamos añadiendo instancias en los respectivos recuadros, el grounding, el profile y el proceso compuesto.


Finalmente, salvámos nuestro proyecto, el cual generará un archivo .owl.

Para más detalles visita: http://owlseditor.semwebcentral.org/documents/tutorial.pdf

Sistema de Recomendación Ontológico usando Servicios Web Semánticos

Introduccion



Los servicios web son una tecnología emergente durante los últimos años y que se ha venido desarrollando en el marco de la Arquitectura Orientada a Servicios (SOA) obedeciendo a la necesidad de implementar procesos de negocios. Este tipo de arquitectura resulta altamente ventajosa con respecto a otras gracias a la escalabilidad e interoperabilidad que ofrece. 
Cada servicio web se comporta como una pieza de software que realiza una tarea acorde a unas entradas (inputs), que son procesadas para luego emitir unas salidas (outputs) que serán finalmente el objetivo principal del servicio.
En nuestro caso particular, poseemos un servicio web (compuesto) que se compone de tres servicios más (atómicos), y al operar éstos últimos entre sí, generan un sólo resultado que se convertirá en el resultado del servicio compuesto. Remitiéndonos a las características esenciales de los servicios web, de que cada uno de éstos es una pieza de software que recibe unas serie de entradas y devuelve el resultado de un proceso, nuestro servicio web recibirá una serie de dispositivos que serán ingresados por un usuario que deseará que el servicio le devuelva el mejor robot que cumpla con dichos dispositivos en algún ambiente particular. Ésto se obtendrá a partir de la tarea específica de cada servicio web atómico, por ejemplo, para la recomendación del robot, se usa un servicio cuya tarea está programada con el algoritmo de la correlación de Pearson.
Un aspecto muy importante a tener en cuenta es que en la comunicación de los servicios web se necesitan una serie de convencionalismos sobre lo que significa cada uno de los datos que intervienen como entradas y salidas, lo que hace que en muchos casos se cometan errores a pesar de la intervención humana. Supongamos que tenemos un servicio web para la búsqueda de libros a partir del nombre de su autor. Este servicio web, tendrá una operación buscar que recibirá un tipo de dato "String" para su funcionamiento. Desde el punto de vista sintáctico, la operación puede ser confundida con otros servicios de búsqueda existentes de productos distintos a libros. Para evitar este tipo de confusiones, es necesario dotar de semántica al servicio, lo cual se hace mediante la creación de una ontología que describe de manera taxonómica el dominio en el cual actúa el servicio web. De esta manera, al definir una ontología de libros y al marcar semánticamente los servicios, la operación buscar quedaría identificada como una operación sólo para los libros. En nuestro caso particular, la ontología del dominio es acerca de robots.
Este tipo de aplicaciones sirven como modelos aplicables a lo que se conoce como "Cloud Robotics" o Robótica en la Nube, suponiendo un ambiente de robots en el cual cada uno está conectado a un servicio web listos para ejecutar un trabajo colaborativo.

Funcionamiento

 

Este sistema que recomienda robots es una aplicación realizada bajo una arquitectura orientada a servicios, ya que contiene tres procesos atómicos independientes que utilizan basados en el protocolo de comunicación sencillo que se trata de enviar un mensaje y recibir otro con las respuestas que se necesitaban. Es una aplicación web semántica ya que se compuso utilizando la ontología owl-s para marcar los servicios y crear con ellos un servicio compuesto utilizado de orquestador.

Creamos en protege una ontología de dominio, teniendo como dominio los robots, con el lenguaje de marcado OWL. Convertimos desde protege la ontología en código de java para que se creen los tipos de datos, relaciones e instancias especificadas en la ontología, importamos ese código, las librerías de protege y las librerías de Jena (para poder leer y manipular la ontología) en un proyecto dentro de la IDE netbeans. 
Además describimos los servicios en wsdl para luego crear a partir de ellos los tres servicios simples que en particular se encargan de:
• Primer servicio: recibe un Array de Dispositivos y devuelve un objeto de la clase Paquete, el cual tiene dos atributos: Un Array de Robots y un array de Dispositivos, será el encargado de consultar en las Ontologías cuales instancias de la clase Robot tienen los dispositivos requeridos y devolverá dicha lista, notemos que no importa si la distancia del Wifi de un Robot A es 50m y dentro de mis requisitos está un Wifi de 80m, este servicio solo obtiene los robots que tengan los dispositivos sin importar sus propiedades de datos. El Paquete devuelto tiene como atributos el Array de robots obtenidos y el Array de dispositivos requeridos, los mismos que se ingresaron como parámetro de entrada.
• Segundo servicio: recibirá una clase Paquete y devolverá una clase paquete. Este servicio será el encargado de eliminar los demás dispositivos que no nos interesan para poder aplicar el algoritmo de la correlación de Pearson en el tercer servicio, ya que este necesita que los objetos a comparar tengan las mismas características en común, es decir, si requerimos un robot con Wifi, Brazo y un Motor y encontramos un Robot con Wifi, Motor, Brazo y Bluetooth debemos ocultar el ultimo dispositivo para trabajar con los que son necesarios. Así que este servicio eliminará los dispositivos que no son necesarios.
• Tercer servicio: recibirá un Paquete y devolverá un Array de Robots, Aplicará la correlación de Pearson comparando cada robot con los valores de los dispositivos dados y luego los ordenará, dando así lugar a un Array con los robots que cumplen las características solicitadas ordenados de forma tal que el primero es el que más se parece al requerido.







Todos los datos de entrada y de salida de los servicios están especificados en la ontología para poder manipularlos con Jena y hacer los procesos necesarios para que se den los resultados esperados.

Luego utilizando OWL-S API instalada en protege, marcamos los servicios web atómicos para crear el compuesto, que se encarga de obtener los inputs y llamar a los demás servicios para que hagan su tarea específica (sin saber con qué fin la están realizando) y devuelvan sus outputs, se hace en forma de secuencia, el mensaje enviado por el cliente al servicio compuesto (un array de dispositivos) va al input del primer servicio que devuelve un objeto de la clase paquete al servicio compuesto, luego ese objeto de la clase paquete es enviado al segundo servicio que devuelve otro objeto de la clase paquete diferente y mejorado que vuelve al servicio compuesto para que se lo envíe al tercer servicio y ese devuelva un array con los robots recomendados al servicio compuesto y este se lo devuelva al cliente.


Conclusiones



·         La aplicación realizada representa un modelo que podría ser aplicable en un ambiente colaborativo de robots, generando una red de éstos, gracias a la funcionalidad que permiten los servicios web.
·         La arquitectura orientada a servicios tiene grandes beneficios, los modelos de negocios evolucionan y hay independencia en la operatividad de las aplicaciones, de esta manera abra mas flexibilidad entre la composición de software complejo .
·         La web semántica se ira expandiendo a medida en que existan más servicios web, mas ontologías asociadas a un dominio particular y unos agentes desarrollados para crear servicios automáticamente.
·         Crear un sistema de recomendación de robots es importante para un futuro cercano, ya que la robótica es un mundo amplio en el que se están aportando mucho. Será algo muy efectivo pero aun es un campo grande y al que se irán aportando más idea a medida que avanza la robótica
·         La robótica en la nube es el futuro de la robótica ya que permitirá procesos más rápidos y complejos que ayuden a la vida diaria en la realización de tareas en diferentes robots.

lunes, 9 de enero de 2012


Identificación de un Área Desconocida e Implementación de un Grafo de Visibilidad para el Cambio de Configuración de un Robot



En la robótica algunos de los desafíos más significativos frente a la robótica autónoma están en el área de planificación automática de movimientos. En esta se busca poder llevar instrucciones generadas en un lenguaje de alto nivel a un robot convirtiéndolas automáticamente a comandos de movimiento de bajo nivel de tal forma que se realice la tarea asignada. Esta tarea consiste típicamente en generar un cambio de configuración del robot de un lugar a otro, mientras se evaden los obstáculos presentes en el ambiente desconocido. Sin embargo, en la mayoría de la literatura se asume que el robot tiene un modelo preciso del ambiente antes de comenzar a desplazarse; menos atención se le ha prestado al problema de los ambientes no conocidos o aquellos parcialmente identificados. Es necesario entonces para resolver este ultimo problema la utilización de sensores capaz de tomar medidas del ambiente a medida que el robot esta en desplazamiento, de tal forma que se pueda generar un modelo del ambiente en el cual basar todas las futuras decisiones que el robot deba tomar; tal modelo, en esta propuesta, es el encargado de generar las principales características de lo que se conoce como grafo de visibilidad, y sobre el cual se planifican todas las posibles trayectorias que se pueden realizar en el ambiente de trabajo del robot. Adicional al uso de lo sensores para la identificación de los diferentes obstáculos presentes en el ambiente, también es fundamental considerar que en todo momento el robot debe conocer su localización en el mundo desconocido, de tal forma que el robot pueda identificar constantemente su ubicación, y la disposición geométrica de los obstáculos dentro del ambiente. Adicional a lo anterior también es de gran relevancia considerar que el robot tiene volumen específico, y por lo tanto no debe ser considerado como un punto en el espacio. Esto permite generar rutas que realmente pueden ser navegadas por el robot sin generar colisión alguna con los obstáculos en el ambiente.

Robot Lego Mindstorm NXT

La aplicación propone implementar el algoritmo de visibilidad sobre un robot Lego Mindstorms NXT 2.0 fabricado por Lego®, el cual es un kit de robótica programable lanzado al mercado en julio del 2006. Este remplazó a la primera generación del kit lego Mindstorm, el cual fue llamado kit de invención de robótica. 
El componente principal en el kit es un computador en forma de ladrillo llamado ladrillo inteligente NXT. En él se pueden conectar y controlar hasta tres motores en los puertos A, B y C y hasta cuatro de los diferentes sensores en los puertos 1, 2,3 y 4. El ladrillo también tiene una pantalla LCD de 100x64 pixeles y cuatro botones que pueden ser utilizados para navegar en los diferentes menús. Además ofrece la opción de conexiones por medio de USB y Bluetooth.  

Sistema sensorial

En esta propuesta se implementa el uso de varios sensores tanto con el fin de identificar el ambiente en el cual el robot esta interactuando como con el  de permitir el mejor posicionamiento posible del robot en el mundo. Los sensores utilizados son:

-          Sensor de ultrasonido: utilizado con el fin de identificar los diferentes obstáculos presentes en el ambiente desconocido, y mediante el posicionamiento del robot identificar las coordenadas de cada obstáculo.

-          Compás magnético: mediante el uso de este sensor se busca que cada vez que el robot haga un giro, este pueda ser realizado con una mayor precisión, y que factores externos como el suelo o las llantas no influyan demasiado en la realización correcta del giro. 
-          Tacómetro: este sensor ubicado en cada uno de los motores, son utilizados para proporcionar las coordenadas del robot en todo momento.   

Reconocimiento de obstáculos

Como fue mencionado antes, en este proyecto se utiliza el sensor de ultrasonido con la intención de identificar los diferentes obstáculos ubicados en el espacio desconocido. Este proceso inicia con un reconocimiento parcial del mundo, recorriendo el área total de trabajo. Por lo tanto es necesario ingresar el punto inicial, final y el área que se debe analizar.
                        
                                         

Luego del ingreso de los datos el robot analiza el área de trabajo y luego identifica los vértices con el fin de generar el grafo de visibilidad. Mediante el uso del sensor de ultrasonido se genera el mapa de un obstaculo mostrado en la parte derecha de la siguiente imagen.


Con dos obstáculos se genera el siguiente mapa



Vídeo de identificación de un obstáculo



Generación de Grafos de Visibilidad y ruta más corta


Luego del reconocimiento de los obstáculos y de la construcción del mapa, se puede realizar el grafo de visibilidad y luego partiendo de este y mediante el algoritmo de Dijkstra se encuentra la ruta mas corta, la cual es recorrida finalmente por el robot. En la siguiente imagen se muestra el grafo de visibilidad generado por el robot al identificar el are con un obstáculo. 




En la siguiente imagen se muestra el grafo de visibilidad generado por el robot al identificar el are con dos obstáculos.