7
Writing player drivers From Experimental Robotics [edit ] General Overview Every driver plugin should define t he following functions: Driver::Driver(ConfigFile *cf, int section, int interface, uint8_t access, size_t datasize, size_t commandsize, size_t reqqueuelen, size_t repqueuelen); In which you read in general configuration data from the player co nfig file. Interface specifies which interface you are supporting, such as localise or position. Driver::Setup() In which you do any device-specific setup, such as opening fil e buffers or configuring serial ports, and then start the driver thread. Driver::Shutdown() In which you do any device-specific cleanup, such as c losing file buffers. Driver::Main() An infinite loop, which repeatedly updates data and sends for whichever interface you are supporting. Driver::SendData() In which we actually put the data in a form that Player can read and send it o ff. [edit ] Super Detailed Guide (I have no idea where we found this, so can't reference it properly. But it is awesome!) plugin_driver HOWTO: Creating a Plugin Driver  The are two distinct type of drivers in Player:  

Writing Player Drivers

  • Upload
    dongarm

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Writing Player Drivers

8/8/2019 Writing Player Drivers

http://slidepdf.com/reader/full/writing-player-drivers 1/7

Writing player drivers

From Experimental Robotics

[edit]

General Overview

Every driver plugin should define the following functions:

Driver::Driver(ConfigFile *cf, int section, int interface, uint8_t access,size_t datasize, size_t commandsize,size_t reqqueuelen, size_t repqueuelen);

In which you read in general configuration data from the player config file. Interface specifies

which interface you are supporting, such as localise or position.

Driver::Setup()

In which you do any device-specific setup, such as opening file buffers or configuring serial

ports, and then start the driver thread.

Driver::Shutdown()

In which you do any device-specific cleanup, such as closing file buffers.

Driver::Main()

An infinite loop, which repeatedly updates data and sends for whichever interface you are

supporting.

Driver::SendData()

In which we actually put the data in a form that Player can read and send it off.

[edit]

Super Detailed Guide(I have no idea where we found this, so can't reference it properly. But it is awesome!)

plugin_driver HOWTO: Creating a Plugin Driver The are two distinct type of drivers in Player: 

Page 2: Writing Player Drivers

8/8/2019 Writing Player Drivers

http://slidepdf.com/reader/full/writing-player-drivers 2/7

- Static drivers have their code in the main Playerdistribution, and are statically linked into the server.  Generallyspeaking, such drivers will be added by the lead developers. - Plugin drivers are shared objects that are loaded at runtime(like loadable modules in the Linux kernel). They are the recommendedmethod for all new, experimental or third party drivers. Plugin drivers have serveral advantanges over their staticcounterparts: - They are easier to build (no mucking about with autotools, ordigging about in the server internals). - They permit rapid development and a much faster code/compile/testcycle (the server does not need to be recompiled/relinked when thedriver changes). - Code can be maintained in a separate source repository.  This isparticularly useful for users with funky one-off drivers that belong

with the rest of their code, data, papers, etc (and not in the Playersource tree). This document describes the process for creating new plugin drivers.It assumes you are familiar with C++, class inheritance, and threadprogramming.  section plugin_drivers_example A plugin driver example Sample code for a very basic plugin driver is provided in theexamples directory; for a default install, this will be:  /usr/local/src/player/examples/plugins/exampledriver/  Copy the files from this directory and renameMakefile.example to Makefile.  Try building theexample:  $ make  This produces a plugin driver named exampledriver.so.You can test the model using the included configuration file:

  $ player ./example.cfg  The driver block in the config file has an additional field @c pluginspecifying the path to the plugin, i.e.,:  driver

Page 3: Writing Player Drivers

8/8/2019 Writing Player Drivers

http://slidepdf.com/reader/full/writing-player-drivers 3/7

(name "exampledriver"plugin "exampledriver.so"provides ["position:0"]...

)   section plugin_drivers_simple Writing a simple driver The first step in creating a new driver is to decide which interfaceit will support.  The existing interfaces are described in the referencesection, and their various messagestructures and constants are defined in player.h.  Although you cancreate a new interface, you should try to fit your driver to anexisting interface, of which there are many.  By deciding to supportan existing interface, you'll have less work to do in the server, andwill likely have instant client support for your driver in severallanguages.

 To create a new driver, you should create a new class for the driver,which should inherit from the Driver class.  This base class defines astandard API, part of which the new driver must implement (other partsit may choose to override).  We now describe the salient aspects ofthe Driver class.  subsection plugin_drivers_simple_c The constructor Simple drivers will use the following Driver constructor:  Driver::Driver(ConfigFile *cf, int section, int interface, uint8_t access,

size_t datasize, size_t commandsize,size_t reqqueuelen, size_t repqueuelen);

  This constructor will establish the buffers and queues that allow thePlayer server to interface with the driver.  The preamble for theexample driver, for example, looks like this:  

ExampleDriver::ExampleDriver(ConfigFile* cf, int section): Driver(cf, section, PLAYER_POSITION_CODE, PLAYER_ALL_MODE,

sizeof(player_position_data_t), sizeof(player_position_cmd_t),10, 10)

{...

}  The preamble indicates that this driver: - Supports the position interface (indicated by @cPLAYER_POSITION_CODE);

- Allows read/write access from clients (@c PLAYER_ALL_MODE);

Page 4: Writing Player Drivers

8/8/2019 Writing Player Drivers

http://slidepdf.com/reader/full/writing-player-drivers 4/7

- Has a data buffer large enough to accomodate astandard position interface data packet (@c

sizeof(player_position_data_t));- Has a command buffer large enough to accomodate astandard position interface command packet (@c

sizeof(player_position_cmd_t));- Can queue up to 10 incoming configuration requests and 10 outgoingconfiguration replies.

 The @c cf and @c section parameters are passed in by the server; thesevalues to access driver-specific options stored in the Playerconfiguration file.  Thus, for example, the driver constructor canread the value of some setting "foo":  this->foop = cf->ReadInt(section, "foo", 0);  This might be the serial port from which to read data, for example.See the ConfigFile documentation for the various kinds of options that

can be read from the configuration file.  subsection plugin_drivers_simple_set Setup() When the first client subscribes to a driver, the driver's Setup()method is called; every driver @b must implement this method.  TheSetup() method generally does two things: - Do some device-specific initialization (e.g., open a serial port).- Start the driver thread using Driver::StartThread(). Player is a multi-threaded application, with most drivers running intheir own thread; this makes it particularly easy to write driversthat read/write data from serial ports, network sockets, disk filesand so on. After initialization, Setup() should return either zero to indicatethat the device was successfully setup, or non-zero to indicate thatsetup failed (the latter will cause Player to terminate).  subsection plugin_drivers_simple_shut Shutdown() When the last client unsubscribes from a device, the driver'sShutdown() method is called; every driver @b must implement thismethod.  The Shutdown() method generally does two things:

 - Stop the driver thread using Driver::StopThread().- Do some device-specific finalization (e.g., close a serial port). Note that the ordering is important here: we must shut down the driverthread @b before we release the resources it is using; to this end,Driver::StopThread() will tell the driver thread to quit, and waituntil it exits before returning. Shutdown() should return either zero to indicate that device was

Page 5: Writing Player Drivers

8/8/2019 Writing Player Drivers

http://slidepdf.com/reader/full/writing-player-drivers 5/7

successfully shutdown, or non-zero to indicate that shutdown failed.  subsection plugin_drivers_simple_main Main() The Driver::Startup() method will result in the creation of a newthread of control, which will immediately call Driver::Main().  Everydriver must this overload this method.  The overloaded Main() methodis generally responsible for translating between some device-specificAPI and the standard Player interfaces.  The basic steps are asfollows: - For incoming data:- Read data from some external device (over a serial port, for example).- Massage the data into one of the Player interface data structures.- Write the data to the Player server using Driver::PutData().

 - For outgoing data (commands):- Read commands from the Player server using Driver::GetCommand().- Massage the command into a device specific format.

- Write the command to the external device. The Driver::PutData() and Driver::GetCommand() methods manage all ofthe buffering and locking required to synchronize the driver andserver threads. The overloaded Main() method is also responsible for handlingany configuration request sent to the driver; the basic steps are asfollows: - Check for a new request using Driver::GetConfig().- Do whatever needs to be done for this request.- Send a response using Driver::PutReply(). Note that your driver must respond, one way or another, to each andevery request.  Failing to respond to requests will cause clientprograms to "hang" when talking to the driver. The overloaded Main() must also be capable of graceful termination(i.e., the function should exit cleanly when the user kills theserver).  This can be achieved by calling @c pthread_testcancel() fromwithin the main loop.  This function checks to see if the driverthread should terminate, and if so, immediately exits Main().  Ifadditional cleanup is required, drivers can also overloadDriver::MainQuit(), which is guaranteed to be called on threadtermination. 

 subsection plugin_drivers_simple_instant Instantiation In order to instantiate a driver, the Player server needs to know twothings: - The driver's name (as it will appear in the configuration file).- The driver's @b factory function (used to create a new instance ofthe driver).  The factory function will generally look somethinglike this:

Page 6: Writing Player Drivers

8/8/2019 Writing Player Drivers

http://slidepdf.com/reader/full/writing-player-drivers 6/7

  Driver* ExampleDriver_Init(ConfigFile* cf, int section){return ((Driver*) (new ExampleDriver(cf, section)));

}  Note that this function may be called multiple times: once for eachoccurance of the driver name in the configuration file. Each driver must register itself with the server using theDriverTable::AddDriver(), providing the driver name and factoryfunction.  Drivers must therefore define a registration functionas follows:  void ExampleDriver_Register(DriverTable* table){table->AddDriver("exampledriver", ExampleDriver_Init);

}  This function must be called exactly once, on program startup.  Forplugin drivers, this can be achieved by defining an initializationfunction for the shared object:  extern "C"{int player_driver_init(DriverTable* table){ExampleDriver_Register(table);return 0;

}}  This function will be called when the shared object is loaded, beforeany drivers are instantiated.  The @c extern @c "C" block is used toprevent C++ name mangling of the intialization function.  section plugin_drivers_building Building the shared library The example driver includes a Makefile for building shared objects.To manually build a shared object, try:

  $ g++ -Wall -g3 -c exampledriver.cc$ g++ -shared -nostartfiles -o exampledriver.so exampledriver.o  While the above method will probably work, it is recommended that youuse pkg-config to get the compile flags; i.e.,  

Page 7: Writing Player Drivers

8/8/2019 Writing Player Drivers

http://slidepdf.com/reader/full/writing-player-drivers 7/7

$ g++ -Wall -g3 `pkg-config --cflags player` -c exampledriver.cc$ g++ -shared -nostartfiles -o exampledriver.so exampledriver.o  @todo- Add example of building plugin using libtool.- Add "theory" from Architecture Chapter of the old manual. */