se2ez
cspacepanel.cpp
Go to the documentation of this file.
1 /* Author: Zachary Kingston */
2 
3 #include <algorithm>
4 
5 #include <QTimer>
6 #include <QFileDialog>
7 
8 #include <se2ez/core/log.h>
9 #include <se2ez/core/colormap.h>
10 #include <se2ez/core/io.h>
11 #include <se2ez/core/joint.h>
12 #include <se2ez/core/frame.h>
13 #include <se2ez/core/robot.h>
14 #include <se2ez/core/state.h>
15 #include <se2ez/core/cspace.h>
16 #include <se2ez/plan/space.h>
17 
18 #include "se2ez/gui/jointpanel.h"
19 #include "se2ez/gui/planpanel.h"
20 #include "se2ez/gui/cspacepanel.h"
21 
22 #include "ui_cspacepanel.h"
23 
24 using namespace se2ez;
25 
27  std::map<std::string, ompl::base::ConstraintPtr> constraints, QWidget *parent)
28  : Panel(name, parent)
29  , ui_(new Ui::CSpacePanel)
30  , robot_(robot)
31  , state_(std::make_shared<State>(robot))
32  , tempState_(std::make_shared<State>(robot))
33  , image_(xSize_, ySize_, QImage::Format_RGB32)
34  , wheel_(wheelSize_, wheelSize_, QImage::Format_RGB32)
35  , constraints_(constraints)
36 {
37  ui_->setupUi(this);
38 
39  ui_->jointA_->clear();
40  ui_->jointB_->clear();
41 
42  for (const auto &name : robot_->getFrameNames())
43  {
44  const auto &joint = robot_->getFrame(name)->getJoint();
45  if (joint.joints.size() - 1 == 1)
46  {
47  ui_->jointA_->addItem(QString(name.c_str()));
48  ui_->jointB_->addItem(QString(name.c_str()));
49  }
50  else
51  {
52  for (unsigned int i = 0; i < joint.joints.size() - 1; ++i)
53  {
54  const auto &name = joint.joints[i].getName();
55  ui_->jointA_->addItem(QString(name.c_str()));
56  ui_->jointB_->addItem(QString(name.c_str()));
57  }
58  }
59  };
60 
61  if (robot_->getNumJoints() > 1)
62  ui_->jointA_->setCurrentIndex(1);
63 
64  ui_->constraints_->addItem("<none>");
65  for (const auto &constraint : constraints)
66  ui_->constraints_->addItem(QString(constraint.first.c_str()));
67 
68  updatePanel();
69  updateGrid();
70 
71  connect(ui_->jointA_, SIGNAL(currentTextChanged(const QString &)), this, SLOT(updateGrid()));
72  connect(ui_->jointB_, SIGNAL(currentTextChanged(const QString &)), this, SLOT(updateGrid()));
73  connect(ui_->states_, SIGNAL(currentTextChanged(const QString &)), this, SLOT(updatePanel()));
74  connect(ui_->constraints_, SIGNAL(currentTextChanged(const QString &)), this, SLOT(updateCallback()));
75  connect(ui_->constraintMax_, SIGNAL(valueChanged(double)), this, SLOT(updateCallback()));
76  connect(ui_->constraintPow_, SIGNAL(valueChanged(int)), this, SLOT(updateCallback()));
77  connect(ui_->jacobian_, SIGNAL(stateChanged(int)), this, SLOT(updateCallback()));
78  connect(ui_->project_, SIGNAL(stateChanged(int)), this, SLOT(updateCallback()));
79  connect(ui_->doProject_, SIGNAL(clicked()), this, SLOT(projectState()));
80  connect(ui_->constraintCollisions_, SIGNAL(stateChanged(int)), this, SLOT(updateCallback()));
81  connect(ui_->display_, SIGNAL(stateChanged(int)), this, SLOT(update()));
82  connect(ui_->fullscreen_, SIGNAL(stateChanged(int)), this, SLOT(update()));
83  connect(ui_->hires_, SIGNAL(stateChanged(int)), this, SLOT(updateGrid()));
84  connect(ui_->state_, SIGNAL(stateChanged(int)), this, SLOT(update()));
85  connect(ui_->sd_, SIGNAL(stateChanged(int)), this, SLOT(updateGrid()));
86  connect(ui_->colors_, SIGNAL(stateChanged(int)), this, SLOT(updateGrid()));
87  connect(ui_->save_, SIGNAL(clicked()), this, SLOT(saveImage()));
88 
89  connect(ui_->plan_, SIGNAL(stateChanged(int)), this, SLOT(update()));
90  connect(ui_->edges_, SIGNAL(stateChanged(int)), this, SLOT(update()));
91  connect(ui_->graph_, SIGNAL(stateChanged(int)), this, SLOT(update()));
92  connect(ui_->planpanels_, SIGNAL(currentTextChanged(const QString &)), this, SLOT(updatePlanPanel()));
93  connect(ui_->slider_, SIGNAL(valueChanged(int)), this, SLOT(updatePlanState()));
94  connect(ui_->animate_, SIGNAL(stateChanged(int)), this, SLOT(updateAnimate()));
95 
96  computeWheel();
97 }
98 
100 {
101 }
102 
104 {
105  // SE2EZ_DEBUG("CSpacePanel::update()");
106  emit stateChanged();
107 }
108 
110 {
111  if (ui_->sd_->isChecked() && ui_->colors_->isChecked())
113  else if (ui_->sd_->isChecked())
114  return CSpaceGrid::DISTANCE;
115  else if (ui_->colors_->isChecked())
116  return CSpaceGrid::COLOR;
117  else
118  return CSpaceGrid::COLLISION;
119 }
120 
122 {
123  // SE2EZ_DEBUG("CSpacePanel::saveImage()");
124 
125  if (save_)
126  {
127  save_->join();
128  delete save_;
129  }
130 
131  QString fileName =
132  QFileDialog::getSaveFileName(this, tr("Save Image"), "./cspace.png", tr("Image (*.png)"));
133 
134  if (fileName.isNull())
135  return;
136 
137  save_ = new std::thread([&, fileName]() {
138  unsigned int ja = ui_->jointA_->currentIndex();
139  unsigned int jb = ui_->jointB_->currentIndex();
140  SE2EZ_INFORM("Saving grid with indices %1% and %2%...", ja, jb);
141 
142  unsigned int xSize = ui_->xSave->value();
143  unsigned int ySize = ui_->ySave->value();
144 
145  QImage toSave(xSize, ySize, QImage::Format_RGB32);
146  auto temp = std::make_shared<CSpaceGrid>(robot_, ja, jb, xSize, ySize, getMode());
147 
148  temp->compute(true, state_, callback_);
149 
150  auto cs = temp->getImage();
151 
152  for (unsigned int i = 0; i < xSize; ++i)
153  {
154  auto *line = (QRgb *)toSave.scanLine(i);
155  for (unsigned int j = 0; j < ySize; ++j)
156  {
157  auto px = cs->getPixel(xSize - i - 1, j);
158  QColor(px.red, px.green, px.blue);
159  line[j] = QColor(px.red, px.green, px.blue).rgb();
160  }
161  }
162 
163  QPainter paint;
164  paint.begin(&toSave);
165 
166  drawGraph(paint, temp, false);
167  drawPlan(paint, temp, false, true);
168  drawState(paint, temp, false, false);
169 
170  toSave.save(fileName, "PNG");
171  SE2EZ_INFORM("Done saving image to %1%", fileName.toStdString());
172  });
173 }
174 
176 {
177  {
179 
180  // Tear down grid
181  imageGen_ = false;
182  grid_->cancel();
183  grid_->waitToComplete();
184  grid_.reset();
185 
186  // Reallocate states
187  state_ = std::make_shared<State>(robot_);
188  tempState_ = std::make_shared<State>(robot_);
189 
190  // Drop panel connections
191  if (jp_)
192  QObject::disconnect(jpc_);
193  jp_ = nullptr;
194 
195  if (pp_)
196  QObject::disconnect(ppc_);
197  pp_ = nullptr;
198 
199  jnames_.clear();
200  pnames_.clear();
201  panelnames_.clear();
202 
203  // Clear other data
204  path_.clear();
205  callback_ = {};
206 
207  if (robot_->getNumJoints() > 0)
208  ui_->jointB_->setCurrentIndex(0);
209 
210  if (robot_->getNumJoints() > 1)
211  ui_->jointA_->setCurrentIndex(1);
212  }
213 
214  updateGrid();
215 }
216 
218 {
219  // SE2EZ_DEBUG("CSpacePanel::updatePlanPanel()");
220  {
222  if (pp_)
223  {
224  QObject::disconnect(ppc_);
225  QObject::disconnect(pdc_);
226  }
227 
228  pp_ = nullptr;
229  if (ui_->planpanels_->currentIndex() != 0)
230  {
231  const std::string &name = ui_->planpanels_->currentText().toStdString();
232  if (panelnames_.find(name) != panelnames_.end())
233  {
234  auto entry = panels->find(name);
235  pp_ = dynamic_cast<gui::PlanPanel *>(entry->second);
236  ppc_ = connect(pp_, SIGNAL(newPlan()), this, SLOT(updatePlan()));
237  ppc_ = connect(pp_, SIGNAL(newPlan()), this, SLOT(updatePlanData()));
238  }
239  }
240  }
241 
242  update();
243 }
244 
246 {
247  // SE2EZ_DEBUG("CSpacePanel::updatePlan()");
248 
249  {
251  path_ = pp_->getPath();
252 
253  if (path_.size())
254  {
255  ui_->slider_->blockSignals(true);
256  ui_->slider_->setMaximum(path_.size() - 1);
257  ui_->slider_->setEnabled(true);
258  ui_->slider_->setValue(0);
259  ui_->slider_->blockSignals(false);
260  }
261  }
262 
263  update();
264 }
265 
267 {
268  {
270  if (pp_)
271  {
272  pd_ = pp_->getPlannerData();
273  }
274  }
275 }
276 
278 {
279  if (path_.size() && ui_->animate_->isChecked())
280  {
281  ui_->slider_->setValue((ui_->slider_->value() + 1) % ui_->slider_->maximum());
282  QTimer::singleShot(1. / ui_->fps_->value() * 1000, this, SLOT(updateAnimate()));
283  }
284 }
285 
287 {
288  // SE2EZ_DEBUG("CSpacePanel::updatePlanState()");
289 
290  {
291  // std::unique_lock<std::mutex> slock(mutex_);
292 
293  if (jp_ && path_.size() && ui_->slider_->value() < (int)path_.size())
294  jp_->setState(path_[ui_->slider_->value()]);
295  }
296 
297  // SE2EZ_DEBUG("exiting CSpacePanel::updatePlanState()");
298 }
299 
301 {
302  // SE2EZ_DEBUG("CSpacePanel::updatePanel()");
303 
304  {
306  if (jp_)
307  QObject::disconnect(jpc_);
308 
309  jp_ = nullptr;
310  if (ui_->states_->currentIndex() != 0)
311  {
312  const std::string &name = ui_->states_->currentText().toStdString();
313  if (panelnames_.find(name) != panelnames_.end())
314  {
315  auto entry = panels->find(name);
316  jp_ = dynamic_cast<gui::JointPanel *>(entry->second);
317  jpc_ = connect(jp_, SIGNAL(stateChanged()), this, SLOT(updateImage()));
318  }
319  }
320  }
321 
322  update();
323  updateImage(true);
324 }
325 
327 {
328  // SE2EZ_DEBUG("CSpacePanel::updateImage()");
329 
331 
332  if (jp_)
333  {
335 
336  Eigen::VectorXd a = tempState_->data;
337  Eigen::VectorXd b = state_->data;
338 
339  state_->copy(tempState_);
340 
341  if (not force)
342  {
343  // Efficiency check. Don't need to recompute if we only vary along axes we've already computed.
344  // TODO: Maybe move this to CSpaceGrid itself
345  unsigned int ja = ui_->jointA_->currentIndex();
346  unsigned int jb = ui_->jointB_->currentIndex();
347  a[ja] = b[ja] = a[jb] = b[jb] = 0;
348 
349  if ((a - b).norm() <= math::eps)
350  return;
351  }
352  }
353 
354  if (grid_)
355  {
356  grid_->compute(false, state_, callback_);
357  imageGen_ = true;
358  }
359 }
360 
362 {
363  // SE2EZ_DEBUG("CSpacePanel::updateGrid()");
364 
365  {
367  unsigned int ja = ui_->jointA_->currentIndex();
368  unsigned int jb = ui_->jointB_->currentIndex();
369  SE2EZ_INFORM("Updating grid with indices %1% and %2%", ja, jb);
370 
371  xCurSize_ = xSize_ * ((ui_->hires_->isChecked()) ? HiRes_ : 1);
372  yCurSize_ = ySize_ * ((ui_->hires_->isChecked()) ? HiRes_ : 1);
373  grid_ = std::make_shared<CSpaceGrid>(robot_, ja, jb, xCurSize_, yCurSize_, getMode());
374  image_ = QImage(xCurSize_, yCurSize_, QImage::Format_RGB32);
375 
376  update();
377  }
378 
379  updateImage(true);
380 }
381 
383 {
384  for (unsigned int i = 0; i < wheelSize_; ++i)
385  {
386  auto *line = (QRgb *)wheel_.scanLine(i);
387  for (unsigned int j = 0; j < wheelSize_; ++j)
388  {
389  double r, g, b;
390  double x = i - wheelSize_ / 2.;
391  double y = (wheelSize_ - j) - wheelSize_ / 2.;
392  double d = std::sqrt(std::pow(x, 2) + std::pow(y, 2)) / (wheelSize_ / 2.);
393  if (d <= 1)
394  {
395  hsv2rgb(std::atan2(y, x), d, 1, r, g, b);
396  line[j] = QColor(255. * r, 255. * g, 255. * b).rgb();
397  }
398  else
399  line[j] = QColor(255, 255, 255).rgb();
400  }
401  }
402 }
403 
405 {
406  if (lockedProjection() && robot_->inLimits(tempState_) && jp_)
408 }
409 
411 {
412  unsigned int iter = 0;
413  double norm = 0;
414 
415  Eigen::VectorXd f(constraint_->getCoDimension());
416  Eigen::MatrixXd j(constraint_->getCoDimension(), constraint_->getAmbientDimension());
417 
418  unsigned int ja = ui_->jointA_->currentIndex();
419  unsigned int jb = ui_->jointB_->currentIndex();
420 
421  constraint_->function(tempState_->data, f);
422  while ((norm = f.norm()) > constraint_->getTolerance() && iter++ < 50)
423  {
424  constraint_->jacobian(tempState_->data, j);
425  Eigen::VectorXd temp = j.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(f);
426  tempState_->data[ja] -= 0.5 * temp[ja];
427  tempState_->data[jb] -= 0.5 * temp[jb];
428  constraint_->function(tempState_->data, f);
429  }
430 
431  return norm < constraint_->getTolerance();
432 }
433 
435 {
436  // SE2EZ_DEBUG("CSpacePanel::updateCallback()");
437 
438  {
440 
441  imageGen_ = false;
442  grid_->cancel();
443  grid_->waitToComplete();
444 
445  if (ui_->constraints_->currentIndex() != 0)
446  {
447  const auto constraint = constraint_ =
448  constraints_.find(ui_->constraints_->currentText().toStdString())->second;
449  unsigned int exp = ui_->constraintPow_->value();
450  double max = ui_->constraintMax_->value();
451  bool jac = ui_->jacobian_->isChecked();
452  bool drawC = ui_->constraintCollisions_->isChecked();
453  unsigned int ja = ui_->jointA_->currentIndex();
454  unsigned int jb = ui_->jointB_->currentIndex();
455 
456  callback_ = [constraint, exp, max, jac, drawC, ja, jb](ompl::PPM::Color &pixel,
457  const StatePtr &state, bool collision) {
458  bool draw = true;
459  double r, g, b;
460  if (not jac)
461  {
462  Eigen::VectorXd f(constraint->getCoDimension());
463  constraint->function(state->data, f);
464  double v = f.norm();
465  if (v < max)
466  {
467  // const double va = max;
468  // static const double vb = 1e-8;
469  double nv = math::remap(max, 0, v, 0, 1);
470  plasma(std::pow(nv, exp), r, g, b);
471  }
472  else
473  draw = false;
474  }
475  else
476  {
477  const double max = 2.;
478  Eigen::MatrixXd j(constraint->getCoDimension(), constraint->getAmbientDimension());
479  constraint->jacobian(state->data, j);
480  double x = j(0, ja);
481  double y = j(0, jb);
482  double t = std::atan2(y, x);
483 
484  double n = std::sqrt(std::pow(x, 2) + std::pow(y, 2));
485  n = math::clamp(n, 0., max);
486  double s = math::remap(0, max, n, 0, 1);
487 
488  hsv2rgb(t, s, 1, r, g, b);
489  }
490 
491  if (draw)
492  {
493  if (collision and drawC)
494  {
495  toGrayscale(r, g, b);
496  r /= 2.;
497  g /= 2.;
498  b /= 2.;
499  }
500 
501  r *= 255;
502  g *= 255;
503  b *= 255;
504 
505  pixel = ompl::PPM::Color{(unsigned char)r, (unsigned char)g, (unsigned char)b};
506  }
507  };
508  }
509  else
510  {
511  constraint_ = nullptr;
512  callback_ = {};
513  }
514  }
515 
516  updateImage(true);
517 }
518 
519 void gui::CSpacePanel::draw(QPainter &painter, RenderArea * /*canvas*/)
520 {
521  // SE2EZ_DEBUG("CSpacePanel::draw()");
522 
523  if (!ui_->display_->isChecked())
524  return;
525 
527 
528  painter.save();
529  painter.resetTransform();
530 
531  if (ui_->fullscreen_->isChecked() && not ui_->hires_->isChecked())
532  painter.scale(3., 3.);
533 
534  QPoint p(xOffset_, yOffset_);
535  painter.fillRect(xOffset_ - xBorder_, yOffset_ - yBorder_, //
536  xCurSize_ + xBorder_ * 2, yCurSize_ + yBorder_ * 2, QColor(255, 0, 0));
537 
538  painter.drawImage(p, image_);
539 
540  QPen pen(QColor(255, 0, 0));
541  painter.setPen(pen);
542 
543  painter.drawText(xOffset_ + xCurSize_ + xBorder_ + 3, yOffset_ + yText_, ui_->jointA_->currentText());
544  painter.drawText(xOffset_, yOffset_ + yCurSize_ + yBorder_ + yText_, ui_->jointB_->currentText());
545 
546  drawGraph(painter, grid_, true);
547  drawPlan(painter, grid_, true, ui_->hires_->isChecked());
548  drawState(painter, grid_, true);
549 
550  painter.restore();
551 }
552 
553 void gui::CSpacePanel::drawGraph(QPainter &painter, CSpaceGridPtr &grid, bool offset)
554 {
555  bool edges = ui_->edges_->isChecked();
556  bool states = ui_->graph_->isChecked();
557 
558  if (pp_ && pd_ && (edges || states))
559  {
560  unsigned int xo = ((offset) ? xOffset_ : 0);
561  unsigned int yo = ((offset) ? yOffset_ : 0);
562 
563  for (unsigned int i = 0; i < pd_->numVertices(); ++i)
564  {
565  const auto &vert = pd_->getVertex(i);
566  const auto &state = vert.getState()->as<plan::StateSpace::StateType>()->state;
567 
568  QColor color(0, 255, 164);
569  if (vert.getTag() == 2)
570  color = QColor(0, 164, 255);
571 
572  QPen pen(color);
573  painter.setPen(pen);
574 
575  if (states)
576  {
577  auto c = grid->getCoords(state);
578  unsigned int x = xo + c.y - xPoint_ / 2.;
579  unsigned int y = yo + (grid->getHeight() - c.x) - yPoint_ / 2.;
580 
581  painter.fillRect(x, y, xPoint_, yPoint_, color);
582  }
583 
584  if (edges)
585  {
587  unsigned int m = pd_->getEdges(i, edge);
588 
589  for (unsigned int j = 0; j < m; ++j)
590  {
591  const auto &next =
592  pd_->getVertex(edge[j]).getState()->as<plan::StateSpace::StateType>()->state;
593 
594  auto lines = grid->getLines(state, next);
595 
596  for (const auto &line : lines)
597  {
598  unsigned int cx = xo + line.a.y;
599  unsigned int cy = yo + (grid->getHeight() - line.a.x);
600 
601  unsigned int dx = xo + line.b.y;
602  unsigned int dy = yo + (grid->getHeight() - line.b.x);
603 
604  painter.drawLine(cx, cy, dx, dy);
605  }
606  }
607  }
608  }
609  }
610 }
611 
612 void gui::CSpacePanel::drawPlan(QPainter &painter, CSpaceGridPtr &grid, bool offset, bool bold)
613 {
614  bool edges = ui_->plan_->isChecked();
615  bool states = ui_->waypoints_->isChecked();
616  if (pp_ && (edges || states))
617  {
618  QColor color(255, 164, 0);
619  QPen pen(color);
620  if (bold)
621  pen.setWidth(3);
622  painter.setPen(pen);
623 
624  unsigned int xo = ((offset) ? xOffset_ : 0);
625  unsigned int yo = ((offset) ? yOffset_ : 0);
626 
627  for (unsigned int i = 0; i < path_.size(); ++i)
628  {
629  const auto &state = path_[i];
630 
631  if (states)
632  {
633  auto c = grid->getCoords(state);
634  unsigned int x = xo + c.y - xPoint_ / 2.;
635  unsigned int y = yo + (grid->getHeight() - c.x) - yPoint_ / 2.;
636 
637  painter.fillRect(x, y, xPoint_, yPoint_, color);
638  }
639 
640  if (edges)
641  {
642  if (i < path_.size() - 1)
643  {
644  const auto &next = path_[i + 1];
645  auto lines = grid->getLines(state, next);
646 
647  for (const auto &line : lines)
648  {
649  unsigned int cx = xo + line.a.y;
650  unsigned int cy = yo + (grid->getHeight() - line.a.x);
651 
652  unsigned int dx = xo + line.b.y;
653  unsigned int dy = yo + (grid->getHeight() - line.b.x);
654 
655  painter.drawLine(cx, cy, dx, dy);
656  }
657  }
658  }
659  }
660  }
661 }
662 
663 void gui::CSpacePanel::drawState(QPainter &painter, CSpaceGridPtr &grid, bool offset, bool interface)
664 {
665  if (jp_ && ui_->state_->isChecked())
666  {
667  QPen pen(QColor(255, 0, 0));
668  painter.setPen(pen);
669 
670  unsigned int xo = ((offset) ? xOffset_ : 0);
671  unsigned int yo = ((offset) ? yOffset_ : 0);
672 
673  auto c = grid->getCoords(state_);
674  unsigned int x = xo + c.y - xPoint_ / 2.;
675  unsigned int y = yo + (grid->getHeight() - c.x) - yPoint_ / 2.;
676 
677  painter.fillRect(x - xPoint_ / 2., y - yPoint_ / 2., xPoint_, yPoint_, QColor(255, 0, 0));
678 
679  if (constraint_)
680  {
681  if (interface)
682  {
683  double ws = wheelSize_ / 2.;
684  int xw = xOffset_ + xCurSize_ + xBorder_ + 3;
685  int yw = yOffset_ + yCurSize_ - wheelSize_ - yText_ - 3;
686  QPoint p(xw, yw);
687  painter.drawImage(p, wheel_);
688 
689  Eigen::MatrixXd j(constraint_->getCoDimension(), constraint_->getAmbientDimension());
690  constraint_->jacobian(state_->data, j);
691 
692  double xj = j(0, ui_->jointA_->currentIndex());
693  double yj = j(0, ui_->jointB_->currentIndex());
694  double xn = math::remap(-2, 2, xj, -ws, ws);
695  double yn = math::remap(-2, 2, yj, -ws, ws);
696  xn = math::clamp(xn, -ws, ws);
697  yn = math::clamp(yn, -ws, ws);
698 
699  double d = constraint_->distance(state_->data);
700  QString s(log::format("||F(q)||: %1$0.5f", d).c_str());
701  painter.drawText(xOffset_ + xCurSize_ + xBorder_ + 3, yOffset_ + yCurSize_, s);
702 
703  painter.save();
704  QPen pen(QColor(0, 0, 0, 100));
705  pen.setWidth(3);
706  painter.setPen(pen);
707 
708  painter.drawLine(xw + ws, yw + ws, //
709  xw + ws - yn, yw + ws + xn);
710  painter.restore();
711  }
712 
713  if (ui_->project_->isChecked())
714  {
715  if (lockedProjection() and robot_->inLimits(tempState_))
716  {
717  auto d = grid->getCoords(tempState_);
718  unsigned int xp = xo + d.y - xPoint_ / 2.;
719  unsigned int yp = yo + (grid->getHeight() - d.x) - yPoint_ / 2.;
720 
721  painter.drawLine(x, y, xp, yp);
722  painter.fillRect(xp - xPoint_ / 2., yp - yPoint_ / 2., xPoint_, yPoint_,
723  QColor(255, 0, 0));
724  }
725  }
726  }
727  }
728 }
729 
730 bool gui::CSpacePanel::click(QMouseEvent * /*event*/, double /*x*/, double /*y*/, int sx, int sy)
731 {
732  // SE2EZ_DEBUG("CSpacePanel::click()");
733 
734  if (jp_ && ui_->state_->isChecked())
735  {
736  unsigned int i = 0, j = 0;
737  if (sx >= (int)xOffset_)
738  {
739  i = sx - xOffset_;
740  if (ui_->fullscreen_->isChecked() && not ui_->hires_->isChecked())
741  i = std::round(i / 3.) - 3;
742  }
743 
744  if (sy >= (int)yOffset_)
745  {
746  j = sy - yOffset_;
747  if (ui_->fullscreen_->isChecked() && not ui_->hires_->isChecked())
748  j = std::round(j / 3.) - 3;
749  }
750 
751  if (i <= xCurSize_ && j <= yCurSize_)
752  {
753  unsigned int jai = ui_->jointA_->currentIndex();
754  unsigned int jbi = ui_->jointB_->currentIndex();
755 
756  auto jab = grid_->getCoords(yCurSize_ - j, i);
757 
758  state_->data[jai] = jab.x;
759  state_->data[jbi] = jab.y;
760 
761  jp_->setState(state_);
762 
763  return true;
764  }
765  }
766 
767  return false;
768 }
769 
770 void gui::CSpacePanel::update(boost::posix_time::ptime /*last*/, boost::posix_time::ptime /*current*/)
771 {
772  // SE2EZ_DEBUG("CSpacePanel::update()");
773 
774  if (imageGen_)
775  {
776  emit stateChanged();
777  if (not grid_->isComputing())
778  imageGen_ = false;
779 
780  // Lock to write image
782 
783  // Copy image contents to QImage that will be blit
784  auto cs = grid_->getImage();
785  for (unsigned int i = 0; i < xCurSize_; ++i)
786  {
787  auto *line = (QRgb *)image_.scanLine(i);
788  for (unsigned int j = 0; j < yCurSize_; ++j)
789  {
790  auto px = cs->getPixel(xCurSize_ - i - 1, j);
791  line[j] = QColor(px.red, px.green, px.blue).rgb();
792  }
793  }
794  }
795 
796  bool update = false;
797 
798  // Storing the states from joint panels
799  for (const auto &panel : *panels)
800  {
801  if (panelnames_.emplace(panel.first).second) // If new panel was added
802  {
803  auto jpanel = dynamic_cast<gui::JointPanel *>(panel.second); // check if it is jpanel
804  if (jpanel)
805  {
806  // If the joint panel controls the robot
807  if (jpanel->getSignature().compare(robot_->getSignature()) == 0)
808  {
809  jnames_.emplace(panel.first);
810  update = true;
811  }
812  }
813 
814  auto ppanel = dynamic_cast<gui::PlanPanel *>(panel.second); // check if it is jpanel
815  if (ppanel)
816  {
817  // TODO: Fix
818  // If the joint panel controls the robot
819  // if (jpanel->getSignature().compare(robot_->getSignature()) == 0)
820  // {
821  pnames_.emplace(panel.first);
822  update = true;
823  // }
824  }
825  }
826  }
827 
828  // update
829  if (update)
830  {
831  ui_->states_->clear();
832  ui_->planpanels_->clear();
833 
834  // Adding the named states
835  ui_->states_->addItem("<none>");
836  for (const auto &name : jnames_)
837  ui_->states_->addItem(QString(name.c_str()));
838 
839  if (jnames_.size())
840  ui_->states_->setCurrentIndex(1);
841 
842  // Adding the plans
843  ui_->planpanels_->addItem("<none>");
844  for (const auto &name : pnames_)
845  ui_->planpanels_->addItem(QString(name.c_str()));
846 
847  if (pnames_.size())
848  ui_->planpanels_->setCurrentIndex(1);
849  }
850 }
void draw(QPainter &painter, RenderArea *canvas) override
void plasma(double s, double &r, double &g, double &b)
Maps a scalar s in [0, 1] to the Plasma colormap.
Definition: colormap.cpp:324
A shared pointer wrapper for se2ez::State.
std::set< std::string > pnames_
Definition: cspacepanel.h:107
unsigned int xCurSize_
Definition: cspacepanel.h:91
CSpacePanel(RobotPtr robot, std::string name, std::map< std::string, ompl::base::ConstraintPtr > constraints={}, QWidget *parent=0)
Definition: cspacepanel.cpp:26
A representation of a state of a Robot.
Definition: state.h:28
const unsigned int xSize_
Definition: cspacepanel.h:89
Definition: cspacepanel.h:22
void setState(const StatePtr &state)
Definition: jointpanel.cpp:92
const unsigned int HiRes_
Definition: cspacepanel.h:94
const unsigned int ySize_
Definition: cspacepanel.h:90
ompl::base::ConstraintPtr constraint_
Definition: cspacepanel.h:123
double clamp(double v, double a, double b)
Clamp a value v between a range [a, b].
Definition: math.cpp:179
T end(T... args)
const unsigned int wheelSize_
Definition: cspacepanel.h:95
Mode
Drawing mode for the grid.
Definition: cspace.h:63
QMetaObject::Connection jpc_
Definition: cspacepanel.h:114
void drawState(QPainter &painter, CSpaceGridPtr &grid, bool offset, bool interface=true)
T atan2(T... args)
const unsigned int xPoint_
Definition: cspacepanel.h:83
#define SE2EZ_INFORM(fmt,...)
Definition: log.h:43
const unsigned int yOffset_
Definition: cspacepanel.h:86
const unsigned int xBorder_
Definition: cspacepanel.h:87
std::vector< StatePtr > path_
Definition: cspacepanel.h:118
std::set< std::string > panelnames_
Definition: cspacepanel.h:108
T join(T... args)
static const double eps
Definition: math.h:36
void updateImage(bool force=false)
ompl::base::PlannerDataPtr getPlannerData()
Definition: planpanel.cpp:358
A shared pointer wrapper for se2ez::CSpaceGrid.
const unsigned int xOffset_
Definition: cspacepanel.h:85
void drawGraph(QPainter &painter, CSpaceGridPtr &grid, bool offset)
T clear(T... args)
void getState(StatePtr state)
Definition: jointpanel.cpp:101
ompl::base::PlannerDataPtr pd_
Definition: cspacepanel.h:120
const unsigned int yText_
Definition: cspacepanel.h:93
const unsigned int yPoint_
Definition: cspacepanel.h:84
T find(T... args)
unsigned int yCurSize_
Definition: cspacepanel.h:92
QString name
Definition: panel.h:45
MainWindow::PanelMapPtr panels
Definition: panel.h:46
const unsigned int yBorder_
Definition: cspacepanel.h:88
CSpaceGrid::Mode getMode() const
T pow(T... args)
Use viridis color palette for signed distance.
Definition: cspace.h:67
Draw collisions as black pixels.
Definition: cspace.h:65
A shared pointer wrapper for se2ez::Robot.
T c_str(T... args)
std::string format(const std::string &fmt, Args &&... args)
Definition: log.h:25
QMetaObject::Connection pdc_
Definition: cspacepanel.h:116
void hsv2rgb(double h, double s, double v, double &r, double &g, double &b)
Convert a RGB color to HSV.
Definition: colormap.cpp:387
std::set< std::string > jnames_
Definition: cspacepanel.h:106
T emplace(T... args)
Signed distance, but penetrations are colored by geometry.
Definition: cspace.h:68
The canvas widget. It contains all the drawing functions as well as all the general settings for draw...
Definition: renderarea.h:48
Color obstacles by geometry color.
Definition: cspace.h:66
Main namespace.
Definition: collision.h:11
T sqrt(T... args)
const std::vector< StatePtr > & getPath() const
Definition: planpanel.cpp:353
bool click(QMouseEvent *event, double x, double y, int sx, int sy) override
double remap(double a1, double a2, double av, double b1, double b2)
Remap a value av in the interval a1, a2 to the interval b1, b2.
Definition: math.cpp:160
QMetaObject::Connection ppc_
Definition: cspacepanel.h:115
void drawPlan(QPainter &painter, CSpaceGridPtr &grid, bool offset, bool bold)
T round(T... args)
CSpaceGrid::GridCallback callback_
Definition: cspacepanel.h:124
Ui::CSpacePanel * ui_
Definition: cspacepanel.h:97
std::map< std::string, ompl::base::ConstraintPtr > constraints_
Definition: cspacepanel.h:122
void toGrayscale(double &r, double &g, double &b)
Maps an RGB color to a greyscale color based on luminosity.
Definition: colormap.cpp:341