covariance_visual.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, Ellon Paiva Mendes @ LAAS-CNRS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "covariance_visual.h"
31 
34 
35 #include <OgreSceneManager.h>
36 #include <OgreSceneNode.h>
37 #include <OgreQuaternion.h>
38 
39 #include <ros/console.h>
40 
41 #include <sstream>
42 
43 namespace rviz
44 {
45 namespace
46 {
47 double deg2rad(double degrees)
48 {
49  return degrees * 4.0 * atan(1.0) / 180.0;
50 }
51 
52 // Local function to force the axis to be right handed for 3D. Taken from ecl_statistics
53 void makeRightHanded(Eigen::Matrix3d& eigenvectors, Eigen::Vector3d& eigenvalues)
54 {
55  // Note that sorting of eigenvalues may end up with left-hand coordinate system.
56  // So here we correctly sort it so that it does end up being right-handed and normalised.
57  Eigen::Vector3d c0 = eigenvectors.col(0);
58  c0.normalize();
59  Eigen::Vector3d c1 = eigenvectors.col(1);
60  c1.normalize();
61  Eigen::Vector3d c2 = eigenvectors.col(2);
62  c2.normalize();
63  Eigen::Vector3d cc = c0.cross(c1);
64  if (cc.dot(c2) < 0)
65  {
66  eigenvectors << c1, c0, c2;
67  std::swap(eigenvalues[0], eigenvalues[1]);
68  }
69  else
70  {
71  eigenvectors << c0, c1, c2;
72  }
73 }
74 
75 // Local function to force the axis to be right handed for 2D. Based on the one from ecl_statistics
76 void makeRightHanded(Eigen::Matrix2d& eigenvectors, Eigen::Vector2d& eigenvalues)
77 {
78  // Note that sorting of eigenvalues may end up with left-hand coordinate system.
79  // So here we correctly sort it so that it does end up being righ-handed and normalised.
80  Eigen::Vector3d c0;
81  c0.setZero();
82  c0.head<2>() = eigenvectors.col(0);
83  c0.normalize();
84  Eigen::Vector3d c1;
85  c1.setZero();
86  c1.head<2>() = eigenvectors.col(1);
87  c1.normalize();
88  Eigen::Vector3d cc = c0.cross(c1);
89  if (cc[2] < 0)
90  {
91  eigenvectors << c1.head<2>(), c0.head<2>();
92  std::swap(eigenvalues[0], eigenvalues[1]);
93  }
94  else
95  {
96  eigenvectors << c0.head<2>(), c1.head<2>();
97  }
98 }
99 
100 void computeShapeScaleAndOrientation3D(const Eigen::Matrix3d& covariance,
101  Ogre::Vector3& scale,
102  Ogre::Quaternion& orientation)
103 {
104  Eigen::Vector3d eigenvalues(Eigen::Vector3d::Identity());
105  Eigen::Matrix3d eigenvectors(Eigen::Matrix3d::Zero());
106 
107  // NOTE: The SelfAdjointEigenSolver only references the lower triangular part of the covariance matrix
108  // FIXME: Should we use Eigen's pseudoEigenvectors() ?
109  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver(covariance);
110  // Compute eigenvectors and eigenvalues
111  if (eigensolver.info() == Eigen::Success)
112  {
113  eigenvalues = eigensolver.eigenvalues();
114  eigenvectors = eigensolver.eigenvectors();
115  }
116  else
117  {
119  1, "failed to compute eigen vectors/values for position. Is the covariance matrix correct?");
120  eigenvalues = Eigen::Vector3d::Zero(); // Setting the scale to zero will hide it on the screen
121  eigenvectors = Eigen::Matrix3d::Identity();
122  }
123 
124  // Be sure we have a right-handed orientation system
125  makeRightHanded(eigenvectors, eigenvalues);
126 
127  // Define the rotation
128  orientation.FromRotationMatrix(Ogre::Matrix3( // clang-format off
129  eigenvectors(0, 0), eigenvectors(0, 1), eigenvectors(0, 2),
130  eigenvectors(1, 0), eigenvectors(1, 1), eigenvectors(1, 2),
131  eigenvectors(2, 0), eigenvectors(2, 1), eigenvectors(2, 2))); // clang-format on
132 
133  // Define the scale. eigenvalues are the variances, so we take the sqrt to draw the standard deviation
134  scale.x = 2 * std::sqrt(eigenvalues[0]);
135  scale.y = 2 * std::sqrt(eigenvalues[1]);
136  scale.z = 2 * std::sqrt(eigenvalues[2]);
137 }
138 
139 enum Plane
140 {
141  YZ_PLANE, // normal is x-axis
142  XZ_PLANE, // normal is y-axis
143  XY_PLANE // normal is z-axis
144 };
145 
146 void computeShapeScaleAndOrientation2D(const Eigen::Matrix2d& covariance,
147  Ogre::Vector3& scale,
148  Ogre::Quaternion& orientation,
149  Plane plane = XY_PLANE)
150 {
151  Eigen::Vector2d eigenvalues(Eigen::Vector2d::Identity());
152  Eigen::Matrix2d eigenvectors(Eigen::Matrix2d::Zero());
153 
154  // NOTE: The SelfAdjointEigenSolver only references the lower triangular part of the covariance matrix
155  // FIXME: Should we use Eigen's pseudoEigenvectors() ?
156  Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eigensolver(covariance);
157  // Compute eigenvectors and eigenvalues
158  if (eigensolver.info() == Eigen::Success)
159  {
160  eigenvalues = eigensolver.eigenvalues();
161  eigenvectors = eigensolver.eigenvectors();
162  }
163  else
164  {
166  1, "failed to compute eigen vectors/values for position. Is the covariance matrix correct?");
167  eigenvalues = Eigen::Vector2d::Zero(); // Setting the scale to zero will hide it on the screen
168  eigenvectors = Eigen::Matrix2d::Identity();
169  }
170 
171  // Be sure we have a right-handed orientation system
172  makeRightHanded(eigenvectors, eigenvalues);
173 
174  // Define the rotation and scale of the plane
175  // The Eigenvalues are the variances. The scales are two times the standard
176  // deviation. The scale of the missing dimension is set to zero.
177  if (plane == YZ_PLANE)
178  {
179  orientation.FromRotationMatrix(Ogre::Matrix3(1, 0, 0, // clang-format off
180  0, eigenvectors(0, 0), eigenvectors(0, 1),
181  0, eigenvectors(1, 0), eigenvectors(1, 1))); // clang-format on
182 
183  scale.x = 0;
184  scale.y = 2 * std::sqrt(eigenvalues[0]);
185  scale.z = 2 * std::sqrt(eigenvalues[1]);
186  }
187  else if (plane == XZ_PLANE)
188  {
189  orientation.FromRotationMatrix(
190  Ogre::Matrix3(eigenvectors(0, 0), 0, eigenvectors(0, 1), // clang-format off
191  0, 1, 0,
192  eigenvectors(1, 0), 0, eigenvectors(1, 1))); // clang-format on
193 
194  scale.x = 2 * std::sqrt(eigenvalues[0]);
195  scale.y = 0;
196  scale.z = 2 * std::sqrt(eigenvalues[1]);
197  }
198  else // plane == XY_PLANE
199  {
200  orientation.FromRotationMatrix(
201  Ogre::Matrix3(eigenvectors(0, 0), eigenvectors(0, 1), 0, // clang-format off
202  eigenvectors(1, 0), eigenvectors(1, 1), 0,
203  0, 0, 1)); // clang-format on
204 
205  scale.x = 2 * std::sqrt(eigenvalues[0]);
206  scale.y = 2 * std::sqrt(eigenvalues[1]);
207  scale.z = 0;
208  }
209 }
210 
211 void radianScaleToMetricScaleBounded(Ogre::Real& radian_scale, float max_degrees)
212 {
213  radian_scale /= 2.0;
214  if (radian_scale > deg2rad(max_degrees))
215  radian_scale = deg2rad(max_degrees);
216  radian_scale = 2.0 * tan(radian_scale);
217 }
218 
219 
220 } // namespace
221 
222 const float CovarianceVisual::max_degrees = 89.0;
223 
224 CovarianceVisual::CovarianceVisual(Ogre::SceneManager* scene_manager,
225  Ogre::SceneNode* parent_node,
226  bool is_local_rotation,
227  bool is_visible,
228  float pos_scale,
229  float ori_scale,
230  float ori_offset)
231  : Object(scene_manager)
232  , local_rotation_(is_local_rotation)
233  , pose_2d_(false)
234  , orientation_visible_(is_visible)
235 {
236  // Main node of the visual
237  root_node_ = parent_node->createChildSceneNode();
238  // Node that will have the same orientation as the fixed frame. Updated from the message on
239  // setCovariance()
240  fixed_orientation_node_ = root_node_->createChildSceneNode();
241  // Node to scale the position part of the covariance from the property value
242  position_scale_node_ = fixed_orientation_node_->createChildSceneNode();
243  // Node to be oriented and scaled from the message's covariance
244  position_node_ = position_scale_node_->createChildSceneNode();
246 
247  // Node to scale the orientation part of the covariance. May be attached to both the local (root) node
248  // or the fixed frame node.
249  // May be re-attached later by setRotatingFrame()
250  if (local_rotation_)
251  orientation_root_node_ = root_node_->createChildSceneNode();
252  else
253  orientation_root_node_ = fixed_orientation_node_->createChildSceneNode();
254 
255  for (int i = 0; i < kNumOriShapes; i++)
256  {
257  // Node to position and orient the shape along the axis. One for each axis.
258  orientation_offset_node_[i] = orientation_root_node_->createChildSceneNode();
259  // Does not inherit scale from the parent. This is needed to keep the cylinders with the same height.
260  // The scale is set by setOrientationScale()
261  orientation_offset_node_[i]->setInheritScale(false);
262 
263  if (i != kYaw2D)
264  orientation_shape_[i] =
266  else
267  orientation_shape_[i] =
269 
270  // Initialize all current scales to 0
271  current_ori_scale_[i] = Ogre::Vector3(0, 0, 0);
272  }
273 
274  // Position the cylindes at position 1.0 in the respective axis, and perpendicular to the axis.
275  // x-axis (roll)
276  orientation_offset_node_[kRoll]->setPosition(Ogre::Vector3::UNIT_X);
277  orientation_offset_node_[kRoll]->setOrientation(
278  Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_X) *
279  Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_Z));
280  // y-axis (pitch)
281  orientation_offset_node_[kPitch]->setPosition(Ogre::Vector3(Ogre::Vector3::UNIT_Y));
282  orientation_offset_node_[kPitch]->setOrientation(
283  Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_Y));
284  // z-axis (yaw)
285  orientation_offset_node_[kYaw]->setPosition(Ogre::Vector3(Ogre::Vector3::UNIT_Z));
286  orientation_offset_node_[kYaw]->setOrientation(
287  Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_X));
288  // z-axis (yaw 2D)
289  // NOTE: rviz use a cone defined by the file rviz/ogre_media/models/rviz_cone.mesh, and it's
290  // origin is not at the top of the cone. Since we want the top to be at the origin of
291  // the pose we need to use an offset here.
292  // WARNING: This number was found by trial-and-error on rviz and it's not the correct
293  // one, so changes on scale are expected to cause the top of the cone to move
294  // from the pose origin, although it's only noticeable with big scales.
295  // FIXME: Find the right value from the cone.mesh file, or implement a class that draws
296  // something like a 2D "pie slice" and use it instead of the cone.
297  static const double cone_origin_to_top = 0.49115;
298  orientation_offset_node_[kYaw2D]->setPosition(cone_origin_to_top * Ogre::Vector3::UNIT_X);
299  orientation_offset_node_[kYaw2D]->setOrientation(
300  Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3::UNIT_Z));
301 
302  // set initial visibility and scale
303  // root node is always visible. The visibility will be updated on its childs.
304  root_node_->setVisible(true);
305  setVisible(is_visible);
306  setScales(pos_scale, ori_scale);
307  setOrientationOffset(ori_offset);
308 }
309 
311 {
312  delete position_shape_;
313  scene_manager_->destroySceneNode(position_node_->getName());
314 
315  for (int i = 0; i < kNumOriShapes; i++)
316  {
317  delete orientation_shape_[i];
318  scene_manager_->destroySceneNode(orientation_offset_node_[i]->getName());
319  }
320 
321  scene_manager_->destroySceneNode(position_scale_node_->getName());
322  scene_manager_->destroySceneNode(fixed_orientation_node_->getName());
323  scene_manager_->destroySceneNode(root_node_->getName());
324 }
325 
326 void CovarianceVisual::setCovariance(const geometry_msgs::PoseWithCovariance& pose)
327 {
328  // check for NaN in covariance
329  for (unsigned i = 0; i < 3; ++i)
330  {
331  if (std::isnan(pose.covariance[i]))
332  {
333  ROS_WARN_THROTTLE(1, "covariance contains NaN");
334  return;
335  }
336  }
337 
338  pose_2d_ = pose.covariance[14] <= 0 && pose.covariance[21] <= 0 && pose.covariance[28] <= 0;
339 
341 
342  // store orientation in Ogre structure
343  Ogre::Quaternion ori;
344  normalizeQuaternion(pose.pose.orientation, ori);
345 
346  // Set the orientation of the fixed node. Since this node is attached to the root node, it's
347  // orientation will be the
348  // inverse of pose's orientation.
349  fixed_orientation_node_->setOrientation(ori.Inverse());
350  // Map covariance to a Eigen::Matrix
351  Eigen::Map<const Eigen::Matrix<double, 6, 6> > covariance(pose.covariance.data());
352 
353  updatePosition(covariance);
354  if (!pose_2d_)
355  {
356  updateOrientation(covariance, kRoll);
357  updateOrientation(covariance, kPitch);
358  updateOrientation(covariance, kYaw);
359  }
360  else
361  {
362  updateOrientation(covariance, kYaw2D);
363  }
364 }
365 
367 {
368  // Compute shape and orientation for the position part of covariance
369  Ogre::Vector3 shape_scale;
370  Ogre::Quaternion shape_orientation;
371  if (pose_2d_)
372  {
373  computeShapeScaleAndOrientation2D(covariance.topLeftCorner<2, 2>(), shape_scale, shape_orientation,
374  XY_PLANE);
375  // Make the scale in z minimal for better visualization
376  shape_scale.z = 0.001;
377  }
378  else
379  {
380  computeShapeScaleAndOrientation3D(covariance.topLeftCorner<3, 3>(), shape_scale, shape_orientation);
381  }
382  // Rotate and scale the position scene node
383  position_node_->setOrientation(shape_orientation);
384  if (!shape_scale.isNaN())
385  position_node_->setScale(shape_scale);
386  else
387  ROS_WARN_STREAM("position shape_scale contains NaN: " << shape_scale);
388 }
389 
391 {
392  Ogre::Vector3 shape_scale;
393  Ogre::Quaternion shape_orientation;
394  // Compute shape and orientation for the orientation shape
395  if (pose_2d_)
396  {
397  // We should only enter on this scope if the index is kYaw2D
398  assert(index == kYaw2D);
399  // 2D poses only depend on yaw.
400  shape_scale.x = 2.0 * sqrt(covariance(5, 5));
401  // To display the cone shape properly the scale along y-axis has to be one.
402  shape_scale.y = 1.0;
403  // Give a minimal height for the cone for better visualization
404  shape_scale.z = 0.001;
405  // Store the computed scale to be used if the user change the scale
406  current_ori_scale_[index] = shape_scale;
407  // Apply the current scale factor
408  shape_scale.x *= current_ori_scale_factor_;
409  // The scale on x means twice the standard deviation, but _in radians_.
410  // So we need to convert it to the linear scale of the shape using tan().
411  // Also, we bound the maximum std
412  radianScaleToMetricScaleBounded(shape_scale.x, max_degrees);
413  }
414  else
415  {
416  assert(index != kYaw2D);
417 
418  // Get the correct sub-matrix based on the index
419  Eigen::Matrix2d covarianceAxis;
420  if (index == kRoll)
421  {
422  covarianceAxis = covariance.bottomRightCorner<2, 2>();
423  }
424  else if (index == kPitch)
425  {
426  covarianceAxis << covariance(3, 3), covariance(3, 5), covariance(5, 3), covariance(5, 5);
427  }
428  else if (index == kYaw)
429  {
430  covarianceAxis = covariance.block<2, 2>(3, 3);
431  }
432 
433  // NOTE: The cylinder mesh is oriented along its y axis, we want to flat it out into the XZ plane
434  computeShapeScaleAndOrientation2D(covarianceAxis, shape_scale, shape_orientation, XZ_PLANE);
435  // Give a minimal height for the cylinder for better visualization
436  shape_scale.y = 0.001;
437  // Store the computed scale to be used if the user change the scale
438  current_ori_scale_[index] = shape_scale;
439  // Apply the current scale factor
440  shape_scale.x *= current_ori_scale_factor_;
441  shape_scale.z *= current_ori_scale_factor_;
442  // The computed scale is equivalent to twice the standard deviation _in radians_.
443  // So we need to convert it to the linear scale of the shape using tan().
444  // Also, we bound the maximum std.
445  radianScaleToMetricScaleBounded(shape_scale.x, max_degrees);
446  radianScaleToMetricScaleBounded(shape_scale.z, max_degrees);
447  }
448 
449  // Rotate and scale the scene node of the orientation part
450  orientation_shape_[index]->setOrientation(shape_orientation);
451  if (!shape_scale.isNaN())
452  orientation_shape_[index]->setScale(shape_scale);
453  else
454  ROS_WARN_STREAM("orientation shape_scale contains NaN: " << shape_scale);
455 }
456 
457 void CovarianceVisual::setScales(float pos_scale, float ori_scale)
458 {
459  setPositionScale(pos_scale);
460  setOrientationScale(ori_scale);
461 }
462 
464 {
465  if (pose_2d_)
466  position_scale_node_->setScale(pos_scale, pos_scale, 1.0);
467  else
468  position_scale_node_->setScale(pos_scale, pos_scale, pos_scale);
469 }
470 
472 {
473  // Scale the orientation root node to position the shapes along the axis
474  orientation_root_node_->setScale(ori_offset, ori_offset, ori_offset);
475  // The scale the offset_nodes as well so the displayed shape represents a 1-sigma
476  // standard deviation when displayed with an scale of 1.0
477  // NOTE: We only want to change the scales of the dimentions that represent the
478  // orientation covariance. The other dimensions are set to 1.0.
479  for (int i = 0; i < kNumOriShapes; i++)
480  {
481  if (i == kYaw2D)
482  {
483  // For 2D, the angle is only encoded on x, but we also scale on y to put the top of the cone at the
484  // pose origin
485  orientation_offset_node_[i]->setScale(ori_offset, ori_offset, 1.0);
486  }
487  else
488  {
489  // For 3D, the angle covariance is encoded on x and z dimensions
490  orientation_offset_node_[i]->setScale(ori_offset, 1.0, ori_offset);
491  }
492  }
493 }
494 
496 {
497  // Here we update the current scale factor, apply it to the current scale _in radians_,
498  // convert it to meters and apply to the shape scale. Note we have different invariant
499  // scales in the 3D and in 2D.
500  current_ori_scale_factor_ = ori_scale;
501  for (int i = 0; i < kNumOriShapes; i++)
502  {
503  // Recover the last computed scale
504  Ogre::Vector3 shape_scale = current_ori_scale_[i];
505  if (i == kYaw2D)
506  {
507  // Changes in scale in 2D only affects the x dimension
508  // Apply the current scale factor
509  shape_scale.x *= current_ori_scale_factor_;
510  // Convert from radians to meters
511  radianScaleToMetricScaleBounded(shape_scale.x, max_degrees);
512  }
513  else
514  {
515  // Changes in scale in 3D only affects the x and z dimensions
516  // Apply the current scale factor
517  shape_scale.x *= current_ori_scale_factor_;
518  shape_scale.z *= current_ori_scale_factor_;
519  // Convert from radians to meters
520  radianScaleToMetricScaleBounded(shape_scale.x, max_degrees);
521  radianScaleToMetricScaleBounded(shape_scale.z, max_degrees);
522  }
523  // Apply the new scale
524  orientation_shape_[i]->setScale(shape_scale);
525  }
526 }
527 
528 void CovarianceVisual::setPositionColor(const Ogre::ColourValue& c)
529 {
531 }
532 
533 void CovarianceVisual::setOrientationColor(const Ogre::ColourValue& c)
534 {
535  for (int i = 0; i < kNumOriShapes; i++)
536  {
538  }
539 }
540 
542 {
543  orientation_shape_[kRoll]->setColor(Ogre::ColourValue(1.0, 0.0, 0.0, a));
544  orientation_shape_[kPitch]->setColor(Ogre::ColourValue(0.0, 1.0, 0.0, a));
545  orientation_shape_[kYaw]->setColor(Ogre::ColourValue(0.0, 0.0, 1.0, a));
546  orientation_shape_[kYaw2D]->setColor(Ogre::ColourValue(0.0, 0.0, 1.0, a));
547 }
548 
549 void CovarianceVisual::setPositionColor(float r, float g, float b, float a)
550 {
551  setPositionColor(Ogre::ColourValue(r, g, b, a));
552 }
553 
554 void CovarianceVisual::setOrientationColor(float r, float g, float b, float a)
555 {
556  setOrientationColor(Ogre::ColourValue(r, g, b, a));
557 }
558 
560 {
561  return position_node_->getScale();
562 }
563 
565 {
566  return position_node_->getOrientation();
567 }
568 
569 void CovarianceVisual::setUserData(const Ogre::Any& data)
570 {
572  for (int i = 0; i < kNumOriShapes; i++)
573  {
575  }
576 }
577 
579 {
580  setPositionVisible(visible);
581  setOrientationVisible(visible);
582 }
583 
585 {
586  position_node_->setVisible(visible);
587 }
588 
590 {
591  orientation_visible_ = visible;
593 }
594 
596 {
601 }
602 
603 
604 const Ogre::Vector3& CovarianceVisual::getPosition()
605 {
606  return position_node_->getPosition();
607 }
608 
609 const Ogre::Quaternion& CovarianceVisual::getOrientation()
610 {
611  return position_node_->getOrientation();
612 }
613 
614 void CovarianceVisual::setPosition(const Ogre::Vector3& position)
615 {
616  root_node_->setPosition(position);
617 }
618 
619 void CovarianceVisual::setOrientation(const Ogre::Quaternion& orientation)
620 {
621  root_node_->setOrientation(orientation);
622 }
623 
624 void CovarianceVisual::setRotatingFrame(bool is_local_rotation)
625 {
626  if (local_rotation_ == is_local_rotation)
627  return;
628 
629  local_rotation_ = is_local_rotation;
630 
631  if (local_rotation_)
632  root_node_->addChild(fixed_orientation_node_->removeChild(orientation_root_node_->getName()));
633  else
634  fixed_orientation_node_->addChild(root_node_->removeChild(orientation_root_node_->getName()));
635 }
636 
638 {
639  return orientation_shape_[index];
640 }
641 
642 } // namespace rviz
virtual void setCovariance(const geometry_msgs::PoseWithCovariance &pose)
Set the covariance.
void setOrientation(const Ogre::Quaternion &orientation) override
Set the orientation of the object.
Definition: shape.cpp:155
void setPositionScale(float pos_scale)
void setScale(const Ogre::Vector3 &scale) override
Set the scale of the object. Always relative to the identity orientation of the object.
Definition: shape.cpp:160
void setScales(float pos_scale, float ori_scale)
Set the position and orientation scales for this covariance.
Ogre::SceneNode * position_node_
virtual void setPositionVisible(bool visible)
Sets visibility of the position part of this covariance.
ROSCONSOLE_CONSOLE_IMPL_DECL std::string getName(void *handle)
virtual void setOrientationColor(float r, float g, float b, float a)
Set the color of the orientation covariance. Values are in the range [0, 1].
rviz::Shape * getOrientationShape(ShapeIndex index)
Get the shape used to display orientation covariance in an especific axis.
void setUserData(const Ogre::Any &data) override
Sets user data on all ogre objects we own.
Definition: shape.cpp:175
void setOrientationColorToRGB(float a)
void updatePosition(const Eigen::Matrix6d &covariance)
void setColor(float r, float g, float b, float a) override
Set the color of the object. Values are in the range [0, 1].
Definition: shape.cpp:140
Base class for visible objects, providing a minimal generic interface.
Definition: object.h:50
void setUserData(const Ogre::Any &data) override
Sets user data on all ogre objects we own.
const Ogre::Vector3 & getPosition() override
Get the local position of this object.
virtual const Ogre::Vector3 & getPositionCovarianceScale()
virtual void setOrientationVisible(bool visible)
Sets visibility of the orientation part of this covariance.
void setOrientationOffset(float ori_offset)
INLINE Rall1d< T, V, S > atan(const Rall1d< T, V, S > &x)
#define ROS_WARN_THROTTLE(period,...)
Ogre::SceneNode * orientation_root_node_
virtual void setRotatingFrame(bool use_rotating_frame)
Sets which frame to attach the covariance of the orientation.
Matrix< double, 6, 6 > Matrix6d
Ogre::SceneNode * fixed_orientation_node_
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
void setPosition(const Ogre::Vector3 &position) override
Sets position of the frame this covariance is attached.
#define ROS_WARN_STREAM(args)
float normalizeQuaternion(float &w, float &x, float &y, float &z)
void setOrientation(const Ogre::Quaternion &orientation) override
Sets orientation of the frame this covariance is attached.
bool orientation_visible_
If the orientation component is visible.
Ogre::SceneNode * position_scale_node_
virtual void setPositionColor(float r, float g, float b, float a)
Set the color of the position covariance. Values are in the range [0, 1].
Ogre::Vector3 current_ori_scale_[kNumOriShapes]
void setScale(const Ogre::Vector3 &) override
Set the scale of the object. Always relative to the identity orientation of the object.
Ogre::SceneManager * scene_manager_
Ogre scene manager this object is part of.
Definition: object.h:106
const double deg2rad
rviz::Shape * orientation_shape_[kNumOriShapes]
Cylinders used for the orientation covariance.
INLINE Rall1d< T, V, S > tan(const Rall1d< T, V, S > &arg)
virtual const Ogre::Quaternion & getPositionCovarianceOrientation()
virtual void setVisible(bool visible)
Sets visibility of this covariance.
CovarianceVisual(Ogre::SceneManager *scene_manager, Ogre::SceneNode *parent_node, bool is_local_rotation, bool is_visible=true, float pos_scale=1.0f, float ori_scale=0.1f, float ori_offset=0.1f)
Constructor.
void setOrientationScale(float ori_scale)
void updateOrientation(const Eigen::Matrix6d &covariance, ShapeIndex index)
rviz::Shape * position_shape_
Ellipse used for the position covariance.
Ogre::SceneNode * orientation_offset_node_[kNumOriShapes]
static const float max_degrees
Ogre::SceneNode * root_node_
const Ogre::Quaternion & getOrientation() override
Get the local orientation of this object.


rviz
Author(s): Dave Hershberger, David Gossow, Josh Faust
autogenerated on Sat May 27 2023 02:06:24