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 "evorobotviewer.h"
00025 #include "displaycontroller.h"
00026 #include "abstracttest.h"
00027 #include "tests.h"
00028 #include "total99resources.h"
00029 #include <QGridLayout>
00030 #include <QPushButton>
00031 #include <QCheckBox>
00032 #include <QFileDialog>
00033 #include <QVBoxLayout>
00034 #include <QDir>
00035 #include <QFileInfo>
00036 #include <QFile>
00037 #include <QEvent>
00038 #include <QCoreApplication>
00039
00040 using namespace qglviewer;
00041
00042
00043
00044
00045 #if defined(_MSC_VER)
00046 #pragma warning(push)
00047 #pragma warning(disable:4996)
00048 #endif
00049
00050 namespace farsa {
00051
00052 EvoRobotViewer::EvoRobotViewer( EvoRobotComponent* component )
00053 : QObject(), ComponentUI(), ConcurrentResourcesUser() {
00054 evorobot = component;
00055 ga = evorobot->getGA();
00056 shareResourcesWith(ga->getEvoRobotExperiment());
00057
00058
00059 usableResources(QStringList() << "world" << "evonet" << "experiment");
00060
00061
00062 ResourcesLocker locker(this);
00063 connect( evorobot, SIGNAL(actionFinished()), this, SLOT(onActionFinished()) );
00064 connect( ga->getEvoRobotExperiment()->getNeuralNetwork(), SIGNAL(evonetUpdated()), this, SLOT(onEvonetUpdated()), Qt::QueuedConnection );
00065 }
00066
00067 EvoRobotViewer::~EvoRobotViewer()
00068 {
00069
00070
00071 }
00072
00073 void EvoRobotViewer::fillActionsMenu( QMenu* actionsMenu ) {
00074 actionsMenu->addAction( "Evolve", evorobot, SLOT(evolve()) );
00075 actionsMenu->addAction( "Stop", evorobot, SLOT(stop()) );
00076 }
00077
00078 QList<ComponentUIViewer> EvoRobotViewer::getViewers( QWidget* parent, Qt::WindowFlags flags ) {
00079 QList<ComponentUIViewer> viewsList;
00080 viewsList.append( evogaControls( parent, flags ) );
00081 viewsList.append( networkView( parent, flags ) );
00082 viewsList.append( neuroMonitorView( parent, flags ) );
00083
00084 viewsList.append( fitview( parent, flags ) );
00085 viewsList.append( statview( parent, flags ) );
00086 viewsList.append( holisticView( parent, flags ) );
00087 viewsList.append( renderWorld( parent, flags ) );
00088
00089 QStringList testsList = AvailableTestList::getList();
00090 for (int i = 0; i < testsList.size(); i++) {
00091 TestIndividual* testIndividual = dynamic_cast<TestIndividual*>(AvailableTestList::getTest(testsList[i]));
00092 if ( testIndividual ) {
00093 viewsList.append( testIndividualUI( testIndividual, parent, flags ) );
00094 }
00095 }
00096 return viewsList;
00097 }
00098
00099 void EvoRobotViewer::addAdditionalMenus( QMenuBar* menuBar ) {
00100 QMenu* testMenu = menuBar->addMenu( "Tests" );
00101 QStringList testsList = AvailableTestList::getList();
00102 for (int i = 0; i < testsList.size(); i++) {
00103 AbstractTest* test = AvailableTestList::getTest(testsList[i]);
00104 QAction* action = testMenu->addAction( test->menuText(), evorobot, SLOT(runTestFromQAction()) );
00105 action->setData( QVariant(testsList[i]) );
00106 action->setToolTip( test->tooltip() );
00107 action->setIcon( QIcon( test->iconFilename() ) );
00108 }
00109 }
00110
00111 void EvoRobotViewer::resourceChanged(QString resourceName, ResourceChangeType changeType)
00112 {
00113
00114 if ((resourceName == "world") && (changeType != Deleted)) {
00115 World* world = getResource<World>();
00116
00117 connect( world, SIGNAL(advanced()), this, SLOT(onWorldAdvance()), Qt::QueuedConnection );
00118 }
00119 }
00120
00121 ComponentUIViewer EvoRobotViewer::renderWorld( QWidget* parent, Qt::WindowFlags flags )
00122 {
00123
00124 renderworldwrapper = new RenderWorldWrapperWidget(parent, flags);
00125 renderworldwrapper->shareResourcesWith(this);
00126
00127 return ComponentUIViewer(renderworldwrapper, "RenderWorld");
00128 }
00129
00130 ComponentUIViewer EvoRobotViewer::evogaControls( QWidget* parent, Qt::WindowFlags flags ) {
00131 QWidget* widget = new QWidget( parent, flags );
00132 QGridLayout* lay = new QGridLayout( widget );
00133
00134
00135
00136 infoEvoga = new QLabel( "Information", widget );
00137 infoEvoga->setStyleSheet( "QLabel { font: bold normal large \"Courier\" }" );
00138 lay->addWidget( infoEvoga, 0, 0, 1, 2 );
00139
00140 QPushButton* bt = new QPushButton( "Do Step", widget );
00141 bt->setAutoRepeat(true);
00142 bt->setEnabled( false );
00143 connect( bt, SIGNAL(clicked(bool)), ga, SLOT(doNextStep()) );
00144
00145 QCheckBox* cb = new QCheckBox( "Step by Step Mode", widget );
00146 connect( cb, SIGNAL(clicked(bool)), ga, SLOT(enableStepByStep(bool)) );
00147 connect( cb, SIGNAL(clicked(bool)), bt, SLOT(setEnabled(bool)) );
00148
00149 lay->addWidget( cb, 1, 0 );
00150 lay->addWidget( bt, 1, 1 );
00151
00152 bt = new QPushButton( "Next Trial", widget );
00153 connect( bt, SIGNAL(clicked()), this, SLOT(evogaNextTrial()) );
00154 lay->addWidget( bt, 2, 0, 1, 2 );
00155
00156
00157
00158 return ComponentUIViewer( widget, "Evoga Controls" );
00159 }
00160
00161 void EvoRobotViewer::evogaNextTrial() {
00162 ga->getEvoRobotExperiment()->stopTrial();
00163 }
00164
00165 ComponentUIViewer EvoRobotViewer::fitview( QWidget* parent, Qt::WindowFlags flags )
00166 {
00167
00168 ftv = new FitViewer(3,4000,parent,flags);
00169 ftv->setChunkProperties(0, "MaxFit", Qt::red, true);
00170 ftv->setChunkProperties(1, "AverageFit", Qt::green, true);
00171 ftv->setChunkProperties(2, "MinFit", Qt::blue, true);
00172 ftv->setLabels(QString("EvoICub Fitness Monitor"), QString("Generations"), QString("Fitness"));
00173 ftv->setGeometry(50, 50, 500, 500);
00174 ftv->setWindowTitle( "Fitness Curves" );
00175 connect( ga, SIGNAL(startingReplication(int)),
00176 this, SLOT(onEvogaStartingReplication(int)), Qt::QueuedConnection );
00177 connect( ga, SIGNAL(recoveredInterruptedEvolution(QString)),
00178 this, SLOT(onEvogaRecoveredInterruptedEvolution(QString)), Qt::QueuedConnection );
00179 connect( ga, SIGNAL(endGeneration(int,int,int,int)),
00180 this, SLOT(onEvogaEndGeneration(int,int,int,int)), Qt::QueuedConnection );
00181 return ComponentUIViewer( ftv, "Fitness monitor" );
00182 }
00183
00184 ComponentUIViewer EvoRobotViewer::networkView( QWidget* parent, Qt::WindowFlags flags )
00185 {
00186 ResourcesLocker locker(this);
00187
00188 Evonet* evonet = getResource<Evonet>( "evonet" );
00189 networkDialog = new NetworkDialog(evonet,parent,flags);
00190 networkDialog->pseudo_activate_net(0);
00191 networkDialog->setWindowTitle( "Neural Network Editor" );
00192 return ComponentUIViewer( networkDialog, "Nervous System" );
00193 }
00194
00195 ComponentUIViewer EvoRobotViewer::neuroMonitorView( QWidget* parent, Qt::WindowFlags flags )
00196 {
00197 ResourcesLocker locker(this);
00198
00199 Evonet* evonet = getResource<Evonet>( "evonet" );
00200 edv = new EvoDataViewer( evonet->getNoNeurons(), 1000, 0, parent, flags );
00201
00202
00203 bool dn;
00204 for (int i = 0; i < evonet->getNoNeurons(); i++) {
00205 if (evonet->neurondisplay[i] == 1) {
00206 dn = true;
00207 } else {
00208 dn = false;
00209 }
00210 if ( evonet->neurondcolor[i].isValid() ) {
00211 edv->setChunkProperties(i, evonet->neuronrange[i][0], evonet->neuronrange[i][1], evonet->neuronl[i], evonet->neurondcolor[i], dn);
00212 } else {
00213
00214 edv->setChunkProperties(i, evonet->neuronrange[i][0], evonet->neuronrange[i][1], evonet->neuronl[i], QColor(255,0,0), dn);
00215 }
00216 }
00217 edv->setWindowTitle( "Neurons Monitor" );
00218 edv->setGeometry(50, 50, 600, 600);
00219 return ComponentUIViewer( edv, "Neurons Monitor" );
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 ComponentUIViewer EvoRobotViewer::statview( QWidget* parent, Qt::WindowFlags flags )
00232 {
00233 statViewer = new QWidget( parent, flags );
00234 statViewer->setWindowTitle( "Statictis Viewer" );
00235 QGridLayout* lay = new QGridLayout( statViewer );
00236 QPushButton* but = new QPushButton( "Load a Stat File", statViewer );
00237 connect( but, SIGNAL(clicked()), this, SLOT(loadStat()) );
00238 lay->addWidget( but, 0, 0 );
00239 but = new QPushButton( "Load All Stat", statViewer );
00240 connect( but, SIGNAL(clicked()), this, SLOT(loadAllStat()) );
00241 lay->addWidget( but, 0, 1 );
00242 return ComponentUIViewer( statViewer, "Statistic Viewer" );
00243 }
00244
00245 void EvoRobotViewer::loadStat() {
00246 QString filename = QFileDialog::getOpenFileName(statViewer, tr("Open Stat File"), ".", tr("Files with statistics (*.fit *.ini)"));
00247 if (filename.isEmpty()) {
00248 return;
00249 }
00250 FitViewer* fitViewer = statViewer->findChild<FitViewer*>( "statFitViewer" );
00251 if ( fitViewer ) {
00252 delete fitViewer;
00253 }
00254 fitViewer = new FitViewer(3, 4000, statViewer);
00255 fitViewer->setObjectName( "statFitViewer" );
00256 fitViewer->setLabels(QString("Stat monitor. File: ").append(filename), QString("Generation"), QString("Fitnes"));
00257 fitViewer->setChunkProperties(0, "MaxFit", Qt::red,true);
00258 fitViewer->setChunkProperties(1, "Average", Qt::green,true);
00259 fitViewer->setChunkProperties(2, "Minimum", Qt::blue,true);
00260 fitViewer->loadRawData(0, filename, 0);
00261 fitViewer->loadRawData(1, filename, 1);
00262 fitViewer->loadRawData(2, filename, 2);
00263 QGridLayout* lay = qobject_cast<QGridLayout*>( statViewer->layout() );
00264 lay->addWidget( fitViewer, 1, 0, 1, 2 );
00265 lay->setRowStretch( 1, 2 );
00266 fitViewer->show();
00267 }
00268
00269 void EvoRobotViewer::loadAllStat()
00270 {
00271 FitViewer* fitViewer = statViewer->findChild<FitViewer*>( "statFitViewer" );
00272 if ( fitViewer ) {
00273 delete fitViewer;
00274 }
00275
00276 QDir currentDir;
00277 QFileInfoList statFiles = currentDir.entryInfoList( QStringList() << "*.fit", QDir::Files, QDir::Name );
00278
00279 fitViewer = new FitViewer(statFiles.size(), ga->getNumOfGenerations(), statViewer);
00280 fitViewer->setObjectName( "statFitViewer" );
00281 QString title = QString("Stat monitor");
00282 fitViewer->setLabels(title, QString("Generation"), QString("Fitness"));
00283
00284 QColor colors[10] = { QColor(Qt::red), QColor(Qt::green), QColor(Qt::blue), QColor(Qt::cyan),
00285 QColor(Qt::magenta), QColor(Qt::darkYellow), QColor(Qt::gray), QColor(255, 140, 0, 255),
00286 QColor(153, 50, 204, 255), QColor(Qt::black) };
00287 for(int i=0; i<statFiles.size(); i++ ) {
00288 QFileInfo statFile = statFiles[i];
00289 QColor col = colors[i%10];
00290 fitViewer->setChunkProperties( i, QString("Seed:").append(statFile.baseName().split("S").last()), col, true );
00291 fitViewer->loadRawData( i, statFile.fileName(), 0 );
00292 }
00293 fitViewer->sortchunks();
00294 QGridLayout* lay = qobject_cast<QGridLayout*>( statViewer->layout() );
00295 lay->addWidget( fitViewer, 1, 0, 1, 2 );
00296 lay->setRowStretch( 1, 2 );
00297 fitViewer->show();
00298 }
00299
00300 ComponentUIViewer EvoRobotViewer::holisticView( QWidget* parent, Qt::WindowFlags flags )
00301 {
00302 ResourcesLocker locker(this);
00303
00304 Evonet* evonet = getResource<Evonet>( "evonet" );
00305 hlv = new HolisticViewer(evonet, parent, flags);
00306 hlv->resize(300, 300);
00307 hlv->setWindowTitle("Holistic Viewer");
00308 return ComponentUIViewer( hlv, "Holistic View" );
00309 }
00310
00311 ComponentUIViewer EvoRobotViewer::testIndividualUI( TestIndividual* test, QWidget* parent, Qt::WindowFlags flags ) {
00312 TestIndividualGUI* testIndUI = new TestIndividualGUI( test, parent, flags );
00313 testIndUI->setWindowTitle( "Select the Individual to Test" );
00314 return ComponentUIViewer( testIndUI, "Individual to Test", QString(), "From this view you can select an individual to test using the \"TestIndividual\" from the \"Tests\" menu" );
00315 }
00316
00317 void EvoRobotViewer::onEvonetUpdated() {
00318 ResourcesLocker locker(this);
00319
00320 EvoRobotExperiment* exp = getResource<EvoRobotExperiment>("experiment");
00321
00322
00323 if ((edv != NULL) ) {
00324
00325 Evonet* evonet = getResource<Evonet>( "evonet" );
00326 float *acts;
00327 do {
00328 acts = evonet->getOldestStoredActivations();
00329 if (acts != NULL) {
00330 for (int ch = 0; ch < evonet->getNoNeurons(); ch++) {
00331 edv->setChunkValue(ch, acts[ch]);
00332 }
00333 edv->setCurrentStep(exp->getCurStep());
00334 }
00335 } while (acts != NULL);
00336 edv->update();
00337 }
00338
00339 if ((hlv != NULL) && ((exp->getCurStep() % 10) == 0)) {
00340 hlv->updateGrid();
00341 hlv->updatePlot();
00342 hlv->update();
00343 }
00344 }
00345
00346 void EvoRobotViewer::onWorldAdvance() {
00347 ResourcesLocker locker(this);
00348
00349 EvoRobotExperiment* exp = getResource<EvoRobotExperiment>("experiment");
00350
00351 if ( exp->getActivityPhase() == EvoRobotExperiment::INTEST ) {
00352 renderworldwrapper->updateRenderWorld();
00353
00354
00355
00356 }
00357
00358 infoEvoga->setText( QString( "Step %1 of %2 --- Trial %3 of %4" )
00359 .arg( exp->getCurStep(), 5 ).arg( exp->getNSteps() )
00360 .arg( exp->getCurTrial(), 5 ).arg( exp->getNTrials() ) );
00361 }
00362
00363 void EvoRobotViewer::onEvogaStartingReplication( int ) {
00364 ftv->reset();
00365 }
00366
00367 void EvoRobotViewer::onEvogaRecoveredInterruptedEvolution( QString statfile ) {
00368 ftv->loadRawData(0,statfile,0);
00369 ftv->loadRawData(1,statfile,1);
00370 ftv->loadRawData(2,statfile,2);
00371 }
00372
00373 void EvoRobotViewer::onEvogaEndGeneration( int generation, int fmax, int faverage, int fmin ) {
00374 ftv->setChunkValue(0,generation,fmax);
00375 ftv->setChunkValue(1,generation,faverage);
00376 ftv->setChunkValue(2,generation,fmin);
00377 ftv->diplayUntilStep(generation);
00378 ftv->update();
00379 }
00380
00381 void EvoRobotViewer::onActionFinished() {
00382 infoEvoga->setText( evorobot->status() );
00383 }
00384
00385 namespace {
00386
00387 class ForceRenderWorldUpdateEvent : public QEvent
00388 {
00389 public:
00390 ForceRenderWorldUpdateEvent() :
00391 QEvent(QEvent::User)
00392 {
00393 }
00394
00395 virtual ~ForceRenderWorldUpdateEvent()
00396 {
00397 }
00398 };
00399 }
00400
00401 RenderWorldWrapperWidget::RenderWorldWrapperWidget(QWidget* parent, Qt::WindowFlags flags) :
00402 QWidget(parent, flags),
00403 ConcurrentResourcesUser(),
00404 m_renderWorld(new RenderWorld(this, "world")),
00405 m_layout(new QVBoxLayout(this)),
00406 m_renderWorldStateRestored(false),
00407 m_setCameraToLookAtRobot(false),
00408 m_robotTm(wMatrix::identity())
00409 {
00410
00411 setWindowTitle("3D World");
00412 m_layout->setContentsMargins(0, 0, 0, 0);
00413 m_layout->addWidget(m_renderWorld);
00414 const QString stateFileName = ".evolver.xml";
00415 m_renderWorld->setStateFileName(stateFileName);
00416 if (QFile::exists(stateFileName)) {
00417 m_renderWorldStateRestored = true;
00418 m_renderWorld->restoreStateFromFile();
00419 }
00420
00421
00422 usableResources(QStringList() << "robot");
00423 }
00424
00425 RenderWorldWrapperWidget::~RenderWorldWrapperWidget()
00426 {
00427
00428 }
00429
00430 void RenderWorldWrapperWidget::updateRenderWorld()
00431 {
00432 if (m_setCameraToLookAtRobot) {
00433 lookAtRobot();
00434
00435 m_setCameraToLookAtRobot = false;
00436
00437 m_renderWorldStateRestored = true;
00438 }
00439
00440 m_renderWorld->update();
00441 }
00442
00443 void RenderWorldWrapperWidget::shareResourcesWith(ResourcesUser* buddy)
00444 {
00445
00446 ConcurrentResourcesUser::shareResourcesWith(buddy);
00447
00448
00449 m_renderWorld->shareResourcesWith(buddy);
00450 }
00451
00452 void RenderWorldWrapperWidget::resourceChanged(QString resourceName, ResourceChangeType changeType)
00453 {
00454 if (resourceName == "robot") {
00455 if ((changeType != Deleted) && (!m_renderWorldStateRestored)) {
00456 try {
00457 m_robotTm = getResource<WObject>()->matrix();
00458 } catch (const ResourceTypeMismatchException&) {
00459 }
00460
00461 m_setCameraToLookAtRobot = true;
00462 }
00463 } else {
00464 Logger::info("Unknown resource " + resourceName + " for RenderWorldWrapperWidget widget");
00465 }
00466
00467
00468 QCoreApplication::postEvent(this, new ForceRenderWorldUpdateEvent());
00469 }
00470
00471 void RenderWorldWrapperWidget::customEvent(QEvent* event)
00472 {
00473 if (event->type() == QEvent::User) {
00474
00475 updateRenderWorld();
00476 }
00477 }
00478
00479 void RenderWorldWrapperWidget::lookAtRobot()
00480 {
00481 wVector cameraDefaultPosition = m_robotTm.transformVector(wVector(-0.8f, 0.0f, +0.6f));
00482 m_renderWorld->camera()->setPosition(Vec(cameraDefaultPosition[0], cameraDefaultPosition[1], cameraDefaultPosition[2]));
00483 m_renderWorld->camera()->setUpVector(Vec(0.0f, 0.0f, 1.0f));
00484 m_renderWorld->camera()->lookAt(Vec(m_robotTm.w_pos[0], m_robotTm.w_pos[1], m_robotTm.w_pos[2]));
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 TestIndividualGUI::TestIndividualGUI(TestIndividual* tb, QWidget *parent, Qt::WindowFlags flags) :
00621 QWidget(parent, flags)
00622 {
00623 test = tb;
00624
00625
00626 QGridLayout* mainLay = new QGridLayout( this );
00627
00628
00629 QPushButton* bt = new QPushButton( "Refresh", this );
00630 connect( bt, SIGNAL(clicked()), this, SLOT(populateCombo()) );
00631 mainLay->addWidget(bt, 0, 0, 1, 2);
00632
00633 combo = new QComboBox();
00634 list = new QListWidget();
00635 mainLay->addWidget(new QLabel("Select File to load:"), 1, 0);
00636 mainLay->addWidget(combo, 1, 1);
00637 mainLay->addWidget(list, 2, 0, 1, 2);
00638
00639
00640 populateCombo();
00641
00642
00643 connect(combo, SIGNAL(activated(QString)), this, SLOT(seedWasChosen()));
00644 connect(list, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(agentClicked()));
00645 }
00646
00647 void TestIndividualGUI::populateCombo()
00648 {
00649 combo->clear();
00650 list->clear();
00651
00652 QString bestF = test->component()->getGA()->bestsFilename();
00653 QString genF = test->component()->getGA()->generationFilename();
00654
00655
00656 QDir* dir = new QDir();
00657 QStringList expression = (QStringList() << bestF << genF);
00658 fileList = dir->entryList(expression);
00659
00660
00661 combo->addItems(fileList);
00662 }
00663
00664 void TestIndividualGUI::seedWasChosen()
00665 {
00666
00667 test->setPopulationToTest( combo->currentText(), false );
00668
00669 list->clear();
00670 int loadindi = test->component()->getGA()->numLoadedGenotypes();
00671 for(int i=1; i<=loadindi; i++)
00672 {
00673 list->addItem(QString::number(i));
00674 }
00675 }
00676
00677 void TestIndividualGUI::agentClicked()
00678 {
00679
00680 test->setIndividualToTest( list->currentRow() );
00681 }
00682
00683 }
00684
00685
00686 #if defined(_MSC_VER)
00687 #pragma warning(pop)
00688 #endif