Estructura del driver

Declaración de la clase RomaaDriver

1 class RomaaDriver : public Driver 2 { 3 public: 4 RomaaDriver( ConfigFile* cf, int section ); 5 ~RomaaDriver(); 6 7 // Must implement the following methods 8 virtual int Setup(); 9 virtual int Shutdown();10 11 // This method will be invoked on each incoming message12 virtual int ProcessMessage( QueuePointer& resp_queue,13 player_msghdr* hdr,14 void* data );15 16 protected:17 private:18 19 // Main function for device thread20 virtual void Main(); 21 };

Métodos virtuales

Setup: 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 Setup() es llamado cada vez que un cliente se subscribe al driver.

Shutdown: Es el opuesto al método Setup() . Shutdown() asegura la terminación de dispositivos como por ej. cerrar un puerto de comunicación serie; también detiene el thread del driver.

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() .

Main: Es la función principal del thread del dispositivo, donde se incluyen todas las interacciones con el dispositivo.

Registro del driver en el servidor e inicialización

El server player inicia el plug-in driver llamando a player_driver_init (función en C), esta función llama a RomaaDriver_Register.

extern "C" { int player_driver_init( DriverTable* table ) { RomaaDriver_Register( table ); return(0); }}

RomaaDriver_Register agrega el driver a una tabla de drivers del player server llamando a RomaaDriver_Init.

void RomaaDriver_Register( DriverTable* table ){ table->AddDriver( "romaadriver", RomaaDriver_Init );}

RomaaDriver_Init crea un nuevo objeto RomaaDriver y devuelve un puntero al driver.

Driver* RomaaDriver_Init( ConfigFile* cf, int section ){ // Create and return a new instance of this driver return ( (Driver*)(new RomaaDriver( cf, section )) );}

Una vez creado el objeto RomaaDriver se ejecuta el constructor, este carga datos del archivo de configuración (*.cfg) del player server . En el siguiente código utiliza un inicializador de constructor para inicializar los miembros datos con los parámetros pasados. Este constructor se utiliza para una única interfaz, en este caso position2d (ver listado de interfaces definidas en Player).

RomaaDriver::RomaaDriver(ConfigFile* cf, int section) : Driver(cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_POSITION2D_CODE){ // Read an option from the configuration file return;}

El prototipo de la clase Driver es

Driver (ConfigFile *cf, int section, bool overwrite_cmds, size_t queue_maxlen, int interf)

Las funciones RomaaDriver_Init y RomaaDriver_Register son funciones declaradas fuera de la clase así pueden ser invocada sin ningún contexto de objeto.

Secuencia del server

Al ejecutar el servidor player mediante =player romaa.cfg=, se imprime lo siguiente en pantalla, donde en color negro se muestran los mensaje del server player, en %RED%rojo%ENDCOLOR% ejecución de métodos y %BLUE%azul%ENDCOLOR% mensajes del driver.

trying to load /home/gfpp/programas/romaa_player_driver/./libromaadriver...

success

invoking player_driver_init()...

%RED%- RomaaDriver _Register%ENDCOLOR%

success

%RED%- RomaaDriver _Init%ENDCOLOR%

%RED%- RomaaDriver::RomaaDriver%ENDCOLOR%

listening on 6665

Added file watch 4

Added file watch 5

Listening on ports: 6665

Added file watch 6

accepted TCP client 0 on port 6665, fd 6

%RED%- RomaaDriver::Setup%ENDCOLOR%

romaadriver initialising...

%BLUE%Connecting at ...%ENDCOLOR%

%BLUE%serial dev: /dev/ttyS1%ENDCOLOR%

%BLUE%baudrate: 38400%ENDCOLOR%

%BLUE%romaadriver ready%ENDCOLOR%

%RED%- RomaaDriver::Main%ENDCOLOR%

%RED%- RomaaDriver::ProcessMessage%ENDCOLOR%

closing TCP connection to client 0 on port 6665

%RED%- RomaaDriver::Shutdown%ENDCOLOR%

Shuting romaadriver down

%BLUE%romaadriver has been shutdown%ENDCOLOR%

Quitting.

%RED%- RomaaDriver::~RomaaDriver%ENDCOLOR%

Se destacan algunos puntos importantes

1 se carga el driver libromaadriver

12 se ejecuta un programa cliente ( =playerv=)

22 se desconecta el cliente

26 se termina la ejecución del servidor

Constructor

En el contructor se lee el archivo de configuración (*.cfg) y se definen las interfaces utilizadas. (ver Configuration file class).

En el caso de una única interfaz position2d para el control de motores y odometria seria

RomaaDriver::RomaaDriver(ConfigFile* cf, int section) : Driver(cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_POSITION2D_CODE) // Read an option from the configuration file this->tty_dev = cf->ReadString(section, "port", "/dev/ttyS0"); this->baudrate = cf->ReadInt(section, "baudrate", 38400); return;}

Si el driver provee de múltiples interfaces se utiliza el siguiente constructor

RomaaDriver::RomaaDriver(ConfigFile* cf, int section) : Driver(cf, section)

Y se deben agregar las interfaces explicitamente

player_devaddr_t position_addr; if ( cf->ReadDeviceAddr( &position_addr, section, "provides", PLAYER_POSITION2D_CODE, -1, NULL) == 0 ) { if ( this->AddInterface( position_addr ) != 0 ) { this->SetError(-1); return; } }

Main

La función Main en el núcleo del plugin driver que se ejecuta en un thread, esto significa que este corre en paralelo con otros drivers. La mayor parte de la función Main esta contenida en un loop while(true) o for(;;) . La función 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 Shutdown .

ProcessMessage: Es una llamada 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.

La función Main es donde se debería leer información de los dispositivos, formatear los datos especificos para un interfaz y publicarlos a Player.