Player Dirver

Developing a plug-in driver for Player

原文地址:http://www.control.aau.dk/~tb/wiki/index.php/Developing_a_plug-in_driver_for_Player#Class_definition

为Player编写驱动有两种方法,第一种是编写静态的驱动,直接编译到player服务器中,当编译player分布式系统的时候会被包含进去。Writing drivers for Player can essentially be done in two ways. One option is to write a driver statically linked into thePlayer server, and thus included when compiling the Player distribution. The second option, is to write a so-called plug-in driver, which is loaded at runtime. Where the first option is generally used by leading developers, the second option is an obvious choice when developing new, experimental or third party drivers. This is due to the plug-in drivers being easier to compile since they do not require the whole distribution to be recompiled, and thus allow for faster development.No matter the choice of driver type, a configuration file is needed to inform Player on which interfaces the given driver supports. A short introductory example of such a configuration file is shown below.

1  driver
2  (
3  name "player_driver"
4  provides ["<host>:<robot>:<interface>:<index>"]
5  )

It is seen that a new driver section is introduced by the first instruction driver(), and subsequently a name of the driver provided. Line 4 contains the instructions on which interface the driver provides and at which address they are available. The host and robot fields indicate where the device can be located, while the interface field obviously indicates which interface the driver provides. Lastly, the index field, allows for supporting multiple instances of the same interface e.g. two laser range finders onthe same robot.


Besides from the obligatory name option, the following options, not included in the example, are also available for use in the driver configuration file:

  • plugin A string option used when a driver has been developed as a plug-in toPlayer. Use of the plugin option is done by providing the name of the shared library containing the developed driver.
  • requires A tuple of strings option, enabling the developer to informPlayer that the given driver requires certain device addresses to be available. Often used when writing so-called “abstract” drivers, that often use several devices to e.g. apply advanced control algorithms to a robot.
  • alwayson Integer option, that when set to 1 forces Player to set up the given driver when the Player server starts. Normally the Player server waits for any client connection. The alwayson option is e.g. advantageous when handling a driver which has a long start-up time to avoid time-outs.


The following presents the structure of a C++ plug-in driver and a description of the various parts it contains. The structure described in the text is taken from a basic example driver bundled withPlayer.


Contents

[hide]
  • 1Class definition
  • 2PlayerDriver_Init()
  • 3PlayerDriver_Register()
  • 4PlayerDriver()
  • 5Setup()
  • 6Shutdown()
  • 7ProcessMessage()
  • 8Main()
  • 9extern “C”()



[ edit]

Class definition

Starting from the class definition seen below, lines 1-16 contains obligatorydeclarations needed forPlayer. These will be described in the following, where theimplementation of the functions is treated.


1 #include <unistd.h>
2 #include <string.h>
3 #include <libplayercore/playercore.h>
4
5 class PlayerDriver : public Driver
6 {
7 public:
8 PlayerDriver(ConfigFile* cf, int section);
9
10 virtual int Setup();
11 virtual int Shutdown();
12
13 virtual int ProcessMessage(MessageQueue* resp_queue,player_msghdr *hdr,void * data);
14
15 private:
16 virtual void Main()
17 int intTest;
18 }

The remaining part of the class definition, is available for the user to declare variables or functions. In this case the integerint_Test is declared. In the following the various parts constituting thePlayer driver is treated:

[ edit]

PlayerDriver_Init()

A factory creation function where a pointer to the new instance of the driver is created and returned.

1 Driver* PlayerDriver_Init(ConfigFile* cf, int section)
2 {
3 return((Driver*)(new PlayerDriver(cf, section)));
4 }
[ edit]

PlayerDriver_Register()

Registers the driver in the given driver table, indicating the device name as wellas instructions on how to create a new instance of the driver i.e. the functionRobotinoDriver_Init().

1 void PlayerDriver_Register(DriverTable* table)
2 {
3 table->AddDriver("player_driver", PlayerDriver_Init);
4 }
[ edit]

PlayerDriver()

The class constructor invoked at any new instance of the given class. The argumentsConfigFile* cf and int section, passed by the Player server, are references to the name and section of the associated configuration file such that options can be read from here. The instruction between the: and { is a “constructor initializer”, which is used for initializing given members with the values in parenthesis. The amount of arguments initialized with the public member functionDriver(),determines whether the constructor is for single- or multiple-interface drivers. The parameters for the function are:


  • cf - Current configuration file
  • section - Current section in configuration file
  • overwrite_cmds - Do new commands overwrite old ones?
  • queue_maxlen - How long can the incoming queue grow?
  • interf - Player interface code. The parameter that, if included, makes the constructor for single-interface drivers otherwise for multiple-interface drivers.


In the example below, the constructor is thus targeted at a single-interface driverproviding the interfaceposition2d. Thus, in the example below, a constructor for a single-device driver is used andafterwards the valueexample_interface, e.g. representing a serial port, is readfrom the configuration file into the driver.

1 PlayerDriver::PlayerDriver(ConfigFile* cf, int section) : Driver(cf,section, false, 
2 PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_POSITION2D_CODE)
3 {
4 this->in_section = cf->ReadInt(section, "player_interface", 0);
5 return;
6 }
[ edit]

Setup()

A function performing device-specific initialization e.g. opening and configuringa serial port for communication as well as starting the driver thread. TheSetup()function is called every time a client subscribes to a driver.Setup() returns 0 for success and −1 when setup has failed causing Player to terminate.

1 int PlayerDriver::Setup()
2 {
3 StartThread();
4 return(0);
5 }
[ edit]

Shutdown()

Opposite the Setup() function, Shutdown() ensures device-specific finalization ase.g. shutting down the communication port and stoppage of the driver thread.Shutdown() returns 0 for success, and −1 values when failed.

1 int PlayerDriver::Shutdown()
2 {
3 StopThread();
4 return(0);
5 }
[ edit]

ProcessMessage()

This function is invoked on each incoming message to the server (see next itemMain()). Furthermore, Player offers the opportunity to send a response i.e. publish a message using thePlayer public member function Publish(). If a message is handled successfully, 0 is returned, whilst −1 is returned when message handling has failed.

1 int PlayerDriver::ProcessMessage(MessageQueue* resp_queue, player_msghdr* hdr, void * data)
2 {
3 return(0);
4 }
[ edit]

Main()

The main function of the device thread, where all interaction with the device is to be included. Line 5 checks whether execution should be cancelled, and line 6 presents the call that ensures thatProcessMessage() is invoked at a certain iterval. Between the instruction at line 6 and 7, device-specific code is inserted to e.g. control motors or read IR-sensors assuming these kind of interfaces are specified. Resulting data is replied back to the associated interfaces using Publish().

1 void PlayerDriver::Main()
2 {
3 for(;;)
4 {
5 pthread_testcancel();
6 ProcessMessages();
7 usleep(100000);
8 }
9 }
[ edit]

extern “C”()

This instruction is used to inform the compiler that one or several functions have been compiled in C. The instruction is a so-called “linkage specification” and ensures that the function name will not be included in the standard name encoding performed by the C++ compiler for type-safe linkage. Omitting this instruction will result in an unrecognized function.

1 extern "C" {
2 int player_driver_init(DriverTable* table)
3 {
4 PlayerDriver_Register(table);
5 return(0);
6 }
7 }

Inserting code into the relevant sections of the above described framework for developingPlayer drivers, is basically what is needed in order to develop Player compatible drivers. This has been done in order to develop drivers for all available hardware on theRobotino® including the PBS-03JN range finder. However, the driver for the range finder has been developed individually, with a possiblePlayer contribution in mind. Thus, the developed Robotino® driver will be compatible with all Robotino® robots, and the PBS-03JN driver possible to use for any robot equipped with the sensor. The developed drivers can be downloaded from theDownloads section.


你可能感兴趣的:(linux)