selection_manager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <algorithm>
31 
32 #include <QTimer>
33 
34 #include <OgreCamera.h>
35 #include <OgreEntity.h>
36 #include <OgreHardwarePixelBuffer.h>
37 #include <OgreManualObject.h>
38 #include <OgreMaterialManager.h>
39 #include <OgreRenderSystem.h>
40 #include <OgreRenderTexture.h>
41 #include <OgreRoot.h>
42 #include <OgreSceneManager.h>
43 #include <OgreSceneNode.h>
44 #include <OgreSubEntity.h>
45 #include <OgreTextureManager.h>
46 #include <OgreViewport.h>
47 #include <OgreWireBoundingBox.h>
48 #include <OgreSharedPtr.h>
49 #include <OgreTechnique.h>
50 #include <OgreRectangle2D.h>
51 
53 #include <sensor_msgs/Image.h>
54 
55 #include <ros/assert.h>
56 #include <ros/node_handle.h>
57 #include <ros/publisher.h>
58 
60 #include "rviz/ogre_helpers/axes.h"
66 #include "rviz/render_panel.h"
67 #include "rviz/view_controller.h"
68 #include "rviz/view_manager.h"
70 
72 #include <vector>
73 
74 
75 namespace rviz
76 {
78  : vis_manager_(manager)
79  , highlight_enabled_(false)
80  , uid_counter_(0)
81  , interaction_enabled_(false)
82  , debug_mode_(false)
83  , property_model_(new PropertyTreeModel(new Property("root")))
84 {
85  for (uint32_t i = 0; i < s_num_render_textures_; ++i)
86  {
87  pixel_boxes_[i].data = nullptr;
88  }
89  depth_pixel_box_.data = nullptr;
90 
91  QTimer* timer = new QTimer(this);
92  connect(timer, SIGNAL(timeout()), this, SLOT(updateProperties()));
93  timer->start(200);
94 }
95 
97 {
98  boost::recursive_mutex::scoped_lock lock(global_mutex_);
99 
101 
102  highlight_node_->getParentSceneNode()->removeAndDestroyChild(highlight_node_->getName());
103  delete highlight_rectangle_;
104 
105  for (uint32_t i = 0; i < s_num_render_textures_; ++i)
106  {
107  delete[](uint8_t*) pixel_boxes_[i].data;
108  }
109  delete[](uint8_t*) depth_pixel_box_.data;
110 
111  vis_manager_->getSceneManager()->destroyCamera(camera_);
112 
113  delete property_model_;
114 }
115 
117 {
118  debug_mode_ = debug;
119 }
120 
122 {
123  // Create our render textures
124  setTextureSize(1);
125 
126  // Create our highlight rectangle
127  Ogre::SceneManager* scene_manager = vis_manager_->getSceneManager();
128  highlight_node_ = scene_manager->getRootSceneNode()->createChildSceneNode();
129 
130  std::stringstream ss;
131  static int count = 0;
132  ss << "SelectionRect" << count++;
133  highlight_rectangle_ = new Ogre::Rectangle2D(true);
134 
135  const static uint32_t texture_data[1] = {0xffff0080};
136  Ogre::DataStreamPtr pixel_stream;
137  pixel_stream.bind(new Ogre::MemoryDataStream((void*)&texture_data[0], 4));
138 
139  Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().loadRawData(
140  ss.str() + "Texture", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, pixel_stream, 1, 1,
141  Ogre::PF_R8G8B8A8, Ogre::TEX_TYPE_2D, 0);
142 
143  Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(
144  ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
145  material->setLightingEnabled(false);
146  // material->getTechnique(0)->getPass(0)->setPolygonMode(Ogre::PM_WIREFRAME);
147  highlight_rectangle_->setMaterial(material->getName());
148  Ogre::AxisAlignedBox aabInf;
149  aabInf.setInfinite();
150  highlight_rectangle_->setBoundingBox(aabInf);
151  highlight_rectangle_->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - 1);
152  material->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
153  material->setCullingMode(Ogre::CULL_NONE);
154 
155  Ogre::TextureUnitState* tex_unit = material->getTechnique(0)->getPass(0)->createTextureUnitState();
156  tex_unit->setTextureName(tex->getName());
157  tex_unit->setTextureFiltering(Ogre::TFO_NONE);
158 
159  highlight_node_->attachObject(highlight_rectangle_);
160 
161  // create picking camera
162  camera_ = scene_manager->createCamera(ss.str() + "_camera");
163 
164  // create fallback picking material
165  fallback_pick_material_ = Ogre::MaterialManager::getSingleton().getByName("rviz/DefaultPickAndDepth");
166  fallback_pick_material_->load();
167 
168  fallback_pick_cull_technique_ = fallback_pick_material_->getTechnique("PickCull");
169  fallback_black_cull_technique_ = fallback_pick_material_->getTechnique("BlackCull");
170  fallback_depth_cull_technique_ = fallback_pick_material_->getTechnique("DepthCull");
171 
172  fallback_pick_technique_ = fallback_pick_material_->getTechnique("Pick");
173  fallback_black_technique_ = fallback_pick_material_->getTechnique("Black");
174  fallback_depth_technique_ = fallback_pick_material_->getTechnique("Depth");
175 }
176 
177 
178 bool SelectionManager::get3DPoint(Ogre::Viewport* viewport, int x, int y, Ogre::Vector3& result_point)
179 {
180  ROS_DEBUG("SelectionManager.get3DPoint()");
181 
182  std::vector<Ogre::Vector3> result_points_temp;
183  bool success = get3DPatch(viewport, x, y, 1, 1, true, result_points_temp);
184  if (result_points_temp.empty())
185  {
186  // return result_point unmodified if get point fails.
187  return false;
188  }
189  result_point = result_points_temp[0];
190 
191  return success;
192 }
193 
194 
195 bool SelectionManager::getPatchDepthImage(Ogre::Viewport* viewport,
196  int x,
197  int y,
198  unsigned width,
199  unsigned height,
200  std::vector<float>& depth_vector)
201 {
202  unsigned int num_pixels = width * height;
203  depth_vector.reserve(num_pixels);
204 
205  setDepthTextureSize(width, height);
206 
207 
208  M_CollisionObjectToSelectionHandler::iterator handler_it = objects_.begin();
209  M_CollisionObjectToSelectionHandler::iterator handler_end = objects_.end();
210 
211  for (; handler_it != handler_end; ++handler_it)
212  {
213  handler_it->second->preRenderPass(0);
214  }
215 
216  if (render(viewport, depth_render_texture_, x, y, x + width, y + height, depth_pixel_box_, "Depth",
218  {
219  uint8_t* data_ptr = (uint8_t*)depth_pixel_box_.data;
220 
221  for (uint32_t pixel = 0; pixel < num_pixels; ++pixel)
222  {
223  uint8_t a = data_ptr[4 * pixel];
224  uint8_t b = data_ptr[4 * pixel + 1];
225  uint8_t c = data_ptr[4 * pixel + 2];
226 
227  int int_depth = (c << 16) | (b << 8) | a;
228  float normalized_depth = ((float)int_depth) / (float)0xffffff;
229  depth_vector.push_back(normalized_depth * camera_->getFarClipDistance());
230  }
231  }
232  else
233  {
234  ROS_WARN("Failed to render depth patch\n");
235  return false;
236  }
237 
238  handler_it = objects_.begin();
239  handler_end = objects_.end();
240  for (; handler_it != handler_end; ++handler_it)
241  {
242  handler_it->second->postRenderPass(0);
243  }
244 
245  return true;
246 }
247 
248 
249 bool SelectionManager::get3DPatch(Ogre::Viewport* viewport,
250  int x,
251  int y,
252  unsigned width,
253  unsigned height,
254  bool skip_missing,
255  std::vector<Ogre::Vector3>& result_points)
256 {
257  boost::recursive_mutex::scoped_lock lock(global_mutex_);
258  ROS_DEBUG("SelectionManager.get3DPatch()");
259 
260  std::vector<float> depth_vector;
261 
262 
263  if (!getPatchDepthImage(viewport, x, y, width, height, depth_vector))
264  return false;
265 
266 
267  unsigned int pixel_counter = 0;
268  Ogre::Matrix4 projection = camera_->getProjectionMatrix();
269  float depth;
270 
271  for (unsigned y_iter = 0; y_iter < height; ++y_iter)
272  for (unsigned x_iter = 0; x_iter < width; ++x_iter)
273  {
274  depth = depth_vector[pixel_counter];
275 
276  // Deal with missing or invalid points
277  if ((depth > camera_->getFarClipDistance()) || (depth == 0))
278  {
279  ++pixel_counter;
280  if (!skip_missing)
281  {
282  result_points.push_back(Ogre::Vector3(NAN, NAN, NAN));
283  }
284  continue;
285  }
286 
287 
288  Ogre::Vector3 result_point;
289  // We want to shoot rays through the center of pixels, not the corners,
290  // so add .5 pixels to the x and y coordinate to get to the center
291  // instead of the top left of the pixel.
292  Ogre::Real screenx = float(x_iter + .5) / float(width);
293  Ogre::Real screeny = float(y_iter + .5) / float(height);
294  if (projection[3][3] == 0.0) // If this is a perspective projection
295  {
296  // get world-space ray from camera & mouse coord
297  Ogre::Ray vp_ray = camera_->getCameraToViewportRay(screenx, screeny);
298 
299  // transform ray direction back into camera coords
300  Ogre::Vector3 dir_cam = camera_->getDerivedOrientation().Inverse() * vp_ray.getDirection();
301 
302  // normalize, so dir_cam.z == -depth
303  dir_cam = dir_cam / dir_cam.z * depth * -1;
304 
305  // compute 3d point from camera origin and direction*/
306  result_point = camera_->getDerivedPosition() + camera_->getDerivedOrientation() * dir_cam;
307  }
308  else // else this must be an orthographic projection.
309  {
310  // For orthographic projection, getCameraToViewportRay() does
311  // the right thing for us, and the above math does not work.
312  Ogre::Ray ray;
313  camera_->getCameraToViewportRay(screenx, screeny, &ray);
314 
315  result_point = ray.getPoint(depth);
316  }
317 
318  result_points.push_back(result_point);
319  ++pixel_counter;
320  }
321 
322  return !result_points.empty();
323 }
324 
325 
326 void SelectionManager::setDepthTextureSize(unsigned width, unsigned height)
327 {
328  // Cap and store requested texture size
329  // It's probably an error if an invalid size is requested.
330  if (width > 1024)
331  {
332  width = 1024;
333  ROS_ERROR_STREAM("SelectionManager::setDepthTextureSize invalid width requested. Max Width: 1024 -- "
334  "Width requested: "
335  << width << ". Capping Width at 1024.");
336  }
337 
338  if (depth_texture_width_ != width)
339  depth_texture_width_ = width;
340 
341  if (height > 1024)
342  {
343  height = 1024;
344  ROS_ERROR_STREAM("SelectionManager::setDepthTextureSize invalid height requested. Max Height: 1024 "
345  "-- Height requested: "
346  << width << ". Capping Height at 1024.");
347  }
348 
349  if (depth_texture_height_ != height)
350  depth_texture_height_ = height;
351 
352  if (!depth_render_texture_.get() || depth_render_texture_->getWidth() != width ||
353  depth_render_texture_->getHeight() != height)
354  {
355  std::string tex_name = "DepthTexture";
356  if (depth_render_texture_.get())
357  {
358  tex_name = depth_render_texture_->getName();
359 
360  // destroy old
361  Ogre::TextureManager::getSingleton().remove(tex_name);
362  }
363 
364  depth_render_texture_ = Ogre::TextureManager::getSingleton().createManual(
365  tex_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
366  depth_texture_width_, depth_texture_height_, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET);
367 
368  Ogre::RenderTexture* render_texture = depth_render_texture_->getBuffer()->getRenderTarget();
369  render_texture->setAutoUpdated(false);
370  }
371 }
372 
373 
375 {
376  if (size > 1024)
377  {
378  size = 1024;
379  }
380 
381  texture_size_ = size;
382 
383  for (uint32_t pass = 0; pass < s_num_render_textures_; ++pass)
384  {
385  // check if we need to change the texture size
386  if (!render_textures_[pass].get() || render_textures_[pass]->getWidth() != size)
387  {
388  std::string tex_name;
389  if (render_textures_[pass].get())
390  {
391  tex_name = render_textures_[pass]->getName();
392 
393  // destroy old
394  Ogre::TextureManager::getSingleton().remove(tex_name);
395  }
396  else
397  {
398  std::stringstream ss;
399  static int count = 0;
400  ss << "SelectionTexture" << count++;
401  tex_name = ss.str();
402  }
403 
404  // create new texture
405  render_textures_[pass] = Ogre::TextureManager::getSingleton().createManual(
406  tex_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, size,
407  size, 0, Ogre::PF_R8G8B8, Ogre::TU_STATIC | Ogre::TU_RENDERTARGET);
408 
409  Ogre::RenderTexture* render_texture = render_textures_[pass]->getBuffer()->getRenderTarget();
410  render_texture->setAutoUpdated(false);
411  }
412  }
413 }
414 
416 {
417  boost::recursive_mutex::scoped_lock lock(global_mutex_);
418 
419  objects_.clear();
420 }
421 
423 {
424  interaction_enabled_ = enable;
425  M_CollisionObjectToSelectionHandler::iterator handler_it = objects_.begin();
426  M_CollisionObjectToSelectionHandler::iterator handler_end = objects_.end();
427  for (; handler_it != handler_end; ++handler_it)
428  {
429  if (InteractiveObjectPtr object = handler_it->second->getInteractiveObject().lock())
430  {
431  object->enableInteraction(enable);
432  }
433  }
434 }
435 
437 {
438  uid_counter_++;
439  if (uid_counter_ > 0x00ffffff)
440  {
441  uid_counter_ = 0;
442  }
443 
444  uint32_t handle = 0;
445 
446  // shuffle around the bits so we get lots of colors
447  // when we're displaying the selection buffer
448  for (unsigned int i = 0; i < 24; i++)
449  {
450  uint32_t shift = (((23 - i) % 3) * 8) + (23 - i) / 3;
451  uint32_t bit = ((uint32_t)(uid_counter_ >> i) & (uint32_t)1) << shift;
452  handle |= bit;
453  }
454 
455  return handle;
456 }
457 
459 {
460  if (!obj)
461  {
462  // ROS_BREAK();
463  return;
464  }
465 
466  boost::recursive_mutex::scoped_lock lock(global_mutex_);
467 
468  InteractiveObjectPtr object = handler->getInteractiveObject().lock();
469  if (object)
470  {
471  object->enableInteraction(interaction_enabled_);
472  }
473 
474  bool inserted = objects_.insert(std::make_pair(obj, handler)).second;
475  ROS_ASSERT(inserted);
476  Q_UNUSED(inserted);
477 }
478 
480 {
481  if (!obj)
482  {
483  return;
484  }
485 
486  boost::recursive_mutex::scoped_lock lock(global_mutex_);
487 
488  M_Picked::iterator it = selection_.find(obj);
489  if (it != selection_.end())
490  {
491  M_Picked objs;
492  objs.insert(std::make_pair(it->first, it->second));
493 
494  removeSelection(objs);
495  }
496 
497  objects_.erase(obj);
498 }
499 
501 {
502  boost::recursive_mutex::scoped_lock lock(global_mutex_);
503 
504  highlight_node_->setVisible(highlight_enabled_);
505 
506  if (highlight_enabled_)
507  {
509 
510 #if 0
511  M_Picked results;
512  highlight_node_->setVisible(false);
514  highlight_node_->setVisible(true);
515 #endif
516  }
517 }
518 
519 void SelectionManager::highlight(Ogre::Viewport* viewport, int x1, int y1, int x2, int y2)
520 {
521  boost::recursive_mutex::scoped_lock lock(global_mutex_);
522 
523  highlight_enabled_ = true;
524 
525  highlight_.viewport = viewport;
526  highlight_.x1 = x1;
527  highlight_.y1 = y1;
528  highlight_.x2 = x2;
529  highlight_.y2 = y2;
530 }
531 
533 {
534  boost::recursive_mutex::scoped_lock lock(global_mutex_);
535 
536  highlight_enabled_ = false;
537 }
538 
539 void SelectionManager::select(Ogre::Viewport* viewport, int x1, int y1, int x2, int y2, SelectType type)
540 {
541  boost::recursive_mutex::scoped_lock lock(global_mutex_);
542 
543  highlight_enabled_ = false;
544  highlight_node_->setVisible(false);
545 
546  M_Picked results;
547  pick(viewport, x1, y1, x2, y2, results);
548 
549  if (type == Add)
550  {
551  addSelection(results);
552  }
553  else if (type == Remove)
554  {
555  removeSelection(results);
556  }
557  else if (type == Replace)
558  {
559  setSelection(results);
560  }
561 }
562 
563 void SelectionManager::setHighlightRect(Ogre::Viewport* viewport, int x1, int y1, int x2, int y2)
564 {
565  float nx1 = ((float)x1 / viewport->getActualWidth()) * 2 - 1;
566  float nx2 = ((float)x2 / viewport->getActualWidth()) * 2 - 1;
567  float ny1 = -(((float)y1 / viewport->getActualHeight()) * 2 - 1);
568  float ny2 = -(((float)y2 / viewport->getActualHeight()) * 2 - 1);
569 
570  nx1 = nx1 < -1 ? -1 : (nx1 > 1 ? 1 : nx1);
571  ny1 = ny1 < -1 ? -1 : (ny1 > 1 ? 1 : ny1);
572  nx2 = nx2 < -1 ? -1 : (nx2 > 1 ? 1 : nx2);
573  ny2 = ny2 < -1 ? -1 : (ny2 > 1 ? 1 : ny2);
574 
575  highlight_rectangle_->setCorners(nx1, ny1, nx2, ny2);
576 }
577 
578 void SelectionManager::unpackColors(Ogre::PixelBox& box, V_CollObject& pixels)
579 {
580  int w = box.getWidth();
581  int h = box.getHeight();
582 
583  pixels.clear();
584  pixels.reserve(w * h);
585  size_t size = Ogre::PixelUtil::getMemorySize(1, 1, 1, box.format);
586 
587  for (int y = 0; y < h; y++)
588  {
589  for (int x = 0; x < w; x++)
590  {
591  uint32_t pos = (x + y * w) * size;
592  uint32_t pix_val = 0;
593  memcpy((uint8_t*)&pix_val, (uint8_t*)box.data + pos, size);
594  pixels.push_back(colorToHandle(box.format, pix_val));
595  }
596  }
597 }
598 
599 void SelectionManager::renderAndUnpack(Ogre::Viewport* viewport,
600  uint32_t pass,
601  int x1,
602  int y1,
603  int x2,
604  int y2,
605  V_CollObject& pixels)
606 {
608 
609  std::stringstream scheme;
610  scheme << "Pick";
611  if (pass > 0)
612  {
613  scheme << pass;
614  }
615 
616  if (render(viewport, render_textures_[pass], x1, y1, x2, y2, pixel_boxes_[pass], scheme.str(),
618  {
619  unpackColors(pixel_boxes_[pass], pixels);
620  }
621 }
622 
623 
624 bool SelectionManager::render(Ogre::Viewport* viewport,
625  Ogre::TexturePtr tex,
626  int x1,
627  int y1,
628  int x2,
629  int y2,
630  Ogre::PixelBox& dst_box,
631  std::string material_scheme,
632  unsigned texture_width,
633  unsigned texture_height)
634 {
636 
637  if (x1 > x2)
638  std::swap(x1, x2);
639  if (y1 > y2)
640  std::swap(y1, y2);
641 
642  if (x1 < 0)
643  x1 = 0;
644  if (y1 < 0)
645  y1 = 0;
646  if (x1 > viewport->getActualWidth() - 2)
647  x1 = viewport->getActualWidth() - 2;
648  if (y1 > viewport->getActualHeight() - 2)
649  y1 = viewport->getActualHeight() - 2;
650  if (x2 < 0)
651  x2 = 0;
652  if (y2 < 0)
653  y2 = 0;
654  if (x2 > viewport->getActualWidth() - 2)
655  x2 = viewport->getActualWidth() - 2;
656  if (y2 > viewport->getActualHeight() - 2)
657  y2 = viewport->getActualHeight() - 2;
658 
659  if (x2 == x1)
660  x2++;
661  if (y2 == y1)
662  y2++;
663 
664  if (x2 == x1 || y2 == y1)
665  {
666  ROS_WARN("SelectionManager::render(): not rendering 0 size area.");
668  return false;
669  }
670 
671  unsigned w = x2 - x1;
672  unsigned h = y2 - y1;
673 
674  Ogre::HardwarePixelBufferSharedPtr pixel_buffer = tex->getBuffer();
675  Ogre::RenderTexture* render_texture = pixel_buffer->getRenderTarget();
676 
677  Ogre::Matrix4 proj_matrix = viewport->getCamera()->getProjectionMatrix();
678  Ogre::Matrix4 scale_matrix = Ogre::Matrix4::IDENTITY;
679  Ogre::Matrix4 trans_matrix = Ogre::Matrix4::IDENTITY;
680 
681  float x1_rel = static_cast<float>(x1) / static_cast<float>(viewport->getActualWidth() - 1) - 0.5f;
682  float y1_rel = static_cast<float>(y1) / static_cast<float>(viewport->getActualHeight() - 1) - 0.5f;
683  float x2_rel = static_cast<float>(x2) / static_cast<float>(viewport->getActualWidth() - 1) - 0.5f;
684  float y2_rel = static_cast<float>(y2) / static_cast<float>(viewport->getActualHeight() - 1) - 0.5f;
685 
686  scale_matrix[0][0] = 1.0 / (x2_rel - x1_rel);
687  scale_matrix[1][1] = 1.0 / (y2_rel - y1_rel);
688 
689  trans_matrix[0][3] -= x1_rel + x2_rel;
690  trans_matrix[1][3] += y1_rel + y2_rel;
691 
692  camera_->setCustomProjectionMatrix(true, scale_matrix * trans_matrix * proj_matrix);
693 
694  camera_->setPosition(viewport->getCamera()->getDerivedPosition());
695  camera_->setOrientation(viewport->getCamera()->getDerivedOrientation());
696 
697  // create a viewport if there is none
698  if (render_texture->getNumViewports() == 0)
699  {
700  render_texture->removeAllViewports();
701  render_texture->addViewport(camera_);
702  Ogre::Viewport* render_viewport = render_texture->getViewport(0);
703  render_viewport->setClearEveryFrame(true);
704  render_viewport->setBackgroundColour(Ogre::ColourValue::Black);
705  render_viewport->setOverlaysEnabled(false);
706  render_viewport->setMaterialScheme(material_scheme);
707  }
708 
709  unsigned render_w = w;
710  unsigned render_h = h;
711 
712  if (w > h)
713  {
714  if (render_w > texture_width)
715  {
716  render_w = texture_width;
717  render_h = round(float(h) * (float)texture_width / (float)w);
718  }
719  }
720  else
721  {
722  if (render_h > texture_height)
723  {
724  render_h = texture_height;
725  render_w = round(float(w) * (float)texture_height / (float)h);
726  }
727  }
728 
729  // safety clamping in case of rounding errors
730  if (render_w > texture_width)
731  render_w = texture_width;
732  if (render_h > texture_height)
733  render_h = texture_height;
734 
735  // set viewport to render to a subwindow of the texture
736  Ogre::Viewport* render_viewport = render_texture->getViewport(0);
737  render_viewport->setDimensions(0, 0, (float)render_w / (float)texture_width,
738  (float)render_h / (float)texture_height);
739 
740  // make sure the same objects are visible as in the original viewport
741  render_viewport->setVisibilityMask(viewport->getVisibilityMask());
742 
744 
745  // update & force ogre to render the scene
746  Ogre::MaterialManager::getSingleton().addListener(this);
747 
748  render_texture->update();
749 
750  // For some reason we need to pretend to render the main window in
751  // order to get the picking render to show up in the pixelbox below.
752  // If we don't do this, it will show up there the *next* time we
753  // pick something, but not this time. This object as a
754  // render queue listener tells the scene manager to skip every
755  // render step, so nothing actually gets drawn.
756  //
757  // TODO: find out what part of _renderScene() actually makes this work.
758  Ogre::Viewport* main_view = vis_manager_->getRenderPanel()->getViewport();
759  vis_manager_->getSceneManager()->addRenderQueueListener(this);
760  vis_manager_->getSceneManager()->_renderScene(main_view->getCamera(), main_view, false);
761  vis_manager_->getSceneManager()->removeRenderQueueListener(this);
762 
764  ros::WallDuration d = end - start;
765  // ROS_DEBUG("Render took [%f] msec", d.toSec() * 1000.0f);
766 
767  Ogre::MaterialManager::getSingleton().removeListener(this);
768 
769  render_w = render_viewport->getActualWidth();
770  render_h = render_viewport->getActualHeight();
771 
772  Ogre::PixelFormat format = pixel_buffer->getFormat();
773 
774  int size = Ogre::PixelUtil::getMemorySize(render_w, render_h, 1, format);
775  uint8_t* data = new uint8_t[size];
776 
777  delete[](uint8_t*) dst_box.data;
778  dst_box = Ogre::PixelBox(render_w, render_h, 1, format, data);
779 
780  pixel_buffer->blitToMemory(dst_box, dst_box);
781 
783 
784  if (debug_mode_)
785  {
786  publishDebugImage(dst_box, material_scheme);
787  }
788 
789  return true;
790 }
791 
792 void SelectionManager::publishDebugImage(const Ogre::PixelBox& pixel_box, const std::string& label)
793 {
794  ros::Publisher pub;
795  ros::NodeHandle nh;
796  PublisherMap::const_iterator iter = debug_publishers_.find(label);
797  if (iter == debug_publishers_.end())
798  {
799  pub = nh.advertise<sensor_msgs::Image>("/rviz_debug/" + label, 2);
800  debug_publishers_[label] = pub;
801  }
802  else
803  {
804  pub = iter->second;
805  }
806 
807  sensor_msgs::Image msg;
808  msg.header.stamp = ros::Time::now();
809  msg.width = pixel_box.getWidth();
810  msg.height = pixel_box.getHeight();
811  msg.encoding = sensor_msgs::image_encodings::RGB8;
812  msg.is_bigendian = false;
813  msg.step = msg.width * 3;
814  int dest_byte_count = msg.width * msg.height * 3;
815  msg.data.resize(dest_byte_count);
816  int dest_index = 0;
817  uint8_t* source_ptr = (uint8_t*)pixel_box.data;
818  int pre_pixel_padding = 0;
819  int post_pixel_padding = 0;
820  switch (pixel_box.format)
821  {
822  case Ogre::PF_R8G8B8:
823  break;
824  case Ogre::PF_A8R8G8B8:
825  case Ogre::PF_X8R8G8B8:
826  post_pixel_padding = 1;
827  break;
828  case Ogre::PF_R8G8B8A8:
829  pre_pixel_padding = 1;
830  break;
831  default:
832  ROS_ERROR("SelectionManager::publishDebugImage(): Incompatible pixel format [%d]", pixel_box.format);
833  return;
834  }
835  uint8_t r, g, b;
836  while (dest_index < dest_byte_count)
837  {
838  source_ptr += pre_pixel_padding;
839  b = *source_ptr++;
840  g = *source_ptr++;
841  r = *source_ptr++;
842  source_ptr += post_pixel_padding;
843  msg.data[dest_index++] = r;
844  msg.data[dest_index++] = g;
845  msg.data[dest_index++] = b;
846  }
847 
848  pub.publish(msg);
849 }
850 
851 void SelectionManager::renderQueueStarted(uint8_t /*queueGroupId*/,
852  const std::string& /*invocation*/,
853  bool& skipThisInvocation)
854 {
855  // This render queue listener function tells the scene manager to
856  // skip every render step, so nothing actually gets drawn.
857 
858  // ROS_DEBUG("SelectionManager renderQueueStarted(%d, '%s') returning skip = true.",
859  // (int)queueGroupId, invocation.c_str());
860  skipThisInvocation = true;
861 }
862 
863 void SelectionManager::pick(Ogre::Viewport* viewport,
864  int x1,
865  int y1,
866  int x2,
867  int y2,
868  M_Picked& results,
869  bool single_render_pass)
870 {
871  boost::recursive_mutex::scoped_lock lock(global_mutex_);
872 
873  bool need_additional_render = false;
874 
875  V_CollObject handles_by_pixel;
876  S_CollObject need_additional;
877 
878  V_CollObject& pixels = pixel_buffer_;
879 
880  // First render is special... does the initial object picking, determines which objects have been
881  // selected
882  // After that, individual handlers can specify that they need additional renders (max # defined in
883  // s_num_render_textures_)
884  {
885  M_CollisionObjectToSelectionHandler::iterator handler_it = objects_.begin();
886  M_CollisionObjectToSelectionHandler::iterator handler_end = objects_.end();
887  for (; handler_it != handler_end; ++handler_it)
888  {
889  handler_it->second->preRenderPass(0);
890  }
891 
892  renderAndUnpack(viewport, 0, x1, y1, x2, y2, pixels);
893 
894  handler_it = objects_.begin();
895  handler_end = objects_.end();
896  for (; handler_it != handler_end; ++handler_it)
897  {
898  handler_it->second->postRenderPass(0);
899  }
900 
901  handles_by_pixel.reserve(pixels.size());
902  V_CollObject::iterator it = pixels.begin();
903  V_CollObject::iterator end = pixels.end();
904  for (; it != end; ++it)
905  {
906  const CollObjectHandle& p = *it;
907 
908  CollObjectHandle handle = p;
909 
910  handles_by_pixel.push_back(handle);
911 
912  if (handle == 0)
913  {
914  continue;
915  }
916 
917  SelectionHandler* handler = getHandler(handle);
918 
919  if (handler)
920  {
921  std::pair<M_Picked::iterator, bool> insert_result =
922  results.insert(std::make_pair(handle, Picked(handle)));
923  if (insert_result.second)
924  {
925  if (handler->needsAdditionalRenderPass(1) && !single_render_pass)
926  {
927  need_additional.insert(handle);
928  need_additional_render = true;
929  }
930  }
931  else
932  {
933  insert_result.first->second.pixel_count++;
934  }
935  }
936  }
937  }
938 
939  uint32_t pass = 1;
940 
941  V_uint64 extra_by_pixel;
942  extra_by_pixel.resize(handles_by_pixel.size());
943  while (need_additional_render && pass < s_num_render_textures_)
944  {
945  {
946  S_CollObject::iterator need_it = need_additional.begin();
947  S_CollObject::iterator need_end = need_additional.end();
948  for (; need_it != need_end; ++need_it)
949  {
950  SelectionHandler* handler = getHandler(*need_it);
951  ROS_ASSERT(handler);
952 
953  handler->preRenderPass(pass);
954  }
955  }
956 
957  renderAndUnpack(viewport, pass, x1, y1, x2, y2, pixels);
958 
959  {
960  S_CollObject::iterator need_it = need_additional.begin();
961  S_CollObject::iterator need_end = need_additional.end();
962  for (; need_it != need_end; ++need_it)
963  {
964  SelectionHandler* handler = getHandler(*need_it);
965  ROS_ASSERT(handler);
966 
967  handler->postRenderPass(pass);
968  }
969  }
970 
971  int i = 0;
972  V_CollObject::iterator pix_it = pixels.begin();
973  V_CollObject::iterator pix_end = pixels.end();
974  for (; pix_it != pix_end; ++pix_it, ++i)
975  {
976  const CollObjectHandle& p = *pix_it;
977 
978  CollObjectHandle handle = handles_by_pixel[i];
979 
980  if (pass == 1)
981  {
982  extra_by_pixel[i] = 0;
983  }
984 
985  if (need_additional.find(handle) != need_additional.end())
986  {
987  CollObjectHandle extra_handle = p;
988  extra_by_pixel[i] |= extra_handle << (32 * (pass - 1));
989  }
990  else
991  {
992  extra_by_pixel[i] = 0;
993  }
994  }
995 
996  need_additional_render = false;
997  need_additional.clear();
998  M_Picked::iterator handle_it = results.begin();
999  M_Picked::iterator handle_end = results.end();
1000  for (; handle_it != handle_end; ++handle_it)
1001  {
1002  CollObjectHandle handle = handle_it->first;
1003 
1004  if (getHandler(handle)->needsAdditionalRenderPass(pass + 1))
1005  {
1006  need_additional_render = true;
1007  need_additional.insert(handle);
1008  }
1009  }
1010  }
1011 
1012  int i = 0;
1013  V_uint64::iterator pix_2_it = extra_by_pixel.begin();
1014  V_uint64::iterator pix_2_end = extra_by_pixel.end();
1015  for (; pix_2_it != pix_2_end; ++pix_2_it, ++i)
1016  {
1017  CollObjectHandle handle = handles_by_pixel[i];
1018 
1019  if (handle == 0)
1020  {
1021  continue;
1022  }
1023 
1024  M_Picked::iterator picked_it = results.find(handle);
1025  if (picked_it == results.end())
1026  {
1027  continue;
1028  }
1029 
1030  Picked& picked = picked_it->second;
1031 
1032  if (*pix_2_it)
1033  {
1034  picked.extra_handles.insert(*pix_2_it);
1035  }
1036  }
1037 }
1038 
1039 Ogre::Technique* SelectionManager::handleSchemeNotFound(unsigned short /*scheme_index*/,
1040  const Ogre::String& scheme_name,
1041  Ogre::Material* original_material,
1042  unsigned short /*lod_index*/,
1043  const Ogre::Renderable* rend)
1044 {
1045  // Find the original culling mode
1046  Ogre::CullingMode culling_mode = Ogre::CULL_CLOCKWISE;
1047  Ogre::Technique* orig_tech = original_material->getTechnique(0);
1048  if (orig_tech && orig_tech->getNumPasses() > 0)
1049  {
1050  culling_mode = orig_tech->getPass(0)->getCullingMode();
1051  }
1052 
1053  // find out if the renderable has the picking param set
1054  bool has_pick_param = !rend->getUserObjectBindings().getUserAny("pick_handle").isEmpty();
1055 
1056  // NOTE: it is important to avoid changing the culling mode of the
1057  // fallback techniques here, because that change then propagates to
1058  // other uses of these fallback techniques in unpredictable ways.
1059  // If you want to change the technique programmatically (like with
1060  // Pass::setCullingMode()), make sure you do it on a cloned material
1061  // which doesn't get shared with other objects.
1062 
1063  // Use the technique with the right name and culling mode.
1064  if (culling_mode == Ogre::CULL_CLOCKWISE)
1065  {
1066  if (scheme_name == "Pick")
1067  {
1069  }
1070  else if (scheme_name == "Depth")
1071  {
1073  }
1074  if (scheme_name == "Pick1")
1075  {
1077  }
1078  else
1079  {
1080  return nullptr;
1081  }
1082  }
1083  else // Must be CULL_NONE because we never use CULL_ANTICLOCKWISE
1084  {
1085  if (scheme_name == "Pick")
1086  {
1087  return has_pick_param ? fallback_pick_technique_ : fallback_black_technique_;
1088  }
1089  else if (scheme_name == "Depth")
1090  {
1092  }
1093  if (scheme_name == "Pick1")
1094  {
1096  }
1097  else
1098  {
1099  return nullptr;
1100  }
1101  }
1102 }
1103 
1105 {
1106  float r = ((handle >> 16) & 0xff) / 255.0f;
1107  float g = ((handle >> 8) & 0xff) / 255.0f;
1108  float b = (handle & 0xff) / 255.0f;
1109  return Ogre::ColourValue(r, g, b, 1.0f);
1110 }
1111 
1113  const Ogre::ColourValue& color,
1114  Ogre::SceneNode* node)
1115 {
1116  if (!node)
1117  {
1118  return;
1119  }
1120  // Loop over all objects attached to this node.
1121  Ogre::SceneNode::ObjectIterator obj_it = node->getAttachedObjectIterator();
1122  while (obj_it.hasMoreElements())
1123  {
1124  Ogre::MovableObject* obj = obj_it.getNext();
1125  setPickData(handle, color, obj);
1126  }
1127  // Loop over and recurse into all child nodes.
1128  Ogre::SceneNode::ChildNodeIterator child_it = node->getChildIterator();
1129  while (child_it.hasMoreElements())
1130  {
1131  Ogre::SceneNode* child = dynamic_cast<Ogre::SceneNode*>(child_it.getNext());
1132  setPickData(handle, color, child);
1133  }
1134 }
1135 
1136 class PickColorSetter : public Ogre::Renderable::Visitor
1137 {
1138 public:
1139  PickColorSetter(CollObjectHandle handle, const Ogre::ColourValue& color)
1140  : color_vector_(color.r, color.g, color.b, 1.0), handle_(handle)
1141  {
1142  }
1143 
1144  void visit(Ogre::Renderable* rend,
1145  ushort /*lodIndex*/,
1146  bool /*isDebug*/,
1147  Ogre::Any* /*pAny*/ = nullptr) override
1148  {
1149  rend->setCustomParameter(PICK_COLOR_PARAMETER, color_vector_);
1150  rend->getUserObjectBindings().setUserAny("pick_handle", Ogre::Any(handle_));
1151  }
1152 
1153  Ogre::Vector4 color_vector_;
1155 };
1156 
1158  const Ogre::ColourValue& color,
1159  Ogre::MovableObject* object)
1160 {
1161  PickColorSetter visitor(handle, color);
1162  object->visitRenderables(&visitor);
1163  object->getUserObjectBindings().setUserAny("pick_handle", Ogre::Any(handle));
1164 }
1165 
1167 {
1168  boost::recursive_mutex::scoped_lock lock(global_mutex_);
1169 
1170  M_CollisionObjectToSelectionHandler::iterator it = objects_.find(obj);
1171  if (it != objects_.end())
1172  {
1173  return it->second;
1174  }
1175 
1176  return nullptr;
1177 }
1178 
1180 {
1181  boost::recursive_mutex::scoped_lock lock(global_mutex_);
1182 
1183  M_Picked::const_iterator it = objs.begin();
1184  M_Picked::const_iterator end = objs.end();
1185  for (; it != end; ++it)
1186  {
1187  removeSelectedObject(it->second);
1188  }
1189 
1190  selectionRemoved(objs);
1191 }
1192 
1194 {
1195  boost::recursive_mutex::scoped_lock lock(global_mutex_);
1196 
1197  M_Picked added;
1198  M_Picked::const_iterator it = objs.begin();
1199  M_Picked::const_iterator end = objs.end();
1200  for (; it != end; ++it)
1201  {
1202  std::pair<Picked, bool> ppb = addSelectedObject(it->second);
1203  if (ppb.second)
1204  {
1205  added.insert(std::make_pair(it->first, ppb.first));
1206  }
1207  }
1208 
1209  selectionAdded(added);
1210 }
1211 
1213 {
1214  boost::recursive_mutex::scoped_lock lock(global_mutex_);
1215 
1216  M_Picked original(selection_.begin(), selection_.end());
1217 
1218  removeSelection(original);
1219  addSelection(objs);
1220 }
1221 
1222 std::pair<Picked, bool> SelectionManager::addSelectedObject(const Picked& obj)
1223 {
1224  boost::recursive_mutex::scoped_lock lock(global_mutex_);
1225 
1226  std::pair<M_Picked::iterator, bool> pib = selection_.insert(std::make_pair(obj.handle, obj));
1227 
1228  SelectionHandler* handler = getHandler(obj.handle);
1229 
1230  if (pib.second)
1231  {
1232  handler->onSelect(obj);
1233  return std::make_pair(obj, true);
1234  }
1235  else
1236  {
1237  Picked& cur = pib.first->second;
1238  Picked added(cur.handle);
1239 
1240  S_uint64::iterator it = obj.extra_handles.begin();
1241  S_uint64::iterator end = obj.extra_handles.end();
1242  for (; it != end; ++it)
1243  {
1244  if (cur.extra_handles.insert(*it).second)
1245  {
1246  added.extra_handles.insert(*it);
1247  }
1248  }
1249 
1250  if (!added.extra_handles.empty())
1251  {
1252  handler->onSelect(added);
1253 
1254  return std::make_pair(added, true);
1255  }
1256  }
1257 
1258  return std::make_pair(Picked(0), false);
1259 }
1260 
1262 {
1263  boost::recursive_mutex::scoped_lock lock(global_mutex_);
1264 
1265  M_Picked::iterator sel_it = selection_.find(obj.handle);
1266  if (sel_it != selection_.end())
1267  {
1268  S_uint64::iterator extra_it = obj.extra_handles.begin();
1269  S_uint64::iterator extra_end = obj.extra_handles.end();
1270  for (; extra_it != extra_end; ++extra_it)
1271  {
1272  sel_it->second.extra_handles.erase(*extra_it);
1273  }
1274 
1275  if (sel_it->second.extra_handles.empty())
1276  {
1277  selection_.erase(sel_it);
1278  }
1279  }
1280 
1281  SelectionHandler* handler = getHandler(obj.handle);
1282  handler->onDeselect(obj);
1283 }
1284 
1286 {
1287  boost::recursive_mutex::scoped_lock lock(global_mutex_);
1288 
1289  if (selection_.empty())
1290  {
1291  return;
1292  }
1293 
1294  Ogre::AxisAlignedBox combined;
1295 
1296  M_Picked::iterator it = selection_.begin();
1297  M_Picked::iterator end = selection_.end();
1298  for (; it != end; ++it)
1299  {
1300  const Picked& p = it->second;
1301 
1302  SelectionHandler* handler = getHandler(p.handle);
1303 
1304  V_AABB aabbs;
1305  handler->getAABBs(p, aabbs);
1306 
1307  V_AABB::iterator aabb_it = aabbs.begin();
1308  V_AABB::iterator aabb_end = aabbs.end();
1309  for (; aabb_it != aabb_end; ++aabb_it)
1310  {
1311  combined.merge(*aabb_it);
1312  }
1313  }
1314 
1315  if (!combined.isInfinite() && !combined.isNull())
1316  {
1317  Ogre::Vector3 center = combined.getCenter();
1319  if (controller)
1320  {
1321  controller->lookAt(center);
1322  }
1323  }
1324 }
1325 
1327 {
1328  M_Picked::const_iterator it = removed.begin();
1329  M_Picked::const_iterator end = removed.end();
1330  for (; it != end; ++it)
1331  {
1332  const Picked& picked = it->second;
1333  SelectionHandler* handler = getHandler(picked.handle);
1334  ROS_ASSERT(handler);
1335 
1336  handler->destroyProperties(picked, property_model_->getRoot());
1337  }
1338 }
1339 
1341 {
1342  M_Picked::const_iterator it = added.begin();
1343  M_Picked::const_iterator end = added.end();
1344  for (; it != end; ++it)
1345  {
1346  const Picked& picked = it->second;
1347  SelectionHandler* handler = getHandler(picked.handle);
1348  ROS_ASSERT(handler);
1349 
1350  handler->createProperties(picked, property_model_->getRoot());
1351  }
1352  property_model_->sort(0, Qt::AscendingOrder);
1353 }
1354 
1356 {
1357  M_Picked::const_iterator it = selection_.begin();
1358  M_Picked::const_iterator end = selection_.end();
1359  for (; it != end; ++it)
1360  {
1361  CollObjectHandle handle = it->first;
1362  SelectionHandler* handler = getHandler(handle);
1363 
1364  handler->updateProperties();
1365  }
1366 }
1367 
1368 
1369 } // namespace rviz
std::vector< uint64_t > V_uint64
Definition: forwards.h:51
d
ViewController * getCurrent() const
Return the current ViewController in use for the main RenderWindow.
void publishDebugImage(const Ogre::PixelBox &pixel_box, const std::string &label)
ROSCPP_DECL void start()
CollObjectHandle createHandle()
void removeSelectedObject(const Picked &obj)
f
void selectionAdded(const M_Picked &added)
virtual void updateProperties()
Override to update property values.
boost::unordered_map< CollObjectHandle, Picked > M_Picked
Definition: forwards.h:63
SelectionManager(VisualizationManager *manager)
Ogre::TexturePtr render_textures_[s_num_render_textures_]
void setSelection(const M_Picked &objs)
A single element of a property tree, with a name, value, description, and possibly children...
Definition: property.h:100
void lookAt(float x, float y, float z)
Convenience function which calls lookAt(Ogre::Vector3).
S_uint64 extra_handles
Definition: forwards.h:61
void removeObject(CollObjectHandle obj)
virtual InteractiveObjectWPtr getInteractiveObject()
Get the object to listen to mouse events and other interaction calls during use of the &#39;interact&#39; too...
virtual void preRenderPass(uint32_t pass)
void unlockRender()
Unlock a mutex, allowing calls to Ogre::Root::renderOneFrame().
void addObject(CollObjectHandle obj, SelectionHandler *handler)
CollObjectHandle handle
Definition: forwards.h:59
virtual bool needsAdditionalRenderPass(uint32_t)
static Ogre::ColourValue handleToColor(CollObjectHandle handle)
void lockRender()
Lock a mutex to delay calls to Ogre::Root::renderOneFrame().
#define ROS_WARN(...)
Ogre::SceneManager * getSceneManager() const override
Returns the Ogre::SceneManager used for the main RenderPanel.
Ogre::Technique * fallback_black_cull_technique_
void setDebugMode(bool debug)
Enables or disables publishing of picking and depth rendering images.
Ogre::PixelBox pixel_boxes_[s_num_render_textures_]
void setDepthTextureSize(unsigned width, unsigned height)
void highlight(Ogre::Viewport *viewport, int x1, int y1, int x2, int y2)
Ogre::Technique * fallback_pick_cull_technique_
void enableInteraction(bool enable)
void setHighlightRect(Ogre::Viewport *viewport, int x1, int y1, int x2, int y2)
void publish(const boost::shared_ptr< M > &message) const
std::vector< Ogre::AxisAlignedBox > V_AABB
PropertyTreeModel * property_model_
bool get3DPatch(Ogre::Viewport *viewport, const int x, const int y, const unsigned width, const unsigned height, const bool skip_missing, std::vector< Ogre::Vector3 > &result_points)
Gets the 3D points in a box around a point in a view port.
void updateProperties()
Call updateProperties() on all SelectionHandlers in the current selection.
Ogre::Technique * fallback_pick_technique_
RenderPanel * getRenderPanel() const
Return the main RenderPanel.
Property * getRoot() const
virtual void getAABBs(const Picked &obj, V_AABB &aabbs)
void visit(Ogre::Renderable *rend, ushort, bool, Ogre::Any *=nullptr) override
static const uint32_t s_num_render_textures_
Ogre::Viewport * getViewport() const
Ogre::Technique * fallback_depth_cull_technique_
void select(Ogre::Viewport *viewport, int x1, int y1, int x2, int y2, SelectType type)
void removeSelection(const M_Picked &objs)
The VisualizationManager class is the central manager class of rviz, holding all the Displays...
SelectionHandler * getHandler(CollObjectHandle obj)
std::vector< CollObjectHandle > V_CollObject
Definition: forwards.h:46
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
Ogre::TexturePtr depth_render_texture_
bool render(Ogre::Viewport *viewport, Ogre::TexturePtr tex, int x1, int y1, int x2, int y2, Ogre::PixelBox &dst_box, std::string material_scheme, unsigned texture_width, unsigned textured_height)
std::pair< Picked, bool > addSelectedObject(const Picked &obj)
virtual void createProperties(const Picked &, Property *)
Override to create properties of the given picked object(s).
#define PICK_COLOR_PARAMETER
void pick(Ogre::Viewport *viewport, int x1, int y1, int x2, int y2, M_Picked &results, bool single_render_pass=false)
Ogre::Technique * fallback_depth_technique_
virtual void onSelect(const Picked &obj)
Ogre::Technique * handleSchemeNotFound(unsigned short scheme_index, const Ogre::String &scheme_name, Ogre::Material *original_material, unsigned short lod_index, const Ogre::Renderable *rend) override
uint32_t colorToHandle(Ogre::PixelFormat fmt, uint32_t col)
Definition: forwards.h:66
Ogre::SceneNode * highlight_node_
static WallTime now()
virtual void destroyProperties(const Picked &obj, Property *parent_property)
Destroy all properties for the given picked object(s).
void unpackColors(Ogre::PixelBox &box, V_CollObject &pixels)
static void setPickData(CollObjectHandle handle, const Ogre::ColourValue &color, Ogre::SceneNode *node)
virtual void postRenderPass(uint32_t pass)
void addSelection(const M_Picked &objs)
void setTextureSize(unsigned size)
VisualizationManager * vis_manager_
virtual void onDeselect(const Picked &obj)
static Time now()
Ogre::Rectangle2D * highlight_rectangle_
void selectionRemoved(const M_Picked &removed)
void renderAndUnpack(Ogre::Viewport *viewport, uint32_t pass, int x1, int y1, int x2, int y2, V_CollObject &pixels)
void renderQueueStarted(uint8_t queueGroupId, const std::string &invocation, bool &skipThisInvocation) override
#define ROS_ERROR_STREAM(args)
#define ROS_ASSERT(cond)
Ogre::MaterialPtr fallback_pick_material_
PickColorSetter(CollObjectHandle handle, const Ogre::ColourValue &color)
bool get3DPoint(Ogre::Viewport *viewport, const int x, const int y, Ogre::Vector3 &result_point)
Ogre::Technique * fallback_black_technique_
ViewManager * getViewManager() const override
Return a pointer to the ViewManager.
r
Ogre::PixelBox depth_pixel_box_
#define ROS_ERROR(...)
boost::recursive_mutex global_mutex_
std::set< CollObjectHandle > S_CollObject
Definition: forwards.h:48
M_CollisionObjectToSelectionHandler objects_
bool getPatchDepthImage(Ogre::Viewport *viewport, const int x, const int y, const unsigned width, const unsigned height, std::vector< float > &depth_vector)
Renders a depth image in a box around a point in a view port.
uint32_t CollObjectHandle
Definition: forwards.h:45
#define ROS_DEBUG(...)


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Sat May 27 2023 02:06:25