Robowflex  v0.1
Making MoveIt Easy
gui.cpp
Go to the documentation of this file.
1 /* Author: Zachary Kingston */
2 
3 #include <condition_variable>
4 #include <mutex>
5 
6 #include <boost/uuid/uuid.hpp> // for UUID generation
7 #include <boost/uuid/uuid_generators.hpp> // for UUID generation
8 #include <boost/uuid/uuid_io.hpp> // for UUID generationinclude <condition_variable>
9 
11 
12 #include <robowflex_dart/gui.h>
13 
15 using namespace robowflex::darts;
16 
18 {
19  boost::uuids::random_generator gen;
20  boost::uuids::uuid u = gen();
21  return boost::lexical_cast<std::string>(u);
22 }
23 
24 //
25 // Viewer
26 //
27 
28 Viewer::Viewer(const WorldPtr &world)
29  : dart::gui::osg::ImGuiViewer(::osg::Vec4(1.0, 1.0, 1.0, 1.0)), world_(world)
30 {
31 }
32 
34 {
35  // world_->lock();
36  osgViewer::Viewer::updateTraversal();
37  // world_->unlock();
38 }
39 
40 //
41 // Window::InteractiveOptions
42 //
43 
45 {
46  linear[0] = false;
47  linear[1] = false;
48  linear[2] = false;
49 }
50 
52 {
53  rotation[0] = false;
54  rotation[1] = false;
55  rotation[2] = false;
56 }
57 
59 {
60  planar[0] = false;
61  planar[1] = false;
62  planar[2] = false;
63 }
64 
66 {
67  disableLinearControls();
68  disableRotationControls();
69  disablePlanarControls();
70 }
71 
72 //
73 // Window
74 //
75 
76 Window::Window(const WorldPtr &world)
77  : dart::gui::osg::WorldNode(world->getSim()), world_(world), viewer_(world)
78 {
79  node_ = this;
80  viewer_.addWorldNode(node_);
81  viewer_.setUpViewInWindow(0, 0, 1080, 720);
82  auto *cm = viewer_.getCameraManipulator();
83  cm->setHomePosition( //
84  ::osg::Vec3(5.00, 5.00, 2.00), //
85  ::osg::Vec3(0.00, 0.00, 0.00), //
86  ::osg::Vec3(-0.24, -0.25, 0.94));
87  viewer_.setCameraManipulator(cm);
88  viewer_.setVerticalFieldOfView(15);
89 
90  widget_ = std::make_shared<WindowWidget>();
92 }
93 
95 {
96  // world_->lock();
97  for (const auto &widget : widgets_)
98  widget->prerefresh();
99 }
100 
102 {
103  // world_->unlock();
104 }
105 
106 void Window::addWidget(const WidgetPtr &widget)
107 {
108  widgets_.emplace_back(widget);
109  widget->initialize(const_cast<Window *>(this));
110  viewer_.getImGuiHandler()->addWidget(widget);
111 }
112 
114 {
116  r.target = std::make_shared<dart::gui::osg::InteractiveFrame>( //
117  options.parent, options.name, options.pose, options.size, options.thickness);
118  world_->getSim()->addSimpleFrame(r.target);
119 
120  for (std::size_t i = 0; i < 3; ++i)
121  {
122  auto *lt = r.target->getTool(dart::gui::osg::InteractiveTool::Type::LINEAR, i);
123  lt->setEnabled(options.linear[i]);
124  auto *rt = r.target->getTool(dart::gui::osg::InteractiveTool::Type::ANGULAR, i);
125  rt->setEnabled(options.rotation[i]);
126  auto *pt = r.target->getTool(dart::gui::osg::InteractiveTool::Type::PLANAR, i);
127  pt->setEnabled(options.planar[i]);
128  }
129 
130  r.dnd = viewer_.enableDragAndDrop(r.target.get());
131  r.dnd->setObstructable(options.obstructable);
132 
133  auto callback = options.callback;
134  r.signal = r.target->onTransformUpdated.connect([callback](const dart::dynamics::Entity *entity) {
135  if (entity)
136  {
137  const auto *cast = dynamic_cast<const dart::gui::osg::InteractiveFrame *>(entity);
138  if (cast and callback)
139  callback(cast);
140  }
141  });
142 
143  return r;
144 }
145 
146 Window::DnDReturn Window::enableNodeDragNDrop(dart::dynamics::BodyNode *node, const DnDCallback &callback)
147 {
148  DnDReturn r;
149  auto *dnd = viewer_.enableDragAndDrop(node, true, true);
150  r.dnd = dnd;
151 
152  r.signal = node->onTransformUpdated.connect([dnd, callback](const dart::dynamics::Entity *entity) {
153  if (dnd->isMoving())
154  callback(dynamic_cast<const dart::dynamics::BodyNode *>(entity));
155  });
156 
157  return r;
158 }
159 
160 void Window::animatePath(const StateSpacePtr &space, const ompl::geometric::PathGeometric &path,
161  std::size_t times, double fps, bool block)
162 {
163  bool active = true;
164 
165  std::mutex m;
167 
168  if (animation_)
169  {
170  animation_->join();
171  animation_.reset();
172  }
173  auto thread = std::make_shared<std::thread>([&] {
174  std::size_t n = path.getStateCount();
175  std::size_t i = times;
176 
178  while ((times == 0) ? true : i--)
179  {
180  space->setWorldState(world_, path.getState(0));
182 
183  for (std::size_t j = 0; j < n; ++j)
184  {
185  space->setWorldState(world_, path.getState(j));
186 
187  std::this_thread::sleep_for(std::chrono::milliseconds((unsigned int)(1000 / fps)));
188  }
189 
191  }
192 
193  active = false;
194  cv.notify_one();
195  });
196 
197  animation_ = thread;
198 
199  if (block)
200  {
202  cv.wait(lk, [&] { return not active; });
203  }
204 }
205 
206 void Window::animatePath(const PlanBuilder &builder, const ompl::geometric::PathGeometric &path,
207  std::size_t times, double fps, bool block)
208 {
209  ompl::geometric::PathGeometric extract(builder.rinfo);
210  for (std::size_t i = 0; i < path.getStateCount(); ++i)
211  extract.append(builder.toStateConst(path.getState(i)));
212 
213  animatePath(builder.rspace, extract, times, fps, block);
214 }
215 
217 {
218  return widget_;
219 }
220 
222 {
223  return world_;
224 }
225 
227 {
228  return world_;
229 }
230 
231 void Window::run(std::function<void()> thread)
232 {
233  if (thread)
234  {
235  std::thread t(thread);
236  viewer_.run();
237  }
238  else
239  viewer_.run();
240 }
241 
242 //
243 // Widget
244 //
245 
246 void Widget::initialize(Window * /*window*/)
247 {
248 }
249 
251 {
252 }
253 
254 //
255 // Window Widget
256 //
257 
258 TextElement::TextElement(const std::string &text) : text(text)
259 {
260 }
261 
263 {
264  ImGui::Text("%s", text.c_str());
265 }
266 
267 CheckboxElement::CheckboxElement(const std::string &text, bool &boolean) : text(text), boolean(boolean)
268 {
269 }
270 
272 {
273  ImGui::Checkbox(text.c_str(), &boolean);
274 }
275 
277  : text(text), callback(callback)
278 {
279 }
280 
282 {
283  const auto &button = ImGui::Button(text.c_str());
284  if (button)
285  callback();
286 }
287 
289 {
290 }
291 
293 {
294  if (callback)
295  callback();
296 }
297 
299 {
300  float avg = 0.;
301  for (std::size_t i = 0; i < total_elements; ++i)
302  avg += elements[i];
303  avg /= (float)max_size;
304  return avg;
305 }
306 
308 {
309  float min = (total_elements) ? std::numeric_limits<float>::max() : 0;
310  for (std::size_t i = 0; i < total_elements; ++i)
311  min = (min > elements[i]) ? elements[i] : min;
312  return min;
313 }
314 
316 {
317  float max = 0.;
318  for (std::size_t i = 0; i < total_elements; ++i)
319  max = (max < elements[i]) ? elements[i] : max;
320  return max;
321 }
322 
324 {
326  if (index >= max_size)
327  index = 0;
328 
329  if (total_elements > max_size)
331 
332  latest = elements[index++] = x;
333  index = index % max_size;
334 
335  if (total_elements < max_size)
336  total_elements++;
337 }
338 
340 {
341  ImGui::PushID(id.c_str());
342  ImGui::PushStyleColor(ImGuiCol_PlotLines,
343  (ImVec4)ImColor((float)color[0], (float)color[1], (float)color[2]));
344 
345  char overlay[64] = "N/A";
346  if (total_elements)
347  sprintf(overlay, "%.3f %s", latest, units.c_str());
348 
349  ImGui::PlotLines(label.c_str(), elements.data(), total_elements, index, overlay);
350 
351  ImGui::PopStyleColor(1);
352  ImGui::PopID();
353 
354  if (show_min)
355  ImGui::Text("min: %.3f %s", minimum(), units.c_str());
356  if (show_avg)
357  ImGui::Text("avg: %.3f %s", average(), units.c_str());
358  if (show_max)
359  ImGui::Text("max: %.3f %s", maximum(), units.c_str());
360 }
361 
363 {
364 }
365 
367 {
368  if (elements_.empty())
369  return;
370 
371  ImGui::SetNextWindowBgAlpha(0.5f);
372  if (!ImGui::Begin("Robowflex DART", nullptr,
373  ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_HorizontalScrollbar))
374  {
375  ImGui::End();
376  return;
377  }
378 
379  for (const auto &element : elements_)
380  element->render();
381 }
382 
384 {
385  addElement(std::make_shared<TextElement>(text));
386 }
387 
389 {
390  addElement(std::make_shared<ButtonElement>(text, callback));
391 }
392 
393 void WindowWidget::addCheckbox(const std::string &text, bool &boolean)
394 {
395  addElement(std::make_shared<CheckboxElement>(text, boolean));
396 }
397 
399 {
400  addElement(std::make_shared<RenderElement>(callback));
401 }
402 
404 {
405  elements_.push_back(element);
406 }
407 
408 //
409 // TSR Widget
410 //
412  : name_(name), original_(spec), spec_(spec)
413 {
414 }
415 
417 {
418  auto world = window->world_;
419 
420  // Create main interactive marker.
421  Window::InteractiveOptions frame_opt;
422  frame_opt.name = "TSREditWidget-" + name_ + "-frame";
423  frame_opt.pose = spec_.pose;
425  frame_opt.parent = world->getRobot(spec_.base.structure)->getFrame(spec_.base.frame);
426  frame_opt.callback = [&](const dart::gui::osg::InteractiveFrame *frame) { updateFrameCB(frame); };
427  frame_ = window->createInteractiveMarker(frame_opt);
428 
429  // Create offset frame for bound frames.
430  offset_ = std::make_shared<dart::dynamics::SimpleFrame>(dart::dynamics::Frame::World(),
431  "TSREditWidget-" + name_ + "-offset");
432  world->getSim()->addSimpleFrame(offset_);
433 
434  // Create lower bound control.
436  ll_opt.name = "TSREditWidget-" + name_ + "-ll";
437  ll_opt.callback = [&](const dart::gui::osg::InteractiveFrame *frame) { updateLLCB(frame); };
438  ll_opt.parent = offset_.get();
439  ll_opt.rotation[0] = false;
440  ll_opt.rotation[1] = false;
441  ll_opt.rotation[2] = false;
442  ll_opt.planar[0] = false;
443  ll_opt.planar[1] = false;
444  ll_opt.planar[2] = false;
445  ll_opt.size = 0.1;
446  ll_opt.thickness = 2;
447  ll_frame_ = window->createInteractiveMarker(ll_opt);
448 
449  // Create upper bound control.
451  uu_opt.name = "TSREditWidget-" + name_ + "-uu";
452  uu_opt.callback = [&](const dart::gui::osg::InteractiveFrame *frame) { updateUUCB(frame); };
453  uu_opt.parent = offset_.get();
454  uu_opt.rotation[0] = false;
455  uu_opt.rotation[1] = false;
456  uu_opt.rotation[2] = false;
457  uu_opt.planar[0] = false;
458  uu_opt.planar[1] = false;
459  uu_opt.planar[2] = false;
460  uu_opt.size = 0.1;
461  uu_opt.thickness = 2;
462  uu_frame_ = window->createInteractiveMarker(uu_opt);
463 
464  // Create shape frame. Shape is separate since it can be offset from main bound TF.
465  shape_ =
466  std::make_shared<dart::dynamics::SimpleFrame>(offset_.get(), "TSREditWidget-" + name_ + "-shape");
467  world->getSim()->addSimpleFrame(shape_);
468 
469  // Create rotation bounds.
470  for (std::size_t i = 0; i < 3; ++i)
471  {
472  rbounds_[i] = std::make_shared<dart::dynamics::SimpleFrame>(
473  offset_.get(), "TSREditWidget-" + name_ + "-rb" + std::to_string(i));
474 
475  Eigen::Isometry3d tf = Eigen::Isometry3d::Identity();
476  if (i == 1)
477  tf.rotate(Eigen::AngleAxisd(-constants::half_pi, Eigen::Vector3d::UnitZ()));
478  else if (i == 2)
479  tf.rotate(Eigen::AngleAxisd(constants::half_pi, Eigen::Vector3d::UnitY()));
480 
481  rbounds_[i]->setRelativeTransform(tf);
482  world->getSim()->addSimpleFrame(rbounds_[i]);
483  }
484 
485  // Create TSR.
486  tsr_ = std::make_shared<darts::TSR>(world, spec_);
487  tsr_->initialize();
488 
489  // Synchronize elements.
490  syncGUI();
491  syncFrame();
492  updateShape();
493 }
494 
496 {
497  frame_.target->setRelativeTransform(spec_.pose);
498  offset_->setTranslation(frame_.target->getWorldTransform().translation());
499  ll_frame_.target->setRelativeTranslation(spec_.position.lower);
500  uu_frame_.target->setRelativeTranslation(spec_.position.upper);
501 }
502 
504 {
505  tsr_->getSpecification() = spec_;
506  tsr_->updatePose();
507  tsr_->updateBounds();
508  tsr_->updateSolver();
509 }
510 
512 {
515 
516  spec_.setXPosTolerance(xp_[0], xp_[1]);
517  spec_.setYPosTolerance(yp_[0], yp_[1]);
518  spec_.setZPosTolerance(zp_[0], zp_[1]);
519 
520  spec_.setXRotTolerance(xr_[0], xr_[1]);
521  spec_.setYRotTolerance(yr_[0], yr_[1]);
522  spec_.setZRotTolerance(zr_[0], zr_[1]);
523 
524  updateMirror();
525  syncTSR();
526 }
527 
529 {
530  auto pos = spec_.getPosition();
531  position_[0] = pos[0];
532  position_[1] = pos[1];
533  position_[2] = pos[2];
534 
535  auto rot = spec_.getEulerRotation();
536  rotation_[0] = rot[0];
537  rotation_[1] = rot[1];
538  rotation_[2] = rot[2];
539 
540  xp_[0] = spec_.position.lower[0];
541  xp_[1] = spec_.position.upper[0];
542  yp_[0] = spec_.position.lower[1];
543  yp_[1] = spec_.position.upper[1];
544  zp_[0] = spec_.position.lower[2];
545  zp_[1] = spec_.position.upper[2];
546 
547  xr_[0] = spec_.orientation.lower[0];
548  xr_[1] = spec_.orientation.upper[0];
549  yr_[0] = spec_.orientation.lower[1];
550  yr_[1] = spec_.orientation.upper[1];
551  zr_[0] = spec_.orientation.lower[2];
552  zr_[1] = spec_.orientation.upper[2];
553 }
554 
555 void TSREditWidget::updateFrameCB(const dart::gui::osg::InteractiveFrame *frame)
556 {
557  if (gui_)
558  return;
559 
560  prev_ = spec_;
561  const auto &tf = frame->getRelativeTransform();
562  spec_.pose = tf;
563 
564  updateMirror();
565  syncGUI();
566  syncTSR();
567 }
568 
569 void TSREditWidget::updateLLCB(const dart::gui::osg::InteractiveFrame *frame)
570 {
571  if (gui_)
572  return;
573 
574  Eigen::Vector3d t = frame->getRelativeTransform().translation();
575  Eigen::Vector3d diff =
576  (sync_bounds_) ? Eigen::Vector3d(t - spec_.position.lower) : Eigen::Vector3d::Zero();
577 
578  spec_.setXPosTolerance(t[0], spec_.position.upper[0] - diff[0]);
579  spec_.setYPosTolerance(t[1], spec_.position.upper[1] - diff[1]);
580  spec_.setZPosTolerance(t[2], spec_.position.upper[2] - diff[2]);
581 
582  syncGUI();
583  syncTSR();
584 }
585 
586 void TSREditWidget::updateUUCB(const dart::gui::osg::InteractiveFrame *frame)
587 {
588  if (gui_)
589  return;
590 
591  Eigen::Vector3d t = frame->getRelativeTransform().translation();
592  Eigen::Vector3d diff =
593  (sync_bounds_) ? Eigen::Vector3d(t - spec_.position.upper) : Eigen::Vector3d::Zero();
594 
595  spec_.setXPosTolerance(spec_.position.lower[0] - diff[0], t[0]);
596  spec_.setYPosTolerance(spec_.position.lower[1] - diff[1], t[1]);
597  spec_.setZPosTolerance(spec_.position.lower[2] - diff[2], t[2]);
598 
599  syncGUI();
600  syncTSR();
601 }
602 
604 {
605  if (not sync_bounds_)
606  return;
607 
608  {
609  auto ld = spec_.position.lower - prev_.position.lower;
610  auto ud = spec_.position.upper - prev_.position.upper;
611 
612  spec_.position.lower -= ud;
613  spec_.position.upper -= ld;
614  }
615 
616  {
619 
620  spec_.orientation.lower -= ud;
621  spec_.orientation.upper -= ld;
622  }
623 }
624 
625 Eigen::Vector3d TSREditWidget::getVolume() const
626 {
628 }
629 
631 {
632  // Position volume
633  {
634  Eigen::Vector3d abs = getVolume();
635 
636  shape_->setShape(makeBox(abs));
637  auto *va = shape_->getVisualAspect(true);
638  va->setColor(dart::Color::Gray(volume_alpha_));
639  va->setShadowed(false);
640  va->setHidden(not show_volume_);
641 
642  shape_->setRelativeTranslation(spec_.position.lower + abs / 2);
643  }
644 
645  // Rotation bounds
646  for (std::size_t i = 0; i < 3; ++i)
647  {
650  auto *va = rbounds_[i]->getVisualAspect(true);
651  va->setShadowed(false);
652  va->setHidden(not show_bounds_);
653 
654  if (i == 0)
655  va->setColor(dart::Color::Red(rotation_alpha_));
656  if (i == 1)
657  va->setColor(dart::Color::Green(rotation_alpha_));
658  if (i == 2)
659  va->setColor(dart::Color::Blue(rotation_alpha_));
660  }
661 }
662 
664 {
665  prev_ = spec_; // save previous spec
666 
667  // Draw main window.
668  ImGui::SetNextWindowBgAlpha(0.5f);
669  std::string title = "TSR Editor - " + name_;
670  if (!ImGui::Begin(title.c_str(), nullptr, ImGuiWindowFlags_HorizontalScrollbar))
671  {
672  ImGui::End();
673  return;
674  }
675 
676  // Draw frame position and orientation values.
677  if (ImGui::TreeNodeEx("Frame", ImGuiTreeNodeFlags_DefaultOpen))
678  {
679  ImGui::DragFloat3("Position", position_, drag_step_, -max_position_, max_position_, "%0.2f");
680  ImGui::DragFloat3("Rotation", rotation_, drag_step_, -constants::pi, constants::pi, "%0.2f");
681 
682  if (ImGui::Button("Reset Position"))
683  {
685  syncGUI();
686  }
687 
688  ImGui::SameLine();
689 
690  if (ImGui::Button("Reset Rotation"))
691  {
693  syncGUI();
694  }
695 
696  ImGui::TreePop();
697  }
698 
699  ImGui::Separator();
700  ImGui::Spacing();
701 
702  // Draw TSR bound interface.
703  if (ImGui::TreeNodeEx("Bounds", ImGuiTreeNodeFlags_DefaultOpen))
704  {
705  ImGui::Checkbox("Sync. Bounds", &sync_bounds_);
706  ImGui::Spacing();
707 
708  ImGui::Text("Position Bounds");
709  auto half = max_position_ / 2;
710  ImGui::DragFloat2("X##1", xp_, drag_step_, -half, half, "%0.4f");
711  ImGui::DragFloat2("Y##1", yp_, drag_step_, -half, half, "%0.4f");
712  ImGui::DragFloat2("Z##1", zp_, drag_step_, -half, half, "%0.4f");
713  ImGui::Checkbox("Show Volume", &show_volume_);
714  ImGui::Spacing();
715  ImGui::Spacing();
716 
717  ImGui::Text("Rotation Bounds");
718  ImGui::DragFloat2("X##2", xr_, drag_step_, -constants::pi, constants::pi, "%0.4f");
719  ImGui::DragFloat2("Y##2", yr_, drag_step_, -constants::pi, constants::pi, "%0.4f");
720  ImGui::DragFloat2("Z##2", zr_, drag_step_, -constants::pi, constants::pi, "%0.4f");
721 
722  ImGui::Checkbox("Show Rot. Bounds", &show_bounds_);
723  ImGui::DragFloat("Bound Rad.", &inner_radius, drag_step_, 0., 0.5, "%0.2f");
724 
725  if (ImGui::Button("Reset Bounds"))
726  {
729  prev_ = spec_;
730  syncGUI();
731  }
732 
733  ImGui::TreePop();
734  }
735 
736  if (ImGui::Button("Print TSR"))
738 
739  gui_ = true;
740  syncSpec();
741  syncGUI();
742  syncFrame();
743  gui_ = false;
744 }
745 
747 {
748  updateShape();
749 }
750 
752 {
753  return spec_;
754 }
755 
757 {
758  return tsr_;
759 }
760 
761 //
762 // TSRSolveWidget
763 //
764 
766  : TSRSolveWidget(std::make_shared<TSRSet>(world, tsrs, false))
767 {
768 }
769 
770 TSRSolveWidget::TSRSolveWidget(const TSRSetPtr &tsrs) : tsrs_(tsrs)
771 {
772 }
773 
775 {
776  // Draw main window.
777  ImGui::SetNextWindowBgAlpha(0.5f);
778  std::string title = "TSR Solver";
779  if (!ImGui::Begin(title.c_str(), nullptr, ImGuiWindowFlags_HorizontalScrollbar))
780  {
781  ImGui::End();
782  return;
783  }
784 
785  // Draw TSR solve interface.
786  if (ImGui::TreeNodeEx("Solving", ImGuiTreeNodeFlags_DefaultOpen))
787  {
788  ImGui::Checkbox("Track TSR", &track_tsr_);
789  ImGui::SameLine();
790  ImGui::Checkbox("Use Gradient?", &use_gradient_);
791 
792  ImGui::Columns(2);
793  if (ImGui::SliderInt("Max Iter.", &maxIter_, 1, max_iteration_))
794  {
795  tsrs_->setMaxIterations(maxIter_);
796  tsrs_->updateSolver();
797  }
798  if (ImGui::SliderFloat("Step", &step_, 0.001f, 1.f))
799  tsrs_->setStep(step_);
800 
801  if (ImGui::SliderFloat("Limit", &limit_, 0.001f, 1.f))
802  tsrs_->setLimit(limit_);
803 
804  ImGui::NextColumn();
805  if (ImGui::SliderFloat("Tol.", &tolerance_, 1e-5f, max_tolerance_, "< %.5f", 3.f))
806  {
807  tsrs_->setMaxIterations(tolerance_);
808  tsrs_->updateSolver();
809  }
810 
811  const char *items[] = {"dSVD", "SVD", "QR"};
812  if (ImGui::Combo("combo", &item_, items, IM_ARRAYSIZE(items)))
813  {
814  if (item_ == 0)
815  {
816  tsrs_->useSVD();
817  tsrs_->useDamping(true);
818  }
819  else if (item_ == 1)
820  {
821  tsrs_->useSVD();
822  tsrs_->useDamping(false);
823  }
824  else
825  tsrs_->useQR();
826  }
827 
828  if (ImGui::SliderFloat("Damp.", &damping_, 1e-8f, 1e-3f, "< %.8f", 10.f))
829  tsrs_->setDamping(damping_);
830 
831  ImGui::Columns(1);
832 
833  if (ImGui::Button("Solve TSR"))
834  need_solve_ = true;
835 
836  ImGui::SameLine();
837 
838  if (last_solve_)
839  ImGui::TextColored((ImVec4)ImColor(0.0f, 1.0f, 0.0f), "Success!");
840  else
841  ImGui::TextColored((ImVec4)ImColor(1.0f, 0.0f, 0.0f), "Failure!");
842 
844 
845  ImGui::TreePop();
846  }
847 
848  ImGui::Separator();
849  ImGui::Spacing();
850 
851  // Draw distance tracking information.
852 
853  const auto &tsrs = tsrs_->getTSRs();
854  for (std::size_t i = 0; i < tsrs.size(); ++i)
855  {
856  const auto &tsr = tsrs[i];
857  const auto &spec = tsr->getSpecification();
858 
859  const std::string title = "B:" + spec.base.frame + ":" + spec.base.structure + //
860  " > T:" + spec.target.frame + ":" + spec.target.structure;
861 
862  if (ImGui::TreeNodeEx(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
863  {
864  ImGui::Columns(2);
865  ImGui::Text("Pos. Error");
866  errors_[i].xpd.render();
867  errors_[i].ypd.render();
868  errors_[i].zpd.render();
869  ImGui::NextColumn();
870 
871  ImGui::Text("Rot. Error");
872  errors_[i].xrd.render();
873  errors_[i].yrd.render();
874  errors_[i].zrd.render();
875 
876  ImGui::Columns(1);
877 
878  ImGui::TreePop();
879  }
880  }
881 }
882 
884 {
885  auto start = std::chrono::steady_clock::now();
886 
887  if (use_gradient_)
888  {
889  Eigen::VectorXd world(tsrs_->getWorldIndices().size());
890  tsrs_->getPositionsWorldState(world);
891 
892  last_solve_ = tsrs_->solveGradientWorldState(world);
893  }
894  else
895  last_solve_ = tsrs_->solveWorld();
896 
897  auto end = std::chrono::steady_clock::now();
898 
899  auto time = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
900  solve_time_.addPoint(time);
901 }
902 
904 {
905  // Compute world indices for all TSRs
906  const auto &tsrs = tsrs_->getTSRs();
908  for (const auto &tsr : tsrs)
909  {
911  (tsr->getNumWorldDofs()) ? tsr->getWorldIndices() : tsr->computeWorldIndices();
912 
913  for (const auto &index : wts)
914  wis.emplace(index);
915  }
916 
918  wts.reserve(wis.size());
919  for (const auto &index : wis)
920  wts.emplace_back(index);
921 
922  tsrs_->useWorldIndices(wts);
923  tsrs_->setWorldIndices(wts);
924  tsrs_->computeLimits();
925 
926  tsrs_->initialize();
927 
928  // Setup solve parameters.
929  maxIter_ = tsrs_->getMaxIterations();
930  tolerance_ = tsrs_->getTolerance();
931  step_ = tsrs_->getStep();
932  limit_ = tsrs_->getLimit();
933  damping_ = tsrs_->getDamping();
934 
935  // Setup solve time plots.
936  solve_time_.label = "Solve Time";
937  solve_time_.units = "microsec.";
938  solve_time_.show_min = true;
939  solve_time_.show_max = true;
940  solve_time_.show_avg = true;
941 
942  // Setup error plots.
943  const std::size_t n = tsrs_->numTSRs();
944  errors_.resize(n);
945 
946  for (std::size_t i = 0; i < n; ++i)
947  {
948  errors_[i].xpd.color = Eigen::Vector3d(1, 0, 0);
949  errors_[i].ypd.color = Eigen::Vector3d(0, 1, 0);
950  errors_[i].zpd.color = Eigen::Vector3d(0, 0, 1);
951 
952  errors_[i].xrd.label = "X";
953  errors_[i].xrd.color = Eigen::Vector3d(1, 0, 0);
954  errors_[i].yrd.label = "Y";
955  errors_[i].yrd.color = Eigen::Vector3d(0, 1, 0);
956  errors_[i].zrd.label = "Z";
957  errors_[i].zrd.color = Eigen::Vector3d(0, 0, 1);
958  }
959 }
960 
962 {
963  if (track_tsr_ or need_solve_)
964  solve();
965 
966  need_solve_ = false;
967 
968  const auto &tsrs = tsrs_->getTSRs();
969  for (std::size_t i = 0; i < tsrs.size(); ++i)
970  {
971  Eigen::VectorXd e = Eigen::VectorXd::Zero(6);
972  tsrs[i]->getErrorWorldRaw(e);
973 
974  errors_[i].xrd.addPoint(e[0]);
975  errors_[i].yrd.addPoint(e[1]);
976  errors_[i].zrd.addPoint(e[2]);
977  errors_[i].xpd.addPoint(e[3]);
978  errors_[i].ypd.addPoint(e[4]);
979  errors_[i].zpd.addPoint(e[5]);
980  }
981 }
T c_str(T... args)
const ButtonCallback callback
Callback.
Definition: gui.h:301
ButtonElement(const std::string &text, const ButtonCallback &callback)
Constructor.
Definition: gui.cpp:276
const std::string text
Display text.
Definition: gui.h:300
void render() const override
Render method. Renders IMGUI contents.
Definition: gui.cpp:281
CheckboxElement(const std::string &text, bool &boolean)
Constructor.
Definition: gui.cpp:267
const std::string text
Display text.
Definition: gui.h:279
void render() const override
Render method. Renders IMGUI contents.
Definition: gui.cpp:271
const StateSpace::StateType * toStateConst(const ompl::base::State *state) const
Extract underlying state from a base state.
A shared pointer wrapper for robowflex::darts::WindowWidget::Element.
float minimum() const
Compute the minimum over the data.
Definition: gui.cpp:307
bool show_avg
Display average value under plot.
Definition: gui.h:333
std::vector< float > elements
All data points.
Definition: gui.h:347
std::string units
Plot Units.
Definition: gui.h:330
Eigen::Vector3d color
Color of plot.
Definition: gui.h:336
std::size_t index
Index in data.
Definition: gui.h:345
float latest
Last input data point.
Definition: gui.h:348
float average() const
Compute the average over the data.
Definition: gui.cpp:298
float maximum() const
Compute the maximum over the data.
Definition: gui.cpp:315
void render() const override
Render method. Renders IMGUI contents.
Definition: gui.cpp:339
bool show_min
Display minimum value under plot.
Definition: gui.h:331
void addPoint(float x)
Add a point to the plot data.
Definition: gui.cpp:323
std::size_t total_elements
Total elements inserted in data.
Definition: gui.h:346
std::size_t max_size
Maximum size of plot data.
Definition: gui.h:335
std::string label
Plot Label.
Definition: gui.h:329
bool show_max
Display maximum value under plot.
Definition: gui.h:332
A helper class to setup common OMPL structures for planning.
StateSpacePtr rspace
Underlying Robot State Space.
ompl::base::SpaceInformationPtr rinfo
Underlying Space Information.
RenderElement(const RenderCallback &callback)
Constructor.
Definition: gui.cpp:288
const RenderCallback callback
Callback.
Definition: gui.h:320
void render() const override
Render method. Renders IMGUI contents.
Definition: gui.cpp:292
A shared pointer wrapper for robowflex::darts::StateSpace.
float xr_[2]
GUI X orientation bounds.
Definition: gui.h:544
TSREditWidget(const std::string &name="TSR", const TSR::Specification &spec={})
Constructor.
Definition: gui.cpp:411
void syncFrame()
Updates the display frames to the specification.
Definition: gui.cpp:495
void syncTSR()
Updates the TSR to the specification.
Definition: gui.cpp:503
void syncSpec()
Updates the specification to the GUI.
Definition: gui.cpp:511
void syncGUI()
Updates the GUI to the specification.
Definition: gui.cpp:528
float yr_[2]
GUI Y orientation bounds.
Definition: gui.h:545
const float drag_step_
Slider drag amount.
Definition: gui.h:535
float yp_[2]
GUI Y position bounds.
Definition: gui.h:541
Eigen::Vector3d getVolume() const
Get the volume for the bounds.
Definition: gui.cpp:625
dart::dynamics::SimpleFramePtr rbounds_[3]
Display rotation bounds.
Definition: gui.h:499
const TSR::Specification original_
Original specification provided to the window.
Definition: gui.h:510
void updateMirror()
If synchronizing bounds, mirrors updates on other bound.
Definition: gui.cpp:603
float zr_[2]
GUI Z orientation bounds.
Definition: gui.h:546
void initialize(Window *window) override
Initialization with window context.
Definition: gui.cpp:416
TSR::Specification prev_
Prior iteration specification.
Definition: gui.h:512
const double volume_alpha_
Volume alpha.
Definition: gui.h:530
TSR::Specification spec_
Current specification.
Definition: gui.h:511
bool show_bounds_
Show TSR rotation bounds.
Definition: gui.h:523
void updateUUCB(const dart::gui::osg::InteractiveFrame *frame)
Frame update callback on moving the upper bound control.
Definition: gui.cpp:586
bool gui_
True if a synchronize call is coming from the GUI update loop.
Definition: gui.h:481
const TSR::Specification & getSpecification() const
Get current TSR specification.
Definition: gui.cpp:751
float inner_radius
GUI Rotation bound inner radius.
Definition: gui.h:548
float zp_[2]
GUI Z position bounds.
Definition: gui.h:542
Window::InteractiveReturn ll_frame_
Lower bound interactive frame.
Definition: gui.h:501
void prerefresh() override
Called before window refresh.
Definition: gui.cpp:746
float xp_[2]
GUI X position bounds.
Definition: gui.h:540
Window::InteractiveReturn frame_
Main interactive frame.
Definition: gui.h:500
TSRPtr tsr_
Corresponding TSR.
Definition: gui.h:513
void updateFrameCB(const dart::gui::osg::InteractiveFrame *frame)
Frame update callback on moving the main interactive frame.
Definition: gui.cpp:555
dart::dynamics::SimpleFramePtr shape_
Display boundary shape frame.
Definition: gui.h:498
void render() override
Render GUI.
Definition: gui.cpp:663
float position_[3]
GUI frame position.
Definition: gui.h:537
const double rotation_alpha_
Rotation bound alpha.
Definition: gui.h:531
float rotation_[3]
GUI frame rotation.
Definition: gui.h:538
void updateShape()
Updates the displayed shape volume for the bounds.
Definition: gui.cpp:630
bool sync_bounds_
Synchronize changes in volume on other bound.
Definition: gui.h:521
void updateLLCB(const dart::gui::osg::InteractiveFrame *frame)
Frame update callback on moving the lower bound control.
Definition: gui.cpp:569
const TSRPtr & getTSR() const
Get the current TSR.
Definition: gui.cpp:756
const std::string name_
Name of this window.
Definition: gui.h:509
bool show_volume_
Show TSR volume.
Definition: gui.h:522
const float max_position_
Max position value.
Definition: gui.h:534
dart::dynamics::SimpleFramePtr offset_
Offset frame for bounds.
Definition: gui.h:497
const double rotation_width_
Rotation bound width.
Definition: gui.h:532
Window::InteractiveReturn uu_frame_
Upper bound interactive frame.
Definition: gui.h:502
A shared pointer wrapper for robowflex::darts::TSR.
A shared pointer wrapper for robowflex::darts::TSRSet.
Manager for a set of TSR constraints. Attempts to reduce redundancy and combines errors and Jacobians...
Definition: tsr.h:726
Class for solving a set of TSRs.
Definition: gui.h:556
bool need_solve_
A solve is requested.
Definition: gui.h:592
void solve()
Solve for a solution to the current TSR.
Definition: gui.cpp:883
TSRSetPtr tsrs_
TSR set.
Definition: gui.h:581
bool track_tsr_
Track the TSR by solving IK.
Definition: gui.h:590
bool use_gradient_
Use gradient solving instead of built-in.
Definition: gui.h:591
const float max_tolerance_
Max tolerance value.
Definition: gui.h:586
float step_
GUI gradient step size.
Definition: gui.h:594
float damping_
GUI SVD damping.
Definition: gui.h:596
void prerefresh() override
Called before window refresh.
Definition: gui.cpp:961
void initialize(Window *window) override
Initialization with window context.
Definition: gui.cpp:903
int item_
GUI solver.
Definition: gui.h:599
LinePlotElement solve_time_
Plot of TSR solve times.
Definition: gui.h:607
int maxIter_
GUI maximum allowed iterations.
Definition: gui.h:598
float limit_
GUI gradient limit.
Definition: gui.h:595
std::vector< ErrorLines > errors_
Definition: gui.h:621
float tolerance_
GUI solver tolerance.
Definition: gui.h:597
const int max_iteration_
Max iteration value.
Definition: gui.h:587
TSRSolveWidget(const WorldPtr &world, const std::vector< TSRPtr > &tsrs)
Constructor.
Definition: gui.cpp:765
bool last_solve_
Result of last TSR solve.
Definition: gui.h:606
void render() override
Render GUI.
Definition: gui.cpp:774
The specification of a TSR.
Definition: tsr.h:70
Eigen::Vector3d lower
Lower position tolerance.
Definition: tsr.h:92
std::string structure
Structure target frame is in.
Definition: tsr.h:76
void setZRotTolerance(double bound)
Set the Z orientation tolerance to (-bound, bound).
Definition: tsr.cpp:183
void setRotation(const Eigen::Quaterniond &orientation)
Set the rotation of the TSR.
Definition: tsr.cpp:74
std::string frame
Name of target frame.
Definition: tsr.h:77
void setYPosTolerance(double bound)
Set the Y position tolerance to (-bound, bound).
Definition: tsr.cpp:133
Eigen::Quaterniond getRotation() const
Get the current desired orientation.
Definition: tsr.cpp:316
RobotPose pose
Pose of TSR.
Definition: tsr.h:86
void print(std::ostream &out) const
Print out this TSR information.
Definition: tsr.cpp:425
void setYRotTolerance(double bound)
Set the Y orientation tolerance to (-bound, bound).
Definition: tsr.cpp:178
Eigen::Vector3d getEulerRotation() const
Get the current desired orientation.
Definition: tsr.cpp:321
struct robowflex::darts::TSR::Specification::@5 position
Position tolerances.
struct robowflex::darts::TSR::Specification::@6 orientation
Orientation tolerances.
ROBOWFLEX_EIGEN Eigen::Vector3d upper
Upper position tolerance.
Definition: tsr.h:91
void setXPosTolerance(double bound)
Setting Position Tolerances.
Definition: tsr.cpp:128
void setZPosTolerance(double bound)
Set the Z position tolerance to (-bound, bound).
Definition: tsr.cpp:138
void setXRotTolerance(double bound)
Setting Orientation Tolerances.
Definition: tsr.cpp:173
Eigen::Vector3d getPosition() const
Getters and Informative Methods.
Definition: tsr.cpp:311
void setPosition(const Eigen::Ref< const Eigen::Vector3d > &position)
Setting TSR Pose.
Definition: tsr.cpp:64
struct robowflex::darts::TSR::Specification::@4 base
Base frame.
TextElement(const std::string &text)
Constructor.
Definition: gui.cpp:258
void render() const override
Render method. Renders IMGUI contents.
Definition: gui.cpp:262
const std::string text
Text to display.
Definition: gui.h:263
Viewer(const WorldPtr &world)
Constructor.
Definition: gui.cpp:28
void updateTraversal() override
Definition: gui.cpp:33
virtual void initialize(Window *window)
Initialization with window context.
Definition: gui.cpp:246
virtual void prerefresh()
Called before window refresh.
Definition: gui.cpp:250
A shared pointer wrapper for robowflex::darts::WindowWidget.
void addCheckbox(const std::string &text, bool &boolean)
Add a new checkbox element to the GUI.
Definition: gui.cpp:393
void addButton(const std::string &text, const ButtonCallback &callback)
Add a new button element to the GUI.
Definition: gui.cpp:388
std::vector< ImGuiElementPtr > elements_
GUI elements.
Definition: gui.h:412
void render() override
Render GUI.
Definition: gui.cpp:366
WindowWidget()
Constructor.
Definition: gui.cpp:362
void addElement(const ImGuiElementPtr &element)
Add a generic element to the GUI.
Definition: gui.cpp:403
void addText(const std::string &text)
Add a new text element to the GUI.
Definition: gui.cpp:383
void addCallback(const RenderCallback &callback)
Add a generic render callback for the GUI.
Definition: gui.cpp:398
Open Scene Graph GUI for DART visualization.
Definition: gui.h:67
Viewer viewer_
Viewer.
Definition: gui.h:213
WindowWidgetPtr widget_
IMGUI widget.
Definition: gui.h:207
WorldPtr getWorld()
Get world used for visualization.
Definition: gui.cpp:221
WindowWidgetPtr getWidget()
Get the IMGUI configurable widget.
Definition: gui.cpp:216
Window(const WorldPtr &world)
Constructor.
Definition: gui.cpp:76
void run(std::function< void()> thread={})
Run the GUI. Blocks.
Definition: gui.cpp:231
void animatePath(const StateSpacePtr &space, const ompl::geometric::PathGeometric &path, std::size_t times=1, double fps=60, bool block=true)
Animate a motion plan using the world.
Definition: gui.cpp:160
std::shared_ptr< std::thread > animation_
Animation thread.
Definition: gui.h:210
std::vector< WidgetPtr > widgets_
Other widgets;.
Definition: gui.h:208
::osg::ref_ptr< Window > node_
OSG Node.
Definition: gui.h:212
void addWidget(const WidgetPtr &widget)
Add a new IMGUI widget.
Definition: gui.cpp:106
WorldPtr world_
World to visualize.
Definition: gui.h:206
InteractiveReturn createInteractiveMarker(const InteractiveOptions &options)
Create a new interactive marker in the GUI.
Definition: gui.cpp:113
void customPreRefresh() override
Definition: gui.cpp:94
const WorldPtr & getWorldConst() const
Get world used for visualization.
Definition: gui.cpp:226
void customPostRefresh() override
Definition: gui.cpp:101
DnDReturn enableNodeDragNDrop(dart::dynamics::BodyNode *node, const DnDCallback &callback={})
Enable drag 'n drop functionality on a body node being visualized. With DnD, the body node will autom...
Definition: gui.cpp:146
A shared pointer wrapper for robowflex::darts::World.
T data(T... args)
T emplace_back(T... args)
T emplace(T... args)
static const double half
Definition: constants.h:14
static const double half_pi
Definition: constants.h:22
static const double pi
Definition: constants.h:21
static const std::string ROOT_FRAME
Definition: tsr.h:31
DART-based robot modeling and planning.
Definition: acm.h:16
std::shared_ptr< dart::dynamics::MeshShape > makeArcsegment(double low, double high, double inner_radius, double outer_radius, std::size_t resolution=32)
Create a circle's arcsector from one angle to another, with a specified radius.
Definition: structure.cpp:419
std::string generateUUID()
Generate a unique identifier.
Definition: gui.cpp:17
std::shared_ptr< dart::dynamics::BoxShape > makeBox(const Eigen::Ref< const Eigen::Vector3d > &v)
Create a box.
Definition: structure.cpp:370
T reserve(T... args)
T reset(T... args)
T resize(T... args)
T size(T... args)
T sleep_for(T... args)
Return from creating a movable frame.
Definition: gui.h:140
dart::gui::osg::BodyNodeDnD * dnd
Drag 'n Drop object.
Definition: gui.h:141
dart::common::Connection signal
Connection from motion to callback.
Definition: gui.h:142
Options for creating an interactive marker.
Definition: gui.h:88
void disableControls()
Disables all controls.
Definition: gui.cpp:65
std::string name
Name of marker.
Definition: gui.h:89
bool rotation[3]
Rotation ring controls enabled.
Definition: gui.h:98
void disableRotationControls()
Disables all rotation controls.
Definition: gui.cpp:51
bool obstructable
Is this frame obstructable?
Definition: gui.h:95
void disableLinearControls()
Disables all linear controls.
Definition: gui.cpp:44
Eigen::Isometry3d pose
Relative pose of marker.
Definition: gui.h:90
InteractiveCallback callback
Callback function on motion.
Definition: gui.h:91
double thickness
Thickness of marker arrows.
Definition: gui.h:94
bool linear[3]
Linear position controls enabled.
Definition: gui.h:97
bool planar[3]
Planar translation controls enabled.
Definition: gui.h:99
void disablePlanarControls()
Disables all planar controls.
Definition: gui.cpp:58
dart::dynamics::Frame * parent
Parent frame.
Definition: gui.h:92
Return from creating an interactive marker.
Definition: gui.h:121
dart::gui::osg::InteractiveFrameDnD * dnd
Drag 'n Drop object.
Definition: gui.h:123
dart::common::Connection signal
Connection from motion to callback.
Definition: gui.h:124
dart::gui::osg::InteractiveFramePtr target
Interactive Frame generated.
Definition: gui.h:122
void callback(movegroup::MoveGroupHelper::Action &action)
Definition: tapedeck.cpp:20
T to_string(T... args)