main_window.cpp
Go to the documentation of this file.
00001 
00008 /*****************************************************************************
00009 ** Includes
00010 *****************************************************************************/
00011 
00012 #include <QtGui>
00013 #include <QMessageBox>
00014 #include <iostream>
00015 #include "../include/tibi_dabo_sequence_editor/main_window.hpp"
00016 
00017 #include "eventexceptions.h"
00018 #include "motor_control_exceptions.h"
00019 #include "motor_config.h"
00020 
00021 /*****************************************************************************
00022 ** Namespaces
00023 *****************************************************************************/
00024 
00025 namespace tibi_dabo_sequence_editor {
00026 
00027 using namespace Qt;
00028 
00029 /*****************************************************************************
00030 ** Implementation [MainWindow]
00031 *****************************************************************************/
00032 
00033 MainWindow::MainWindow(int argc, char** argv, QWidget *parent)
00034         : QMainWindow(parent)
00035         , qnode(argc,argv)
00036 {
00037   QStringList headers;
00038   QString joint,value;
00039   unsigned int i=0;
00040 
00041   // initialize internal attributes
00042   this->event_server=CEventServer::instance();
00043   this->motion_file_name="";
00044   this->current_step=0;
00045   this->seq.clear();
00046 
00047   // assign slots to signals
00048   ui.setupUi(this); // Calling this incidentally connects all ui's triggers to on_...() callbacks in this class.
00049   QObject::connect(ui.actionAbout_Qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); // qApp is a global variable for the application
00050   QObject::connect(ui.motion_steps, SIGNAL(currentCellChanged(int,int,int,int)), this, SLOT(on_motion_step_changed())); // qApp is a global variable for the application
00051 
00052   // initialize the widget arrays for easy access
00053   this->min_pos_text[0]=this->ui.min_pos_text_1;
00054   this->min_pos_text[1]=this->ui.min_pos_text_2;
00055   this->min_pos_text[2]=this->ui.min_pos_text_5;
00056   this->min_pos_text[3]=this->ui.min_pos_text_6;
00057   this->min_pos_text[4]=this->ui.min_pos_text_7;
00058   this->min_pos_text[5]=this->ui.min_pos_text_8;
00059   this->max_pos_text[0]=this->ui.max_pos_text_1;
00060   this->max_pos_text[1]=this->ui.max_pos_text_2;
00061   this->max_pos_text[2]=this->ui.max_pos_text_5;
00062   this->max_pos_text[3]=this->ui.max_pos_text_6;
00063   this->max_pos_text[4]=this->ui.max_pos_text_7;
00064   this->max_pos_text[5]=this->ui.max_pos_text_8;
00065   this->min_vel_text[0]=this->ui.min_vel_text_1;
00066   this->min_vel_text[1]=this->ui.min_vel_text_2;
00067   this->min_vel_text[2]=this->ui.min_vel_text_5;
00068   this->min_vel_text[3]=this->ui.min_vel_text_6;
00069   this->min_vel_text[4]=this->ui.min_vel_text_7;
00070   this->min_vel_text[5]=this->ui.min_vel_text_8;
00071   this->max_vel_text[0]=this->ui.max_vel_text_1;
00072   this->max_vel_text[1]=this->ui.max_vel_text_2;
00073   this->max_vel_text[2]=this->ui.max_vel_text_5;
00074   this->max_vel_text[3]=this->ui.max_vel_text_6;
00075   this->max_vel_text[4]=this->ui.max_vel_text_7;
00076   this->max_vel_text[5]=this->ui.max_vel_text_8;
00077   this->desired_pos[0]=this->ui.desired_pos_1;
00078   this->desired_pos[1]=this->ui.desired_pos_2;
00079   this->desired_pos[2]=this->ui.desired_pos_5;
00080   this->desired_pos[3]=this->ui.desired_pos_6;
00081   this->desired_pos[4]=this->ui.desired_pos_7;
00082   this->desired_pos[5]=this->ui.desired_pos_8;
00083   this->desired_vel[0]=this->ui.desired_vel_1;
00084   this->desired_vel[1]=this->ui.desired_vel_2;
00085   this->desired_vel[2]=this->ui.desired_vel_5;
00086   this->desired_vel[3]=this->ui.desired_vel_6;
00087   this->desired_vel[4]=this->ui.desired_vel_7;
00088   this->desired_vel[5]=this->ui.desired_vel_8;
00089   this->desired_pos_value[0]=this->ui.desired_pos_value_1;
00090   this->desired_pos_value[1]=this->ui.desired_pos_value_2;
00091   this->desired_pos_value[2]=this->ui.desired_pos_value_5;
00092   this->desired_pos_value[3]=this->ui.desired_pos_value_6;
00093   this->desired_pos_value[4]=this->ui.desired_pos_value_7;
00094   this->desired_pos_value[5]=this->ui.desired_pos_value_8;
00095   this->desired_vel_value[0]=this->ui.desired_vel_value_1;
00096   this->desired_vel_value[1]=this->ui.desired_vel_value_2;
00097   this->desired_vel_value[2]=this->ui.desired_vel_value_5;
00098   this->desired_vel_value[3]=this->ui.desired_vel_value_6;
00099   this->desired_vel_value[4]=this->ui.desired_vel_value_7;
00100   this->desired_vel_value[5]=this->ui.desired_vel_value_8;
00101   this->position_text[0]=this->ui.position_text_1;
00102   this->position_text[1]=this->ui.position_text_2;
00103   this->position_text[2]=this->ui.position_text_3;
00104   this->position_text[3]=this->ui.position_text_4;
00105   this->position_text[4]=this->ui.position_text_5;
00106   this->position_text[5]=this->ui.position_text_6;
00107   this->velocity_text[0]=this->ui.velocity_text_1;
00108   this->velocity_text[1]=this->ui.velocity_text_2;
00109   this->velocity_text[2]=this->ui.velocity_text_3;
00110   this->velocity_text[3]=this->ui.velocity_text_4;
00111   this->velocity_text[4]=this->ui.velocity_text_5;
00112   this->velocity_text[5]=this->ui.velocity_text_6;
00113 
00114   this->load_joints_config();
00115 
00116   // initialize the screen widgets
00117   for(i=0;i<this->dof;i++)
00118     config_joint(i,true,this->min_pos[0],this->max_pos[0],this->min_vel[0],this->max_vel[0]);
00119 
00120   this->ui.motion_steps->setSortingEnabled(false);
00121   this->ui.motion_steps->setColumnCount(2+this->dof*2);
00122   headers.push_back("step no.");
00123   for(i=0;i<this->dof;i++) 
00124   {
00125     joint.setNum(i);
00126     headers.push_back("joint " + joint + " pos");
00127     headers.push_back("joint " + joint + " vel");
00128   }
00129   headers.push_back("delay");
00130   this->ui.motion_steps->setHorizontalHeaderLabels(headers);
00131   this->ui.motion_steps->setSelectionBehavior(QAbstractItemView::SelectRows);// only select rows
00132   this->ui.motion_steps->setSelectionMode(QAbstractItemView::SingleSelection);// select only one item
00133   value.setNum(this->seq.size());
00134   this->ui.num_steps->setText(value);
00135   value.setNum(0);
00136   this->ui.delay->setText(value);
00137 
00138   // start the timer
00139   this->startTimer(100);
00140 }
00141 
00142 MainWindow::~MainWindow()
00143 {
00144   this->seq.clear();
00145 }
00146 
00147 void MainWindow::timerEvent(QTimerEvent * event)
00148 {
00149   // do periodic updates
00150   if(this->event_server->event_is_set(this->qnode.get_action_feedback_event_id()))
00151   {
00152     this->ui.get_current->click();
00153     this->event_server->reset_event(this->qnode.get_action_feedback_event_id());
00154   }
00155 }
00156 
00157 void MainWindow::config_joint(int index,bool enable,float min_pos,float max_pos,float min_vel, float max_vel)
00158 {
00159   QString value;
00160 
00161   this->position_text[index]->setEnabled(enable);
00162   this->velocity_text[index]->setEnabled(enable);
00163   this->desired_pos[index]->setEnabled(enable);
00164   this->desired_vel[index]->setEnabled(enable);
00165   this->desired_pos_value[index]->setEnabled(enable);
00166   this->desired_vel_value[index]->setEnabled(enable);
00167   this->min_pos_text[index]->setEnabled(enable);
00168   value.setNum(min_pos);
00169   this->min_pos_text[index]->setText(value);
00170   this->max_pos_text[index]->setEnabled(enable);
00171   value.setNum(max_pos);
00172   this->max_pos_text[index]->setText(value);
00173   this->min_vel_text[index]->setEnabled(enable);
00174   value.setNum(min_vel);
00175   this->min_vel_text[index]->setText(value);
00176   this->max_vel_text[index]->setEnabled(enable);
00177   value.setNum(max_vel);
00178   this->max_vel_text[index]->setText(value);
00179   this->desired_pos[index]->setRange(min_pos,max_pos);
00180   this->desired_vel[index]->setRange(min_vel,max_vel);
00181 }
00182 
00183 void MainWindow::load_joints_config(void)
00184 {
00185   motor_config_t::axis_config_iterator iterator;
00186   std::vector<std::string> config_files;
00187   std::string config_file_full_path;
00188   unsigned int i=0;
00189 
00190   config_files=this->qnode.get_config_files();
00191   this->dof=0;
00192   try{
00193     for(i=0;i<config_files.size();i++)
00194     {
00195       std::auto_ptr<motor_config_t> cfg(motor_config(config_files[i].c_str(),xml_schema::flags::dont_validate));
00196       this->dof+=cfg->num_axis();
00197       for(iterator=cfg->axis_config().begin();iterator!=cfg->axis_config().end();iterator++)
00198       {
00199         this->min_vel.push_back(iterator->velocity_range().min());
00200         this->max_vel.push_back(iterator->velocity_range().max());
00201         this->min_pos.push_back(iterator->position_range().min());
00202         this->max_pos.push_back(iterator->position_range().max());
00203       }
00204     }
00205   }catch (const xml_schema::exception& e){
00206     /* handle exceptions */
00207     std::ostringstream os;
00208     os << e;
00209     QMessageBox msgBox;
00210     msgBox.setText(QString(os.str().c_str()));
00211     msgBox.setIcon(QMessageBox::Warning);
00212     msgBox.exec();
00213   }
00214 
00215   // wait_for the first feedback values
00216 }
00217 
00218 void MainWindow::fill_motion_table(void)
00219 {
00220   unsigned int i=0,num_row;
00221   QString value;
00222 
00223   // clear all rows of the current table, if any
00224   num_row=this->ui.motion_steps->rowCount();
00225   for(i=0;i<num_row;i++)
00226     this->ui.motion_steps->removeRow(0);
00227   value.setNum(0);
00228   this->ui.num_steps->setText(value);
00229   for(i=0;i<this->seq.size();i++)
00230     this->add_motion_step(this->seq[i].position,this->seq[i].velocity,this->seq[i].delay);
00231 }
00232 
00233 void MainWindow::add_motion_step(std::vector<float> position, std::vector<float> velocity, float delay)
00234 {
00235   QTableWidgetItem *item;
00236   unsigned int row,i;
00237   QString value;
00238 
00239   row=this->ui.motion_steps->rowCount();
00240   this->ui.motion_steps->setRowCount(row+1);
00241   value.setNum(row);
00242   item=new QTableWidgetItem(value);
00243   this->ui.motion_steps->setItem(row,0,item);
00244   value.setNum(delay);
00245   item=new QTableWidgetItem(value);
00246   this->ui.motion_steps->setItem(row,2*this->dof+1,item);
00247   for(i=0;i<position.size();i++)
00248   {
00249     value.setNum(position[i]);
00250     item=new QTableWidgetItem(value);
00251     this->ui.motion_steps->setItem(row,2*i+1,item);
00252     value.setNum(velocity[i]);
00253     item=new QTableWidgetItem(value);
00254     this->ui.motion_steps->setItem(row,2*i+2,item);
00255   }
00256   value.setNum(row+1);
00257   this->ui.num_steps->setText(value);
00258 }
00259 
00260 /*****************************************************************************
00261 ** Implementation [Slots]
00262 *****************************************************************************/
00263 
00264 void MainWindow::on_get_current_clicked()
00265 {
00266   std::list<std::string> events;
00267   std::vector<float> current_pos;
00268   std::vector<float> current_vel;
00269   unsigned int i=0;
00270   QString value;
00271 
00272   events.push_back(this->qnode.get_new_feedback_event_id());
00273   try{
00274     this->event_server->wait_all(events,1000);
00275     this->qnode.get_motion_feedback(current_pos,current_vel);
00276     for(i=0;i<current_pos.size();i++)
00277     {
00278       this->desired_pos[i]->setValue(current_pos[i]*180.0/3.14159);
00279       value.setNum(current_pos[i]*180.0/3.14159);
00280       this->desired_pos_value[i]->setText(value);
00281       this->desired_vel[i]->setValue(current_vel[i]*180.0/3.14159);
00282       value.setNum(current_vel[i]*180.0/3.14159);
00283       this->desired_vel_value[i]->setText(value);
00284     }
00285     this->event_server->reset_event(this->qnode.get_new_feedback_event_id());
00286   }catch(CEventTimeoutException &e){
00287     /* handle the exception */
00288     QMessageBox msgBox;
00289     msgBox.setText("No connection to the node");
00290     msgBox.setIcon(QMessageBox::Warning);
00291     msgBox.exec();
00292   }
00293 }
00294 
00295 void MainWindow::on_load_sequence_clicked()
00296 {
00297   QString caption("Open motion sequence file"),directory("."),filter("*.xml"),filename;
00298   std::string control_mode, motion_mode;
00299   sequence_t::step_iterator iterator;
00300   QFileDialog *open_file;
00301   QStringList file_list;
00302   unsigned int num=0;
00303   TMotionStep step;
00304 
00305   open_file=new QFileDialog(this,caption,directory,filter); 
00306 
00307   if(open_file->exec())
00308   {
00309     file_list=open_file->selectedFiles();
00310     if(file_list.size()==1)
00311     {
00312       try{
00313         filename=file_list.at(0);
00314         this->motion_file_name=file_list.at(0).toLocal8Bit().constData();
00315         this->ui.sequence_name->setText(filename.toAscii().data());
00316         std::cout << filename.toAscii().data() << std::endl;
00317         std::auto_ptr<sequence_t> seq(motion_seq(filename.toAscii().data(),xml_schema::flags::dont_validate));
00318         if((num=seq->num_motors())!=this->dof)
00319         {
00320           /* handle exceptions */
00321           throw CMotionSequenceException(_HERE_,"The number of motors in the loaded sequence does not coincide with the number of motors in the associated motor groupY");
00322         }
00323         else
00324         {
00325           // get the number of steps
00326           num=seq->num_steps();
00327           // get the control type: position or speed
00328           control_mode=seq->control();
00329           // set the control mode to all CMotorControl objects
00330           if(control_mode=="position")
00331           {
00332             this->ui.position_control->setChecked(true);
00333             this->ui.velocity_control->setChecked(false);
00334           }
00335           else
00336           {
00337             this->ui.position_control->setChecked(false);
00338             this->ui.velocity_control->setChecked(true);
00339           }
00340           // get the motion type: absolute or relative
00341           motion_mode=seq->motion();
00342           // set the motion mode to all CMotorControl objects
00343           if(motion_mode=="absolute")
00344           {
00345             this->ui.absolute_motion->setChecked(true);
00346             this->ui.relative_motion->setChecked(false);
00347           }
00348           else
00349           {
00350             this->ui.absolute_motion->setChecked(false);
00351             this->ui.relative_motion->setChecked(true);
00352           }
00353           // erase the previous sequence
00354           this->seq.clear();
00355           for(iterator=seq->step().begin();iterator!=seq->step().end();iterator++)
00356           {
00357             step.delay=iterator->delay();
00358             step.position.clear();
00359             step.velocity.clear();
00360             step.position=iterator->position();
00361             step.velocity=iterator->velocity();
00362             this->seq.push_back(step);
00363           }
00364           this->fill_motion_table();
00365           this->ui.motion_steps->selectRow(0);
00366         }
00367       }catch (const xml_schema::exception& e){
00368         /* handle exceptions */
00369         std::ostringstream os;
00370         os << e;
00371         QMessageBox msgBox;
00372         msgBox.setText(QString(os.str().c_str()));
00373         msgBox.setIcon(QMessageBox::Warning);
00374         msgBox.exec();
00375       }
00376     } 
00377   }
00378   delete open_file;
00379 }
00380 
00381 void MainWindow::on_save_sequence_clicked()
00382 {
00383   if(this->ui.sequence_name->text().size()!=0)
00384   {
00385     // get the desired filename
00386     this->motion_file_name=this->ui.sequence_name->text().toLocal8Bit().constData();
00387   }
00388   else
00389   {
00390     QMessageBox msgBox;
00391     msgBox.setText("No filename specified. Impossible to create a new motion sequence file.");
00392     msgBox.setIcon(QMessageBox::Warning);
00393     msgBox.exec();
00394   }
00395 
00396 }
00397 
00398 void MainWindow::on_create_sequence_clicked()
00399 {
00400   QString filename;
00401 
00402   // clear the current sequence
00403   this->seq.clear();
00404   this->current_step=0;
00405   this->fill_motion_table();
00406 }
00407 
00408 void MainWindow::on_execute_sequence_clicked()
00409 {
00410   try{
00411     this->qnode.execute_sequence(this->seq);
00412   }catch(std::string &error){
00413     QMessageBox msgBox;
00414     msgBox.setText(error.c_str());
00415     msgBox.setIcon(QMessageBox::Warning);
00416     msgBox.exec();
00417   }
00418 }
00419 
00420 void MainWindow::on_add_step_clicked()
00421 {
00422   TMotionStep step;
00423   unsigned int i;
00424   QString value;
00425 
00426   step.delay=this->ui.delay->text().toInt();
00427   step.position.resize(this->dof);
00428   step.velocity.resize(this->dof);
00429   for(i=0;i<this->dof;i++)
00430   {
00431     step.position[i]=this->desired_pos[i]->value();
00432     step.velocity[i]=this->desired_vel[i]->value();
00433   }
00434   this->seq.push_back(step);
00435   this->add_motion_step(step.position,step.velocity,step.delay);
00436   this->ui.motion_steps->selectRow(this->seq.size()-1);
00437 }
00438 
00439 void MainWindow::on_delete_step_clicked()
00440 {
00441   std::vector<TMotionStep> sequence;
00442   unsigned int row,i;
00443   TMotionStep step;
00444 
00445   row=this->ui.motion_steps->currentRow();
00446   if(row==(unsigned int)-1)
00447   {
00448     QMessageBox msgBox;
00449     msgBox.setText("No motion step selected.");
00450     msgBox.setIcon(QMessageBox::Warning);
00451     msgBox.exec();
00452   }
00453   else
00454   {
00455     sequence=this->seq;
00456     this->seq.clear();
00457     for(i=0;i<sequence.size();i++)
00458     {
00459       if(i!=row)
00460         this->seq.push_back(sequence[i]);
00461     }
00462     this->fill_motion_table();
00463     if(row==this->seq.size())
00464       this->ui.motion_steps->selectRow(this->seq.size()-1);
00465     else
00466       this->ui.motion_steps->selectRow(row);
00467   }
00468 }
00469 
00470 void MainWindow::on_insert_step_clicked()
00471 {
00472   std::vector<TMotionStep> sequence;
00473   unsigned int row,i;
00474   TMotionStep step;
00475 
00476   row=this->ui.motion_steps->currentRow();
00477   if(row==(unsigned int)-1)
00478     this->ui.add_step->click();
00479   else
00480   {
00481     step.delay=this->ui.delay->text().toInt();
00482     step.position.resize(this->dof);
00483     step.velocity.resize(this->dof);
00484     for(i=0;i<this->dof;i++)
00485     {
00486       step.position[i]=this->desired_pos[i]->value();
00487       step.velocity[i]=this->desired_vel[i]->value();
00488     }
00489     sequence=this->seq;
00490     this->seq.clear();
00491     for(i=0;i<sequence.size();i++)
00492     {
00493       if(i==row)
00494         this->seq.push_back(step);
00495       this->seq.push_back(sequence[i]);
00496     }
00497     this->fill_motion_table();
00498     this->ui.motion_steps->selectRow(row);
00499   }
00500 }
00501 
00502 void MainWindow::on_motion_step_changed()
00503 {
00504   this->current_step=this->ui.motion_steps->currentRow();
00505 }
00506 
00507 /*****************************************************************************
00508 ** Implementation [Menu]
00509 *****************************************************************************/
00510 
00511 void MainWindow::on_actionAbout_triggered() 
00512 {
00513     QMessageBox::about(this, tr("About ..."),tr("<h2>PACKAGE_NAME Test Program 0.10</h2><p>Copyright Yujin Robot</p><p>This package needs an about description.</p>"));
00514 }
00515 
00516 /*****************************************************************************
00517 ** Implementation [Configuration]
00518 *****************************************************************************/
00519 
00520 void MainWindow::closeEvent(QCloseEvent *event)
00521 {
00522   QMainWindow::closeEvent(event);
00523 }
00524 
00525 }  // namespace tibi_dabo_sequence_editor
00526 


tibi_dabo_sequence_editor
Author(s): Sergi Hernandez Juan
autogenerated on Fri Dec 6 2013 23:02:16