GridMapVisual.cpp
Go to the documentation of this file.
1 /*
2  * GridMapVisual.cpp
3  *
4  * Created on: Aug 3, 2016
5  * Author: Philipp Krüsi, Péter Fankhauser
6  * Institute: ETH Zurich, ANYbotics
7  */
8 
10 #include <OGRE/OgreMaterialManager.h>
11 #include <OGRE/OgreTextureManager.h>
12 #include <OGRE/OgreTechnique.h>
13 
14 #include <OGRE/OgreVector3.h>
15 #include <OGRE/OgreSceneNode.h>
16 #include <OGRE/OgreSceneManager.h>
17 #include <OGRE/OgreManualObject.h>
18 
20 
24 
25 namespace grid_map_rviz_plugin {
26 
27 GridMapVisual::GridMapVisual(Ogre::SceneManager* sceneManager, Ogre::SceneNode* parentNode)
28  : manualObject_(0),
29  haveMap_(false)
30 {
31  sceneManager_ = sceneManager;
32  frameNode_ = parentNode->createChildSceneNode();
33 
34  // Create BillboardLine object.
36 }
37 
39 {
40  // Destroy the ManualObject.
41  sceneManager_->destroyManualObject(manualObject_);
42  material_->unload();
43  Ogre::MaterialManager::getSingleton().remove(material_->getName());
44 
45  // Destroy the frame node.
46  sceneManager_->destroySceneNode(frameNode_);
47 }
48 
49 void GridMapVisual::setMessage(const grid_map_msgs::GridMap::ConstPtr& msg)
50 {
51  // Convert grid map message.
53  haveMap_ = true;
54 }
55 
56 void GridMapVisual::computeVisualization(float alpha, bool showGridLines, bool flatTerrain, std::string heightLayer,
57  bool flatColor, bool noColor, Ogre::ColourValue meshColor, bool mapLayerColor,
58  std::string colorLayer, bool useRainbow, bool invertRainbow,
59  Ogre::ColourValue minColor, Ogre::ColourValue maxColor,
60  bool autocomputeIntensity, float minIntensity, float maxIntensity)
61 {
62  if (!haveMap_) {
63  ROS_DEBUG("Unable to visualize grid map, no map data. Use setMessage() first!");
64  return;
65  }
66 
67  // Get list of layers and check if the requested ones are present.
68  std::vector<std::string> layerNames = map_.getLayers();
69  if (layerNames.size() < 1) {
70  ROS_DEBUG("Unable to visualize grid map, map must contain at least one layer.");
71  return;
72  }
73  if ((!flatTerrain && !map_.exists(heightLayer)) || (!noColor && !flatColor && !map_.exists(colorLayer))) {
74  ROS_DEBUG("Unable to visualize grid map, requested layer(s) not available.");
75  return;
76  }
77 
78  // Convert to simple format, makes things easier.
80 
81  // Basic grid map data.
82  const size_t rows = map_.getSize()(0);
83  const size_t cols = map_.getSize()(1);
84  if (rows < 2 || cols < 2) {
85  ROS_DEBUG("GridMap has not enough cells.");
86  return;
87  }
88  const double resolution = map_.getResolution();
89  const grid_map::Matrix& heightData = map_[flatTerrain ? layerNames[0] : heightLayer];
90  const grid_map::Matrix& colorData = map_[flatColor ? layerNames[0] : colorLayer];
91 
92  // initialize ManualObject
93  if (!manualObject_) {
94  static uint32_t count = 0;
96  ss << "Mesh" << count++;
97  manualObject_ = sceneManager_->createManualObject(ss.str());
98  frameNode_->attachObject(manualObject_);
99 
100  ss << "Material";
101  materialName_ = ss.str();
102  material_ = Ogre::MaterialManager::getSingleton().create(materialName_, "rviz");
103  material_->setReceiveShadows(false);
104  material_->getTechnique(0)->setLightingEnabled(true);
105  material_->setCullingMode(Ogre::CULL_NONE);
106  }
107 
108  manualObject_->clear();
109  size_t nVertices = 4 + 6 * (cols * rows - cols - rows);
110  manualObject_->estimateVertexCount(nVertices);
111  manualObject_->begin(materialName_, Ogre::RenderOperation::OT_TRIANGLE_LIST);
112 
113  meshLines_->clear();
114  if (showGridLines) {
115  meshLines_->setColor(0.0, 0.0, 0.0, alpha);
116  meshLines_->setLineWidth(resolution / 10.0);
117  meshLines_->setMaxPointsPerLine(2);
118  // In the algorithm below, we have to account for max. 4 lines per cell.
119  size_t nLines = 2 * (rows * (cols - 1) + cols * (rows - 1));
120  meshLines_->setNumLines(nLines);
121  }
122 
123  // Determine max and min intensity.
124  if (autocomputeIntensity && !flatColor && !mapLayerColor) {
125  minIntensity = colorData.minCoeffOfFinites();
126  maxIntensity = colorData.maxCoeffOfFinites();
127  }
128 
129  if (!map_.hasBasicLayers()) map_.setBasicLayers({heightLayer});
130 
131  // Plot mesh.
132  for (size_t i = 0; i < rows - 1; ++i) {
133  for (size_t j = 0; j < cols - 1; ++j) {
134  std::vector<Ogre::Vector3> vertices;
135  std::vector<Ogre::ColourValue> colors;
136  for (size_t k = 0; k < 2; k++) {
137  for (size_t l = 0; l < 2; l++) {
138  grid_map::Position position;
139  grid_map::Index index(i + k, j + l);
140  if (!map_.isValid(index)) continue;
141 
142  map_.getPosition(index, position);
143  float height = heightData(index(0), index(1));
144  vertices.push_back(Ogre::Vector3(position(0), position(1), flatTerrain ? 0.0 : height));
145  if (!flatColor) {
146  float color = colorData(index(0), index(1));
147  Ogre::ColourValue colorValue;
148  if (mapLayerColor) {
149  Eigen::Vector3f colorVectorRGB;
150  grid_map::colorValueToVector(color, colorVectorRGB);
151  colorValue = Ogre::ColourValue(colorVectorRGB(0), colorVectorRGB(1), colorVectorRGB(2));
152  } else {
153  normalizeIntensity(color, minIntensity, maxIntensity);
154  colorValue = useRainbow ? (invertRainbow ? getRainbowColor(1.0f - color)
155  : getRainbowColor(color))
156  : getInterpolatedColor(color, minColor, maxColor);
157  }
158  colors.push_back(colorValue);
159  }
160  }
161  }
162 
163  // Plot triangles if we have enough vertices.
164  if (vertices.size() > 2) {
165  Ogre::Vector3 normal = vertices.size() == 4
166  ? (vertices[3] - vertices[0]).crossProduct(vertices[2] -vertices[1])
167  : (vertices[2] - vertices[1]).crossProduct(vertices[1] - vertices[0]);
168  normal.normalise();
169  // Create one or two triangles from the vertices depending on how many vertices we have.
170  if (!noColor) {
171  for (size_t m = 1; m < vertices.size() - 1; m++) {
172  manualObject_->position(vertices[m-1]);
173  manualObject_->normal(normal);
174  Ogre::ColourValue color = flatColor ? meshColor : colors[m-1];
175  manualObject_->colour(color.r, color.g, color.b, alpha);
176 
177  manualObject_->position(vertices[m]);
178  manualObject_->normal(normal);
179  color = flatColor ? meshColor : colors[m];
180  manualObject_->colour(color.r, color.g, color.b, alpha);
181 
182  manualObject_->position(vertices[m+1]);
183  manualObject_->normal(normal);
184  color = flatColor ? meshColor : colors[m+1];
185  manualObject_->colour(color.r, color.g, color.b, alpha);
186  }
187  }
188 
189  // plot grid lines
190  if (showGridLines) {
191  meshLines_->addPoint(vertices[0]);
192  meshLines_->addPoint(vertices[1]);
193  meshLines_->newLine();
194 
195  if (vertices.size() == 3) {
196  meshLines_->addPoint(vertices[1]);
197  meshLines_->addPoint(vertices[2]);
198  meshLines_->newLine();
199  } else {
200  meshLines_->addPoint(vertices[1]);
201  meshLines_->addPoint(vertices[3]);
202  meshLines_->newLine();
203 
204  meshLines_->addPoint(vertices[3]);
205  meshLines_->addPoint(vertices[2]);
206  meshLines_->newLine();
207  }
208 
209  meshLines_->addPoint(vertices[2]);
210  meshLines_->addPoint(vertices[0]);
211  meshLines_->newLine();
212  }
213  }
214  }
215  }
216 
217  manualObject_->end();
218  material_->getTechnique(0)->setLightingEnabled(false);
219 
220  if (alpha < 0.9998) {
221  material_->getTechnique(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
222  material_->getTechnique(0)->setDepthWriteEnabled(false);
223  } else {
224  material_->getTechnique(0)->setSceneBlending(Ogre::SBT_REPLACE);
225  material_->getTechnique(0)->setDepthWriteEnabled(true);
226  }
227 }
228 
229 void GridMapVisual::setFramePosition(const Ogre::Vector3& position)
230 {
231  frameNode_->setPosition(position);
232 }
233 
234 void GridMapVisual::setFrameOrientation(const Ogre::Quaternion& orientation)
235 {
236  frameNode_->setOrientation(orientation);
237 }
238 
239 std::vector<std::string> GridMapVisual::getLayerNames()
240 {
241  return map_.getLayers();
242 }
243 
244 // Compute intensity value in the interval [0,1].
245 void GridMapVisual::normalizeIntensity(float& intensity, float min_intensity, float max_intensity)
246 {
247  intensity = std::min(intensity, max_intensity);
248  intensity = std::max(intensity, min_intensity);
249  intensity = (intensity - min_intensity) / (max_intensity - min_intensity);
250 }
251 
252 // Copied from rviz/src/rviz/default_plugin/point_cloud_transformers.cpp.
253 Ogre::ColourValue GridMapVisual::getRainbowColor(float intensity)
254 {
255  intensity = std::min(intensity, 1.0f);
256  intensity = std::max(intensity, 0.0f);
257 
258  float h = intensity * 5.0f + 1.0f;
259  int i = floor(h);
260  float f = h - i;
261  if (!(i & 1)) f = 1 - f; // if i is even
262  float n = 1 - f;
263 
264  Ogre::ColourValue color;
265  if (i <= 1) color[0] = n, color[1] = 0, color[2] = 1;
266  else if (i == 2) color[0] = 0, color[1] = n, color[2] = 1;
267  else if (i == 3) color[0] = 0, color[1] = 1, color[2] = n;
268  else if (i == 4) color[0] = n, color[1] = 1, color[2] = 0;
269  else if (i >= 5) color[0] = 1, color[1] = n, color[2] = 0;
270 
271  return color;
272 }
273 
274 // Get interpolated color value.
275 Ogre::ColourValue GridMapVisual::getInterpolatedColor(float intensity, Ogre::ColourValue min_color,
276  Ogre::ColourValue max_color)
277 {
278  intensity = std::min(intensity, 1.0f);
279  intensity = std::max(intensity, 0.0f);
280 
281  Ogre::ColourValue color;
282  color.r = intensity * (max_color.r - min_color.r) + min_color.r;
283  color.g = intensity * (max_color.g - min_color.g) + min_color.g;
284  color.b = intensity * (max_color.b - min_color.b) + min_color.b;
285 
286  return color;
287 }
288 
289 } // namespace
Eigen::Array2i Index
boost::shared_ptr< rviz::BillboardLine > meshLines_
f
bool getPosition(const Index &index, Position &position) const
void setBasicLayers(const std::vector< std::string > &basicLayers)
void setFramePosition(const Ogre::Vector3 &position)
Eigen::MatrixXf Matrix
void computeVisualization(float alpha, bool showGridLines, bool flatTerrain, std::string heightLayer, bool flatColor, bool noColor, Ogre::ColourValue meshColor, bool mapLayerColor, std::string colorLayer, bool useRainbow, bool invertRainbow, Ogre::ColourValue minColor, Ogre::ColourValue maxColor, bool autocomputeIntensity, float minIntensity, float maxIntensity)
void normalizeIntensity(float &intensity, float minIntensity, float maxIntensity)
Ogre::ColourValue getRainbowColor(float intensity)
void convertToDefaultStartIndex()
bool isValid(const Index &index) const
bool exists(const std::string &layer) const
static bool fromMessage(const grid_map_msgs::GridMap &message, grid_map::GridMap &gridMap)
Ogre::ColourValue getInterpolatedColor(float intensity, Ogre::ColourValue minColor, Ogre::ColourValue maxColor)
double getResolution() const
const std::vector< std::string > & getLayers() const
Eigen::Vector2d Position
std::vector< std::string > getLayerNames()
GridMapVisual(Ogre::SceneManager *sceneManager, Ogre::SceneNode *parentNode)
bool hasBasicLayers() const
void setFrameOrientation(const Ogre::Quaternion &orientation)
bool colorValueToVector(const unsigned long &colorValue, Eigen::Vector3i &colorVector)
const Size & getSize() const
void setMessage(const grid_map_msgs::GridMap::ConstPtr &msg)
#define ROS_DEBUG(...)


grid_map_rviz_plugin
Author(s): Philipp Krüsi, Péter Fankhauser
autogenerated on Tue Jun 25 2019 20:02:28