window.cpp
Go to the documentation of this file.
1 
9 #include <gui/window.hpp>
10 #include <gui/viewCtrl.hpp>
11 #include <gui/selectCtrl.hpp>
12 #include <QVBoxLayout>
13 #include <QGridLayout>
14 #include <QLineEdit>
15 #include <QDoubleValidator>
16 #include <QSettings>
17 #include <QFileDialog>
18 #include <QDialogButtonBox>
19 #include <QMessageBox>
20 
21 
22 const double QtCtrlGUI::time_step = .2;
23 
24 /* The constructor requires <tt>main()</tt>'s arguments (they can
25  * be forwarded by the @ref ROSnode "ROS node" to ROS).
26  *
27  * Parameter argc the arguments' count,
28  * argv the arguments' value,
29  * parent the main widget parent, if any (optional).
30  *
31  * See ROSnode::ROSnode().
32  */
33 QtCtrlGUI::QtCtrlGUI(const int argc, char** argv, QWidget* parent)
34  : QMainWindow(parent), menu_bar(this), app_menu(&menu_bar),
35  help_menu(&menu_bar), tool_bar(this), start_stop_action(this),
36  about_action(this), about_Qt_action(this), ROS_server(this),
37  motion_model(-.5, .5, M_PI/4, -.6, .5, -M_PI/8, M_PI/8),
38  controller( new NoCtrl(motion_model) ), ctrl_node(argc, argv),
39  ctrl_wdgt( new ViewCtrlWdgt(*this, *controller, motion_model) ),
40  display(*this), logs(this) { // setup the UI
41  setWindowTitle( tr("ROS - Qt Controlers Benchmark") );
42  setWindowIcon( QIcon(":/files/icon.png") );
43  // handle the ROS server's signal
44  connect( &ROS_server,
45  SIGNAL( errorOccurred(const int, const QString&) ),
46  this, SLOT( threadError(const int, const QString&) ) );
47  // set the Start, "About Qt Ctrl" and "About Qt" actions
48  start_stop_action.setText( tr("Start Ctrl") );
49  start_stop_action.setShortcut(Qt::Key_S);
50  connect( &start_stop_action, SIGNAL( triggered() ),
51  this, SLOT( buttonStartStop() ) );
52  about_action.setText( tr("About Qt &Ctrl") );
53  connect( &about_action, SIGNAL( triggered() ),
54  this, SLOT( actionAbout() ) );
55  about_Qt_action.setText( tr("About &Qt") );
56  connect( &about_Qt_action, SIGNAL( triggered() ),
57  qApp, SLOT( aboutQt() ) );
58  // set the menu bar and the menus
59  setMenuBar(&menu_bar);
60  app_menu.setTitle( tr("&App") );
61  app_menu.addAction(&start_stop_action);
62  menu_bar.addMenu(&app_menu);
63  help_menu.setTitle( tr("&Help") );
64  help_menu.addAction(&about_action);
65  help_menu.addAction(&about_Qt_action);
66  menu_bar.addMenu(&help_menu);
67  // set the tool bar and add start button
68  addToolBar(&tool_bar);
69  tool_bar.addAction(&start_stop_action);
70  // set the main widget, with teleoperation and logging
71  QWidget *central_widget = new QWidget(this);
72  setCentralWidget(central_widget);
73  // create a layout for the central widget
74  QGridLayout *central_layout = new QGridLayout(central_widget);
75  central_layout->addWidget(&( ctrl_wdgt->widget() ), 0, 0);
76  central_layout->addWidget(&display, 0, 1);
77  QGroupBox *log_box = new QGroupBox(tr("Logs"), central_widget);
78  QBoxLayout *log_layout = // create a layout for the log box
79  new QBoxLayout(QBoxLayout::LeftToRight, log_box);
80  logs.setMinimumSize(400, 100);
81  log_layout->addWidget(&logs);
82  central_layout->addWidget(log_box, 1, 0, 1, 2);
83  // restore the settings
84  readSettings();
85  // initialises the state's display
87  // idem for the commands
89  // connects log signal of the ROS node to the GUI method
90  logs.setModel(&( ctrl_node.loggingModel() ) );
91  connect( &(ctrl_node), SIGNAL( loggingUpdated() ),
92  this, SLOT( updateLogging() ) );
93  // needed after Q_DECLARE_METATYPE and before the connects
94  qRegisterMetaType<State>();
95  connectCtrl(); // connects the controller signals to the GUI methods
96 } // end of QtCtrlGUI::QtCtrlGUI(int, char**, QWidget*) --------------
97 
98 // Load up Qt program settings at startup.
100  QSettings settings("Qt-Ros Package", "qt_ctrl");
101  restoreGeometry(settings.value("geometry").toByteArray());
102  restoreState(settings.value("windowState").toByteArray());
103  QString master_url = settings.value
104  ("master_url",QString("http://192.168.1.2:11311/")).toString();
105  QString host_url = settings.value
106  ("host_url", QString("192.168.1.3")).toString(); /*
107  //QString topic_name = settings.value
108  //("topic_name", QString("/chatter")).toString();
109  ui.line_edit_master->setText(master_url);
110  ui.line_edit_host->setText(host_url);
111  //ui.line_edit_topic->setText(topic_name);
112  bool remember = settings.value("remember_settings", false).toBool();
113  ui.checkbox_remember_settings->setChecked(remember);
114  bool checked = settings.value("use_environment_variables", false).toBool();
115  ui.checkbox_use_environment->setChecked(checked);
116  if ( checked ) {
117  ui.line_edit_master->setEnabled(false);
118  ui.line_edit_host->setEnabled(false);
119  //ui.line_edit_topic->setEnabled(false);
120  } */
121 } // end of void QtCtrlGUI::readSettings() ---------------------------
122 
123 // Save Qt program settings when closing.
125  QSettings settings("Qt-Ros Package", "qt_ctrl"); /*
126  settings.setValue("master_url",ui.line_edit_master->text());
127  settings.setValue("host_url",ui.line_edit_host->text());
128  //settings.setValue("topic_name",ui.line_edit_topic->text());
129  settings.setValue("use_environment_variables",QVariant
130  (ui.checkbox_use_environment->isChecked()));
131  settings.setValue("geometry", saveGeometry());
132  settings.setValue("windowState", saveState());
133  settings.setValue("remember_settings",QVariant
134  (ui.checkbox_remember_settings->isChecked()));
135  */
136 } // end of void QtCtrlGUI::writeSettings() --------------------------
137 
138 // Signals which error occured when starting ROS server.
139 // Parameter: error the error which occured.
140 // program the name of the script started. @since 0.3.3
141 void QtCtrlGUI::threadError(const int error, const QString& program) {
142  static const char* error_msg[]
143  = { "Failed to start", "Crashed", "Timeout",
144  "Write error", "Read error", "Unknown error" };
145  QMessageBox::critical
146  ( this, "Thread Error Occured",
147  QString("Starting %1 generated error #%2 (%3)")
148  .arg( program ).arg( error ).arg( error_msg[error] ),
149  QMessageBox::Ok, QMessageBox::Ok );
150 } // end of void ROSserver::error(QProcess::ProcessError) ------------
151 
152 // Method activated by the "About" menu item (not yet used).
154  QMessageBox::about
155  (this, tr("About ROS-Qt Control GUI"),
156  tr("<h2>ROS-Qt Control GUI</h2>\
157  <p>Copyright <a href=\"http://members.loria.fr/AScheuer\"\
158  >Alexis Scheuer</a>, <a href= \
159  \"http://www.univ-lorraine.fr\">UL</a>|<a href= \
160  \"http://fst.univ-lorraine.fr\">FST</a> &amp; <a href=\
161  \"http://www.loria.fr\">Loria</a></p> \
162  <p>This package proposes several controllers for ROS \
163  with a Qt GUI, in order to compare them.</p>"));
164 } // end of void QtCtrlGUI::actionAbout() ----------------------------
165 
168  bool not_connected, trying, tracking, reaching;
169  start_stop_action.setEnabled(false);// prevent the button activation
170  if ( ctrl_node.connected() ) { // ### stop the control ############
171  ctrl_node.end(); // stop ROS node (= server + ctrl)
172  if ( ROS_server.isRunning() ) { // should we stop the ROS master?
173  const QMessageBox::StandardButton ans = QMessageBox::question
174  (this, tr("Stopping ROS master?"), // title of the dialog
175  tr("Should this GUI stop the TurtleBot simulation "
176  "(you may not be able to start it again)?"),
177  // 3 buttons, Cancel is the default
178  QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
179  if (ans == QMessageBox::Yes)
180  ROS_server.stop(); // stop ROS server's thread
181  } // en of if (ROS server is running)
182  start_stop_action.setText( tr("Start Ctrl") );
183  } else { // ### start the control #################################
184  do {
185  QtCtrlSelect dialog(this, time_step, motion_model);
186  trying = dialog.exec() == QDialog::Accepted;
187  if (trying) { /* not yet working
188  const char*msg = "Do you want to clear the motion history?";
189  if (QMessageBox::question(this, tr("Clear history?"), tr(msg),
190  QMessageBox::Yes | QMessageBox::No)
191  == QMessageBox::No) display.newTrajectory(); */
192  if ( dialog.startROS() ) { // starts ROS with a workspace
193 
194  const std::string wrksp = ctrl_node.worldCommandFile
195  ( dialog.emptyROSworkspace() );
196  QMessageBox::information( this, "Workspace Script",
197  QString("Using script '%1'")
198  .arg( wrksp.c_str() ),
199  QMessageBox::Ok, QMessageBox::Ok);
200  ROS_server.setWorkspace( wrksp );
201  ROS_server.start();
202  // previous call returns immediatly, but needs...
203  ROS_server.sleep(5); // ... about 5 s to be effective
204  } // end of if (start ROS)
205  // memorize old pointers before reallocation (free later)
206  Controller* old_ctrl = controller;
207  ControlWidget* old_wdgt = ctrl_wdgt;
208  controller = dialog.newController();
209  ctrl_wdgt = dialog.newCtrlWidget();
210  connectCtrl(); // connects controller signals to GUI methods
211  hide(); // hide the window before modifying it
212  // add the new control widget to the main window
213  QGridLayout *central_layout =
214  (QGridLayout*)( centralWidget()->layout() );
215  old_wdgt->widget().hide(); // remove not enough, hide needed
216  central_layout->removeWidget( &( old_wdgt->widget() ) );
217  central_layout->addWidget(&( ctrl_wdgt->widget() ), 0, 0);
218  show(); // show/redraw window once modifications are done
219  // change has been done, let's free old pointers
220  delete old_wdgt;
221  delete old_ctrl;
222  // valid save file => set it
223  const QString& saveFile = dialog.saveFileName();
224  if ( (! saveFile.isNull() ) && (! saveFile.isEmpty() ) )
225  display.setOutput( saveFile.toStdString().c_str() );
226  ctrl_node.init(*controller); // try to start control node
227  not_connected = ! ctrl_node.connected();
228  } // end of if (trying)
229  } while (trying && not_connected);
230  if (trying) start_stop_action.setText( tr("Stop Ctrl") );
231  } // end of else (start control)
232  start_stop_action.setEnabled(true);
233 } // end of void QtCtrlGUI::buttonStart() ----------------------------
234 
246 int main(int argc, char** argv) {
247  QApplication app(argc, argv); // start the Qt main loop
248  QtCtrlGUI ctrl(argc, argv); // create the Qt control main window
249  ctrl.show(); // show this window
250  // stop the Qt main loop when last window (= main window) is closed
251  app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
252  return app.exec(); // return Qt main loop's return value
253 } // end of int main(int, char**) ------------------------------------
ROSnode ctrl_node
The ROS node at the center of this GUI.
Definition: window.hpp:90
Qt based GUI for qt_ctrl package.
bool emptyROSworkspace() const
Indicates if starting ROS should use empty workspace.
Definition: selectCtrl.hpp:96
Controller is the abstract class inherited by all the implemented controllers.
Definition: controller.hpp:28
QMenuBar menu_bar
The menu bar of this GUI.
Definition: window.hpp:49
void updateLogging()
Method activated when this GUI&#39;s log view is updated.
Definition: window.hpp:197
void buttonStartStop()
Method activated by the "Start/Stop" button.
Definition: window.cpp:167
QMenu app_menu
The actions&#39; menu of this GUI.
Definition: window.hpp:53
int main(int argc, char **argv)
This is qt_ctrl main function, starting a Qt control GUI in a Qt application.
Definition: window.cpp:246
ROSserver ROS_server
The instance used to start a ROS server, if needed.
Definition: window.hpp:75
Qt control widget showing current and aimed velocities.
void setOutput(const char *output_file_name)
Change the output stream to a new file.
Definition: display.hpp:95
QToolBar tool_bar
The tool bar of this GUI.
Definition: window.hpp:64
void init(Controller &ctrl)
Connects to ROS server with main arguments.
Definition: ROS_node.hpp:141
bool startROS() const
Indicates whether ROS should be started.
Definition: selectCtrl.hpp:91
virtual void updateState(const State &state)=0
Update the display of the odometry.
QMenu help_menu
The help menu of this GUI.
Definition: window.hpp:57
Default controller, which does not move.
Definition: controller.hpp:132
This abstract class is inherited by all those containing a Qt widget intended to show the controller&#39;...
Definition: ctrlWdgt.hpp:24
void connectCtrl()
Connects the controller signals to this class&#39; methods.
Definition: window.hpp:110
void actionAbout()
Method activated by the "About" menu item (not yet used).
Definition: window.cpp:153
This class is a Qt widget which allows to show the controller&#39;s behaviour (current and aimed velociti...
Definition: viewCtrl.hpp:24
ControlWidget * ctrl_wdgt
The widget showing the controller&#39;s velocities can also change.
Definition: window.hpp:94
std::string worldCommandFile(const bool empty=true)
File name for the script starting the simulation.
Definition: ROS_node.hpp:163
void readSettings()
Load up Qt program settings at startup.
Definition: window.cpp:99
static const double time_step
The default time step.
Definition: window.hpp:45
QStringListModel & loggingModel()
The Qt object used to show the logs.
Definition: ROS_node.hpp:158
ControlWidget * newCtrlWidget()
Gives the selected controller&#39;s widget, or null pointer if the dialog was cancelled.
Definition: selectCtrl.hpp:107
void stop()
Stops the ROS server (and the thread&#39;s execution).
Definition: thread.hpp:60
This class defines a state, i.e. a configuration and its (translation and rotation) velocities...
Definition: state.hpp:22
Controller * controller
The controller of the ROS node can change.
Definition: window.hpp:87
bool connected() const
Indicates whether the node is connected to ROS.
Definition: ROS_node.hpp:135
void setWorkspace(const std::string &wrksp)
Set the workspace name.
Definition: thread.hpp:48
QAction about_action
The Qt action starting a dialog box about Qt Ctrl.
Definition: window.hpp:72
void writeSettings()
Save Qt program settings when closing.
Definition: window.cpp:124
Qt dialog window to select the control used by the qt_ctrl GUI.
MotionModel motion_model
The motion model of the controlled robot.
Definition: window.hpp:83
virtual void updateCommands(const double &trans_vel, const double &rot_vel)=0
Update the display of the ROS node.
virtual QWidget & widget()=0
Returns the widget used to display the behaviour.
DataWidget display
The data display widget of the ROS node.
Definition: window.hpp:98
QAction about_Qt_action
The Qt action starting a dialog box about Qt.
Definition: window.hpp:79
This class is the Qt main window of qt_ctrl package.
Definition: window.hpp:41
QtCtrlGUI(const int argc, char **argv, QWidget *parent=0)
The constructor requires main()&#39;s arguments (they can be forwarded by the ROS node to ROS)...
Definition: window.cpp:33
QAction start_stop_action
The Qt action starting the ROS node.
Definition: window.hpp:68
const QString & saveFileName() const
Gives the save file name.
Definition: selectCtrl.hpp:110
void end()
Stops ROS if it has been started.
Definition: ROS_node.cpp:17
void threadError(const int error, const QString &program)
Signals which error occured when starting ROS server.
Definition: window.cpp:141
This class defines an accept/cancel dialog to create a controller and its display widget which will b...
Definition: selectCtrl.hpp:34
QListView logs
The Qt list view showing the logs of the ROS node.
Definition: window.hpp:102
Controller * newController()
Gives the selected controller, or null pointer if the dialog was cancelled.
Definition: selectCtrl.hpp:102
void sleep(const long &seconds) const
Waits for a given duration, in seconds.
Definition: thread.hpp:57


qt_ctrl
Author(s): Alexis Scheuer
autogenerated on Wed Dec 16 2020 15:51:32