PathVecDisplay.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 <boost/bind.hpp>
31 
32 #include <OgreSceneNode.h>
33 #include <OgreSceneManager.h>
34 #include <OgreManualObject.h>
35 #include <OgreBillboardSet.h>
36 #include <OgreMatrix4.h>
37 
38 #include <tf/transform_listener.h>
39 
40 #include "rviz/display_context.h"
41 #include "rviz/frame_manager.h"
47 #include "rviz/validate_floats.h"
48 
50 
51 // #include <PathVec/PathVecVisual.h>
52 #include <PathVec/PathVecDisplay.h>
53 
54 using namespace rviz;
55 
56 namespace tuw_nav_rviz
57 {
58 
59 PathVecDisplay::PathVecDisplay()
60 {
61  style_property_ = new EnumProperty( "Line Style", "Lines",
62  "The rendering operation to use to draw the grid lines.",
63  this, SLOT( updateStyle() ));
64 
65  style_property_->addOption( "Lines", LINES );
66  style_property_->addOption( "Billboards", BILLBOARDS );
67 
68  line_width_property_ = new FloatProperty( "Line Width", 0.03,
69  "The width, in meters, of each path line."
70  "Only works with the 'Billboards' style.",
71  this, SLOT( updateLineWidth() ), this );
72  line_width_property_->setMin( 0.001 );
73  line_width_property_->hide();
74 
75  color_property_ = new ColorProperty( "Color", QColor( 25, 255, 0 ),
76  "Color to draw the path.", this );
77 
78  alpha_property_ = new FloatProperty( "Alpha", 1.0,
79  "Amount of transparency to apply to the path.", this );
80 
81  buffer_length_property_ = new IntProperty( "Buffer Length", 1,
82  "Number of paths to display.",
83  this, SLOT( updateBufferLength() ));
84  buffer_length_property_->setMin( 1 );
85 
86  offset_property_ = new VectorProperty( "Offset", Ogre::Vector3::ZERO,
87  "Allows you to offset the path from the origin of the reference frame. In meters.",
88  this, SLOT( updateOffset() ));
89 
90  pose_style_property_ = new EnumProperty( "Pose Style", "None", "Shape to display the pose as.",
91  this, SLOT( updatePoseStyle() ));
92  pose_style_property_->addOption( "None", NONE );
93  pose_style_property_->addOption( "Axes", AXES );
94  pose_style_property_->addOption( "Arrows", ARROWS );
95 
96  pose_axes_length_property_ = new rviz::FloatProperty( "Length", 0.3,
97  "Length of the axes.",
98  this, SLOT(updatePoseAxisGeometry()) );
99  pose_axes_radius_property_ = new rviz::FloatProperty( "Radius", 0.03,
100  "Radius of the axes.",
101  this, SLOT(updatePoseAxisGeometry()) );
102 
103  pose_arrow_color_property_ = new ColorProperty( "Color",
104  QColor( 255, 85, 255 ),
105  "Color to draw the poses.",
106  this, SLOT(updatePoseArrowColor()));
107  pose_arrow_shaft_length_property_ = new rviz::FloatProperty( "Shaft Length", 0.1,
108  "Length of the arrow shaft.",
109  this,
110  SLOT(updatePoseArrowGeometry()));
111  pose_arrow_head_length_property_ = new rviz::FloatProperty( "Head Length", 0.2,
112  "Length of the arrow head.",
113  this,
114  SLOT(updatePoseArrowGeometry()));
115  pose_arrow_shaft_diameter_property_ = new rviz::FloatProperty( "Shaft Diameter", 0.1,
116  "Diameter of the arrow shaft.",
117  this,
118  SLOT(updatePoseArrowGeometry()));
119  pose_arrow_head_diameter_property_ = new rviz::FloatProperty( "Head Diameter", 0.3,
120  "Diameter of the arrow head.",
121  this,
122  SLOT(updatePoseArrowGeometry()));
123  pose_axes_length_property_->hide();
124  pose_axes_radius_property_->hide();
125  pose_arrow_color_property_->hide();
126  pose_arrow_shaft_length_property_->hide();
127  pose_arrow_head_length_property_->hide();
128  pose_arrow_shaft_diameter_property_->hide();
129  pose_arrow_head_diameter_property_->hide();
130 }
131 
132 PathVecDisplay::~PathVecDisplay()
133 {
134  destroyObjects();
135  destroyPoseAxesChain();
136  destroyPoseArrowChain();
137 }
138 
139 void PathVecDisplay::onInitialize()
140 {
141  MFDClass::onInitialize();
142  updateBufferLength();
143 }
144 
145 void PathVecDisplay::reset()
146 {
147  MFDClass::reset();
148  updateBufferLength();
149 }
150 
151 
152 void PathVecDisplay::allocateAxesVector(std::vector<rviz::Axes*>& axes_vect, int num)
153 {
154  if (num > axes_vect.size()) {
155  for (size_t i = axes_vect.size(); i < num; i++) {
156  rviz::Axes* axes = new rviz::Axes( scene_manager_, scene_node_,
157  pose_axes_length_property_->getFloat(),
158  pose_axes_radius_property_->getFloat());
159  axes_vect.push_back(axes);
160  }
161  }
162  else if (num < axes_vect.size()) {
163  for (int i = axes_vect.size() - 1; num <= i; i--) {
164  delete axes_vect[i];
165  }
166  axes_vect.resize(num);
167  }
168 }
169 
170 void PathVecDisplay::allocateArrowVector(std::vector<rviz::Arrow*>& arrow_vect, int num)
171 {
172  if (num > arrow_vect.size()) {
173  for (size_t i = arrow_vect.size(); i < num; i++) {
174  rviz::Arrow* arrow = new rviz::Arrow( scene_manager_, scene_node_ );
175  arrow_vect.push_back(arrow);
176  }
177  }
178  else if (num < arrow_vect.size()) {
179  for (int i = arrow_vect.size() - 1; num <= i; i--) {
180  delete arrow_vect[i];
181  }
182  arrow_vect.resize(num);
183  }
184 }
185 
186 void PathVecDisplay::destroyPoseAxesChain()
187 {
188  for( size_t i = 0; i < axes_chain_.size(); i++ )
189  {
190  for( size_t j = 0; j < axes_chain_[i].size(); j++ )
191  {
192  allocateAxesVector(axes_chain_[i][j], 0);
193  }
194  axes_chain_[i].resize(0);
195  }
196  axes_chain_.resize(0);
197 }
198 
199 void PathVecDisplay::destroyPoseArrowChain()
200 {
201  for( size_t i = 0; i < arrow_chain_.size(); i++ )
202  {
203  for( size_t j = 0; j < arrow_chain_[i].size(); j++ )
204  {
205  allocateArrowVector(arrow_chain_[i][j], 0);
206  }
207  arrow_chain_[i].resize(0);
208  }
209  arrow_chain_.resize(0);
210 }
211 
212 void PathVecDisplay::updateStyle()
213 {
214  LineStyle style = (LineStyle) style_property_->getOptionInt();
215 
216  switch( style )
217  {
218  case LINES:
219  default:
220  line_width_property_->hide();
221  break;
222 
223  case BILLBOARDS:
224  line_width_property_->show();
225  break;
226  }
227 
228  updateBufferLength();
229 }
230 
231 void PathVecDisplay::updateLineWidth()
232 {
233  LineStyle style = (LineStyle) style_property_->getOptionInt();
234  float line_width = line_width_property_->getFloat();
235 
236  if(style == BILLBOARDS) {
237  for( size_t i = 0; i < billboard_lines_.size(); i++ )
238  for( size_t j = 0; j < billboard_lines_[i].size(); j++ )
239  {
240  rviz::BillboardLine* billboard_line = billboard_lines_[ i ][ j ];
241  if( billboard_line ) billboard_line->setLineWidth( line_width );
242  }
243  }
244  context_->queueRender();
245 }
246 
247 void PathVecDisplay::updateOffset()
248 {
249  scene_node_->setPosition( offset_property_->getVector() );
250  context_->queueRender();
251 }
252 
253 void PathVecDisplay::updatePoseStyle()
254 {
255  PoseStyle pose_style = (PoseStyle) pose_style_property_->getOptionInt();
256  switch (pose_style)
257  {
258  case AXES:
259  pose_axes_length_property_->show();
260  pose_axes_radius_property_->show();
261  pose_arrow_color_property_->hide();
262  pose_arrow_shaft_length_property_->hide();
263  pose_arrow_head_length_property_->hide();
264  pose_arrow_shaft_diameter_property_->hide();
265  pose_arrow_head_diameter_property_->hide();
266  break;
267  case ARROWS:
268  pose_axes_length_property_->hide();
269  pose_axes_radius_property_->hide();
270  pose_arrow_color_property_->show();
271  pose_arrow_shaft_length_property_->show();
272  pose_arrow_head_length_property_->show();
273  pose_arrow_shaft_diameter_property_->show();
274  pose_arrow_head_diameter_property_->show();
275  break;
276  default:
277  pose_axes_length_property_->hide();
278  pose_axes_radius_property_->hide();
279  pose_arrow_color_property_->hide();
280  pose_arrow_shaft_length_property_->hide();
281  pose_arrow_head_length_property_->hide();
282  pose_arrow_shaft_diameter_property_->hide();
283  pose_arrow_head_diameter_property_->hide();
284  }
285  updateBufferLength();
286 }
287 
288 void PathVecDisplay::updatePoseAxisGeometry()
289 {
290  for(size_t i = 0; i < axes_chain_.size() ; i++)
291  {
292  for(size_t j = 0; i < axes_chain_[i].size() ; j++)
293  {
294  std::vector<rviz::Axes*>& axes_vect = axes_chain_[i][j];
295  for(size_t k = 0; k < axes_vect.size() ; k++)
296  {
297  axes_vect[k]->set( pose_axes_length_property_->getFloat(),
298  pose_axes_radius_property_->getFloat() );
299  }
300  }
301  }
302  context_->queueRender();
303 }
304 
305 void PathVecDisplay::updatePoseArrowColor()
306 {
307  QColor color = pose_arrow_color_property_->getColor();
308 
309  for( size_t i = 0; i < arrow_chain_.size(); i++ )
310  {
311  for( size_t j = 0; j < arrow_chain_[i].size(); j++ )
312  {
313  std::vector<rviz::Arrow*>& arrow_vect = arrow_chain_[i][j];
314  for( size_t k = 0; k < arrow_vect.size(); k++ )
315  {
316  arrow_vect[k]->setColor( color.redF(), color.greenF(), color.blueF(), 1.0f );
317  }
318  }
319  }
320  context_->queueRender();
321 }
322 
323 void PathVecDisplay::updatePoseArrowGeometry()
324 {
325  for( size_t i = 0; i < arrow_chain_.size(); i++ )
326  {
327  for( size_t j = 0; j < arrow_chain_[i].size(); j++ )
328  {
329  std::vector<rviz::Arrow*>& arrow_vect = arrow_chain_[i][j];
330  for( size_t k = 0; k < arrow_vect.size(); k++ )
331  {
332  arrow_vect[k]->set(pose_arrow_shaft_length_property_->getFloat(),
333  pose_arrow_shaft_diameter_property_->getFloat(),
334  pose_arrow_head_length_property_->getFloat(),
335  pose_arrow_head_diameter_property_->getFloat());
336  }
337  }
338  }
339  context_->queueRender();
340 }
341 
342 void PathVecDisplay::destroyObjects()
343 {
344  // Destroy all simple lines, if any
345  for( size_t i = 0; i < manual_objects_.size(); i++ )
346  {
347  for( size_t j = 0; j < manual_objects_[i].size(); j++ )
348  {
349  Ogre::ManualObject*& manual_object = manual_objects_[ i ][ j ];
350  if( manual_object )
351  {
352  manual_object->clear();
353  scene_manager_->destroyManualObject( manual_object );
354  manual_object = NULL; // ensure it doesn't get destroyed again
355  }
356  }
357  }
358 
359  // Destroy all billboards, if any
360  for( size_t i = 0; i < billboard_lines_.size(); i++ )
361  {
362  for( size_t j = 0; j < billboard_lines_[i].size(); j++ )
363  {
364  rviz::BillboardLine*& billboard_line = billboard_lines_[ i ][ j ];
365  if( billboard_line )
366  {
367  delete billboard_line; // also destroys the corresponding scene node
368  billboard_line = NULL; // ensure it doesn't get destroyed again
369  }
370  }
371  }
372 }
373 
374 void PathVecDisplay::updateBufferLength()
375 {
376  // Delete old path objects
377  destroyObjects();
378 
379  // Destroy all axes and arrows
380  destroyPoseAxesChain();
381  destroyPoseArrowChain();
382 
383  // Read options
384  int buffer_length = buffer_length_property_->getInt();
385  LineStyle style = (LineStyle) style_property_->getOptionInt();
386  pathsSize_ .resize( buffer_length );
387 
388  // Create new path objects
389  switch(style)
390  {
391  case LINES: // simple lines with fixed width of 1px
392  manual_objects_.resize( buffer_length );
393  for( size_t i = 0; i < manual_objects_.size(); i++ )
394  {
395  manual_objects_[i].resize(pathsSize_[i]);
396  for( size_t j = 0; j < manual_objects_[i].size(); j++ )
397  {
398  Ogre::ManualObject* manual_object = scene_manager_->createManualObject();
399  manual_object->setDynamic( true );
400  scene_node_->attachObject( manual_object );
401 
402  manual_objects_[ i ][ j ] = manual_object;
403  }
404  }
405  break;
406 
407  case BILLBOARDS: // billboards with configurable width
408  billboard_lines_.resize( buffer_length );
409  for( size_t i = 0; i < billboard_lines_.size(); i++ )
410  {
411  billboard_lines_[i].resize(pathsSize_[i]);
412  for( size_t j = 0; j < billboard_lines_[i].size(); j++ )
413  {
414  rviz::BillboardLine* billboard_line = new rviz::BillboardLine(scene_manager_, scene_node_);
415  billboard_lines_[ i ][ j ] = billboard_line;
416  }
417  }
418  break;
419  }
420  axes_chain_ .resize( buffer_length ); for( size_t i = 0; i < axes_chain_ .size(); ++i ){ axes_chain_ [i].resize(pathsSize_[i]); }
421  arrow_chain_.resize( buffer_length ); for( size_t i = 0; i < arrow_chain_.size(); ++i ){ arrow_chain_[i].resize(pathsSize_[i]); }
422 
423 }
424 
425 bool validateFloats( const tuw_nav_msgs::PathVec& msg )
426 {
427  bool valid = true;
428  for(auto& msgPathI : msg.paths){ valid = valid && rviz::validateFloats( msgPathI.poses ); }
429  return valid;
430 }
431 
432 void PathVecDisplay::processMessage( const tuw_nav_msgs::PathVec::ConstPtr& msg )
433 {
434  // Calculate index of oldest element in cyclic buffer
435  size_t bufferIndex = messages_received_ % buffer_length_property_->getInt();
436  LineStyle style = (LineStyle) style_property_->getOptionInt();
437  pathsSize_ [bufferIndex] = msg->paths.size();
438 
439  updateBufferLength();
440 
441  // Check if path contains invalid coordinate values
442  if( !validateFloats( *msg ))
443  {
444  setStatus( rviz::StatusProperty::Error, "Topic", "Message contained invalid floating point values (nans or infs)" );
445  return;
446  }
447 
448  // Lookup transform into fixed frame
449  Ogre::Vector3 position;
450  Ogre::Quaternion orientation;
451  if( !context_->getFrameManager()->getTransform( msg->header, position, orientation ))
452  {
453  ROS_DEBUG( "Error transforming from frame '%s' to frame '%s'", msg->header.frame_id.c_str(), qPrintable( fixed_frame_ ));
454  }
455 
456  Ogre::Matrix4 transform( orientation );
457  transform.setTrans( position );
458 
459 // scene_node_->setPosition( position );
460 // scene_node_->setOrientation( orientation );
461 
462  Ogre::ColourValue color = color_property_->getOgreColor();
463  color.a = alpha_property_->getFloat();
464 
465  float line_width = line_width_property_->getFloat();
466  PoseStyle pose_style = (PoseStyle) pose_style_property_->getOptionInt();
467  QColor colorArrow = pose_arrow_color_property_->getColor();
468 
469  switch(style)
470  {
471  case LINES : manual_objects_ [bufferIndex].resize(msg->paths.size()); break;
472  case BILLBOARDS:billboard_lines_[bufferIndex].resize(msg->paths.size()); break;
473  }
474 
475  for( size_t k = 0; k < msg->paths.size(); ++k ) {
476 
477  auto& msgPathI = msg->paths[k];
478  uint32_t num_points = msgPathI.poses.size();
479 
480  switch(style)
481  {
482  case LINES: {
483  Ogre::ManualObject* manual_object = manual_objects_ [ bufferIndex ][k];
484  manual_object->estimateVertexCount( num_points );
485  manual_object->begin( "BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP );
486  for( uint32_t i=0; i < num_points; ++i)
487  {
488  const geometry_msgs::Point& pos = msgPathI.poses[ i ].pose.position;
489  Ogre::Vector3 xpos = transform * Ogre::Vector3( pos.x, pos.y, pos.z );
490  manual_object->position( xpos.x, xpos.y, xpos.z );
491  manual_object->colour( color );
492  }
493 
494  manual_object->end();
495  } break;
496 
497  case BILLBOARDS: {
498  rviz::BillboardLine* billboard_line = billboard_lines_[ bufferIndex ][k];
499  billboard_line->setNumLines( 1 );
500  billboard_line->setMaxPointsPerLine( num_points );
501  billboard_line->setLineWidth( line_width );
502 
503  for( uint32_t i=0; i < num_points; ++i)
504  {
505  const geometry_msgs::Point& pos = msgPathI.poses[ i ].pose.position;
506  Ogre::Vector3 xpos = transform * Ogre::Vector3( pos.x, pos.y, pos.z );
507  billboard_line->addPoint( xpos, color );
508  }
509 
510  } break;
511  }
512 
513  // process pose markers
514 
515  switch(pose_style)
516  {
517  case AXES: {
518  std::vector<rviz::Axes*>& axes_vect = axes_chain_ [ bufferIndex ][k];
519  allocateAxesVector(axes_vect, num_points);
520  for( uint32_t i=0; i < num_points; ++i)
521  {
522  const geometry_msgs::Point& pos = msgPathI.poses[ i ].pose.position;
523  Ogre::Vector3 xpos = transform * Ogre::Vector3( pos.x, pos.y, pos.z );
524  axes_vect[i]->setPosition(xpos);
525  Ogre::Quaternion orientation(msgPathI.poses[ i ].pose.orientation.w,
526  msgPathI.poses[ i ].pose.orientation.x,
527  msgPathI.poses[ i ].pose.orientation.y,
528  msgPathI.poses[ i ].pose.orientation.z);
529  axes_vect[i]->setOrientation(orientation);
530  }
531  } break;
532 
533  case ARROWS: {
534  std::vector<rviz::Arrow*>& arrow_vect = arrow_chain_[ bufferIndex ][k];
535  allocateArrowVector(arrow_vect, num_points);
536  for( uint32_t i=0; i < num_points; ++i)
537  {
538  const geometry_msgs::Point& pos = msgPathI.poses[ i ].pose.position;
539  Ogre::Vector3 xpos = transform * Ogre::Vector3( pos.x, pos.y, pos.z );
540 
541 
542  arrow_vect[i]->setColor( colorArrow.redF(), colorArrow.greenF(), colorArrow.blueF(), 1.0f );
543 
544  arrow_vect[i]->set(pose_arrow_shaft_length_property_->getFloat(),
545  pose_arrow_shaft_diameter_property_->getFloat(),
546  pose_arrow_head_length_property_->getFloat(),
547  pose_arrow_head_diameter_property_->getFloat());
548  arrow_vect[i]->setPosition(xpos);
549  Ogre::Quaternion orientation(msgPathI.poses[ i ].pose.orientation.w,
550  msgPathI.poses[ i ].pose.orientation.x,
551  msgPathI.poses[ i ].pose.orientation.y,
552  msgPathI.poses[ i ].pose.orientation.z);
553 
554  Ogre::Vector3 dir(1, 0, 0);
555  dir = orientation * dir;
556  arrow_vect[i]->setDirection(dir);
557  }
558  } break;
559 
560  default:
561  break;
562  }
563  }
564  context_->queueRender();
565 
566 }
567 
568 } // namespace tuw_nav_rviz
569 
#define NULL
void addPoint(const Ogre::Vector3 &point)
bool validateFloats(const visualization_msgs::InteractiveMarker &msg)
void setNumLines(uint32_t num)
void setMaxPointsPerLine(uint32_t max)
Displays a tuw_nav_msgs::PathVec message.
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
void setLineWidth(float width)
#define ROS_DEBUG(...)


tuw_nav_rviz
Author(s):
autogenerated on Mon Jun 10 2019 15:40:12