55 case visualization_msgs::Marker::CUBE:
56 case visualization_msgs::Marker::CYLINDER:
57 case visualization_msgs::Marker::SPHERE:
60 case visualization_msgs::Marker::ARROW:
63 case visualization_msgs::Marker::LINE_STRIP:
66 case visualization_msgs::Marker::LINE_LIST:
69 case visualization_msgs::Marker::SPHERE_LIST:
70 case visualization_msgs::Marker::CUBE_LIST:
71 case visualization_msgs::Marker::POINTS:
74 case visualization_msgs::Marker::TEXT_VIEW_FACING:
77 case visualization_msgs::Marker::MESH_RESOURCE:
80 case visualization_msgs::Marker::TRIANGLE_LIST:
90 void addSeparatorIfRequired(std::stringstream& ss)
101 if (new_status > current_status)
102 current_status = new_status;
105 template <
typename T>
106 constexpr
const char* fieldName();
108 constexpr
const char* fieldName<::geometry_msgs::Point>()
113 constexpr
const char* fieldName<::geometry_msgs::Quaternion>()
115 return "Orientation";
118 constexpr
const char* fieldName<::geometry_msgs::Vector3>()
123 constexpr
const char* fieldName<::std_msgs::ColorRGBA>()
128 template <
typename T>
133 addSeparatorIfRequired(ss);
134 ss << fieldName<T>() <<
" contains invalid floating point values (nans or infs)";
139 void checkQuaternion(
const visualization_msgs::Marker& marker,
140 std::stringstream& ss,
143 checkFloats(marker.pose.orientation, ss, level);
144 if (marker.pose.orientation.x == 0.0 && marker.pose.orientation.y == 0.0 &&
145 marker.pose.orientation.z == 0.0 && marker.pose.orientation.w == 0.0)
147 addSeparatorIfRequired(ss);
148 ss <<
"Uninitialized quaternion, assuming identity.";
153 addSeparatorIfRequired(ss);
154 ss <<
"Unnormalized quaternion in marker message.";
159 void checkScale(
const visualization_msgs::Marker& marker,
160 std::stringstream& ss,
163 checkFloats(marker.scale, ss, level);
165 if (marker.type == visualization_msgs::Marker::ARROW && marker.scale.x != 0.0 && marker.scale.y != 0.0)
168 if (marker.scale.x == 0.0 || marker.scale.y == 0.0 || marker.scale.z == 0.0)
170 addSeparatorIfRequired(ss);
171 ss <<
"Scale contains 0.0 in x, y or z.";
176 void checkScaleLineStripAndList(
const visualization_msgs::Marker& marker,
177 std::stringstream& ss,
180 if (marker.scale.x == 0.0)
182 addSeparatorIfRequired(ss);
183 ss <<
"Width LINE_LIST or LINE_STRIP is 0.0 (scale.x).";
188 void checkScalePoints(
const visualization_msgs::Marker& marker,
189 std::stringstream& ss,
192 if (marker.scale.x == 0.0 || marker.scale.y == 0.0)
194 addSeparatorIfRequired(ss);
195 ss <<
"Width and/or height of POINTS is 0.0 (scale.x, scale.y).";
200 void checkScaleText(
const visualization_msgs::Marker& marker,
201 std::stringstream& ss,
204 if (marker.scale.z == 0.0)
206 addSeparatorIfRequired(ss);
207 ss <<
"Text height of TEXT_VIEW_FACING is 0.0 (scale.z).";
212 void checkColor(
const visualization_msgs::Marker& marker,
213 std::stringstream& ss,
216 checkFloats(marker.color, ss, level);
217 if (marker.color.a == 0.0 &&
220 !(marker.type == visualization_msgs::Marker::MESH_RESOURCE && marker.mesh_use_embedded_materials &&
221 marker.color.r == 0.0 && marker.color.g == 0.0 && marker.color.b == 0.0))
223 addSeparatorIfRequired(ss);
224 ss <<
"Marker is fully transparent (color.a is 0.0).";
229 void checkPointsArrow(
const visualization_msgs::Marker& marker,
230 std::stringstream& ss,
233 if (!marker.points.empty() && marker.points.size() != 2)
235 addSeparatorIfRequired(ss);
236 ss <<
"Number of points for an ARROW marker should be either 0 or 2.";
240 for (
const auto& p : marker.points)
241 checkFloats(p, ss, level);
244 void checkPointsNotEmpty(
const visualization_msgs::Marker& marker,
245 std::stringstream& ss,
248 if (marker.points.empty())
250 addSeparatorIfRequired(ss);
251 ss <<
"Points should not be empty for specified marker type.";
256 case visualization_msgs::Marker::TRIANGLE_LIST:
257 if (marker.points.size() % 3 != 0)
259 addSeparatorIfRequired(ss);
260 ss <<
"Number of points should be a multiple of 3 for TRIANGLE_LIST marker.";
264 case visualization_msgs::Marker::LINE_LIST:
265 if (marker.points.size() % 2 != 0)
267 addSeparatorIfRequired(ss);
268 ss <<
"Number of points should be a multiple of 2 for LINE_LIST marker.";
272 case visualization_msgs::Marker::LINE_STRIP:
273 if (marker.points.size() <= 1)
275 addSeparatorIfRequired(ss);
276 ss <<
"At least two points are required for a LINE_STRIP marker.";
285 void checkPointsEmpty(
const visualization_msgs::Marker& marker,
286 std::stringstream& ss,
289 if (!marker.points.empty())
291 addSeparatorIfRequired(ss);
292 ss <<
"Non-empty points array is ignored.";
297 void checkColors(
const visualization_msgs::Marker& marker,
298 std::stringstream& ss,
300 unsigned int multiple)
302 if (marker.colors.empty())
304 checkColor(marker, ss, level);
307 if (marker.colors.size() != marker.points.size() &&
308 (multiple == 1 || multiple * marker.colors.size() != marker.points.size()))
310 addSeparatorIfRequired(ss);
311 ss <<
"Number of colors doesn't match number of points.";
316 void checkColorsEmpty(
const visualization_msgs::Marker& marker,
317 std::stringstream& ss,
320 if (!marker.colors.empty())
322 addSeparatorIfRequired(ss);
323 ss <<
"Non-empty colors array is ignored.";
328 void checkTextNotEmptyOrWhitespace(
const visualization_msgs::Marker& marker,
329 std::stringstream& ss,
332 if (marker.text.find_first_not_of(
" \t\n\v\f\r") == std::string::npos)
334 addSeparatorIfRequired(ss);
335 ss <<
"Text is empty or only consists of whitespace.";
340 void checkTextEmpty(
const visualization_msgs::Marker& marker,
341 std::stringstream& ss,
344 if (!marker.text.empty())
346 addSeparatorIfRequired(ss);
347 ss <<
"Non-empty text is ignored.";
352 void checkMesh(
const visualization_msgs::Marker& marker,
353 std::stringstream& ss,
356 if (marker.mesh_resource.empty())
358 addSeparatorIfRequired(ss);
359 ss <<
"Empty mesh_resource path.";
364 void checkMeshEmpty(
const visualization_msgs::Marker& marker,
365 std::stringstream& ss,
368 if (!marker.mesh_resource.empty())
370 addSeparatorIfRequired(ss);
371 ss <<
"Non-empty mesh_resource is ignored.";
374 if (marker.mesh_use_embedded_materials)
376 addSeparatorIfRequired(ss);
377 ss <<
"mesh_use_embedded_materials is ignored.";
386 if (marker.action != visualization_msgs::Marker::ADD)
389 std::stringstream ss;
391 checkFloats(marker.pose.position, ss, level);
395 case visualization_msgs::Marker::ARROW:
396 checkQuaternion(marker, ss, level);
397 checkScale(marker, ss, level);
398 checkColor(marker, ss, level);
399 checkPointsArrow(marker, ss, level);
400 checkColorsEmpty(marker, ss, level);
401 checkTextEmpty(marker, ss, level);
402 checkMeshEmpty(marker, ss, level);
405 case visualization_msgs::Marker::CUBE:
406 case visualization_msgs::Marker::CYLINDER:
407 case visualization_msgs::Marker::SPHERE:
408 checkQuaternion(marker, ss, level);
409 checkScale(marker, ss, level);
410 checkColor(marker, ss, level);
411 checkPointsEmpty(marker, ss, level);
412 checkColorsEmpty(marker, ss, level);
413 checkTextEmpty(marker, ss, level);
414 checkMeshEmpty(marker, ss, level);
418 case visualization_msgs::Marker::LINE_STRIP:
419 case visualization_msgs::Marker::LINE_LIST:
420 checkQuaternion(marker, ss, level);
421 checkScaleLineStripAndList(marker, ss, level);
422 checkPointsNotEmpty(marker, ss, level);
423 checkColors(marker, ss, level, 1);
424 checkTextEmpty(marker, ss, level);
425 checkMeshEmpty(marker, ss, level);
428 case visualization_msgs::Marker::SPHERE_LIST:
429 case visualization_msgs::Marker::CUBE_LIST:
430 case visualization_msgs::Marker::TRIANGLE_LIST:
431 checkQuaternion(marker, ss, level);
432 checkScale(marker, ss, level);
433 checkPointsNotEmpty(marker, ss, level);
434 checkColors(marker, ss, level, marker.type == visualization_msgs::Marker::TRIANGLE_LIST ? 3 : 1);
435 checkTextEmpty(marker, ss, level);
436 checkMeshEmpty(marker, ss, level);
439 case visualization_msgs::Marker::POINTS:
440 checkScalePoints(marker, ss, level);
441 checkPointsNotEmpty(marker, ss, level);
442 checkColors(marker, ss, level, 1);
443 checkTextEmpty(marker, ss, level);
444 checkMeshEmpty(marker, ss, level);
447 case visualization_msgs::Marker::TEXT_VIEW_FACING:
448 checkColor(marker, ss, level);
449 checkScaleText(marker, ss, level);
450 checkTextNotEmptyOrWhitespace(marker, ss, level);
451 checkPointsEmpty(marker, ss, level);
452 checkColorsEmpty(marker, ss, level);
453 checkMeshEmpty(marker, ss, level);
456 case visualization_msgs::Marker::MESH_RESOURCE:
457 checkQuaternion(marker, ss, level);
458 checkColor(marker, ss, level);
459 checkScale(marker, ss, level);
460 checkPointsEmpty(marker, ss, level);
461 checkColorsEmpty(marker, ss, level);
462 checkTextEmpty(marker, ss, level);
463 checkMesh(marker, ss, level);
467 ss <<
"Unknown marker type: " << marker.type <<
'.';
468 level = ::ros::console::levels::Error;
473 std::string warning = ss.str();
475 bool fatal = level >= ::ros::console::levels::Error;
481 marker.id, warning.c_str());
493 std::vector<MarkerID> marker_ids;
494 marker_ids.reserve(array.markers.size());
497 std::stringstream ss;
499 for (
const visualization_msgs::Marker& marker : array.markers)
501 if (marker.action == visualization_msgs::Marker::DELETEALL)
503 if (!marker_ids.empty())
505 addSeparatorIfRequired(ss);
506 ss <<
"DELETEALL after having markers added. These will never show.";
513 MarkerID current_id(marker.ns, marker.id);
514 std::vector<MarkerID>::iterator
search =
515 std::lower_bound(marker_ids.begin(), marker_ids.end(), current_id);
516 if (search != marker_ids.end() && *search == current_id)
518 addSeparatorIfRequired(ss);
520 if (marker.action == visualization_msgs::Marker::DELETE)
522 ss <<
"Deleting just added marker '" << marker.ns.c_str() <<
"/" << marker.id <<
"'.";
523 marker_ids.erase(search);
526 ss <<
"Adding marker '" << marker.ns.c_str() <<
"/" << marker.id <<
"' multiple times.";
530 marker_ids.insert(search, current_id);
536 std::string warning = ss.str();
538 bool fatal = level >= ::ros::console::levels::Error;
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...
void deleteStatusStd(const std::string &name)
Delete the status entry with the given std::string name. This is thread-safe.
void setMarkerStatus(MarkerID id, StatusLevel level, const std::string &text)
bool checkMarkerMsg(const visualization_msgs::Marker &marker, MarkerDisplay *owner)
geometry_msgs::TransformStamped t
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)
Pure-virtual base class for objects which give Display subclasses context in which to work...
bool validateFloats(const sensor_msgs::CameraInfo &msg)
void deleteMarkerStatus(MarkerID id)
#define ROS_LOG(level, name,...)
bool validateQuaternions(const visualization_msgs::InteractiveMarker &marker)
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