00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "evorobotexperiment.h"
00025 #include "sensors.h"
00026 #include "motors.h"
00027 #include "evoga.h"
00028 #include "configurationhelper.h"
00029 #include "factory.h"
00030 #include "logger.h"
00031
00032 #include <QFile>
00033 #include <QTextStream>
00034 #include <QString>
00035 #include <QTime>
00036 #include <QThread>
00037 #include <iostream>
00038 #include <cstdlib>
00039
00040
00041
00042
00043 #if defined(_MSC_VER)
00044 #pragma warning(push)
00045 #pragma warning(disable:4996)
00046 #endif
00047
00048 namespace farsa {
00049
00050
00051
00052
00053 EvoRobotExperiment::EvoRobotExperiment()
00054 {
00055 ga = NULL;
00056 evonet = NULL;
00057 neuronsIterator = new EvonetIterator();
00058 robot = NULL;
00059 world = NULL;
00060 savedConfigurationParameters = NULL;
00061 savedPrefix = NULL;
00062 ntrial = 0;
00063 stopCurrentTrial = false;
00064 skipCurrentTrial = false;
00065 restartCurrentTrial = false;
00066 endCurrentIndividualLife = false;
00067
00068 gaPhase = NONE;
00069
00070
00071
00072
00073 batchRunning = false;
00074
00075
00076
00077
00078 usableResources( QStringList() << "world" << "evonet" << "neuronsIterator" << "experiment" );
00079 }
00080
00081 EvoRobotExperiment::~EvoRobotExperiment()
00082 {
00083 delete savedConfigurationParameters;
00084 delete savedPrefix;
00085 delete evonet;
00086 for (int i = 0; i < sensors.size(); i++) {
00087 delete sensors[i];
00088 }
00089 for (int i = 0; i < motors.size(); i++) {
00090 delete motors[i];
00091 }
00092 delete world;
00093 }
00094
00095 void EvoRobotExperiment::configure(ConfigurationParameters& params, QString prefix)
00096 {
00097
00098 delete savedConfigurationParameters;
00099 delete savedPrefix;
00100 savedConfigurationParameters = new ConfigurationParameters(params);
00101 savedPrefix = new QString(prefix);
00102
00103
00104 params.setResourcesUser(this);
00105
00106 ntrials = 1;
00107 nsteps = 1;
00108
00109 batchRunning = ConfigurationHelper::getBool(params, "__INTERNAL__/BatchRunning", batchRunning);
00110 ntrials = ConfigurationHelper::getInt(params, prefix + "ntrials", ntrials);
00111 nsteps = ConfigurationHelper::getInt(params, prefix + "nsteps", nsteps);
00112
00113
00114
00115 QStringList sensorsList = params.getGroupsWithPrefixList(prefix, "Sensor:");
00116 sensorsList.sort();
00117 foreach( QString sensorGroup, sensorsList ) {
00118 Sensor* sensor = params.getObjectFromGroup<Sensor>(prefix + sensorGroup);
00119 if ( sensor == NULL ) {
00120 Logger::error("Cannot create the Sensor from group " + prefix + sensorGroup + ". Aborting");
00121 abort();
00122 }
00123
00124
00125 if ( sensor->name() == QString("unnamed") ) {
00126 sensor->setName( sensorGroup );
00127 }
00128 sensors.append( sensor );
00129 sensors.last()->shareResourcesWith( this );
00130 Logger::info( "Created a Sensor named "+sensor->name() );
00131
00132 if ( sensorsMap.contains( sensor->name() ) ) {
00133 Logger::error( "More than one sensor has name "+sensor->name()+" !! The name has to be unique !!" );
00134 } else {
00135
00136 sensorsMap[sensor->name()] = sensor;
00137 }
00138 }
00139
00140
00141 QStringList motorsList = params.getGroupsWithPrefixList(prefix, "Motor:");
00142 motorsList.sort();
00143 foreach( QString motorGroup, motorsList ) {
00144 Motor* motor = params.getObjectFromGroup<Motor>(prefix + motorGroup);
00145 if (motor == NULL) {
00146 Logger::error("Cannot create the Motor from group " + prefix + motorGroup + ". Aborting");
00147 abort();
00148 }
00149
00150
00151 if ( motor->name() == QString("unnamed") ) {
00152 motor->setName( motorGroup );
00153 }
00154 motors.append( motor );
00155 motors.last()->shareResourcesWith( this );
00156 Logger::info( "Created a Motor named "+motor->name() );
00157
00158 if ( motorsMap.contains( motor->name() ) ) {
00159 Logger::error( "More than one motor has name "+motor->name()+" !! The name has to be unique !!" );
00160 } else {
00161
00162 motorsMap[motor->name()] = motor;
00163 }
00164 }
00165
00166
00167
00168 recreateWorld();
00169 recreateRobot();
00170
00171 recreateNeuralNetwork();
00172
00173 declareResource( "neuronsIterator", neuronsIterator, "evonet" );
00174 declareResource( "experiment", static_cast<ParameterSettableWithConfigureFunction*>(this) );
00175
00176 Logger::info( params.getValue(prefix+"type") + " Configured" );
00177 }
00178
00179 void EvoRobotExperiment::save(ConfigurationParameters&, QString)
00180 {
00181 Logger::error("NOT IMPLEMENTED (EvoRobotExperiment::save)");
00182 abort();
00183 }
00184
00185 void EvoRobotExperiment::describe( QString type ) {
00186 Descriptor d = addTypeDescription( type, "The experimental setup that defines the conditions and the fitness function of the evolutionary experiment" );
00187 d.describeInt( "ntrials" ).def(1).limits(1,MaxInteger).help("The number of trials the individual will be tested to calculate its fitness");
00188 d.describeInt( "nsteps" ).def(1).limits(1,MaxInteger).help("The number of step a trials will last");
00189 d.describeSubgroup( "NET" ).props( IsMandatory ).type( "Evonet" ).help( "The Neural Network controlling the robot");
00190 d.describeSubgroup( "ROBOT" ).props( IsMandatory ).type( "Robot" ).help( "The Neural Network controlling the robot");
00191 d.describeSubgroup( "Sensor" ).props( AllowMultiple ).type( "Sensor" ).help( "One of the Sensors from which the neural network will receive information about the environment" );
00192 d.describeSubgroup( "Motor" ).props( AllowMultiple ).type( "Motor" ).help( "One of the Motors with which the neural network acts on the robot and on the environment" );
00193 }
00194
00195 void EvoRobotExperiment::postConfigureInitialization()
00196 {
00197 if (!batchRunning) {
00198
00199 ga->doNotUseMultipleThreads();
00200 }
00201
00202 gaPhase=EvoRobotExperiment::INEVOLUTION;
00203 }
00204
00205 void EvoRobotExperiment::doTrial()
00206 {
00207 restartCurrentTrial = false;
00208 stopCurrentTrial = false;
00209 trialFitnessValue = 0.0;
00210 for(nstep = 0; nstep < nsteps; nstep++) {
00211 initStep( nstep );
00212 if ( ga->commitStep() || restartCurrentTrial ) {
00213 break;
00214 }
00215 doStep();
00216 if ( ga->commitStep() ) break;
00217 endStep( nstep );
00218 if (ga->commitStep() || stopCurrentTrial || restartCurrentTrial) {
00219 break;
00220 }
00221 }
00222 }
00223
00224 void EvoRobotExperiment::doAllTrialsForIndividual(int individual)
00225 {
00226 endCurrentIndividualLife = false;
00227 totalFitnessValue = 0.0;
00228
00229 initIndividual(individual);
00230 if ( ga->commitStep() ) return;
00231
00232 for (ntrial = 0; ntrial < ntrials; ntrial++) {
00233 skipCurrentTrial = false;
00234
00235 initTrial(ntrial);
00236 if ( ga->commitStep() ) break;
00237 if (skipCurrentTrial) {
00238 continue;
00239 }
00240 if (!endCurrentIndividualLife) {
00241 doTrial();
00242 }
00243 if ( ga->isStopped() ) break;
00244 if (restartCurrentTrial) {
00245 ntrial--;
00246 continue;
00247 }
00248 endTrial(ntrial);
00249
00250 if (gaPhase == INTEST) {
00251 Logger::info("Fitness for trial: " + QString::number(trialFitnessValue));
00252 }
00253
00254 if ( ga->commitStep() || endCurrentIndividualLife ) {
00255 break;
00256 }
00257
00258 }
00259
00260 endIndividual(individual);
00261 ga->commitStep();
00262 }
00263
00264 void EvoRobotExperiment::initGeneration(int)
00265 {
00266 }
00267
00268 void EvoRobotExperiment::initIndividual(int)
00269 {
00270 }
00271
00272 void EvoRobotExperiment::initTrial(int)
00273 {
00274
00275 ResourcesLocker locker(this);
00276 evonet->resetNet();
00277 }
00278
00279 void EvoRobotExperiment::initStep(int)
00280 {
00281 }
00282
00283 double EvoRobotExperiment::getFitness()
00284 {
00285 return totalFitnessValue;
00286 }
00287
00288 void EvoRobotExperiment::afterSensorsUpdate()
00289 {
00290 }
00291
00292 void EvoRobotExperiment::beforeMotorsUpdate()
00293 {
00294 }
00295
00296 void EvoRobotExperiment::endTrial(int)
00297 {
00298 totalFitnessValue += trialFitnessValue;
00299 }
00300
00301 void EvoRobotExperiment::endIndividual(int)
00302 {
00303 }
00304
00305 void EvoRobotExperiment::endGeneration(int)
00306 {
00307 }
00308
00309 void EvoRobotExperiment::doStep()
00310 {
00311
00312
00313 ResourcesLocker locker(this, false);
00314
00315
00316 for (int s = 0; s < sensors.size(); s++) {
00317 sensors[s]->update();
00318 }
00319 afterSensorsUpdate();
00320
00321 locker.lock();
00322 evonet->updateNet();
00323 locker.unlock();
00324 if (!batchRunning) {
00325
00326 class T : public QThread
00327 {
00328 public:
00329 using QThread::sleep;
00330 using QThread::msleep;
00331 using QThread::usleep;
00332 };
00333
00334
00335 T::msleep(3);
00336 }
00337 beforeMotorsUpdate();
00338
00339 for (int m = 0; m < motors.size(); m++) {
00340 motors[m]->update();
00341 }
00342
00343 locker.lock();
00344 world->advance();
00345 locker.unlock();
00346 }
00347
00348 void EvoRobotExperiment::stopTrial()
00349 {
00350 stopCurrentTrial = true;
00351 }
00352
00353 void EvoRobotExperiment::skipTrial()
00354 {
00355 skipCurrentTrial = true;
00356 }
00357
00358 void EvoRobotExperiment::restartTrial()
00359 {
00360 restartCurrentTrial = true;
00361 }
00362
00363 void EvoRobotExperiment::endIndividualLife()
00364 {
00365 endCurrentIndividualLife = true;
00366 stopCurrentTrial = true;
00367 }
00368
00369 int EvoRobotExperiment::getGenomeLength()
00370 {
00371 ResourcesLocker locker(this);
00372
00373 return evonet->freeParameters();
00374 }
00375
00376 Sensor* EvoRobotExperiment::getSensor( QString name ) {
00377 if ( sensorsMap.contains( name ) ) {
00378 return sensorsMap[name];
00379 } else {
00380 Logger::error( "getSensor returned NULL pointer because there is no sensor named "+name );
00381 return NULL;
00382 }
00383 }
00384
00385 Motor* EvoRobotExperiment::getMotor( QString name ) {
00386 if ( motorsMap.contains( name ) ) {
00387 return motorsMap[name];
00388 } else {
00389 Logger::error( "getMotor returned NULL pointer because there is no motor named "+name );
00390 return NULL;
00391 }
00392 }
00393
00394 bool EvoRobotExperiment::inBatchRunning()
00395 {
00396 return batchRunning;
00397 }
00398
00399 Evonet* EvoRobotExperiment::getNeuralNetwork()
00400 {
00401 return evonet;
00402 }
00403
00404 void EvoRobotExperiment::setEvoga( Evoga* ga )
00405 {
00406 this->ga = ga;
00407 }
00408
00409 Evoga* EvoRobotExperiment::getEvoga() {
00410 return ga;
00411 }
00412
00413 void EvoRobotExperiment::setNetParameters(int *genes)
00414 {
00415 ResourcesLocker locker(this);
00416
00417 evonet->getParameters(genes);
00418 }
00419
00420 void EvoRobotExperiment::setTestingAgentAndSeed(int,int)
00421 {
00422 Logger::error("EvoRobotExperiment::setTestingAgentAndSeed() not yet implemented");
00423 }
00424
00425 void EvoRobotExperiment::recreateWorld() {
00426
00427
00428
00429 Robot* const old_robot = robot;
00430 World* const old_world = world;
00431 robot = NULL;
00432
00433
00434 world = new World( "World", true );
00435 world->setTimeStep(0.05f);
00436 world->setSize( wVector( -2.0f, -2.0f, -0.50f ), wVector( +2.0f, +2.0f, +2.0f ) );
00437 world->setFrictionModel( "exact" );
00438 world->setSolverModel( "exact" );
00439 world->setMultiThread( 1 );
00440
00441
00442 if ( old_robot != NULL ) {
00443 deleteResource( "robot" );
00444 robot = NULL;
00445 }
00446 declareResource( "world", world );
00447
00448
00449 delete old_robot;
00450 delete old_world;
00451 }
00452
00453 void EvoRobotExperiment::recreateRobot() {
00454
00455 if ( !world ) {
00456 recreateWorld();
00457 }
00458
00459
00460 ResourcesLocker locker(this);
00461
00462 Robot* const old_robot = robot;
00463
00464
00465 savedConfigurationParameters->setResourcesUser(this);
00466 robot = savedConfigurationParameters->getObjectFromGroup<Robot>((*savedPrefix) + "ROBOT");
00467
00468
00469 locker.unlock();
00470
00471 declareResource( "robot", robot, "world" );
00472 delete old_robot;
00473 }
00474
00475 void EvoRobotExperiment::recreateNeuralNetwork() {
00476
00477 Evonet* const old_evonet = evonet;
00478
00479
00480 if ( savedConfigurationParameters->getValue( (*savedPrefix)+"NET/netFile" ).isEmpty() ) {
00481
00482 int nSensors = 0;
00483 foreach( Sensor* sensor, sensors ) {
00484 nSensors += sensor->size();
00485 }
00486 int nMotors = 0;
00487 foreach( Motor* motor, motors ) {
00488 nMotors += motor->size();
00489 }
00490
00491 savedConfigurationParameters->createParameter( (*savedPrefix)+"NET", "nSensors", QString::number(nSensors) );
00492 savedConfigurationParameters->createParameter( (*savedPrefix)+"NET", "nMotors", QString::number(nMotors) );
00493 }
00494
00495
00496 ResourcesLocker locker(this);
00497 savedConfigurationParameters->setResourcesUser(this);
00498 evonet = savedConfigurationParameters->getObjectFromGroup<Evonet>( (*savedPrefix)+"NET" );
00499 locker.unlock();
00500
00501 declareResource("evonet", static_cast<farsa::ParameterSettable*>(evonet));
00502
00503
00504 locker.lock();
00505 delete old_evonet;
00506 neuronsIterator->setEvonet( evonet );
00507
00508 int startIndex = 0;
00509 foreach( Sensor* sensor, sensors ) {
00510 neuronsIterator->defineBlock( sensor->name(), EvonetIterator::InputLayer, startIndex, sensor->size() );
00511 startIndex += sensor->size();
00512 }
00513 startIndex = 0;
00514 foreach( Motor* motor, motors ) {
00515 neuronsIterator->defineBlock( motor->name(), EvonetIterator::OutputLayer, startIndex, motor->size() );
00516 startIndex += motor->size();
00517 }
00518 }
00519
00520 }
00521
00522
00523 #if defined(_MSC_VER)
00524 #pragma warning(pop)
00525 #endif