GaussianVisualization.cpp
Go to the documentation of this file.
1 
19 
20 namespace Visualization {
21 
23  : mHandle()
24  , mScale(1.0)
25  {
26  mPublisher.reset(new ros::Publisher(mHandle.advertise<visualization_msgs::Marker>("psm_scene_objects", 1)));
27  }
28 
30  {
31  }
32 
34  {
35  mMean = pMean;
36  mCovariance = pCovariance;
37  }
38 
40  {
41  mScale = pScale;
42  }
43 
44  void GaussianVisualization::setObjectLocationFrameID(const std::string& pObjectLocationFrameID)
45  {
46  mObjectLocationFrameID = pObjectLocationFrameID;
47  }
48 
49  void GaussianVisualization::setAlphaChannel(const float pAlphaChannel)
50  {
51  mAlphaChannel = pAlphaChannel;
52  }
53 
54  void GaussianVisualization::setSigmaMultiplicator(const float pSigmaMultiplicator)
55  {
56  // Check that we validly scale variances in frame resulting from eigenvalue decomposition.
57  if(pSigmaMultiplicator <= 0.0f)
58  throw std::out_of_range("Dimensions of a geometric primitive must be non-negative.");
59 
60  // Init ellisoid scaling with provided data.
61  mSigmaMultiplicator = pSigmaMultiplicator;
62  }
63 
64  void GaussianVisualization::publishCovarianceEllipsoidMarker(const int pMarkerID, const std_msgs::ColorRGBA& pEllipsoidColor)
65  {
66  // Call to advertise() should not have returned an empty publisher.
67  if(!mPublisher)
68  throw std::invalid_argument("Empty ros::publisher cannot be used to publish marker messages.");
69 
70  // Generate marker for given distribution and publish it on given topic.
71  mPublisher->publish((*generateCovarianceEllipsoidMarker(pMarkerID, visualization_msgs::Marker::SPHERE, std::vector<std::vector<std::vector<float> > >(), 0, pEllipsoidColor)));
72  }
73 
74  boost::shared_ptr<visualization_msgs::Marker> GaussianVisualization::generateCovarianceEllipsoidMarker(const int pMarkerID, const int pMarkerShape, const std::vector<std::vector<std::vector<float> > >& pWireFramePolygons, const float& pWireFrameWidth, const std_msgs::ColorRGBA& pEllipsoidColor)
75  {
76  if(pMarkerShape != visualization_msgs::Marker::SPHERE && pMarkerShape != visualization_msgs::Marker::LINE_LIST)
77  throw std::invalid_argument("Chosen marker shape is not supported to visualize.");
78 
79  // All color parameter values must be in [0,1].
80  if((pEllipsoidColor.r < 0.0f || pEllipsoidColor.r > 1.0f) || (pEllipsoidColor.g < 0.0f || pEllipsoidColor.g > 1.0f) || (pEllipsoidColor.b < 0.0f || pEllipsoidColor.b > 1.0f) || (pEllipsoidColor.a < 0.0f || pEllipsoidColor.a > 1.0f))
81  throw std::out_of_range("ColorRGBA message is no valid color information.");
82 
83  // Data structure representing visualization object.
84  boost::shared_ptr<visualization_msgs::Marker> ellipsoidMarker(new visualization_msgs::Marker);
85 
86  // Use the learners frame_id relative to which all locations in this model are given.
87  ellipsoidMarker->header.frame_id = mObjectLocationFrameID;
88 
89  // Set timestamp. See the TF tutorials for information on this.
90  ellipsoidMarker->header.stamp = ros::Time::now();
91 
92  // Marker namespace are associated to different types of shapes used to represent object location distributions.
93  ellipsoidMarker->ns = "distribution";
94 
95  // Markers with different namespaces but same id represent same object location distribution with different shapes.
96  ellipsoidMarker->id = pMarkerID;
97 
98  // The marker type decides on shape of marker and accordingly how marker parameters are interpreted by RViz.
99  ellipsoidMarker->type = pMarkerShape;
100 
101  // We always want to show a marker by publishing ros messages here.
102  ellipsoidMarker->action = visualization_msgs::Marker::ADD;
103 
104  // Columns of eigen matrix are eigen vectors representing the axes of the coordinate frame of the ellipsoid. Therefore eigen matrix is equal to an orientation matrix of the ellipsoid. This solver calculates the eigen matrix and vectors.
105  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es(*mCovariance);
106  Eigen::Matrix3d rotationMatrixOrientation = es.eigenvectors();
107 
108  // The position of the ellipsoid is equal to the mean vector of the normal distribution.
109  tf::Vector3 tfEllipsoidPosition((*mMean)[0], (*mMean)[1], (*mMean)[2]);
110 
111  // TODO take care of
112  // Transform ellipsoid orientation matrix to ros tf representation to be able to transform it to a quaternion.
113  // Invert first and second eigen vectors as they do not correspond to the eigen vector calculated by wolfram alpha.
114 // tf::Matrix3x3 tfRotationMatrixOrientation(-1.0 * rotationMatrixOrientation(0,0), -1.0 * rotationMatrixOrientation(0,1), rotationMatrixOrientation(0,2),
115 // -1.0 * rotationMatrixOrientation(1,0), -1.0 * rotationMatrixOrientation(1,1), rotationMatrixOrientation(1,2),
116 // -1.0 * rotationMatrixOrientation(2,0), -1.0 * rotationMatrixOrientation(2,1), rotationMatrixOrientation(2,2));
117 
118  tf::Matrix3x3 tfRotationMatrixOrientation(rotationMatrixOrientation(0,0), rotationMatrixOrientation(0,1), rotationMatrixOrientation(0,2),
119  rotationMatrixOrientation(1,0), rotationMatrixOrientation(1,1), rotationMatrixOrientation(1,2),
120  rotationMatrixOrientation(2,0), rotationMatrixOrientation(2,1), rotationMatrixOrientation(2,2));
121 
122  // Get transform needed for conversion to ros pose msg representation.
123  tf::Transform tfEllipsoidPose(tfRotationMatrixOrientation, tfEllipsoidPosition);
124 
125  // Fill marker pose with tf transform.
126  tf::poseTFToMsg(tfEllipsoidPose, ellipsoidMarker->pose);
127 
128  // Scale position.
129  ellipsoidMarker->pose.position.x *= mScale;
130  ellipsoidMarker->pose.position.y *= mScale;
131  ellipsoidMarker->pose.position.z *= mScale;
132 
133  // Extract eigen values of covariance matrix which represent the relative scaling factors for the axes of the coordinate frame of the ellipoid extracted above or the variances in the diagonalized matrix.
134  Eigen::Vector3d squaredEllipsoidLengths = es.eigenvalues();
135 
136  // If surface model of ellipsoid is desired, set size of ellipsoid directly in marker using scale parameter
137  if(pMarkerShape == visualization_msgs::Marker::SPHERE)
138  {
139  // Multiply the relative lengths (square roots of corresponding eigen values) of the half axes of the ellipse with a multiplicator parameter set for visualization purposes. Then double value as scale does not represent radius, but diameter of the marker.
140  ellipsoidMarker->scale.x = 2.0f * std::sqrt(squaredEllipsoidLengths[0]) * mSigmaMultiplicator * mScale;
141  ellipsoidMarker->scale.y = 2.0f * std::sqrt(squaredEllipsoidLengths[1]) * mSigmaMultiplicator * mScale;
142  ellipsoidMarker->scale.z = 2.0f * std::sqrt(squaredEllipsoidLengths[2]) * mSigmaMultiplicator * mScale;
143  }
144  // Otherwise a wire-frame model is desired. In this case its size as well as its general appeareance is encoded in the points constituting the wire-frame polygons.
145  else {
146 
147  // Access one of the ellipse-shaped wires making up the wire-frame.
148  std::vector<std::vector<std::vector<float> > >::const_iterator ellipseIterator;
149 
150  // Go through all ellipses
151  for(ellipseIterator = pWireFramePolygons.begin(); ellipseIterator != pWireFramePolygons.end(); ellipseIterator++) {
152 
153  // Access a point on the ellipse-shaped polygon.
154  std::vector<std::vector<float> >::const_iterator polygonPointIterator = ellipseIterator->begin();
155 
156  // Geometry_msgs representation of 3D point for polygon point...
157  geometry_msgs::Point rosPolygonPoint;
158 
159  // ...is needed for insertion into marker message.
160  stlVectorToPointMsg(*polygonPointIterator, rosPolygonPoint);
161 
162  // Add starting of first segment of ellipse to points array containing all segments as pairs of starting- and endpoints.
163  ellipsoidMarker->points.push_back(rosPolygonPoint);
164 
165  // Go through all points in the polygon ignoring first try.
166  for(polygonPointIterator++; polygonPointIterator != ellipseIterator->end(); polygonPointIterator++) {
167 
168  // Add end point of segment already being processed.
169  stlVectorToPointMsg(*polygonPointIterator, rosPolygonPoint);
170  ellipsoidMarker->points.push_back(rosPolygonPoint);
171 
172  // Add starting point of next segment
173  ellipsoidMarker->points.push_back(rosPolygonPoint);
174 
175  }
176  // Close the loop with the polygon segment [end(),begin()].
177  stlVectorToPointMsg(*(ellipseIterator->begin()), rosPolygonPoint);
178  ellipsoidMarker->points.push_back(rosPolygonPoint);
179 
180  }
181  // Nevertheless the width of the wires is set solely using x component of scale parameter.
182  ellipsoidMarker->scale.x = pWireFrameWidth;
183 
184  }
185 
186  // Set the color of the ellipsoid for rviz.
187  ellipsoidMarker->color = pEllipsoidColor;
188 
189  // Overwrite alpha channel.
190  ellipsoidMarker->color.a = mAlphaChannel;
191 
192  // How long the object should last before being automatically deleted. (Here forever.)
193  ellipsoidMarker->lifetime = ros::Duration();
194 
195  // Give others access to completed covariance ellipsoid.
196  return ellipsoidMarker;
197  }
198 
200  {
201  // Columns of eigen matrix are eigen vectors representing the axes of the coordinate frame of the ellipsoid. Therefore eigen matrix is equal to an orientation matrix of the ellipsoid. This solver calculates the eigen matrix and vectors.
202  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es(*mCovariance);
203 
204  // Visualize the coordinate system as arrows.
205  for(int i = 0; i < 3; i++)
206  {
207  visualization_msgs::Marker msg;
208 
209  // Get the eigenvector.
210  Eigen::Vector3d eigenvector = es.eigenvectors().col(i) * es.eigenvalues()[i];
211 
212  // Set time and frame id.
213  msg.header.stamp = ros::Time::now();
214  msg.header.frame_id = mObjectLocationFrameID;
215 
216  // Arrows should be small.
217  msg.scale.x = 0.005;
218  msg.scale.y = 0.005;
219  msg.scale.z = 0.005;
220 
221  // This should be an arrow.
222  msg.type = visualization_msgs::Marker::ARROW;
223 
224  // We always want to show a marker by publishing ros messages here.
225  msg.action = visualization_msgs::Marker::ADD;
226 
227  // Create the starting point.
228  geometry_msgs::Point start;
229  start.x = (*mMean)[0] * mScale;
230  start.y = (*mMean)[1] * mScale;
231  start.z = (*mMean)[2] * mScale;
232  msg.points.push_back(start);
233 
234  // Create the point to point to ;).
235  geometry_msgs::Point stop;
236  stop.x = ((*mMean)[0] + eigenvector[0]) * mScale;
237  stop.y = ((*mMean)[1] + eigenvector[1]) * mScale;
238  stop.z = ((*mMean)[2] + eigenvector[2]) * mScale;
239  msg.points.push_back(stop);
240 
241  // Set an unique id and namespace for every eigenvector.
242  msg.id = i;
243  msg.ns = "distribution_frame/" + boost::lexical_cast<std::string>(pMarkerID);
244 
245  // Set color based on the loop index to get a RGB coordinate frame.
246  msg.color.r = (i == 0) ? 1.0 : 0.0;
247  msg.color.g = (i - 1 == 0) ? 1.0 : 0.0;
248  msg.color.b = (i - 2 == 0) ? 1.0 : 0.0;
249  msg.color.a = 1.0;
250 
251  // Publish eigenvector message.
252  mPublisher->publish(msg);
253  }
254  }
255 
256  void GaussianVisualization::publishArrowToPoint(const int pMarkerID, const std_msgs::ColorRGBA& pColor, const boost::shared_ptr<Eigen::Quaternion<double> > pPoint)
257  {
258  // Call to advertise() should not have returned an empty publisher.
259  if(!mPublisher)
260  throw std::invalid_argument("Empty ros::publisher cannot be used to publish marker messages.");
261 
262  // Generate marker for given point and publish it on given topic.
263  mPublisher->publish(generateArrowToPoint(pMarkerID, pColor, pPoint));
264  }
265 
266  visualization_msgs::Marker GaussianVisualization::generateArrowToPoint(const int pMarkerID, const std_msgs::ColorRGBA& pColor, const boost::shared_ptr<Eigen::Quaternion<double> > pPoint)
267  {
268  // All color parameter values must be in [0,1].
269  if((pColor.r < 0.0f || pColor.r > 1.0f) || (pColor.g < 0.0f || pColor.g > 1.0f) || (pColor.b < 0.0f || pColor.b > 1.0f) || (pColor.a < 0.0f || pColor.a > 1.0f))
270  throw std::out_of_range("ColorRGBA message is no valid color information.");
271 
272  visualization_msgs::Marker msg;
273 
274  // Set time and frame id.
275  msg.header.stamp = ros::Time::now();
276  msg.header.frame_id = mObjectLocationFrameID;
277 
278  // Scale it to be very small and long.
279  msg.scale.x = 0.04;
280  msg.scale.y = 0.1;
281  msg.scale.z = 0.1;
282 
283  // This should be an arrow.
284  msg.type = visualization_msgs::Marker::ARROW;
285 
286  // Namespace will represent the nature of the message.
287  // Yeah, it's really hard to find comments for every line...
288  msg.ns = "evidence";
289 
290  // Markers with different namespaces but same id represent same object location distribution with different shapes.
291  // Haha, I stole the comment from above and nobody realized ;)!
292  msg.id = pMarkerID;
293 
294  // We always want to show a marker by publishing ros messages here.
295  msg.action = visualization_msgs::Marker::ADD;
296 
297  // Create the starting point.
298  geometry_msgs::Point start;
299  start.x = pPoint->x() * mScale;
300  start.y = pPoint->y() * mScale;
301  start.z = pPoint->z() * mScale + 0.5;
302  msg.points.push_back(start);
303 
304  // Create the point to point to ;).
305  geometry_msgs::Point stop;
306  stop.x = pPoint->x() * mScale;
307  stop.y = pPoint->y() * mScale;
308  stop.z = pPoint->z() * mScale;
309  msg.points.push_back(stop);
310 
311  // Set the color of the arrow for rviz.
312  msg.color = pColor;
313 
314  return msg;
315  }
316 
317  void GaussianVisualization::publishPointCloud(const int pMarkerID, const std::vector<boost::shared_ptr<Eigen::Quaternion<double> > > pCloud)
318  {
319  // Call to advertise() should not have returned an empty publisher.
320  if(!mPublisher)
321  throw std::invalid_argument("Empty ros::publisher cannot be used to publish marker messages.");
322 
323  // Generate point cloud and publish it on given topic.
324  for(unsigned int i = 0; i < pCloud.size(); i++)
325  mPublisher->publish(generatePointCloudPoint(pMarkerID, i, pCloud[i]));
326  }
327 
328  visualization_msgs::Marker GaussianVisualization::generatePointCloudPoint(const int pMarkerID, const unsigned int pId, const boost::shared_ptr<Eigen::Quaternion<double> >& pPoint)
329  {
330  visualization_msgs::Marker msg;
331 
332  // Set time and frame id.
333  msg.header.stamp = ros::Time::now();
334  msg.header.frame_id = mObjectLocationFrameID;
335 
336  // Namespace will represent the nature of the message.
337  msg.ns = "samples/" + boost::lexical_cast<std::string>(pMarkerID);
338 
339  // Every sample has its own id.
340  msg.id = pId;
341 
342  // Point is represented by a sphere.
343  msg.type = visualization_msgs::Marker::SPHERE;
344 
345  // We always want to show a marker by publishing ros messages here.
346  msg.action = visualization_msgs::Marker::ADD;
347 
348  // Set the position of the sphere based on the current point and apply visualization scale factor.
349  msg.pose.position.x = pPoint->x() * mScale;
350  msg.pose.position.y = pPoint->y() * mScale;
351  msg.pose.position.z = pPoint->z() * mScale;
352 
353  // We don't need somespacial orientation.
354  msg.pose.orientation.x = 1;
355  msg.pose.orientation.y = 1;
356  msg.pose.orientation.z = 1;
357  msg.pose.orientation.w = 1;
358 
359  // Sphere should be very small.
360  msg.scale.x = 0.005;
361  msg.scale.y = 0.005;
362  msg.scale.z = 0.005;
363 
364  // And black! We love black!
365  msg.color.a = 1.0;
366  msg.color.r = 0.0;
367  msg.color.g = 0.0;
368  msg.color.b = 0.0;
369 
370  // Return the point
371  return msg;
372  }
373 
374  template <class T> void GaussianVisualization::stlVectorToPointMsg(const std::vector<T> pPositionVector, geometry_msgs::Point& pROSPositionMsg)
375  {
376  //pPositionVector must represent a position to be converted.
377  if(pPositionVector.size() != 3)
378  throw std::invalid_argument("pPositionVector is not a position in terms of dimensionality.");
379 
380  //Copy position information per dimension.
381  pROSPositionMsg.x = pPositionVector.at(0);
382  pROSPositionMsg.y = pPositionVector.at(1);
383  pROSPositionMsg.z = pPositionVector.at(2);
384  }
385 
386 }
f
visualization_msgs::Marker generatePointCloudPoint(const int pMarkerID, const unsigned int pId, const boost::shared_ptr< Eigen::Quaternion< double > > &pPoint)
void setSigmaMultiplicator(const float pSigmaMultiplicator)
void publishCovarianceEllipsoidMarker(const int pMarkerID, const std_msgs::ColorRGBA &pEllipsoidColor)
void publishArrowToPoint(const int pMarkerID, const std_msgs::ColorRGBA &pColor, const boost::shared_ptr< Eigen::Quaternion< double > > pPoint)
void publishPointCloud(const int pMarkerID, const std::vector< boost::shared_ptr< Eigen::Quaternion< double > > > pCloud)
visualization_msgs::Marker generateArrowToPoint(const int pMarkerID, const std_msgs::ColorRGBA &pColor, const boost::shared_ptr< Eigen::Quaternion< double > > pPoint)
void stlVectorToPointMsg(const std::vector< T > pPositionVector, geometry_msgs::Point &pROSPositionMsg)
void setKernel(const boost::shared_ptr< Eigen::Vector3d > &pMean, const boost::shared_ptr< Eigen::Matrix3d > &pCovariance)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
boost::shared_ptr< Eigen::Vector3d > mMean
boost::shared_ptr< ros::Publisher > mPublisher
boost::shared_ptr< visualization_msgs::Marker > generateCovarianceEllipsoidMarker(const int pMarkerID, const int pMarkerShape, const std::vector< std::vector< std::vector< float > > > &pWireFramePolygons, const float &pWireFrameWidth, const std_msgs::ColorRGBA &pEllipsoidColor)
static void poseTFToMsg(const Pose &bt, geometry_msgs::Pose &msg)
static Time now()
boost::shared_ptr< Eigen::Matrix3d > mCovariance
void setObjectLocationFrameID(const std::string &pObjectLocationFrameID)
void publishCovarianceEllipsoidCoordinateSystemMarker(const int pMarkerID)
void setAlphaChannel(const float pAlphaChannel)


asr_psm_visualizations
Author(s): Gehrung Joachim, Meißner Pascal
autogenerated on Sat Nov 9 2019 03:49:12