Tutorial yarp devices
¿Qué es un YARP device?
Es, en esencia, una clase C++ que se puede cargar dinámicamente a través de una cadena de texto que contiene su nombre. El hecho de cargar una clase cuya implementación interna sólo depende de una cadena de texto que contiene su nombre es extremadamente útil (además de difícil de implementar de cero).
¿Para qué se utilizan los YARP device?
Imagínate que dentro de tu código llamas a funciones de lectura de un encoder. Lo habitual es incorporar una capa de abstracción para tener una clase base para cualquier tipo de encoder. El polimorfismo característico de C++ te permite cambiar de:
EncoderTypeA enc; enc.getEncoders(&encoderValues);
a:
EncoderTypeB enc; enc.getEncoders(&encoderValues);
para cambiar de implementación. Esto es, de buenas a primeras, debemos cambiar nuestro código y recompilar si queremos pasar de utilizar la implementación de la clase EncoderTypeA a utilizar la de la clase EncoderTypeB. En esencia, YARP devices nos permite un código mucho más parecido a;
std::cout << "¿Qué tipo de encoders utilizas (EncoderTypeA o EncoderTypeB)?"; std::cin >> encoderType; ... options.put("device",encoderType); ... enc->getEncoders(&encoderValues);
Esto es, la selección de implementación de encoder se realiza en tiempo de ejecución, y no es necesario modificar el código ni recompilar para conmutar entre una implementación y otra.
¿Qué más nos permiten los YARP device?
Recordamos que YARP es, de base, una librería para comunicaciones a través de puertos. En el ejemplo del encoder, se ha cargado una librería con una implementación, no se han abierto puertos. Siguiendo con el ejemplo del encoder, YARP device permite alternar de forma sencilla (sin tener que recompilar) entre dos formas de trabajar:
- Librería local. Esto es el ejemplo que hemos visto.
- Remotamente. En un PC que actúa de servidor, se carga el YARP device del dispositivo real, y simultáneamente se abren unos puertos. Se mapean <comandos que entran por los puertos> a <llamadas a las funciones del dispositivo>. Del lado cliente, se carga un YARP device que NO carga el YARP device del dispositivo real, sino que únicamente mapea las llamadas a las funciones a comandos que se envían al servidor. La idea es que la sintaxis no cambia con respecto a como si lo estuviésemos utilizando como librería local.
¿Cómo se lanza/invoca un YARP device desde consola?
Para ver los YARP devices disponibles, tecleamos:
yarpdev --list
Para lanzar un YARP device, tecleamos:
yarpdev --device nombre_dispositivo
¿Cómo se lanza/invoca un YARP device desde programa?
Aquí un ejemplo C++, pero incluso se pueden invocar YARP devices C++ desde Python, Java, etc.
int main(int argc, char *argv[]) { yarp::os::Network yarp; if ( ! yarp::os::Network::checkNetwork() ) { printf("Please start a yarp name server first\n"); return(1); } yarp::os::Property options; options.put("device","nombre_dispositivo"); //-- Se pueden pasar más parámetros al YARP device en el formato: //options.put("mas_parametros","valor_de_ese_parametro"); //options.put("mas_parametros","valor_de_ese_parametro"); //-- ... yarp::dev::PolyDriver dd(options); if( ! dd.isValid() ) { printf("Device not available.\n"); dd.close(); yarp::os::Network::fini(); return 1; } while(1); //-- Esta no es la mejor práctica, la idea es no cerrar el programa! return 0; }
¿Cómo se implementa un YARP device?
En cuanto a implementación, por norma general es una clase C++ que hereda de yarp::dev::DeviceDriver y otras clases. Necesita además un poco de magia CMake. Las versiones actuales de YARP compilan esta clase en una librería dinámica.