| Prev: The iCub robot | Up: Home | Next: Writing tests for evolutionary experiments |
|---|---|---|
Table of contents
For evolutionary experiments you need to implement your own fitness function. When you use the EvoRobotExperiment component, to set the fitness of the current individual genotype you simply have to set the value of the totalFitnessValue member variable. In this page we assume that your experiment makes use of a subclass of EvoRobotExperiment
In the case of robotic experiments, tipically the fitness depends on the state of the robot and of the environmemt. For information on how to access to the relevant variables that you need, see the sections on robots and the environment of this section of the documentation.
Depending on the type of experiment that you are implementing, you might decide to compute the fitness function and/or to update the totalFitnessValue variable after each step, after each trial, or after the evaluation of all trials. This means that you can do that in the endStep(), endTrial() or endIndividual() functions. For example, in the case of a robot that should move as quickly as possible and as straight as possible, it might be convenient to update the fitness value at the end of each step on the basis of the current speed of the robot’s wheels. In the case of a foraging robot, that should find and ingest food sources, the fitness might be increased every time the robot manages to ingest a food token. In the case of a robot that should reach a certain desired location, it might be update at the end of each trial. In some cases it might be useful to normalize the fitness value by dividing the total fitness for the number of trials and eventually for the number of steps. In any case, what matters for the evolutionary process, is the value of the fitness achieved at the end of the individual lifetime, that is stored in the totalFitnessValue variable.
The following portion of code extracted from the KheperaDiscriminationExperiment experimental plugin, illustrates an example of how a fitness function can be implemented. This experiment involves a wheeled robot situated in an arena containing a cylindrical object. The calculation of the fitness requires to access the robot and arena components in order to verify whether the distance between the robot and the cylinder is lower than a given threshold at the end of each step. The variable containing the fitness for the current trial (trialFitnessValue) is reset at the beginning of the trial and updated at the end of each step. The instructions for updating the totalFitnessValue variable are included in the endTrial() method, as shown below. The instructions in the endIndividual() method are used to normalize the fitness obtained by the number or trials performed.
:::C++
void KheperaDiscriminationExperiment::initTrial(int trial)
{
...
// Resetting fitness for the current trial
trialFitnessValue = 0;
}
void KheperaDiscriminationExperiment::endStep(int step)
{
farsa::ResourcesLocker locker(this);
farsa::RobotOnPlane* robot = getResource<farsa::RobotOnPlane>("agent[0]:robot");
const farsa::Arena* arena = getResource<farsa::Arena>("arena");
// If robot collided with something, stopping the trial
if (arena->getKinematicRobotCollisionsSet("agent[0]:robot").size() != 0) {
stopTrial();
return;
}
// Computing the distance of the robot with the object
const farsa::real distance = robotObjectDistance(robot);
if (distance < m_distanceThreshold) {
trialFitnessValue += 1.0;
}
}
void KheperaDiscriminationExperiment::endTrial(int trial)
{
totalFitnessValue += trialFitnessValue / getNSteps();
}
void KheperaDiscriminationExperiment::endIndividual(int individual)
{
totalFitnessValue = totalFitnessValue / getNTrials();
}
The following portion of code is extracted from the GraspExperiment experimental plugin, which involves an iCub robot trained for the ability to reach, grasp, and elevate a ball initially laying over a table. The code that computes the fitness value of the current individual is included in the endStep() method. In this case the computation of the fitness is relatively complex since the fitness function involves several components (i.e. the robot is rewarded not only on the basis of whether the ball has been successfully elevated with respect to the plane, but also on the basis of whether it is able to reach the ball with the hand, to touch it, etc.). For this reason the source code of the experimental plugin includes a series of sub-functions that receive a pointer to the icub robot and update the value of each corresponding component.
:::C++
void GraspExperiment::endStep(int step)
{
...
// Updating all fitness components
update_CommonComponentsValues(icub);
update_DistComponent(icub);
update_TouchComponent(icub);
update_OpenFarComponent(icub);
update_CloseNearComponent(icub);
update_GraspQualityComponent(icub);
...
// The value of the fitness components, that is updated
// every time step, is stored in local variables and then
// used to update totalFitnessValue at the end of the trial
// and more precisely 20 steps before the end of the trial,
// as shown below
...
if (step == (nsteps - 21)) {
trialFitnessValue = (dist * 0.3) + (touch * 0.2) + (openFar * closeNear * 0.2) + (graspQ * 0.3);
}
...
}
Manual: CustomizeEnvironment
Manual: CustomizingRobots
Manual: EvorobotExperimentTest
Manual: Home
Manual: iCubRobot
Anonymous