00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "evorobotcomponent.h"
00024 #include "evorobotviewer.h"
00025 #include "abstracttest.h"
00026 #include "tests.h"
00027 #include "configurationhelper.h"
00028 #include "logger.h"
00029
00030 namespace farsa {
00031
00033 class EvolveOperation : public ThreadOperation {
00034 public:
00035 EvolveOperation( Evoga* ga, EvoRobotComponent* evorobot ) :
00036 ga(ga),
00037 evorobot(evorobot) { };
00038 virtual ~EvolveOperation() { };
00040 virtual void stop() {
00041 ga->stop();
00042 };
00044 virtual void run() {
00045 evorobot->setStatus( "In Evolution ..." );
00046 ga->getEvoRobotExperiment()->setActivityPhase( EvoRobotExperiment::INEVOLUTION );
00047 ga->evolveAllReplicas();
00048 QString message;
00049 if ( ga->isStopped() ) {
00050 message = "Evolution Stopped";
00051 } else {
00052 message = "Evolution Finished";
00053 }
00054
00055 ga->resetStop();
00056 evorobot->onThreadOperationDone( message );
00057 };
00058 private:
00059 Evoga* ga;
00060 EvoRobotComponent* evorobot;
00061 };
00062
00064 class TestOperation : public ThreadOperation {
00065 public:
00066 TestOperation( AbstractTest* test, Evoga* ga, EvoRobotComponent* evorobot ) :
00067 test(test),
00068 ga(ga),
00069 evorobot(evorobot) { };
00070 virtual ~TestOperation() { };
00072 virtual void stop() {
00073 ga->stop();
00074 };
00076 virtual void run() {
00077 evorobot->setStatus( QString("Running ")+test->menuText()+" ..." );
00078 test->runTest();
00079 QString message;
00080 if ( ga->isStopped() ) {
00081 message = "Test Stopped";
00082 } else {
00083 message = "Test Finished";
00084 }
00085
00086 ga->resetStop();
00087 evorobot->onThreadOperationDone( message );
00088 };
00089 private:
00090 AbstractTest* test;
00091 Evoga* ga;
00092 EvoRobotComponent* evorobot;
00093 };
00094
00095 EvoRobotComponent::EvoRobotComponent() :
00096 Component(),
00097 ga(NULL),
00098 batchRunning(false),
00099 runningOperation(false),
00100 mutex() {
00101 gaThread = new WorkerThread( this );
00102
00103 connect(gaThread, SIGNAL(exceptionDuringOperation(BaseException*)), this, SLOT(exceptionDuringOperation(BaseException*)), Qt::BlockingQueuedConnection);
00104 }
00105
00106 EvoRobotComponent::~EvoRobotComponent() {
00107 gaThread->quit();
00108 delete gaThread;
00109 delete ga;
00110 }
00111
00112 ComponentUI* EvoRobotComponent::getUIManager() {
00113 return new EvoRobotViewer( this );
00114 }
00115
00116 void EvoRobotComponent::configure(farsa::ConfigurationParameters& params, QString prefix) {
00117 if ( ga ) {
00118
00119 gaThread->quit();
00120 delete gaThread;
00121 delete ga;
00122 }
00123 batchRunning = ConfigurationHelper::getBool(params, "__INTERNAL__/BatchRunning", batchRunning);
00124 ga = params.getObjectFromGroup<Evoga>( prefix+"GA" );
00125
00126
00127
00128
00129
00130
00131
00132 bool testAllAdded = false;
00133 bool testIndividualAdded = false;
00134 bool testRandomAdded = false;
00135 bool testZeroAdded = false;
00136
00137 currentTestName = QString();
00138 QStringList testGroups = params.getGroupsWithPrefixList( prefix, "TEST:" );
00139 for( int i=0; i<testGroups.size(); i++ ) {
00140 if ( i==0 ) {
00141
00142 currentTestName = testGroups[i];
00143 }
00144 AbstractTest* test = params.getObjectFromGroup<AbstractTest>(prefix+testGroups[i]);
00145 test->setComponent( this );
00146 AvailableTestList::addTest( testGroups[i], test );
00147
00148
00149
00150 if (dynamic_cast<TestIndividual *>(test) != NULL) {
00151 testIndividualAdded = true;
00152 } else if (dynamic_cast<TestRandom *>(test) != NULL) {
00153 testRandomAdded = true;
00154 }
00155
00156
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 if (!testIndividualAdded) {
00168
00169
00170 AbstractTest* test = new TestIndividual();
00171 test->setComponent( this );
00172 AvailableTestList::addTest("TestIndividual", test);
00173 }
00174 if (!testRandomAdded) {
00175
00176
00177 AbstractTest* test = new TestRandom();
00178 test->setComponent( this );
00179 AvailableTestList::addTest("TestRandom", test);
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 if ( currentTestName.isEmpty() ) {
00192
00193
00194 currentTestName = "TestIndividual";
00195 }
00196 currentTestName = ConfigurationHelper::getString( params, prefix+"testToRun", currentTestName );
00197
00198
00199 gaThread->start();
00200
00201 setStatus( "Configured" );
00202 }
00203
00204 void EvoRobotComponent::save(farsa::ConfigurationParameters& params, QString prefix) {
00205 ga->save( params, prefix+"/GA" );
00206 }
00207
00208 void EvoRobotComponent::postConfigureInitialization() {
00209 }
00210
00211 void EvoRobotComponent::describe( QString type ) {
00212 Descriptor d = addTypeDescription( type, "This component allow to do evolutionary robotics experiments" );
00213 d.describeSubgroup( "GA" ).type( "Evoga" ).props( IsMandatory ).help( "The Genetic Algorithm to use to perform the evolutionary process" );
00214 d.describeSubgroup( "TEST" ).type( "AbstractTest" ).props( AllowMultiple ).help( "let to configure a test condition for the evolved individual" );
00215 }
00216
00217 Evoga* EvoRobotComponent::getGA() {
00218 return ga;
00219 }
00220
00221 void EvoRobotComponent::stop() {
00222 gaThread->stopCurrentOperation();
00223 }
00224
00225 void EvoRobotComponent::evolve()
00226 {
00227 if ( batchRunning ) {
00228 ga->getEvoRobotExperiment()->setActivityPhase( EvoRobotExperiment::INEVOLUTION );
00229 ga->evolveAllReplicas();
00230 ga->resetStop();
00231 } else {
00232 mutex.lock();
00233 if ( runningOperation ) {
00234 mutex.unlock();
00235 Logger::error( "EvoRobotComponent - Cannot run evolve because another action is currently running; please wait until it finish, or stop it before run evolve action" );
00236 return;
00237 }
00238 runningOperation = true;
00239 mutex.unlock();
00240 gaThread->addOperation( new EvolveOperation( ga, this ) );
00241 }
00242 }
00243
00244 void EvoRobotComponent::runTest() {
00245 AbstractTest* test = AvailableTestList::getTest( currentTestName );
00246 if ( !test ) {
00247 Logger::error( QString("EvoRobotComponent - Test ") + currentTestName + " is not present into the list of available Tests" );
00248 return;
00249 }
00250 if ( batchRunning ) {
00251 test->runTest();
00252 ga->resetStop();
00253 } else {
00254 mutex.lock();
00255 if ( runningOperation ) {
00256 mutex.unlock();
00257 Logger::error( QString("EvoRobotComponent - Cannot run test %1 because another action is currently running; please wait until it finish, or stop it before run test %1").arg(currentTestName) );
00258 return;
00259 }
00260 runningOperation = true;
00261 mutex.unlock();
00262 gaThread->addOperation( new TestOperation( test, ga, this ) );
00263 }
00264 }
00265
00266 void EvoRobotComponent::runTestFromQAction() {
00267
00268 QAction* action = dynamic_cast<QAction*>( sender() );
00269 if ( !action ) {
00270 Logger::error( "EvoRobotComponent - runTestFromQAction can only be called by a QAction" );
00271 return;
00272 }
00273 currentTestName = action->data().toString();
00274 runTest();
00275 }
00276
00277 void EvoRobotComponent::exceptionDuringOperation(BaseException *e) {
00278 if (batchRunning) {
00279 return;
00280 }
00281 Logger::error( QString("EvoRobotComponent - Error while executing the current operation, an exception was thrown. Reason: ") + e->what() );
00282 }
00283
00284 void EvoRobotComponent::onThreadOperationDone( QString message ) {
00285 mutex.lock();
00286 runningOperation = false;
00287 mutex.unlock();
00288 setStatus( message );
00289 emit actionFinished();
00290 }
00291
00292 }