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;