The WebotsPuppyMixin class connects the Puppy robot model to the Webots’ programming interface. It is designed such that it simplifies and unifies the development of a custom Puppy controller. Just like the Supervisor, the WebotsPuppyMixin has to be instantiated through a builder. At creation, the class requires an actor callback (which implements the controller) and some timings. The timings define the length of different epochs, namely the intervalls at which the actor is executed and how many sensor readings will be available. The callback must be compliant with RobotActor. Note that although the interface is specified in a class structure, it is designed in a way that also fits a plain function.

Similar to WebotsSupervisorMixin, the method implements the main, infinite control loop. Within the loop, a sense-think-act cycle is running. Sensor data are automatically read, so the sense-part is taken care of. Since the think and act parts are problem-dependent, they have to be implemented by the actor. Each call to the actor must return an iterator for the next of motor targets. These are incrementally enforced on the motors, such that the actor may indeed define the robot’s behaviour. To do so, the sensor readings between two calls are supplied. To see how this works exactly, consult the documentation of WebotsPuppyMixin and RobotActor.

The WebotsPuppyMixin abstracts from the Webots API in the sense that it takes care of initialization and readout of Puppy’s sensors. Thus, the actor may focus on the pure controller implementation. Some simple controllers have been prepared, for them see the Control page.


In the controller script, Webots’ controller module will be present, so it is imported together with the PuPy module.

>>> from controller import Robot
>>> import PuPy

As a simple illustrative walking pattern, a Gait is initialized. Details are not relevant right here (see the Control page for that), this just specifies a way of moving around.

>>> gait = PuPy.Gait({
>>>     'frequency' : (1.0, 1.0, 1.0, 1.0),
>>>     'offset'    : ( -0.23, -0.23, -0.37, -0.37),
>>>     'amplitude' : ( 0.56, 0.56, 0.65, 0.65),
>>>     'phase'     : (0.0, 0.0, 0.5, 0.5)
>>> })

With this specification, an actor can be set up. Again, it’s not important what the actor concretely does but its mere existence: It implements the act-step in the sense-think-act cycle. Again, for details see Control.

>>> actor = PuPy.ConstantGaitControl(gait)

When everything is ready, the robot instance is created through the respective builder, as already mentioned. The first argument is Webots’ Robot class, followed by arguments of WebotsPuppyMixin (actor in this case).

>>> r = PuPy.robotBuilder(Robot, actor)

The instance is ready, its main loop awaits execution. Let’s do this as the last script line:


When the simulation terminates (i.e. reverts or quits), the main loop will actually be broken and the above call returns. Make sure that if there’s code below this point, it doesn’t prevent termination. There’s a one second timeframe before the script gets killed by Webots.


class PuPy.WebotsPuppyMixin(*args, **kwargs)

Bases: PuPy.webots.WebotsRobotMixin

The actual Puppy Robot implementation.

List of receiver callbacks. Only allowed as keyword argument. The callbacks must implement the event_handler_template() interface.
class PuPy.WebotsRobotMixin(actor, sampling_period_ms=20, ctrl_period_ms=2000, motor_period_ms=None, event_period_ms=None, noise_ctrl=None, noise_obs=None)

Webots Robot controller. It samples all sensors and periodically consults an actor for control decisions.


A function which determines the motor targets for the next control period. See RobotActor for specifics.

The function must return an interator which is valid for at least ctrl_period_ms / motor_period_ms steps. In each step, it must return a list of four motor targets.

The actor’s interface is defined by RobotActor. Note however, that the interface is organized such that the class structure may be obsolete.

The period according to which sensors are sampled. In milliseconds.
The period of control actions. In milliseconds. Must be a larger than or equal to the motor period and, if larger, a multiple thereof.
The period according to which motor targets are set. In milliseconds. Usually, the same as sampling_period_ms (the default). If not, it’s advised that it’s a multiple of the sampling period, otherwise the observations per control decision may become funny.
The period in milliseconds that is used for polling the receiver. Should optimally be a multiple of the control or sampling period or the Supervisor’s sampling period.
Additive zero-mean gaussian noise on the motor targets. Additional to whatever webots does. Either a scalar of 4-tuple is expected, which represents the noise variances for all of the motors or each individual one, respectively. Use None to discard the noise (default).
Additive zero-mean gaussian noise on the motor targets. Additional to whatever webots does. Either a scalar of dict is expected, which represents the noise variances for all of the sensors or each individual one, respectively. In the latter approach, the dict keys have to correspond to the sensor name. Use None to discard the noise (default).

Add an emittor called name.

add_motor(name, device)

Add a motor name to the robot with the corresponding webots node device.

add_receiver(receiver_name, callback=None)

Add a receiver_name for polling. If a new message is available callback is to be called. If callback is a list, all its items will be called on the same message.

add_sensor(name, clbk, dim=1)

Add a sensor name to the robot. The function clbk reads out sensor value(s). Each readout must either produce one (dim = 1) or three (dim = 3) readout values.


Return labels and a generator for reading out sensor values. The labels and values returned by the generator have the same order.


Return the motor’s names.


Main controller loop. Runs infinitely unless aborted by webots.

The controller operates on a sense, think, act cycle. In every step - according to the sampling period - the sensors are read out (sense). This information is passed to the control decision machine (think) and its result used for updating the motors (act).

The actor is provided with all sensor readings, starting from the previous call up to the current one. The very last readout is equal to the current state of the robot. The motor targets (denoted by trg) are the ones that have been applied in the previous step. This can be interpreted as the target that caused the sensor readings. Also note, that the motor targets returned by the actor will be effective immediately, i.e. the first target will be set right after the actor was called.

Changed in version 1365: After version 1365 (10eb3eed-6697-4d8c-9aac-32ebf1d36239), the behaviour of the main loop was changed: There’s an initialization of the motor target and the target executed before the measurement (so long, it was executed after). We need to discuss and test this to be more specific about the behaviour.

send_msg(msg, emittor_name=None)

Send a message msg through a device emittor_name. If the emittor_name is None, the message will be sent through all available devices.

PuPy.event_handler_template(robot, epoch, current_time, msg)

Template function for event_handler function of WebotsRobotMixin:.

Instance of WebotsRobotMixin with the current robot.
dict containing the current sensor readings.
int() with the current time step in ms.
str() containing the event message.

Table Of Contents

Previous topic


Next topic


This Page