57 case visualization_msgs::Marker::CUBE:
58 case visualization_msgs::Marker::CYLINDER:
59 case visualization_msgs::Marker::SPHERE:
62 case visualization_msgs::Marker::ARROW:
65 case visualization_msgs::Marker::LINE_STRIP:
68 case visualization_msgs::Marker::LINE_LIST:
71 case visualization_msgs::Marker::SPHERE_LIST:
72 case visualization_msgs::Marker::CUBE_LIST:
73 case visualization_msgs::Marker::POINTS:
76 case visualization_msgs::Marker::TEXT_VIEW_FACING:
79 case visualization_msgs::Marker::MESH_RESOURCE:
82 case visualization_msgs::Marker::TRIANGLE_LIST:
94 case visualization_msgs::Marker::ARROW:
96 case visualization_msgs::Marker::CUBE:
98 case visualization_msgs::Marker::CUBE_LIST:
100 case visualization_msgs::Marker::TRIANGLE_LIST:
101 return "Triangle List";
102 case visualization_msgs::Marker::SPHERE:
104 case visualization_msgs::Marker::SPHERE_LIST:
105 return "Sphere List";
106 case visualization_msgs::Marker::CYLINDER:
108 case visualization_msgs::Marker::LINE_STRIP:
110 case visualization_msgs::Marker::LINE_LIST:
112 case visualization_msgs::Marker::POINTS:
114 case visualization_msgs::Marker::TEXT_VIEW_FACING:
115 return "Text View Facing";
116 case visualization_msgs::Marker::MESH_RESOURCE:
125 void addSeparatorIfRequired(std::stringstream& ss)
136 if (new_status > current_status)
137 current_status = new_status;
140 template <
typename T>
141 constexpr
const char* fieldName();
143 constexpr
const char* fieldName<::geometry_msgs::Point>()
148 constexpr
const char* fieldName<::geometry_msgs::Quaternion>()
150 return "Orientation";
153 constexpr
const char* fieldName<::geometry_msgs::Vector3>()
158 constexpr
const char* fieldName<::std_msgs::ColorRGBA>()
163 template <
typename T>
168 addSeparatorIfRequired(ss);
169 ss << fieldName<T>() <<
" contains invalid floating point values (nans or infs)";
174 void checkQuaternion(
const visualization_msgs::Marker& marker,
175 std::stringstream& ss,
178 checkFloats(marker.pose.orientation, ss, level);
179 if (marker.pose.orientation.x == 0.0 && marker.pose.orientation.y == 0.0 &&
180 marker.pose.orientation.z == 0.0 && marker.pose.orientation.w == 0.0)
182 addSeparatorIfRequired(ss);
183 ss <<
"Uninitialized quaternion, assuming identity.";
188 addSeparatorIfRequired(ss);
189 ss <<
"Unnormalized quaternion in marker message.";
194 void checkScale(
const visualization_msgs::Marker& marker,
195 std::stringstream& ss,
198 checkFloats(marker.scale, ss, level);
200 if (marker.type == visualization_msgs::Marker::ARROW && marker.scale.x != 0.0 && marker.scale.y != 0.0)
203 if (marker.scale.x == 0.0 || marker.scale.y == 0.0 || marker.scale.z == 0.0)
205 addSeparatorIfRequired(ss);
206 ss <<
"Scale contains 0.0 in x, y or z.";
211 void checkScaleLineStripAndList(
const visualization_msgs::Marker& marker,
212 std::stringstream& ss,
215 if (marker.scale.x == 0.0)
217 addSeparatorIfRequired(ss);
218 ss <<
"Width LINE_LIST or LINE_STRIP is 0.0 (scale.x).";
223 void checkScalePoints(
const visualization_msgs::Marker& marker,
224 std::stringstream& ss,
227 if (marker.scale.x == 0.0 || marker.scale.y == 0.0)
229 addSeparatorIfRequired(ss);
230 ss <<
"Width and/or height of POINTS is 0.0 (scale.x, scale.y).";
235 void checkScaleText(
const visualization_msgs::Marker& marker,
236 std::stringstream& ss,
239 if (marker.scale.z == 0.0)
241 addSeparatorIfRequired(ss);
242 ss <<
"Text height of TEXT_VIEW_FACING is 0.0 (scale.z).";
247 void checkColor(
const visualization_msgs::Marker& marker,
248 std::stringstream& ss,
251 checkFloats(marker.color, ss, level);
252 if (marker.color.a == 0.0 &&
255 !(marker.type == visualization_msgs::Marker::MESH_RESOURCE && marker.mesh_use_embedded_materials &&
256 marker.color.r == 0.0 && marker.color.g == 0.0 && marker.color.b == 0.0))
258 addSeparatorIfRequired(ss);
259 ss <<
"Marker is fully transparent (color.a is 0.0).";
264 void checkPointsArrow(
const visualization_msgs::Marker& marker,
265 std::stringstream& ss,
268 if (!marker.points.empty() && marker.points.size() != 2)
270 addSeparatorIfRequired(ss);
271 ss <<
"Number of points for an ARROW marker should be either 0 or 2.";
275 for (
const auto& p : marker.points)
276 checkFloats(p, ss, level);
279 void checkPointsNotEmpty(
const visualization_msgs::Marker& marker,
280 std::stringstream& ss,
283 if (marker.points.empty())
285 addSeparatorIfRequired(ss);
286 ss <<
"Points should not be empty for specified marker type.";
291 case visualization_msgs::Marker::TRIANGLE_LIST:
292 if (marker.points.size() % 3 != 0)
294 addSeparatorIfRequired(ss);
295 ss <<
"Number of points should be a multiple of 3 for TRIANGLE_LIST marker.";
299 case visualization_msgs::Marker::LINE_LIST:
300 if (marker.points.size() % 2 != 0)
302 addSeparatorIfRequired(ss);
303 ss <<
"Number of points should be a multiple of 2 for LINE_LIST marker.";
307 case visualization_msgs::Marker::LINE_STRIP:
308 if (marker.points.size() <= 1)
310 addSeparatorIfRequired(ss);
311 ss <<
"At least two points are required for a LINE_STRIP marker.";
320 void checkPointsEmpty(
const visualization_msgs::Marker& marker,
321 std::stringstream& ss,
324 if (!marker.points.empty())
326 addSeparatorIfRequired(ss);
327 ss <<
"Non-empty points array is ignored.";
332 void checkColors(
const visualization_msgs::Marker& marker,
333 std::stringstream& ss,
335 unsigned int multiple)
337 if (marker.colors.empty())
339 checkColor(marker, ss, level);
342 if (marker.colors.size() != marker.points.size() &&
343 (multiple == 1 || multiple * marker.colors.size() != marker.points.size()))
345 addSeparatorIfRequired(ss);
346 ss <<
"Number of colors doesn't match number of points.";
351 void checkColorsEmpty(
const visualization_msgs::Marker& marker,
352 std::stringstream& ss,
355 if (!marker.colors.empty())
357 addSeparatorIfRequired(ss);
358 ss <<
"Non-empty colors array is ignored.";
363 void checkTextNotEmptyOrWhitespace(
const visualization_msgs::Marker& marker,
364 std::stringstream& ss,
367 if (marker.text.find_first_not_of(
" \t\n\v\f\r") == std::string::npos)
369 addSeparatorIfRequired(ss);
370 ss <<
"Text is empty or only consists of whitespace.";
375 void checkTextEmpty(
const visualization_msgs::Marker& marker,
376 std::stringstream& ss,
379 if (!marker.text.empty())
381 addSeparatorIfRequired(ss);
382 ss <<
"Non-empty text is ignored.";
387 void checkMesh(
const visualization_msgs::Marker& marker,
388 std::stringstream& ss,
391 if (marker.mesh_resource.empty())
393 addSeparatorIfRequired(ss);
394 ss <<
"Empty mesh_resource path.";
399 void checkMeshEmpty(
const visualization_msgs::Marker& marker,
400 std::stringstream& ss,
403 if (!marker.mesh_resource.empty())
405 addSeparatorIfRequired(ss);
406 ss <<
"Non-empty mesh_resource is ignored.";
409 if (marker.mesh_use_embedded_materials)
411 addSeparatorIfRequired(ss);
412 ss <<
"mesh_use_embedded_materials is ignored.";
421 if (marker.action != visualization_msgs::Marker::ADD)
424 std::stringstream ss;
426 checkFloats(marker.pose.position, ss, level);
430 case visualization_msgs::Marker::ARROW:
431 checkQuaternion(marker, ss, level);
432 checkScale(marker, ss, level);
433 checkColor(marker, ss, level);
434 checkPointsArrow(marker, ss, level);
435 checkColorsEmpty(marker, ss, level);
436 checkTextEmpty(marker, ss, level);
437 checkMeshEmpty(marker, ss, level);
440 case visualization_msgs::Marker::CUBE:
441 case visualization_msgs::Marker::CYLINDER:
442 case visualization_msgs::Marker::SPHERE:
443 checkQuaternion(marker, ss, level);
444 checkScale(marker, ss, level);
445 checkColor(marker, ss, level);
446 checkPointsEmpty(marker, ss, level);
447 checkColorsEmpty(marker, ss, level);
448 checkTextEmpty(marker, ss, level);
449 checkMeshEmpty(marker, ss, level);
453 case visualization_msgs::Marker::LINE_STRIP:
454 case visualization_msgs::Marker::LINE_LIST:
455 checkQuaternion(marker, ss, level);
456 checkScaleLineStripAndList(marker, ss, level);
457 checkPointsNotEmpty(marker, ss, level);
458 checkColors(marker, ss, level, 1);
459 checkTextEmpty(marker, ss, level);
460 checkMeshEmpty(marker, ss, level);
463 case visualization_msgs::Marker::SPHERE_LIST:
464 case visualization_msgs::Marker::CUBE_LIST:
465 case visualization_msgs::Marker::TRIANGLE_LIST:
466 checkQuaternion(marker, ss, level);
467 checkScale(marker, ss, level);
468 checkPointsNotEmpty(marker, ss, level);
469 checkColors(marker, ss, level, marker.type == visualization_msgs::Marker::TRIANGLE_LIST ? 3 : 1);
470 checkTextEmpty(marker, ss, level);
471 checkMeshEmpty(marker, ss, level);
474 case visualization_msgs::Marker::POINTS:
475 checkScalePoints(marker, ss, level);
476 checkPointsNotEmpty(marker, ss, level);
477 checkColors(marker, ss, level, 1);
478 checkTextEmpty(marker, ss, level);
479 checkMeshEmpty(marker, ss, level);
482 case visualization_msgs::Marker::TEXT_VIEW_FACING:
483 checkColor(marker, ss, level);
484 checkScaleText(marker, ss, level);
485 checkTextNotEmptyOrWhitespace(marker, ss, level);
486 checkPointsEmpty(marker, ss, level);
487 checkColorsEmpty(marker, ss, level);
488 checkMeshEmpty(marker, ss, level);
491 case visualization_msgs::Marker::MESH_RESOURCE:
492 checkQuaternion(marker, ss, level);
493 checkColor(marker, ss, level);
494 checkScale(marker, ss, level);
495 checkPointsEmpty(marker, ss, level);
496 checkColorsEmpty(marker, ss, level);
497 checkTextEmpty(marker, ss, level);
498 checkMesh(marker, ss, level);
502 ss <<
"Unknown marker type: " << marker.type <<
'.';
503 level = ::ros::console::levels::Error;
508 std::string warning = ss.str();
510 bool fatal = level >= ::ros::console::levels::Error;
516 marker.id, warning.c_str());
528 std::vector<MarkerID> marker_ids;
529 marker_ids.reserve(array.markers.size());
532 std::stringstream ss;
534 for (
const visualization_msgs::Marker& marker : array.markers)
536 if (marker.action == visualization_msgs::Marker::DELETEALL)
538 if (!marker_ids.empty())
540 addSeparatorIfRequired(ss);
541 ss <<
"DELETEALL after having markers added. These will never show.";
548 MarkerID current_id(marker.ns, marker.id);
549 std::vector<MarkerID>::iterator
search =
550 std::lower_bound(marker_ids.begin(), marker_ids.end(), current_id);
551 if (
search != marker_ids.end() && *
search == current_id)
553 addSeparatorIfRequired(ss);
555 if (marker.action == visualization_msgs::Marker::DELETE)
557 ss <<
"Deleting just added marker '" << marker.ns.c_str() <<
"/" << marker.id <<
"'.";
561 ss <<
"Adding marker '" << marker.ns.c_str() <<
"/" << marker.id <<
"' multiple times.";
565 marker_ids.insert(
search, current_id);
571 std::string warning = ss.str();
573 bool fatal = level >= ::ros::console::levels::Error;