Skip to content

Driver Capabilities

Rich edited this page Apr 8, 2017 · 1 revision

Player drivers are programmed to support one or more interfaces. Each interface has a variety of request and command messages that the driver can handle, but drivers don't necessarily have to handle all of the messages in an interface. For example, a motor controller driver using the position2d interface may not have an on-board PID controller. The driver would therefore have no reason to handle the PLAYER_POSITION2D_REQ_SPEED_PID or the PLAYER_POSITION2D_REQ_VELOCITY_PID requests defined in the position2d interface. Using driver capabilities, a client program can check to see if the driver providing the position2d interface does in fact support setting PID values before attempting to do so.

Table of Contents

Adding Capability Requests to Drivers

Capability requests are special messages with the message type PLAYER_CAPABILITIES_REQ, and are passed through the Player server to drivers like any other message. Player provides a handler macro, called HANDLE_CAPABILITY_REQUEST, in libplayercore/driver.h. The HANDLE_CAPABILITY_REQUEST compares the message types in the incoming request message to the message types provided in the macro. If the messages match, the macro will publish an ACK back to the requester, indicating that the capability is implemented. Otherwise, the message will keep falling through the ProcessMessage function.

Drivers should check for capability requests in their ProcessMessage functions, as shown below:

int ExampleDriver::ProcessMessage (QueuePointer &resp_queue, player_msghdr *hdr, void *data)
{
    // Check to see if the driver supports capability requests at all.
    HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_CAPABILITIES_REQ);
    // Check to see if the driver supports the PLAYER_RANGER_REQ_GET_GEOM request
    HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_GET_GEOM);

    // Additional message processing code
}

The above sample code shows checks for two message types: the PLAYER_CAPIBILITIES_REQ request and the PLAYER_RANGER_REQ_GET_GEOM request from the Ranger interface. The PLAYER_CAPIBILITIES_REQ should be handled in all drivers that support capability requests: it indicates to client programs that the driver has the provisions to respond to capability requests correctly. Drivers without capability requests implemented will not handle this messagetype, and the message will fall through the ProcessMessage function until it reaches the end, triggering a NACK message to be sent back.

Checking for Capabilities from a Client program

The client libraries all provide a way to query drivers for capibilities.

libplayerc

libplayerc contains the function "playerc_device_hascapability" which can be used to query for capabilities as follows:

#include <stdio.h>
include <libplayerc/playerc.h>
int main(int argc, const char **argv)
{
  playerc_client_t *client;
  playerc_position2d_t *position2d;
  bool has_capabilites;

  // Create a client and connect it to the server.
  client = playerc_client_create(NULL, "localhost", 6665);
  if (0 != playerc_client_connect(client))
    return -1;

  // Create and subscribe to a position2d device.
  position2d = playerc_position2d_create(client, 0);
  if (playerc_position2d_subscribe(position2d, PLAYER_OPEN_MODE))
    return -1;

  // Check to see if the position2d device supports the PLAYER_POSITION2D_REQ_GET_GEOM request
  has_capabilities = playerc_device_hascapability(position2d, PLAYER_MSGTYPE_REQ, PLAYER_CAPABILITIES_REQ);
  printf("Device capability check result: %d\n", has_capabilities);
}

libplayerc++

The libplayerc++ ClientProxy class contains the method HasCapability() to check for driver capabilities. It can be used as follows:

#include <iostream>
include <libplayerc++/playerc++.h>
int main(int argc, char *argv[])
{
  using namespace PlayerCc;

  PlayerClient    robot("localhost");
  Position2dProxy pp(&robot,0);

  bool has_capabilities = pp.HasCapability(PLAYER_MSGTYPE_REQ, PLAYER_CAPABILITIES_REQ);
  std::cout << "Device capability check result: " << has_capabilities << std::endl;
}