Plug-in structure

From Rsewiki

Introduction

A plug-in is a library module that be loaded by an AURS server and extend the functionality of the server. The plug-in can use the services provided by the server core.

The services provided by the server includes:

  • Service to direct commands from a client to the plugin (XML-formatted)
  • API to decode XML commands
  • Access to specific data sources - e.g. odometry pose, laser scans or camera images.
  • API for global variable creation and access - for parameter configuration and module status.
  • Access to data from other plug-ins
  • API to call functions in other plug-ins
  • API to allow other plug-ins to call this plug-in

Minimum plugin

A minimum plug-in can reply to a command and show a bit of online help.

Two codefiles and a Makefile is needed (see the minimum directory in the code)

Makefile
ufuncminimum.h
ufuncminimum.cpp

Class definition

The ufuncminimum.h defines the UFuncMinimum plug-in class as

class UFuncMinimum : public UFuncPlugBase
{
  public:
  UFuncMinimum()
  { // command list and version text
    setCommand("minimum", "minimum plugin example");
  }
  virtual bool handleCommand(UServerInMsg * msg, void * extra);
};

The class enherits all the needed core functionality from UFuncPlugBase. The plugin gets the command key-name minimum from the setCommand(..) call in the class constructor.

When the server gets a command with the keyword minimum it calls the function

bool handleCommand(UServerInMsg * msg, void * extra);

This function has two parameters, the command message itself in msg and an extra parameter used in some event-related commands, and may point to the data structure related to the event (push commands).

Method implementation

The ufuncminimum.cpp file defines the handleCommand(...) method. In this case it looks like this:

1  #include "ufuncminimum.h"
2  #ifdef LIBRARY_OPEN_NEEDED
3  UFunctionBase * createFunc()
4  { // create an object of this type
5    return new UFuncMinimum();
6  }
7  #endif
8
9  bool UFuncMinimum::handleCommand(UServerInMsg * msg, void * extra)
10 {
11  const int MRL = 500;
12  char reply[MRL];
13  bool ask4help;
14  double a = 100.0, b = 100.0;
15  //
16  ask4help = msg->tag.getAttValue("help", NULL, 0);
17  msg->tag.getAttDouble("a", &a, a);
18  msg->tag.getAttDouble("b", &b, b);
19  //
20  if (ask4help)
21  { // create the reply in XML-like (html - like) format
22    sendHelpStart("MINIMUM");
23    sendText("--- MINIMUM is a demonstration plug-in that calculates the minimum of two numbers\n");
24    sendText("a=A        Value of A (default is 100)\n");
25    sendText("b=B        Value of B (default is 100)\n");
26    sendText("help       This message\n");
27    sendHelpDone();
28  }
29  else
30  { // calculate minimum value
31    snprintf(reply, MRL, "minimum(a=%g, b=%g) is %g", a, b, fmin(a,b));
32    sendInfo(reply);
33  }
34  return true;
35 }
  • The first line is to include the class definition.
  • The lines 2-7 defines the function the server calls to create an instance of the UFuncMinimum plug-in class.

The rest (line 16-35) is a simple command handling method, with a recommendable structure:

  • Line 16-18 retrives the options from the command line

The msg->tag.getAttValue("help", const char * val, const int valCnt) in line 16 uses the 'tag' structure in the message 'msg'. The tag structure holds the original XML formatted command, and has a few methods to extract values. The basic is to get the value string 'val' (of size valCnt) associated with an attribute. (The tag is an instance of the class USmlTagIn, see the class documentation for the full API)

Line 17 and 18 uses a specialized method (bool tag.getAttDouble("a", &a, a)) to get a double sized value from an attribute named "a". The second parameter is where the value is placed and the third parameter is the default value, used if the value string is empty. (The function returns false if an attribute with this name is not available).

  • Line 20-28 is the on-line help reply.

The reply must be packed in the XML format, and this code makes a reply to a minimum help command:

>> minimum help
<help subject="MINIMUM">
--- MINIMUM is a demonstration plug-in that calculates the minimum of two numbers
a=A        Value of A (default is 100)
b=B        Value of B (default is 100)
help       This message
</help>
<minimum info="done"/>
 

The help text is packed in <help> ... </help> bracket marking that this is intended for on-line help (and not for computer interpretation.

The last tag <minimum info="done"> is to satisfy a handshake that there should always be a reply of the same tag name as the command (in this case minimum). This handshake convension is not mandatory, but provides an indication of that the command is executed.

  • line 29-33 is where the real functionality of the plug-in is executed and the replay assembled.

When following is examples on commands and the reply from the minimum plug-in:

>> minimum
<minimum info="minimum(a=100, b=100) is 100"/>
>>
>> minimum A=9 B=8.99
<minimum info="minimum(a=9, b=8.99) is 8.99"/>
>>
>> minimum b=8.2
<minimum info="minimum(a=100, b=8.2) is 8.2"/>
>>
>> minimum b=8.2 a=8.3
<minimum info="minimum(a=8.3, b=8.2) is 8.2"/>
>>
>> <minimum b="8.2" a='8.3'/>
<minimum info="minimum(a=8.3, b=8.2) is 8.2"/>

The commands and attribute names are not case sensitive.

In the last example the command is packed as an XML formatted tag, but in the used tag interpreter, the requirement for the tag frame < .../> and the quotes or apostrophes around the values are relaxed. Quotes or apostrophes are mandatory if the value includes a space character.

  • line 34 returns true (can return false if the number of calls are important and this command failed, e.g. if no source image is available right now. Number of successful calls can be used in push commands.

Makefile

The Makefile gives the name of the plug-in and must know which files to compile.

1  libname = minimum.so
2  CPPFLAGS = -I../include
3  LDFLAGS = -g0 -shared -Wl,-soname,$(libname) 
4  DEFINES = -D LIBRARY_OPEN_NEEDED
5  CXXFLAGS = -g0 -O2 -Wall -pedantic -fPIC $(DEFINES)
6 
7  objects = ufuncminimum.o
8  shlib = $(libname).0
9
10 all: $(objects)
11	c++ -o $(shlib) $(objects) $(LDFLAGS)
12 
13 .PHONY : clean install
14 clean :
15	rm -f $(shlib) $(objects)
16	-@rm -fr *~ .deps
17
18 install:
19	cp $(shlib) ../bin
20

The two lines to update for a new plugin is:

  • Line 1 defines the name of the plugin minimum.so
libname = minimum.so
  • Line 7 defines the compile output-files - in this case just one, compile the ufuncminimum.cpp to ufuncminimum.o.
objects = ufuncminimum.o

The remaining lines can be left unhanged and holds the compile options needed for a plug-in in this environment, and will in most cases detect the dependencies to be recompiled after a change in any of the files.

Global variables and inter-plug-in calls

See Variables.

The inter-plug-in calls has an alternative implementation that takes UVariable as parameter (for both strings, doubles and arrays) this makes calls simpler in some cases.

@todo describe the call implementation using UVariable parameters.

Laser scanner access

@todo

Camera image access

@todo