From 646240b59324459eb06dc45a2c0f5c45ece92aec Mon Sep 17 00:00:00 2001 From: James Goppert Date: Tue, 24 Jan 2012 20:00:12 -0500 Subject: [PATCH] Working on gui threading. --- CMakeLists.txt | 4 +- config.h.cmake => config.h.in | 0 gui/MainWindow.cpp | 160 +++++++++++++------------------ gui/MainWindow.hpp | 16 ++-- pc.cmake => pc.in | 0 src/initialization/FGTrimmer.cpp | 5 +- 6 files changed, 75 insertions(+), 110 deletions(-) rename config.h.cmake => config.h.in (100%) rename pc.cmake => pc.in (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9c5ca59..0318f5df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,14 +158,14 @@ install(DIRECTORY "${PROJECT_SOURCE_DIR}/systems" DESTINATION share/${PROJECT_NA install(DIRECTORY ${EP_BASE_DIR}/${EP_INSTALL_PREFIX} DESTINATION ${CMAKE_INSTALL_PREFIX}) # pkgconfig -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pc.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc) install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig ) # config file -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) # build settings include_directories(src src/simgear/xml) diff --git a/config.h.cmake b/config.h.in similarity index 100% rename from config.h.cmake rename to config.h.in diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index d4232e9a..4b99c818 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -156,15 +156,15 @@ void MainWindow::readSettings() settings->beginGroup("aircraft"); lineEdit_modelSimRate->setText(settings->value("modelSimRate",120).toString()); - lineEdit_enginePath->setText(settings->value("enginePath",root+"/aircraft/easystar/Engines").toString()); - lineEdit_systemsPath->setText(settings->value("systemsPath",root+"/aircraft/easystar/Systems").toString()); - lineEdit_aircraftPath->setText(settings->value("aircraftPath",root+"/aircraft/easystar").toString()); - lineEdit_aircraft->setText(settings->value("aircraft","easystar-windtunnel").toString()); - lineEdit_initScript->setText(settings->value("initScript","").toString()); + lineEdit_enginePath->setText(settings->value("enginePath",root+"/engine").toString()); + lineEdit_systemsPath->setText(settings->value("systemsPath",root+"/aircraft/f16/Systems").toString()); + lineEdit_aircraftPath->setText(settings->value("aircraftPath",root+"/aircraft/f16").toString()); + lineEdit_aircraft->setText(settings->value("aircraft","f16").toString()); + lineEdit_initScript->setText(settings->value("initScript","/aircraft/f16/reset00.xml").toString()); settings->endGroup(); settings->beginGroup("trim"); - lineEdit_velocity->setText(settings->value("velocity",40).toString()); + lineEdit_velocity->setText(settings->value("velocity",600).toString()); lineEdit_rollRate->setText(settings->value("rollRate",0).toString()); lineEdit_pitchRate->setText(settings->value("pitchRate",0).toString()); lineEdit_yawRate->setText(settings->value("yawRate",0).toString()); @@ -277,35 +277,12 @@ void MainWindow::on_toolButton_initScript_pressed() void MainWindow::on_pushButton_trim_pressed() { - on_pushButton_stop_pressed(); - writeSettings(); - try - { - trimThread.start(); - } - catch(const std::exception & e) - { - label_status->setText(e.what()); - } - catch(...) - { - label_status->setText("unknown exception"); - } + trimThread.start(); } void MainWindow::on_pushButton_linearize_pressed() { - on_pushButton_stop_pressed(); - linearize(); -} - -void MainWindow::linearize() { using namespace JSBSim; - on_pushButton_stop_pressed(); - - setupFdm(); - - QMutexLocker locker(&fdmMutex); writeSettings(); @@ -357,7 +334,6 @@ void MainWindow::linearize() { void MainWindow::on_pushButton_stop_pressed() { - stopSolver(); simThread.quit(); trimThread.quit(); label_status->setText("stopped"); @@ -365,8 +341,7 @@ void MainWindow::on_pushButton_stop_pressed() void MainWindow::on_pushButton_simulate_pressed() { - on_pushButton_stop_pressed(); - setupFdm(); + if (!fdm) return; simThread.start(); label_status->setText("simulating"); } @@ -383,27 +358,25 @@ void MainWindow::showMsg(const QString & str) msgBox.exec(); }; -void MainWindow::setupFdm() { +bool MainWindow::setupFdm() { using namespace JSBSim; - - QMutexLocker locker(&fdmMutex); - if (fdm) delete fdm; fdm = new FGFDMExec; trimmer->setFdm(fdm); ss->setFdm(fdm); double dt = 1./atof(lineEdit_modelSimRate->text().toAscii()); + int debugLevel = atoi(comboBox_debugLevel->currentText().toAscii()); fdm->Setdt(dt); - + fdm->SetDebugLevel(debugLevel); // paths std::string aircraft=lineEdit_aircraft->text().toStdString(); std::string aircraftPath=lineEdit_aircraftPath->text().toStdString(); std::string enginePath=lineEdit_enginePath->text().toStdString(); std::string systemsPath=lineEdit_systemsPath->text().toStdString(); - + std::string initScript=lineEdit_initScript->text().toStdString(); // flight conditions bool stabAxisRoll = checkBox_stabAxisRoll->isChecked(); @@ -411,8 +384,8 @@ void MainWindow::setupFdm() { if (!fdm->LoadModel(aircraftPath,enginePath,systemsPath,aircraft,false)) { - label_status->setText("model paths incorrect"); - return; + label_status->setText("model paths incorrect"); + return false; } std::string aircraftName = fdm->GetAircraft()->GetAircraftName(); std::cout << "\tsuccessfully loaded: " << aircraftName << std::endl; @@ -465,23 +438,33 @@ void MainWindow::setupFdm() { // state feedback ss->y = ss->x; - // if there is a trim solution, load it if (trimmer && solver && solver->status() == 0) { trimmer->printSolution(solver->getSolution()); // this also loads the solution into the fdm } + return true; +} + +void MainWindow::simulate() +{ + fdm->Run(); + double maxDeflection = 20.0*3.14/180.0; // TODO: this is rough + viewer->mutex.lock(); + plane->setEuler(ss->x.get(6),ss->x.get(2),ss->x.get(9)); + plane->setU(ss->u.get(0),ss->u.get(1)*maxDeflection, + ss->u.get(2)*maxDeflection,ss->u.get(3)*maxDeflection); + viewer->mutex.unlock(); } void MainWindow::trim() { using namespace JSBSim; - setupFdm(); - - QMutexLocker locker(&fdmMutex); - - - label_status->setText("trimming"); + if (!setupFdm()) { + simThread.quit(); + trimThread.quit(); + return; + } // constraints constraints->velocity = atof(lineEdit_velocity->text().toAscii()); @@ -496,7 +479,6 @@ void MainWindow::trim() bool showConvergeStatus = checkBox_showConvergence->isChecked(); bool showSimplex = checkBox_showSimplex->isChecked(); bool pause = checkBox_pause->isChecked(); - int debugLevel = atoi(comboBox_debugLevel->currentText().toAscii()); double rtol = atof(lineEdit_rtol->text().toAscii()); double abstol = atof(lineEdit_abstol->text().toAscii()); double speed = atof(lineEdit_speed->text().toAscii()); @@ -541,78 +523,64 @@ void MainWindow::trim() iterMax,rtol,abstol,speed, random, showConvergeStatus,showSimplex,pause,callback); stopRequested = false; while(1) { - if (stopRequested) { - label_status->setText("solver stopped"); - return; - } else if (solver->status()==0) { - label_status->setText("solver converged"); + if (stopRequested || (solver->status() != 1) ) { break; - } else if (solver->status()==-1) { - label_status->setText("solver failed to converge"); - break; - } else if (solver->status()==1) { - solver->update(); } else { - label_status->setText("unknown solver status"); - return; + solver->update(); } } // output trimmer->printSolution(solver->getSolution()); // this also loads the solution into the fdm - - //std::cout << "\nsimulating flight to determine trim stability" << std::endl; - - //std::cout << "\nt = 5 seconds" << std::endl; - //for (int i=0;i<5*120;i++) fdm.Run(); - //trimmer->printState(); - - //std::cout << "\nt = 10 seconds" << std::endl; - //for (int i=0;i<5*120;i++) fdm.Run(); - //trimmer->printState(); - -} - -void MainWindow::simulate() -{ - QMutexLocker locker(&fdmMutex); - fdm->Run(); - double maxDeflection = 20.0*3.14/180.0; // TODO: this is rough - viewer->mutex.lock(); - plane->setEuler(ss->x.get(6),ss->x.get(2),ss->x.get(9)); - plane->setU(ss->u.get(0),ss->u.get(1)*maxDeflection, - ss->u.get(2)*maxDeflection,ss->u.get(3)*maxDeflection); - viewer->mutex.unlock(); } SimulateThread::SimulateThread(MainWindow * window) : window(window), timer(this) { - connect(&timer, SIGNAL(timeout()), window, SLOT(simulate())); + moveToThread(this); + connect(&timer, SIGNAL(timeout()), window, SLOT(simulate()),Qt::QueuedConnection); } + void SimulateThread::run() { - using namespace JSBSim; - std::cout << "simulation started" << std::endl; timer.start(1000/120); exec(); } +void SimulateThread::quit() +{ + timer.stop(); + QThread::quit(); +} TrimThread::TrimThread(MainWindow * window) : window(window) { + moveToThread(this); +} + +void TrimThread::trim() { + window->trim(); } void TrimThread::run() { - try - { - window->trim(); - } - catch(std::exception & e) - { - std::cerr << "exception: " << e.what() << std::endl; - window->label_status->setText(e.what()); - } + window->label_status->setText("trimming"); + QTimer::singleShot(0,this,SLOT(trim())); + exec(); +} + +void TrimThread::quit() +{ + window->stopSolver(); + if (window->stopRequested) { + window->label_status->setText("solver stopped"); + } else if (window->solver->status()==0) { + window->label_status->setText("solver converged"); + } else if (window->solver->status()==-1) { + window->label_status->setText("solver failed to converge"); + } else { + window->label_status->setText("unknown solver status"); + } + QThread::quit(); } // vim:ts=4:sw=4 diff --git a/gui/MainWindow.hpp b/gui/MainWindow.hpp index c639456f..eb87a476 100644 --- a/gui/MainWindow.hpp +++ b/gui/MainWindow.hpp @@ -30,7 +30,6 @@ #include #include #include -#include class MainWindow; @@ -43,20 +42,19 @@ class SimulateThread : public QThread void run(); MainWindow * window; QTimer timer; - void quit() - { - timer.stop(); - QThread::quit(); - } + void quit(); }; class TrimThread : public QThread { Q_OBJECT +private slots: + void trim(); public: TrimThread(MainWindow * window); void run(); MainWindow * window; + void quit(); }; class MainWindow : public QMainWindow, private Ui::MainWindow @@ -67,7 +65,6 @@ class MainWindow : public QMainWindow, private Ui::MainWindow public: MainWindow(); virtual ~MainWindow(); - QMutex fdmMutex; signals: void showMsgBuffered(const QString & str); @@ -84,7 +81,7 @@ private slots: void on_pushButton_simulate_pressed(); void showMsg(const QString & str); void simulate(); - void trim(); + void trim(); private: class SolverCallback : public JSBSim::FGNelderMead::Callback @@ -129,8 +126,7 @@ private slots: QSettings * settings; void writeSettings(); void readSettings(); - void setupFdm(); - void linearize(); + bool setupFdm(); arkosg::Plane * plane; JSBSim::FGFDMExec * fdm; JSBSim::FGStateSpace * ss; diff --git a/pc.cmake b/pc.in similarity index 100% rename from pc.cmake rename to pc.in diff --git a/src/initialization/FGTrimmer.cpp b/src/initialization/FGTrimmer.cpp index 721e13a3..a334a490 100644 --- a/src/initialization/FGTrimmer.cpp +++ b/src/initialization/FGTrimmer.cpp @@ -378,14 +378,14 @@ double FGTrimmer::eval(const std::vector & v) dq0 = dq; dr0 = dr; - if (deltaCost < std::numeric_limits::epsilon() || deltaCost < 1e-12) + if (deltaCost < std::numeric_limits::epsilon() || deltaCost < 1e-11) { if (steadyCount++ > 10) { //std::cout << "\tcost converged in " << iter << " cycles" << std::endl; break; } } - else if (iter>1000) + else if (iter>10000) { std::cout << "\ncost failed to converge to steady value" << std::scientific @@ -394,6 +394,7 @@ double FGTrimmer::eval(const std::vector & v) << "\ncheck constraints and initial conditions" << std::endl; throw(std::runtime_error("FGTrimmer: cost failed to converge to steady value, most likely out of flight envelope, check constraints and initial conditions")); + cost = 1e30; } else {