ed_rviz_plugins
world_model_display.cpp
Go to the documentation of this file.
1 #include <boost/make_shared.hpp>
2 
3 #include <OGRE/OgreSceneNode.h>
4 #include <OGRE/OgreSceneManager.h>
5 
6 #include <rviz/visualization_manager.h>
7 #include <rviz/properties/color_property.h>
8 #include <rviz/properties/float_property.h>
9 #include <rviz/properties/int_property.h>
10 #include <rviz/frame_manager.h>
11 
12 #include "world_model_display.h"
13 #include "../visuals/entity_visual.h"
14 
15 #include <algorithm>
16 #include <vector>
17 
18 // ----------------------------------------------------------------------------------------------------
19 
20 float COLORS[27][3] = { { 0.6, 0.6, 0.6},
21  { 0.6, 0.6, 0.4},
22  { 0.6, 0.6, 0.2},
23  { 0.6, 0.4, 0.6},
24  { 0.6, 0.4, 0.4},
25  { 0.6, 0.4, 0.2},
26  { 0.6, 0.2, 0.6},
27  { 0.6, 0.2, 0.4},
28  { 0.6, 0.2, 0.2},
29  { 0.4, 0.6, 0.6},
30  { 0.4, 0.6, 0.4},
31  { 0.4, 0.6, 0.2},
32  { 0.4, 0.4, 0.6},
33  { 0.4, 0.4, 0.4},
34  { 0.4, 0.4, 0.2},
35  { 0.4, 0.2, 0.6},
36  { 0.4, 0.2, 0.4},
37  { 0.4, 0.2, 0.2},
38  { 0.2, 0.6, 0.6},
39  { 0.2, 0.6, 0.4},
40  { 0.2, 0.6, 0.2},
41  { 0.2, 0.4, 0.6},
42  { 0.2, 0.4, 0.4},
43  { 0.2, 0.4, 0.2},
44  { 0.2, 0.2, 0.6},
45  { 0.2, 0.2, 0.4},
46  { 0.2, 0.2, 0.2}
47  };
48 
49 // ----------------------------------------------------------------------------------------------------
50 
51 unsigned int djb2(const std::string& str)
52 {
53  int hash = 5381;
54  for (const char& c: str)
55  hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
56 
57  if (hash < 0)
58  hash = -hash;
59 
60  return hash;
61 }
62 
63 // ----------------------------------------------------------------------------------------------------
64 
65 /*
66 * @brief split Implementation by using delimiter as a character. Multiple delimeters are removed.
67 * @param strToSplit input string, which is splitted
68 * @param delimeter char on which the string is split
69 * @return vector of sub-strings
70 */
71 std::vector<std::string> split(const std::string& str_to_split, char delimeter)
72 {
73  std::stringstream ss(str_to_split);
74  std::string item;
75  std::vector<std::string> splitted_strings;
76  while (std::getline(ss, item, delimeter))
77  {
78  if (!item.empty() && item[0] != delimeter)
79  splitted_strings.push_back(item);
80  }
81  return splitted_strings;
82 }
83 
84 // ----------------------------------------------------------------------------------------------------
85 
86 void stringsToRegexs(const std::string& str_to_split, std::vector<std::regex>& v_regex, char delimeter=';')
87 {
88  std::vector<std::string> splitted_strings = split(str_to_split, delimeter);
89  v_regex.clear();
90  v_regex.reserve(splitted_strings.size());
91  std::transform(splitted_strings.cbegin(), splitted_strings.cend(), std::back_inserter(v_regex), [](const std::string& str) { return std::regex(str, std::regex_constants::icase); });
92 }
93 
94 // ----------------------------------------------------------------------------------------------------
95 
96 namespace ed_rviz_plugins
97 {
98 
100 {
101  service_name_property_ = std::make_unique<rviz::StringProperty>("Mesh query service name", "ed/gui/query_meshes", "Service name for querying meshes", this, SLOT(updateProperties()));
102 
103  entity_label_opacity_property_ = std::make_unique<rviz::FloatProperty>("Entity label opacity", 1.0, "Opacity of entity label", this);
104  entity_volume_label_opacity_property_ = std::make_unique<rviz::FloatProperty>("Entity Volume label opacity", 0.4, "Opacity of entity label", this);
105  entity_volume_opacity_property_ = std::make_unique<rviz::FloatProperty>("Entity Volume opacity", 0.2, "Opacity of entity label", this);
106  exclude_entities_property_ = std::make_unique<rviz::StringProperty>("Exclude entities", "", "Exclude entities regex (seperate with semi-colons)", this, SLOT(updateExcludeEntities()));
107  exclude_entity_types_propetry_ = std::make_unique<rviz::StringProperty>("Exclude entity types", "", "Exclude entity types regex (seperate with semi-colons)", this, SLOT(updateExcludeEntityTypes()));
108  exclude_labels_property_ = std::make_unique<rviz::StringProperty>("Exclude labels", "", "Exclude labels regex (seperate with semi-colons)", this, SLOT(updateExcludeLabels()));
109 
111 }
112 
114 {
115  if (service_client_.exists())
116  service_client_.shutdown();
117 
118  ros::NodeHandle nh;
119  service_client_ = nh.serviceClient<ed_gui_server_msgs::QueryMeshes>(service_name_property_->getStdString());
120 }
121 
123 {
125 }
126 
128 {
130 }
131 
133 {
135 }
136 
138 {
139  MFDClass::onInitialize();
140 }
141 
143 {
144 }
145 
147 {
148  MFDClass::reset();
149 }
150 
151 void WorldModelDisplay::processMessage(const ed_gui_server_msgs::EntityInfos::ConstPtr &msg)
152 {
153  // Transform to rviz frame
154  Ogre::Quaternion frame_orientation;
155  Ogre::Vector3 frame_position;
156  if (!context_->getFrameManager()->getTransform("map", ros::Time::now(), frame_position, frame_orientation))
157  {
158  ROS_DEBUG("Error transforming from frame 'map' to frame '%s'", qPrintable(fixed_frame_));
159  return;
160  }
161 
162  std::vector<std::string> alive_ids;
163  for (const ed_gui_server_msgs::EntityInfo& info: msg->entities)
164  {
165  if (info.id.size() >= 5 && (info.id.substr(info.id.size() - 5) == "floor" || info.id.substr(0, 5) == "floor"))
166  continue; // Filter floor
167 
168  if (!info.has_pose)
169  continue;
170 
171  if (std::any_of(exclude_entities_.cbegin(), exclude_entities_.cend(), [&info](const std::regex& regex){ return std::regex_match(info.id, regex); }))
172  // Skip entities matching the regexs from exclude entities.
173  continue;
174 
175  if (std::any_of(exclude_entity_types_.cbegin(), exclude_entity_types_.cend(), [&info](const std::regex& regex){ return std::regex_match(info.type, regex); }))
176  // Skip entities having a matching type according the regexs from exclude entity types.
177  continue;
178 
179  if (visuals_.find(info.id) == visuals_.end()) // Visual does not exist yet; create visual
180  visuals_[info.id] = boost::make_shared<EntityVisual>(context_->getSceneManager(), scene_node_);
181 
182  boost::shared_ptr<EntityVisual> visual = visuals_[info.id];
183 
184  // Get position and orientation
185  Ogre::Vector3 position;
186  Ogre::Quaternion orientation;
187  position.x = info.pose.position.x;
188  position.y = info.pose.position.y;
189  position.z = info.pose.position.z;
190 
191  orientation.x = info.pose.orientation.x;
192  orientation.y = info.pose.orientation.y;
193  orientation.z = info.pose.orientation.z;
194  orientation.w = info.pose.orientation.w;
195 
196  visual->setFramePosition(frame_position + position);
197  visual->setFrameOrientation(frame_orientation * orientation);
198 
199  bool visual_needs_update = info.visual_revision > visual->visualRevision();
200  bool volumes_needs_update = info.volumes_revision > visual->volumesRevision();
201  if (visual_needs_update || volumes_needs_update)
202  {
203  query_meshes_srv_.request.entity_ids.push_back(info.id); // Mesh
204  query_meshes_srv_.request.visual_requests.push_back(visual_needs_update);
205  query_meshes_srv_.request.volumes_requests.push_back(volumes_needs_update);
206  }
207  else if (info.visual_revision == 0)
208  visual->setConvexHull(info.polygon); // Convex hull
209 
210  // Set the color
211  double r,g,b;
212  if (info.color.a != 0) // If a color specified, take color from the info
213  {
214  r = static_cast<float>(info.color.r) / 255;
215  g = static_cast<float>(info.color.g) / 255;
216  b = static_cast<float>(info.color.b) / 255;
217  }
218  else // random color
219  {
220  int i_color = djb2(info.id) % 27;
221  r = COLORS[i_color][0];
222  g = COLORS[i_color][1];
223  b = COLORS[i_color][2];
224  }
225  visual->setColor(Ogre::ColourValue(r, g, b, 1.0f), entity_label_opacity_property_->getFloat(),
227 
228  std::string label;
229  // exclude label (label remains empty string) in case it starts with one of defined prefixes
230  if (std::none_of(exclude_labels_.cbegin(), exclude_labels_.cend(), [&info](const std::regex& regex){ return std::regex_match(info.id, regex); }))
231  {
232  label = info.id.substr(0, 6);
233 
234  if (!info.type.empty())
235  label += " (" + info.type + ")";
236  }
237  visual->setLabel(label);
238 
239  alive_ids.push_back(info.id);
240  }
241 
242  // Check which ids are not present
243  std::vector<std::string> ids_to_be_removed;
244  for (const auto& kv : visuals_)
245  {
246  if (std::find(alive_ids.cbegin(), alive_ids.cend(), kv.first) == alive_ids.cend()) // Not in alive ids
247  ids_to_be_removed.push_back(kv.first);
248  }
249 
250  // Remove stale visuals
251  for (const std::string& id : ids_to_be_removed)
252  visuals_.erase(id);
253 
254  // Perform service call to get missing meshes
255  if (!query_meshes_srv_.request.entity_ids.empty())
256  {
258  {
259  for (const auto& geom : query_meshes_srv_.response.entity_geometries)
260  {
261  const std::string& id = geom.id;
262 
263  if (visuals_.find(id) == visuals_.end())
264  continue;
265 
266  visuals_[id]->setEntityMeshAndVolumes(geom);
267  }
268  }
269  else
270  {
271  ROS_ERROR("Could not query for meshes; does the service '%s' exist?", service_name_property_->getStdString().c_str());
272  }
273  }
274 
275  // No more meshes missing :)
276  query_meshes_srv_.request.entity_ids.clear();
277  query_meshes_srv_.request.visual_requests.clear();
278  query_meshes_srv_.request.volumes_requests.clear();
279 }
280 
281 }
282 
283 #include <pluginlib/class_list_macros.h>
284 PLUGINLIB_EXPORT_CLASS(ed_rviz_plugins::WorldModelDisplay,rviz::Display)
std::string
stringsToRegexs
void stringsToRegexs(const std::string &str_to_split, std::vector< std::regex > &v_regex, char delimeter=';')
Definition: world_model_display.cpp:86
ed_rviz_plugins::WorldModelDisplay::exclude_entity_types_propetry_
std::unique_ptr< rviz::StringProperty > exclude_entity_types_propetry_
Definition: world_model_display.h:62
std::vector::reserve
T reserve(T... args)
ed_rviz_plugins::WorldModelDisplay::updateProperties
void updateProperties()
Definition: world_model_display.cpp:113
ed_rviz_plugins::WorldModelDisplay::entity_volume_label_opacity_property_
std::unique_ptr< rviz::FloatProperty > entity_volume_label_opacity_property_
Definition: world_model_display.h:59
ed_rviz_plugins::WorldModelDisplay::exclude_labels_
std::vector< std::regex > exclude_labels_
Definition: world_model_display.h:67
ed_rviz_plugins::WorldModelDisplay::service_client_
ros::ServiceClient service_client_
Definition: world_model_display.h:51
ed_rviz_plugins::WorldModelDisplay::query_meshes_srv_
ed_gui_server_msgs::QueryMeshes query_meshes_srv_
Definition: world_model_display.h:52
vector
std::find
T find(T... args)
std::vector::size
T size(T... args)
std::back_inserter
T back_inserter(T... args)
ed_rviz_plugins::WorldModelDisplay::updateExcludeLabels
void updateExcludeLabels()
Definition: world_model_display.cpp:132
djb2
unsigned int djb2(const std::string &str)
Definition: world_model_display.cpp:51
ed_rviz_plugins::WorldModelDisplay
Definition: world_model_display.h:30
std::stringstream
COLORS
float COLORS[27][3]
Definition: world_model_display.cpp:20
ed_rviz_plugins::WorldModelDisplay::service_name_property_
std::unique_ptr< rviz::StringProperty > service_name_property_
Definition: world_model_display.h:57
std::any_of
T any_of(T... args)
world_model_display.h
ed_rviz_plugins::WorldModelDisplay::WorldModelDisplay
WorldModelDisplay()
Definition: world_model_display.cpp:99
algorithm
std::vector::clear
T clear(T... args)
std::vector::push_back
T push_back(T... args)
ed_rviz_plugins::WorldModelDisplay::exclude_entity_types_
std::vector< std::regex > exclude_entity_types_
Definition: world_model_display.h:66
ed_rviz_plugins::WorldModelDisplay::exclude_labels_property_
std::unique_ptr< rviz::StringProperty > exclude_labels_property_
Definition: world_model_display.h:63
ed_rviz_plugins::WorldModelDisplay::exclude_entities_
std::vector< std::regex > exclude_entities_
Definition: world_model_display.h:65
ed_rviz_plugins::WorldModelDisplay::updateExcludeEntities
void updateExcludeEntities()
Definition: world_model_display.cpp:122
ed_rviz_plugins::WorldModelDisplay::onInitialize
virtual void onInitialize()
Definition: world_model_display.cpp:137
std::regex
std::transform
T transform(T... args)
ed_rviz_plugins::WorldModelDisplay::updateExcludeEntityTypes
void updateExcludeEntityTypes()
Definition: world_model_display.cpp:127
std::string::substr
T substr(T... args)
ed_rviz_plugins::WorldModelDisplay::~WorldModelDisplay
virtual ~WorldModelDisplay()
Definition: world_model_display.cpp:142
std::vector::cbegin
T cbegin(T... args)
std::getline
T getline(T... args)
ed_rviz_plugins::WorldModelDisplay::processMessage
void processMessage(const ed_gui_server_msgs::EntityInfos::ConstPtr &msg)
Definition: world_model_display.cpp:151
ed_rviz_plugins::WorldModelDisplay::visuals_
std::map< std::string, boost::shared_ptr< EntityVisual > > visuals_
Definition: world_model_display.h:54
ed_rviz_plugins
Definition: world_model_display.cpp:96
std::string::empty
T empty(T... args)
ed_rviz_plugins::WorldModelDisplay::exclude_entities_property_
std::unique_ptr< rviz::StringProperty > exclude_entities_property_
Definition: world_model_display.h:61
ed_rviz_plugins::WorldModelDisplay::entity_label_opacity_property_
std::unique_ptr< rviz::FloatProperty > entity_label_opacity_property_
Definition: world_model_display.h:58
std::vector::cend
T cend(T... args)
split
std::vector< std::string > split(const std::string &str_to_split, char delimeter)
Definition: world_model_display.cpp:71
ed_rviz_plugins::WorldModelDisplay::entity_volume_opacity_property_
std::unique_ptr< rviz::FloatProperty > entity_volume_opacity_property_
Definition: world_model_display.h:60
ed_rviz_plugins::WorldModelDisplay::reset
virtual void reset()
Definition: world_model_display.cpp:146