Webots User Guide - chapter 6 - section 6

Webots User Guide


6.6 Controller plugin

The controller functionnality can be extended with user-implemented plugins. The purpose of the controller plugins is to facilitate the programming of robot-specific robot windows and remote-control wrappers.

Programming controller plugin rather than programming directly in the controller is more convenient because it increases considerably the modularity and the scalability of the code. For example a robot window can be used for several robots.

6.6.1 Fundamentals

Whatever its language, a controller executable is linked with the Webots controller library (libController) at startup. A controller plugin is a shared library loaded dynamically (at runtime) by libController after a specific event depending on its type.

The figure 6.3 shows an overview of the controller plugin system. In this figure, the dashed arrows shows how the shared libraries are loaded, and the large dash lines represents an Inter-Process Communication (IPC). The IPC between libController and Webots is a pipe (On Windows this is a named pipe, and otherwise a local domain socket). The IPC between libRemoteControl and the real robot is defined by the user (TCP/IP, Serial, etc.).

The system has been designed as follow. Every entities (the controller, the remote control library and the robot window library) should only call the libController interface (Webots API) functions. The controller should not be aware of its robot window and its real robot for modularity reasons. The only exception is about the robot window library which can be aware of the remote control library to initialise and monitor it. This can be done trough the libController API through the wb_robot_get_mode(), wb_robot_set_mode() and the wb_remote_control_custom_function() functions. Of course these rules can be easily broken because every entities runs into the same process. However we recommend to respect them to get a good design.

The controller plugins have been designed to be written in C/C++, because the result should be a dynamic library. However it's certainly possible to write them in other languages using a C/C++ wrapper inbetween.

After its loading, some controller plugin functions (entry points) are called by libController. A set of entry points have to be defined to let the controller plugin work smoothly. Some of these entry points are required and some are optional.

The Robot node defines the location of the controller plugin through its libRobotWindow and its libRemoteControl fields (cf. reference manual)

The controller plugins run in the main thread of the process (also known as Gui thread): the same a the controller executable. This implies that if an entry point of a plugin is blocking, the controller will also be blocked. And if the plugin crashes, the controller is also crashed.

The extension of the shared library file is .dll on windows, .so on linux, and .dylib on mac. Controller plugins are designed to be located in the lib directory of the project directory. Moreover the shared library should be created in a subdirectory starting with the lib prefix, and with the same basename as the shared library. For example: my_project/lib/libmyrobotwindow/libmyrobotwindow.so

Each distributed shared library is built thanks to a Makefile which includes this file: $WEBOTS_HOME/resources/projects/default/lib/Makefile.include

controller_plugin

Figure 6.3: Controller plugins overview

6.6.2 Robot window plugin

The robot window plugin allows to create simply and efficiently custom robot windows. The robot windows can be open by double-clicking on the virtual robot, or by selecting the Robot | Show Robot Window menu item.

The robotWindow field of the Robot node allows to select which robot window (cf. documentation in the reference manual).

The entry points of the robot window controller plugin are:

The internal behavior of the wb_robot_step() call is the key point to understand how the different entry points of the robot window plugin are called (pseudo-code):

wb_robot_step() {
  wbw_write_actuators()
  wbw_pre_update_gui()
  write_request_to_webots_pipe()
  wbw_update_gui() // returns when something on the pipe
  read_request_to_webots_pipe()
  wbw_read_sensors()
}

As the Qt libraries are included in Webots (used by the Webots GUI), and all our samples are based on it, we recommend to choose also this framework to create your GUI. The Makefile.include mentionned above allows you to linked efficiently with the Qt framework embedded in Webots.

If the robot window cannot be loaded (bad path, bad initialization, etc.), a generic robot window is open instead. This generic robot window display several sensors and actuators. The source code of this robot window is a good demonstrator of the robot window plugin abilities. All the source code is located there: $WEBOTS_HOME/resources/projects/default/lib/libgenericwindow

Other samples can be found:

$WEBOTS_HOME/resources/projects/default/lib/libbotstudio

$WEBOTS_HOME/resources/projects/robots/e-puck/lib/libepuckwindow

6.6.3 Remote-control plugin

The remote-control plugin allows to create simply and efficiently an interface using the Webots API to communicate with a real robot. The main purpose of a remote-control library is to wrap all the Webots API functions used by the robot with a protocol communicating to the real robot. Generally, a program (client) runs on the real robot, and decodes the communication protocol to dialog with the real robot devices.

The remote-control library is initialized when an entity calls the wb_robot_set_mode() libController function. This entity is typically libRobotWindow, because it's quite convenient to use the GUI to initialize the communication (i.e. entering the IP address of the robot, etc.)

There are two entry points to the remote-control library:

The WbrInterface structure has several functions (mandatory) which have to be mapped to let the remote-control library runs smoothly. Here they are:

As said above, all the Webots API functionnalities that should work with the real robot have to be wrapped into the remote-control library. To achieve this:

This file contains the complete definition of the remote control API and of the WbrInterface structure: $WEBOTS_HOME/include/controller/c/webots/remote_control.h

For example, if you want to be able to use the distance sensor of the real robot, you have to wrap the wbr_set_refresh_rate() function (to set the internal state of the remote control library to read this distance sensor only when required), and to calls wbr_distance_sensor_set_value() into the remote-control library when the distance sensor is refresh (typically into the wbr_robot_step() function).

A complete sample (communicating with the e-puck robot using bluetooth) can be found in this directory:

$WEBOTS_HOME/resources/projects/robots/e-puck/lib/libbluetooth

release 7.0.2
Copyright © 2012 Cyberbotics Ltd. All right reserved.