path_planning_widget.cpp
Go to the documentation of this file.
1 #include <QHBoxLayout>
2 #include <QVBoxLayout>
3 #include <QPushButton>
4 #include <QLabel>
5 #include <QRadioButton>
6 #include <QSpinBox>
7 #include <QDoubleSpinBox>
8 #include <QMessageBox>
9 #include <QCheckBox>
10 #include <QFuture>
11 #include <QtConcurrent/QtConcurrentRun>
12 
13 #include "path_planning_widget.h"
14 #include <ros/package.h>
15 
17 {
18  setObjectName("PathPlanningWidget_");
19  QLabel* surfacing_mode_label = new QLabel("Surfacing mode ");
20  surfacing_mode_ = new QCheckBox;
21  surfacing_mode_->setChecked(false);
22  QHBoxLayout* surfacing_mode_layout = new QHBoxLayout;
23  surfacing_mode_layout->addWidget(surfacing_mode_label);
24  surfacing_mode_layout->addWidget(surfacing_mode_);
25 
26  depth_of_pass_label_ = new QLabel("Depth of pass");
27  depth_of_pass_ = new QDoubleSpinBox;
28  depth_of_pass_->setSuffix(" mm");
29  depth_of_pass_->setValue(1.0);
30  depth_of_pass_->setDecimals(3);
31  depth_of_pass_->setRange(0.001, 100);
32  QHBoxLayout* depth_of_pass_layout = new QHBoxLayout;
33  depth_of_pass_layout->addWidget(depth_of_pass_label_);
34  depth_of_pass_layout->addWidget(depth_of_pass_);
35 
36  QLabel* covering_percentage_label = new QLabel("Covering percentage:");
37  covering_percentage_ = new QSpinBox;
38  covering_percentage_->setSuffix("%");
39  covering_percentage_->setValue(40);
40  covering_percentage_->setRange(0, 99);
41  QHBoxLayout* covering_percentage_layout = new QHBoxLayout;
42  covering_percentage_layout->addWidget(covering_percentage_label);
43  covering_percentage_layout->addWidget(covering_percentage_);
44 
45  QLabel* extrication_radius_label = new QLabel("Extrication radius:");
46  extrication_radius_ = new QSpinBox;
47  extrication_radius_->setSuffix(" mm");
48  extrication_radius_->setValue(20);
49  extrication_radius_->setRange(1, 200);
50  QHBoxLayout* extrication_radius_layout = new QHBoxLayout;
51  extrication_radius_layout->addWidget(extrication_radius_label);
52  extrication_radius_layout->addWidget(extrication_radius_);
53 
54  QLabel* grind_diameter_label = new QLabel("Grinder width:");
55  grinder_width_ = new QDoubleSpinBox;
56  grinder_width_->setSuffix(" mm");
57  grinder_width_->setValue(30);
58  grinder_width_->setDecimals(1);
59  grinder_width_->setRange(1.0, 200.0);
60  QHBoxLayout* grind_diameter_layout = new QHBoxLayout;
61  grind_diameter_layout->addWidget(grind_diameter_label);
62  grind_diameter_layout->addWidget(grinder_width_);
63 
64  QLabel* lean_angle_axis_label = new QLabel("Axis of rotation:");
65  lean_angle_axis_x_ = new QRadioButton("x");
66  lean_angle_axis_y_ = new QRadioButton("y");
67  lean_angle_axis_z_ = new QRadioButton("z");
68  QHBoxLayout* lean_angle_axis_layout = new QHBoxLayout;
69  lean_angle_axis_layout->addWidget(lean_angle_axis_label);
70  lean_angle_axis_layout->addStretch(1);
71  lean_angle_axis_layout->addWidget(lean_angle_axis_x_);
72  lean_angle_axis_layout->addWidget(lean_angle_axis_y_);
73  lean_angle_axis_layout->addWidget(lean_angle_axis_z_);
74  lean_angle_axis_layout->addStretch(1);
75 
76  QLabel* angle_value_label = new QLabel("Angle value:");
77  angle_value_ = new QDoubleSpinBox;
78  angle_value_->setSuffix(" degrees");
79  angle_value_->setRange(-90, 90);
80  QHBoxLayout* angle_value_layout = new QHBoxLayout;
81  angle_value_layout->addWidget(angle_value_label);
82  angle_value_layout->addWidget(angle_value_);
83 
84  compute_trajectory_ = new QPushButton("Compute trajectory");
85  compute_trajectory_->setMinimumHeight(90);
86 
87  QLabel* trajectory_z_offset_label = new QLabel("Trajectory Z offset:");
88  trajectory_z_offset_ = new QDoubleSpinBox;
89  trajectory_z_offset_->setSuffix(" mm");
90  trajectory_z_offset_->setRange(-1000, 1000);
91  QHBoxLayout* trajectory_z_offset_layout = new QHBoxLayout();
92  trajectory_z_offset_layout->addWidget(trajectory_z_offset_label);
93  trajectory_z_offset_layout->addWidget(trajectory_z_offset_);
94 
95  execute_trajectory_ = new QPushButton("Execute trajectory");
96  execute_trajectory_->setEnabled(false);
97  execute_trajectory_->setMinimumHeight(60);
98 
99  QVBoxLayout* path_planning_layout = new QVBoxLayout(this);
100  path_planning_layout->addLayout(surfacing_mode_layout);
101  path_planning_layout->addLayout(depth_of_pass_layout);
102  path_planning_layout->addLayout(covering_percentage_layout);
103  path_planning_layout->addLayout(extrication_radius_layout);
104  path_planning_layout->addLayout(grind_diameter_layout);
105  path_planning_layout->addLayout(lean_angle_axis_layout);
106  path_planning_layout->addLayout(angle_value_layout);
107  path_planning_layout->addStretch(2);
108  path_planning_layout->addWidget(compute_trajectory_);
109  path_planning_layout->addStretch(1);
110  path_planning_layout->addWidget(trajectory_z_offset_label);
111  path_planning_layout->addWidget(trajectory_z_offset_);
112  path_planning_layout->addWidget(execute_trajectory_);
113  path_planning_layout->addStretch(8);
114 
115  //Connect handlers
116  // At each modification of the widget, we call triggerSave
117  connect(surfacing_mode_, SIGNAL(stateChanged(int)), this, SLOT(setDepthOfPassEnable(int)));
118  connect(surfacing_mode_, SIGNAL(stateChanged(int)), this, SLOT(triggerSave()));
119  connect(covering_percentage_, SIGNAL(valueChanged(int)), this, SLOT(triggerSave()));
120  connect(extrication_radius_, SIGNAL(valueChanged(int)), this, SLOT(triggerSave()));
121  connect(grinder_width_, SIGNAL(valueChanged(double)), this, SLOT(triggerSave()));
122  connect(depth_of_pass_, SIGNAL(valueChanged(double)), this, SLOT(triggerSave()));
123  connect(lean_angle_axis_x_, SIGNAL(clicked()), this, SLOT(triggerSave()));
124  connect(lean_angle_axis_y_, SIGNAL(clicked()), this, SLOT(triggerSave()));
125  connect(lean_angle_axis_z_, SIGNAL(clicked()), this, SLOT(triggerSave()));
126  connect(angle_value_, SIGNAL(valueChanged(double)), this, SLOT(triggerSave()));
127  connect(trajectory_z_offset_, SIGNAL(valueChanged(int)), this, SLOT(triggerSave()));
128 
129  // Enable or disable compute_trajectory_button_
130  connect(this, SIGNAL(enableComputeTrajectoryButton(bool)), this, SLOT(enableComputeTrajectoryButtonHandler(bool)));
131  // Enable or disable execute_trajectory_button_
132  connect(this, SIGNAL(enableExecuteTrajectoryButton(bool)), this, SLOT(enableExecuteTrajectoryButtonHandler(bool)));
133 
134  // connect each buttons to different functions
135  connect(compute_trajectory_, SIGNAL(released()), this, SLOT(computeTrajectoryButtonHandler()));
136  connect(execute_trajectory_, SIGNAL(released()), this, SLOT(executeTrajectoryButtonHandler()));
137 
138  // Subscriber to receive messages from the exterior
140 
141  // Setup client
142  path_planning_service_ = nh_.serviceClient<fanuc_grinding_path_planning::PathPlanningService>("path_planning_service");
143 
144  QFuture<void> future = QtConcurrent::run(this, &fanuc_grinding_rviz_plugin::PathPlanningWidget::connectToServices);
145 }
146 
147 void fanuc_grinding_rviz_plugin::PathPlanningWidget::newStatusMessage(const std_msgs::String::ConstPtr &msg)
148 {
149  Q_EMIT sendStatus(QString::fromStdString(msg->data));
150 }
151 
153 {
154  compute_trajectory_->setEnabled(state);
155 }
156 
158 {
159  execute_trajectory_->setEnabled(state);
160 }
161 
162 void fanuc_grinding_rviz_plugin::PathPlanningWidget::setPathPlanningParams(fanuc_grinding_path_planning::PathPlanningService::Request &params)
163 {
164  srv_path_planning_.request.SurfacingMode = params.SurfacingMode;
165  srv_path_planning_.request.CoveringPercentage = params.CoveringPercentage;
166  srv_path_planning_.request.ExtricationRadius = params.ExtricationRadius;
167  srv_path_planning_.request.GrinderWidth = params.GrinderWidth;
168  srv_path_planning_.request.DepthOfPass = params.DepthOfPass;
169  srv_path_planning_.request.AngleX = params.AngleX;
170  srv_path_planning_.request.AngleY = params.AngleY;
171  srv_path_planning_.request.AngleZ = params.AngleZ;
172  srv_path_planning_.request.LeanAngle = params.LeanAngle;
173  srv_path_planning_.request.TrajectoryZOffset = params.TrajectoryZOffset;
174  updateGUI();
175 }
176 
178 {
179  surfacing_mode_->setChecked(srv_path_planning_.request.SurfacingMode);
180  covering_percentage_->setValue(srv_path_planning_.request.CoveringPercentage);
181  extrication_radius_->setValue(srv_path_planning_.request.ExtricationRadius * 1000.0); // meters to millimeters
182  grinder_width_->setValue(srv_path_planning_.request.GrinderWidth * 1000.0); // meters to millimeters
183  depth_of_pass_->setValue(srv_path_planning_.request.DepthOfPass * 1000.0); // meters to millimeters
184  lean_angle_axis_x_->setChecked(srv_path_planning_.request.AngleX);
185  lean_angle_axis_y_->setChecked(srv_path_planning_.request.AngleY);
186  lean_angle_axis_z_->setChecked(srv_path_planning_.request.AngleZ);
187  angle_value_->setValue(srv_path_planning_.request.LeanAngle * 360.0 / M_PI); // radians to degrees
188  trajectory_z_offset_->setValue(srv_path_planning_.request.TrajectoryZOffset);
189 }
190 
192 {
193  srv_path_planning_.request.SurfacingMode = surfacing_mode_->isChecked();
194  srv_path_planning_.request.CoveringPercentage = covering_percentage_->value();
195  srv_path_planning_.request.ExtricationRadius = extrication_radius_->value() / 1000.0; // millimeters to meters
196  srv_path_planning_.request.GrinderWidth = grinder_width_->value() / 1000.0; // millimeters to meters
197  srv_path_planning_.request.DepthOfPass = depth_of_pass_->value() / 1000.0; // millimeters to meters
198  srv_path_planning_.request.AngleX = lean_angle_axis_x_->isChecked();
199  srv_path_planning_.request.AngleY = lean_angle_axis_y_->isChecked();
200  srv_path_planning_.request.AngleZ = lean_angle_axis_z_->isChecked();
201  srv_path_planning_.request.LeanAngle = angle_value_->value() / 360.0 * M_PI; // degrees to radians
202  srv_path_planning_.request.TrajectoryZOffset = trajectory_z_offset_->value() / 1000.0; // millimeters to meters
203 }
204 
206 {
207  depth_of_pass_->setEnabled(!state);
208  depth_of_pass_label_->setEnabled(!state);
209 }
210 
212  const QString scan_filename)
213 {
214  std::string defect_mesh_file = ros::package::getPath("fanuc_grinding_scanning");
215  defect_mesh_file += "/meshes/DAC_580813_defect.ply";
216  srv_path_planning_.request.CADFileName = defect_mesh_file;
217  //srv_path_planning_.request.CADFileName = cad_filename.toStdString();
218  srv_path_planning_.request.ScanFileName = scan_filename.toStdString();
219 }
220 
222 {
223  return srv_path_planning_.response.RobotPosesOutput;
224 }
225 
227 {
228  std::vector<bool> tmp;
229  for (unsigned i = 0; i < srv_path_planning_.response.IsGrindingPose.size(); ++i)
230  tmp.push_back(srv_path_planning_.response.IsGrindingPose[i]);
231 
232  return tmp;
233 }
234 
236 {
237  // Fill service parameters with GUI values
239  // get CAD and Scan params which are stored in grinding rviz plugin
240  Q_EMIT getCADAndScanParams();
241 
242  // Fill in the request
243  srv_path_planning_.request.Compute = true;
244  srv_path_planning_.request.Simulate = false;
245 
246  QFuture<void> future = QtConcurrent::run(this, &PathPlanningWidget::pathPlanningService);
247 }
248 
250 {
251  // If GUI has been changed, compute_trajectory_button_ is enable.
252  // So, the pose is not up-to-date with GUI values
253  // We inform the user that is an old pose
254  if(compute_trajectory_->isEnabled() == true)
255  {
256  QMessageBox msgBox;
257  msgBox.setText("Values have been modified");
258  msgBox.setIcon(QMessageBox::Warning);
259  msgBox.setInformativeText("If you continue, you will deal with an old trajectory");
260  msgBox.setStandardButtons(QMessageBox::Abort | QMessageBox::Ok);
261  msgBox.setDefaultButton(QMessageBox::Ok);
262 
263  if(msgBox.exec() == QMessageBox::Abort)
264  return;
265  }
266 
267  // Fill service parameters with GUI values
269 
270  // get CAD and Scan params which are stored in grinding RViz plugin
271  Q_EMIT getCADAndScanParams();
272 
273  // Fill in the request
274  srv_path_planning_.request.Compute = false;
275  srv_path_planning_.request.Simulate = true;
276  // Start client service call in an other thread
277  QFuture<void> future = QtConcurrent::run(this, &PathPlanningWidget::pathPlanningService);
278 }
279 
281 {
282  if(srv_path_planning_.request.Compute)
283  Q_EMIT enableComputeTrajectoryButton(false);
284 
285  // Disable UI
286  Q_EMIT enablePanel(false);
287 
288  // Call client service
290  Q_EMIT sendStatus(QString::fromStdString(srv_path_planning_.response.ReturnMessage));
291 
292  if(srv_path_planning_.response.ReturnStatus == true)
293  {
294  if (srv_path_planning_.request.Compute)
295  {
296  Q_EMIT enablePanelPostProcessor();
297  Q_EMIT enableExecuteTrajectoryButton(true);
298  }
299  }
300  else
301  {
302  Q_EMIT sendMsgBox("Error in path planning service",
303  QString::fromStdString(srv_path_planning_.response.ReturnMessage), "");
304  if (srv_path_planning_.request.Compute)
305  {
306  Q_EMIT enableExecuteTrajectoryButton(false);
307  Q_EMIT enableComputeTrajectoryButton(true);
308  }
309 
310  else if (srv_path_planning_.request.Simulate)
311  {
312  Q_EMIT enableExecuteTrajectoryButton(true);
313  }
314  }
315 
316  // Re-enable UI
317  Q_EMIT enablePanel(true); // Enable UI
318 }
319 
321 {
322  Q_EMIT enablePanel(false);
323 
324  // Check offset_move_robot_ connection
325  Q_EMIT sendStatus("Connecting to service");
326  while (ros::ok())
327  {
329  {
330  ROS_INFO_STREAM(objectName().toStdString() + " RViz panel connected to the service " << path_planning_service_.getService());
331  Q_EMIT sendStatus(QString::fromStdString("RViz panel connected to the service: " + path_planning_service_.getService()));
332  break;
333  }
334  else
335  {
336  ROS_WARN_STREAM(objectName().toStdString() + " RViz panel could not connect to ROS service:\n\t" << path_planning_service_.getService());
337  Q_EMIT sendStatus(QString::fromStdString("RViz panel could not connect to ROS service: " + path_planning_service_.getService()));
338  sleep(1);
339  }
340  }
341 
342  ROS_INFO_STREAM(objectName().toStdString() + " service connections have been made");
343  Q_EMIT sendStatus("Ready to take commands");
344  Q_EMIT enablePanel(true);
345 }
346 
348 {
349  Q_EMIT guiChanged();
351  updateGUI();
352  Q_EMIT enableComputeTrajectoryButton(true);
353 }
354 
355 // Save all configuration data from this panel to the given Config object
357 {
358  // Save offset value into the config file
359  config.mapSetValue(objectName() + "surfacing_mode", surfacing_mode_->isChecked());
360  config.mapSetValue(objectName() + "covering_percentage", covering_percentage_->value());
361  config.mapSetValue(objectName() + "extrication_radius", extrication_radius_->value());
362  config.mapSetValue(objectName() + "grinder_width", grinder_width_->value());
363  config.mapSetValue(objectName() + "depth_of_path", depth_of_pass_->value());
364  config.mapSetValue(objectName() + "radio_x", lean_angle_axis_x_->isChecked());
365  config.mapSetValue(objectName() + "radio_y", lean_angle_axis_y_->isChecked());
366  config.mapSetValue(objectName() + "radio_z", lean_angle_axis_z_->isChecked());
367  config.mapSetValue(objectName() + "angle_value", angle_value_->value());
368  config.mapSetValue(objectName() + "trajectory_z_offset", trajectory_z_offset_->value());
369 }
370 
371 // Load all configuration data for this panel from the given Config object.
373 {
374  int tmp_int;
375  bool tmp_bool;
376  float tmp_float;
377  QString tmp_string;
378  // Load offset value from config file (if it exists)
379  if (config.mapGetBool(objectName() + "surfacing_mode", &tmp_bool))
380  surfacing_mode_->setChecked(tmp_bool);
381  else
382  surfacing_mode_->setChecked(false);
383  if (config.mapGetInt(objectName() + "covering_percentage", &tmp_int))
384  covering_percentage_->setValue(tmp_int);
385  else
386  covering_percentage_->setValue(40);
387 
388  if (config.mapGetInt(objectName() + "extrication_radius", &tmp_int))
389  extrication_radius_->setValue(tmp_int);
390  else
391  extrication_radius_->setValue(3);
392 
393  if (config.mapGetInt(objectName() + "grinder_width", &tmp_int))
394  grinder_width_->setValue(tmp_int);
395  else
396  grinder_width_->setValue(120);
397 
398  if (config.mapGetInt(objectName() + "depth_of_path", &tmp_int))
399  depth_of_pass_->setValue(tmp_int);
400  else
401  depth_of_pass_->setValue(1.0);
402 
403  if (config.mapGetBool(objectName() + "radio_x", &tmp_bool))
404  lean_angle_axis_x_->setChecked(tmp_bool);
405  if (config.mapGetBool(objectName() + "radio_y", &tmp_bool))
406  lean_angle_axis_y_->setChecked(tmp_bool);
407  if (config.mapGetBool(objectName() + "radio_z", &tmp_bool))
408  lean_angle_axis_z_->setChecked(tmp_bool);
409  if (!lean_angle_axis_x_->isChecked() && !lean_angle_axis_y_->isChecked() && !lean_angle_axis_z_->isChecked())
410  {
411  lean_angle_axis_z_->setChecked(true);
412  }
413 
414  if (config.mapGetFloat(objectName() + "angle_value", &tmp_float))
415  angle_value_->setValue(tmp_float);
416  else
417  angle_value_->setValue(10);
418 
419  if (config.mapGetFloat(objectName() + "trajectory_z_offset", &tmp_float))
420  trajectory_z_offset_->setValue(tmp_float);
421  else
422  trajectory_z_offset_->setValue(0);
423 }
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
void newStatusMessage(const std_msgs::String::ConstPtr &msg)
void setCADAndScanParams(const QString cad_filename, const QString scan_filename)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool call(MReq &req, MRes &res)
bool mapGetFloat(const QString &key, float *value_out) const
fanuc_grinding_path_planning::PathPlanningService srv_path_planning_
#define M_PI
void setPathPlanningParams(fanuc_grinding_path_planning::PathPlanningService::Request &params)
void sendMsgBox(QString title, QString msg, QString info_msg)
void mapSetValue(const QString &key, QVariant value)
bool waitForExistence(ros::Duration timeout=ros::Duration(-1))
ROSCPP_DECL bool ok()
bool mapGetBool(const QString &key, bool *value_out) const
#define ROS_WARN_STREAM(args)
bool mapGetInt(const QString &key, int *value_out) const
ROSLIB_DECL std::string getPath(const std::string &package_name)
#define ROS_INFO_STREAM(args)
std::string getService()
std::vector< geometry_msgs::Pose > getRobotPoses()


rviz_plugin
Author(s): Kévin Bolloré, Victor Lamoine - Institut Maupertuis
autogenerated on Thu Dec 19 2019 03:38:28