## page was renamed from Robotica/PlayerDriverRoMAA200Web #acl BecariosGrupo:read,write,revert All:read = Driver de Player para el control 2.0 del robot RoMAA-II = <> == Objetivos == Desarrollar el nuevo driver del robot RoMAA para la versión 2.0 del sistema de control embebido compatible con Player versión 3.0. == Control embebido 2.0 == El control embebido tiene tres modos de funcionamiento * A lazo abierto mediante comandos de PWM a cada motor * A lazo cerrado en velocidad independiente para cada motor * Lazo cerrado cross-coupling utilizando comandos de velocidad lineal y angular Para más detalles del control embebido ver [[LabElectronica/FreeRTOSLpc2114Web|"Hardware de Control de Plataforma Robótica Móvil con Arquitectura ARM y RTOS. Caracterización"]]. == Player driver == Para la programación de un driver de Player se utilizan las librerías incluidas en player que permite generar un driver plugin. Los drivers plugin se carga en tiempo de ejecución del servidor. La instalación de Player incluye un ejemplo de programación de driver plugin que puede encontrarse, junto con el archivo CMakeList.txt para la compilación, en `${prefix}/share/player/example`. === Estructura del driver plugin (player v3.0) === {{{ #include class Romaa : public ThreadedDriver { public: // Constructor Romaa(ConfigFile* cf, int section); // This method will be invoked on each incoming message virtual int ProcessMessage(QueuePointer &resp_queue, player_msghdr * hdr, void * data); private: // Main function for device thread. virtual void Main(); virtual int MainSetup(); virtual void MainQuit(); }; }}} El driver plugin se programa como una clase de C++ heredara de la clase {{{ThreadedDriver}}}. Esta clase tiene los siguientes métodos virtuales * '''!MainSetup()''':Realiza funciones de inicialización especificas del dispositivo por ej. abrir y configurar un puerto de comunicación serie; también ejecuta el thread del driver. El método {{{MainSetup}}} se llama cada vez que un cliente se subscribe al driver. * '''!MainQuit()''': Es el opuesto al método {{{MainSetup}}}. {{{MainQuit}}} asegura la terminación de dispositivos como por ej. cerrar un puerto de comunicación serie; también detiene el thread del driver. * '''Main()''': Es la función principal del thread del dispositivo, donde se incluyen todas las interacciones con el dispositivo. * '''!ProcessMessage()''':Este método se invoca con cada mensaje entrante al servidor y ofrece la posibilidad de enviar una respuesta publicando un mensaje utilizando la función miembro pública {{{Publish}}}. El server player inicia el plugin driver llamando a {{{player_driver_init}}} (función en C), esta función llama a {{{Romaa_Register}}}, la cual agrega el driver a una tabla de drivers del servidor Player mediante método {{{AddDriver}}} que llama a {{{Romaa_Init}}}. {{{Romaa_Init}}} crea un nuevo objeto {{{Romaa}}} y devuelve un puntero al driver. Una vez creado el objeto {{{Romaa}}} se ejecuta el constructor. En el constructor se cargan los datos del '''archivo de configuración''' (.cfg) del servidor Player. Luego se ejecuta {{{MainSetup}}} y el método principal {{{Main}}}. {{{ /* need the extern to avoid C++ name-mangling */ extern "C" { int player_driver_init(DriverTable* table) { puts("romaa driver initializing"); Romaa_Register(table); puts("romaa driver done"); return(0); } } void Romaa_Register(DriverTable* table) { table->AddDriver("romaa", Romaa_Init); } Driver* Romaa_Init(ConfigFile* cf, int section) { // Create and return a new instance of this driver return((Driver*)(new Romaa(cf, section))); } }}} El método {{{Main}}} es el núcleo del driver plugin y se ejecuta en un thread lo que significa que corre en paralelo con otros drivers. La mayor parte del método {{{Main}}} esta contenida en un loop infinito. El método {{{Main}}} tiene que llamar unas pocas funciones específicas: * '''pthread_testcancel''':Verifica si el thread fue terminado (killed). La función saldrá del loop y ejecutara la el método {{{MainQuit}}}. * '''!ProcessMessages''': Le pasa el control a Player que llamará la función !ProcessMessage() del plugin con cada mensaje esperando en la cola de mensajes. * '''usleep''': Es un comando de sleep para liberar los recursos utilizados por el driver. {{{ Romaa::Main() { // The main loop; interact with the device here for(;;) { // test if we are supposed to cancel pthread_testcancel(); // Process incoming messages. Romaa::ProcessMessage() is // called on each message. ProcessMessages(); // Interact with the device, and push out the resulting data, using // Driver::Publish() // Sleep (you might, for example, block on a read() instead) usleep(100000); } } }}} === Procesamiento de mensajes === Las diferentes interfaces en Player interactúan unas con otras enviando y recibiendo mensajes a través de Player. Algunos de los diferentes tipos de mensajes son {{{PLAYER_MSGTYPE_DATA}}} (datos), {{{PLAYER_MSGTYPE_CMD}}} (comando), {{{PLAYER_MSGTYPE_REQ}}} (petición), {{{PLAYER_MSGTYPE_RESP_ACK}}} (respuesta), etc. Tipos de mensajes * '''Commands''': Se utilizan para darle instrucciones al driver cuando no se requiere una respuesta * '''Requests''': Son mensajes desde otros drivers para acceder a datos que no son publicados regularmente o enviar comandos que requieren algún tipo de respuesta * '''Data''': Los mensajes de datos son publicados en cada iteración del loop Main del driver. Además, cada interfaz soporta un subconjunto de los mensajes anteriores. Los mensajes se transfieren como un puntero a objetos {{{Message}}}. Un método importante de la clase {{{Messages}}} es {{{MatchMessage}}} que se utiliza dentro de {{{ProcessMessage}}} para determinar si el encabezado de un mensaje coincide con algunos de los tipos preestablecidos. == Archivo de configuración == En el archivo de configuración para el driver del robot RoMAA se fijan los parámetros de la comunicación como el puerto serie y la velocidad. Además de los parámetros de los controladores PID tanto para los motores como para el lazo cruzado de control de velocidad lineal y angular. Otro parámetro importante es `wheel_control` que permite (cuando vale 0) controlar el robot mediante velocidad lineal/angular, o bien (cuando vale 1) controlar el robot mediante velocidad lineal de cada rueda. === Para el RoMAA === Los comandos de la interfaz {{{position2d}}} implementados son: {{{PLAYER_POSITION2D_CMD_VEL}}}, {{{PLAYER_POSITION2D_REQ_RESET_ODOM}}}, {{{PLAYER_POSITION2D_REQ_SET_ODOM}}}, {{{PLAYER_POSITION2D_REQ_GET_GEOM}}}, {{{PLAYER_POSITION2D_REQ_MOTOR_POWER}}}, {{{PLAYER_POSITION2D_DATA_STATE}}} El archivo de configuración para cargar el driver es el siguiente {{{ driver ( name "romaa" plugin "libromaa" provides [ "position2d:0" ] port "/dev/ttyUSB0" baudrate 115200 motorpid [ 1300.0 5000.0 1.0 ] vwpid [ 0.0 25.0 0.0 ] wheel_control 0 todometry 25 tloop 20 ) }}} los parámetros son los siguientes * `motorpid`: valores de las constantes del PID del lazo cerrado de velocidad de cada motor (Kp,Ki,Kd) * `vwpid`: valores de la constante del PID del cross-coupling, somamante integrador (Ki) * `wheel_control`: puesto a 1 permite controlar el RoMAA mediante velocidad en cada rueda * `todometry`: tiempo (en ms) en que el controlador embebido actualiza el valor de odometría * `tloop`: tiempo (en ms) en que el controlador embebido calcula el lazo cerrado === Para el joystick === La siguiente sección `driver` permite controlar al robot RoMAA con el driver del joystick del lado del servidor de Player. En este caso se fija como velocidad lineal máxima 1m/s y se controla con el eje 1, y de velocidad angular máxima de 30deg/s y se controla con el eje 2. Para el control mediante vw se tiene que fijar `wheel_control 0` en el driver del RoMAA. {{{ # 1 m/sec max linear velocity # 30 deg/sec max angular velocity # Axis 1 is X # Axis 2 is Yaw # Y is not used here driver ( name "linuxjoystick" provides [ "joystick:0" ] requires [ "position2d:0" ] max_speed [1 0 30] axes [1 -1 2] port "/dev/input/js0" alwayson 1 ) }}} La siguiente sección `driver` permite controlar al robot RoMAA con el driver del joystick del lado del servidor de Player. En este caso se fija como velocidad lineal máxima de cada rueda a 0.5m/s y se controlan con los ejes 1 y 3. Para el control mediante vw se tiene que fijar `wheel_control 1` en el driver del RoMAA. {{{ # control wheel linear speed # Axis 1 is X # Axis 3 is Y # Yaw is not used here driver ( name "linuxjoystick" provides [ "joystick:0" ] requires [ "position2d:0" ] max_speed [0.5 0.5 0] axes [1 3 -1] port "/dev/input/js0" alwayson 1 ) }}} == Links == * [[http://playerstage.sourceforge.net/wiki/Player_3.0_Upgrade|Player 3.0 Upgrade]] * [[http://playerstage.sourceforge.net/wiki/Compiling_Player_3_clients_and_plugins|Compiling Player 3 clients and plugins]] * [[http://psurobotics.org/wiki/index.php?title=Writing_a_Player_Plugin|Writing a Player Plugin]]