marker_utils.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009, 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 "marker_utils.h"
40 #include "rviz/display_context.h"
45 
46 
47 
48 namespace rviz
49 {
50 
51 MarkerBase* createMarker(int marker_type, MarkerDisplay* owner, DisplayContext* context, Ogre::SceneNode* parent_node)
52 {
53  switch (marker_type) {
54  case visualization_msgs::Marker::CUBE:
55  case visualization_msgs::Marker::CYLINDER:
56  case visualization_msgs::Marker::SPHERE:
57  return new rviz::ShapeMarker(owner, context, parent_node);
58 
59  case visualization_msgs::Marker::ARROW:
60  return new rviz::ArrowMarker(owner, context, parent_node);
61 
62  case visualization_msgs::Marker::LINE_STRIP:
63  return new rviz::LineStripMarker(owner, context, parent_node);
64 
65  case visualization_msgs::Marker::LINE_LIST:
66  return new rviz::LineListMarker(owner, context, parent_node);
67 
68  case visualization_msgs::Marker::SPHERE_LIST:
69  case visualization_msgs::Marker::CUBE_LIST:
70  case visualization_msgs::Marker::POINTS:
71  return new rviz::PointsMarker(owner, context, parent_node);
72 
73  case visualization_msgs::Marker::TEXT_VIEW_FACING:
74  return new rviz::TextViewFacingMarker(owner, context, parent_node);
75 
76  case visualization_msgs::Marker::MESH_RESOURCE:
77  return new rviz::MeshResourceMarker(owner, context, parent_node);
78 
79  case visualization_msgs::Marker::TRIANGLE_LIST:
80  return new rviz::TriangleListMarker(owner, context, parent_node);
81 
82  default:
83  return nullptr;
84  }
85 }
86 
87 bool checkMarkerMsg(const visualization_msgs::Marker& marker, MarkerDisplay* owner)
88 {
89 
90  if(marker.action != visualization_msgs::Marker::ADD)
91  return true;
92 
93  std::stringstream ss;
95 
96  switch (marker.type) {
97  case visualization_msgs::Marker::ARROW:
98  checkQuaternion(marker, ss, level);
99  checkScale(marker, ss, level);
100  checkColor(marker, ss, level);
101  checkPointsArrow(marker, ss, level);
102  checkColorsEmpty(marker, ss, level);
103  checkTextEmpty(marker, ss, level);
104  checkMeshEmpty(marker, ss, level);
105  break;
106 
107  case visualization_msgs::Marker::CUBE:
108  case visualization_msgs::Marker::CYLINDER:
109  case visualization_msgs::Marker::SPHERE:
110  checkQuaternion(marker, ss, level);
111  checkScale(marker, ss, level);
112  checkColor(marker, ss, level);
113  checkPointsEmpty(marker, ss, level);
114  checkColorsEmpty(marker, ss, level);
115  checkTextEmpty(marker, ss, level);
116  checkMeshEmpty(marker, ss, level);
117  break;
118 
119 
120  case visualization_msgs::Marker::LINE_STRIP:
121  case visualization_msgs::Marker::LINE_LIST:
122  checkQuaternion(marker, ss, level);
123  checkScaleLineStripAndList(marker, ss, level);
124  checkPointsNotEmpty(marker, ss, level);
125  checkColors(marker, ss, level);
126  checkTextEmpty(marker, ss, level);
127  checkMeshEmpty(marker, ss, level);
128  break;
129 
130  case visualization_msgs::Marker::SPHERE_LIST:
131  case visualization_msgs::Marker::CUBE_LIST:
132  case visualization_msgs::Marker::TRIANGLE_LIST:
133  checkQuaternion(marker, ss, level);
134  checkScale(marker, ss, level);
135  checkPointsNotEmpty(marker, ss, level);
136  checkColors(marker, ss, level);
137  checkTextEmpty(marker, ss, level);
138  checkMeshEmpty(marker, ss, level);
139  break;
140 
141  case visualization_msgs::Marker::POINTS:
142  checkScalePoints(marker, ss, level);
143  checkPointsNotEmpty(marker, ss, level);
144  checkColors(marker, ss, level);
145  checkTextEmpty(marker, ss, level);
146  checkMeshEmpty(marker, ss, level);
147  break;
148 
149  case visualization_msgs::Marker::TEXT_VIEW_FACING:
150  checkColor(marker, ss, level);
151  checkScaleText(marker, ss, level);
152  checkTextNotEmptyOrWhitespace(marker, ss, level);
153  checkPointsEmpty(marker, ss, level);
154  checkColorsEmpty(marker, ss, level);
155  checkMeshEmpty(marker, ss, level);
156  break;
157 
158  case visualization_msgs::Marker::MESH_RESOURCE:
159  checkQuaternion(marker, ss, level);
160  checkColor(marker, ss, level);
161  checkScale(marker, ss, level);
162  checkPointsEmpty(marker, ss, level);
163  checkColorsEmpty(marker, ss, level);
164  checkTextEmpty(marker, ss, level);
165  break;
166 
167  default:
168  ss << "Unknown marker type: " << marker.type << '.' ;
169  level = StatusProperty::Error;
170  }
171 
172  if(ss.tellp() != 0) //stringstream is not empty
173  {
174  std::string warning = ss.str();
175 
176  if (owner)
177  owner->setMarkerStatus(MarkerID(marker.ns, marker.id), level, warning);
179  ROSCONSOLE_DEFAULT_NAME, "Marker '%s/%d': %s", marker.ns.c_str(), marker.id, warning.c_str());
180 
181  return false;
182  }
183 
184  if (owner)
185  owner->deleteMarkerStatus(MarkerID(marker.ns, marker.id));
186  return true;
187 }
188 
189 bool checkMarkerArrayMsg(const visualization_msgs::MarkerArray& array, MarkerDisplay* owner)
190 {
191  std::vector<MarkerID> marker_ids;
192  marker_ids.reserve(array.markers.size());
193 
195  std::stringstream ss;
196  bool markers_added = false;
197 
198  for(const visualization_msgs::Marker& marker : array.markers)
199  {
200  if (marker.action == visualization_msgs::Marker::ADD)
201  markers_added = true;
202 
203  else if (marker.action == visualization_msgs::Marker::DELETEALL)
204  {
205  if (markers_added)
206  {
208  ss << "Found a DELETEALL after having markers added. These markers will never show";
210  }
211  markers_added = false;
212  // marker_ids.clear();
213  }
214 
215  MarkerID current_id(marker.ns, marker.id);
216  std::vector<MarkerID>::iterator search = std::lower_bound(marker_ids.begin(), marker_ids.end(), current_id);
217  if (search != marker_ids.end())
218  {
220  ss << "Found '" << marker.ns.c_str() << "/" << marker.id << "' multiple times";
222  }
223  else
224  {
225  marker_ids.insert(search, current_id);
226  }
227  }
228 
229  if(ss.tellp() != 0) //stringstream is not empty
230  {
231  std::string warning = ss.str();
232 
233  if (owner)
234  owner->setStatusStd(level, "marker_array", warning);
236  ROSCONSOLE_DEFAULT_NAME, "MarkerArray: %s", warning.c_str());
237 
238  return false;
239  }
240 
241  if (owner)
242  owner->deleteStatusStd("marker_array");
243  return true;
244 }
245 
246 
247 void checkQuaternion(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
248 {
249  if (marker.pose.orientation.x == 0.0 && marker.pose.orientation.y == 0.0 && marker.pose.orientation.z == 0.0 &&
250  marker.pose.orientation.w == 0.0)
251  {
253  ss << "Uninitialized quaternion assuming identity.";
255  }
256  else if(!validateQuaternions(marker.pose))
257  {
259  ss << "Unnormalized quaternion in marker message.";
261  }
262 }
263 
264 void checkScale(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
265 {
266  // for ARROW markers, scale.z is the optional head length
267  if(marker.type == visualization_msgs::Marker::ARROW && marker.scale.x != 0.0 && marker.scale.y != 0.0)
268  return;
269 
270  if(marker.scale.x == 0.0 || marker.scale.y == 0.0 || marker.scale.z == 0.0)
271  {
273  ss << "Scale contains 0.0 in x, y or z.";
275  }
276 }
277 
278 void checkScaleLineStripAndList(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
279 {
280  if(marker.scale.x == 0.0)
281  {
283  ss << "Width LINE_LIST or LINE_STRIP is 0.0 (scale.x).";
285  }
286  else if(marker.scale.y != 0.0 || marker.scale.z != 0.0)
287  {
289  ss << "scale.y and scale.z of LINE_LIST or LINE_STRIP are ignored.";
291  }
292 }
293 
294 void checkScalePoints(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
295 {
296  if(marker.scale.x == 0.0 || marker.scale.y == 0.0)
297  {
299  ss << "Width and/or height of POINTS is 0.0 (scale.x, scale.y).";
301  }
302  else if(marker.scale.z != 0.0)
303  {
305  ss << "scale.z of POINTS is ignored.";
307  }
308 }
309 
310 void checkScaleText(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
311 {
312  if(marker.scale.z == 0.0)
313  {
315  ss << "Text height of TEXT_VIEW_FACING is 0.0 (scale.z).";
317  }
318  else if(marker.scale.x != 0.0 || marker.scale.y != 0.0)
319  {
321  ss << "scale.x and scale.y of TEXT_VIEW_FACING are ignored.";
323  }
324 }
325 
326 void checkColor(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
327 {
328  if(marker.color.a == 0.0)
329  {
331  ss << "Marker is fully transparent (color.a is 0.0).";
333  }
334 }
335 
336 void checkPointsArrow(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
337 {
338  if(marker.points.size() != 0 && marker.points.size() != 2)
339  {
341  ss << "Number of points for an ARROW marker should be either 0 or 2.";
343  }
344 }
345 
346 void checkPointsNotEmpty(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
347 {
348  if(marker.points.empty())
349  {
351  ss << "Points should not be empty for specified marker type.";
353  }
354  else if(marker.type == visualization_msgs::Marker::TRIANGLE_LIST && (marker.points.size() % 3) != 0)
355  {
357  ss << "Number of points should be a multiple of 3 for TRIANGLE_LIST Marker.";
359  }
360  else if(marker.type == visualization_msgs::Marker::LINE_LIST && (marker.points.size() % 2) != 0)
361  {
363  ss << "Number of points should be a multiple of 2 for LINE_LIST Marker.";
365  }
366  else if(marker.type == visualization_msgs::Marker::LINE_STRIP && marker.points.size() <= 1)
367  {
369  ss << "At least two points are required for a LINE_STRIP Marker.";
371  }
372 }
373 
374 void checkPointsEmpty(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
375 {
376  if(!marker.points.empty())
377  {
379  ss << "Points array is ignored by specified marker type.";
381  }
382 }
383 
384 void checkColors(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
385 {
386  if(marker.colors.size() == 0)
387  {
388  checkColor(marker, ss, level);
389  return;
390  }
391  if(marker.colors.size() != marker.points.size())
392  {
394  ss << "Number of colors is not equal to number of points or 0.";
396  }
397 }
398 
399 void checkColorsEmpty(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
400 {
401  if(!marker.colors.empty())
402  {
404  ss << "Colors array is ignored by specified marker type.";
406  }
407 }
408 
409 void checkTextNotEmptyOrWhitespace(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
410 {
411  if(marker.text.empty())
412  {
414  ss << "Text is empty for TEXT_VIEW_FACING type marker.";
416  }
417  else if(marker.text.find_first_not_of(" \t\n\v\f\r") == std::string::npos)
418  {
420  ss << "Text of TEXT_VIEW_FACING Marker only consists of whitespaces.";
422  }
423 }
424 
425 void checkTextEmpty(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
426 {
427  if(!marker.text.empty())
428  {
430  ss << "Text is ignored for specified marker type.";
432  }
433 }
434 
435 void checkMesh(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
436 {
437  if(marker.mesh_resource.empty())
438  {
440  ss << "Path to mesh resource is empty for MESH_RESOURCE marker.";
442  }
443 }
444 
445 void checkMeshEmpty(const visualization_msgs::Marker& marker, std::stringstream& ss, StatusProperty::Level& level)
446 {
447  if (!marker.mesh_resource.empty())
448  {
450  ss << "Mesh_resource is ignored for specified marker type.";
452  }
453  if (marker.mesh_use_embedded_materials)
454  {
456  ss << "Using embedded materials is not supported for markers other than MESH_RESOURCE.";
458  }
459 }
460 
461 void addSeparatorIfRequired(std::stringstream& ss)
462 {
463  if (ss.tellp() != 0) // check if string is not empty
464  {
465  ss << " \n";
466  }
467 }
468 
470 {
471  if(new_status > current_status)
472  current_status = new_status;
473 }
474 } // namespace rviz
void setStatusStd(StatusProperty::Level level, const std::string &name, const std::string &text)
Show status level and text, using a std::string. Convenience function which converts std::string to Q...
Definition: display.h:157
void deleteStatusStd(const std::string &name)
Delete the status entry with the given std::string name. This is thread-safe.
Definition: display.h:166
void setMarkerStatus(MarkerID id, StatusLevel level, const std::string &text)
void checkColors(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void checkQuaternion(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
bool checkMarkerMsg(const visualization_msgs::Marker &marker, MarkerDisplay *owner)
void checkScale(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void checkPointsEmpty(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void checkColor(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void checkMesh(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void checkColorsEmpty(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
MarkerBase * createMarker(int marker_type, MarkerDisplay *owner, DisplayContext *context, Ogre::SceneNode *parent_node)
std::pair< std::string, int32_t > MarkerID
bool checkMarkerArrayMsg(const visualization_msgs::MarkerArray &array, MarkerDisplay *owner)
void increaseWarningLevel(StatusProperty::Level new_status, StatusProperty::Level &current_status)
void checkPointsArrow(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
Pure-virtual base class for objects which give Display subclasses context in which to work...
void checkPointsNotEmpty(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void addSeparatorIfRequired(std::stringstream &ss)
void deleteMarkerStatus(MarkerID id)
void checkTextNotEmptyOrWhitespace(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void checkMeshEmpty(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
#define ROS_LOG(level, name,...)
void checkScalePoints(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void checkScaleText(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
void checkScaleLineStripAndList(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
bool validateQuaternions(const visualization_msgs::InteractiveMarker &marker)
void checkTextEmpty(const visualization_msgs::Marker &marker, std::stringstream &ss, StatusProperty::Level &level)
ROSCPP_DECL bool search(const std::string &ns, const std::string &key, std::string &result)
Displays "markers" sent in by other ROS nodes on the "visualization_marker" topic.
#define ROSCONSOLE_DEFAULT_NAME


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Wed Aug 28 2019 04:01:51