3232#include < OgreSceneManager.h>
3333
3434#include " imu_acc_visual.h"
35+
36+ #include < cmath>
37+ #include < rclcpp/rclcpp.hpp>
38+ #include < rviz_common/logging.hpp>
3539#include < rviz_rendering/objects/arrow.hpp>
3640
3741namespace rviz_imu_plugin {
3842
3943ImuAccVisual::ImuAccVisual (Ogre::SceneManager* scene_manager,
4044 Ogre::SceneNode* parent_node)
4145 : acc_vector_(NULL ),
46+ quat_valid_ (true ),
4247 arrow_length_(9.81 ),
4348 arrow_radius_(0.50 ),
4449 head_length_(1.00 ),
@@ -92,25 +97,46 @@ void ImuAccVisual::hide()
9297
9398void ImuAccVisual::setMessage (const sensor_msgs::msg::Imu::ConstSharedPtr msg)
9499{
95- direction_ =
100+ raw_acc_ =
96101 Ogre::Vector3 (msg->linear_acceleration .x , msg->linear_acceleration .y ,
97102 msg->linear_acceleration .z );
103+ arrow_length_ = raw_acc_.length ();
98104
99- // Rotate the acceleration vector by the IMU orientation. This makes
100- // sense since the visualization of the IMU is also rotated by the
101- // orientation. In this way, both appear in the inertial frame.
102- if (derotated_)
105+ if (checkQuaternionValidity (msg))
103106 {
104- Ogre::Quaternion orientation (msg->orientation .w , msg->orientation .x ,
105- msg->orientation .y , msg->orientation .z );
106-
107- direction_ = orientation * direction_;
107+ if (!quat_valid_)
108+ {
109+ RVIZ_COMMON_LOG_INFO_STREAM (
110+ " rviz_imu_plugin got valid quaternion, "
111+ " applying acceleration derotation" );
112+ quat_valid_ = true ;
113+ }
114+ orientation_ = Ogre::Quaternion (msg->orientation .w , msg->orientation .x ,
115+ msg->orientation .y , msg->orientation .z );
116+ } else
117+ {
118+ if (quat_valid_)
119+ {
120+ RVIZ_COMMON_LOG_WARNING_STREAM (
121+ " rviz_imu_plugin got invalid quaternion ("
122+ << msg->orientation .w << " ," << msg->orientation .x << " ,"
123+ << msg->orientation .y << " ," << msg->orientation .z
124+ << " ); skipping acceleration derotation" );
125+ quat_valid_ = false ;
126+ }
127+ orientation_ = Ogre::Quaternion ();
108128 }
109129
110- arrow_length_ =
111- sqrt (msg->linear_acceleration .x * msg->linear_acceleration .x +
112- msg->linear_acceleration .y * msg->linear_acceleration .y +
113- msg->linear_acceleration .z * msg->linear_acceleration .z );
130+ updateDirection ();
131+ }
132+
133+ void ImuAccVisual::updateDirection ()
134+ {
135+ direction_ = raw_acc_;
136+ if (derotated_ && quat_valid_)
137+ {
138+ direction_ = orientation_ * direction_;
139+ }
114140
115141 if (acc_vector_)
116142 {
@@ -150,9 +176,7 @@ void ImuAccVisual::setAlpha(float alpha)
150176void ImuAccVisual::setDerotated (bool derotated)
151177{
152178 derotated_ = derotated;
153- if (acc_vector_)
154- acc_vector_->setColor (color_.redF (), color_.greenF (), color_.blueF (),
155- alpha_);
179+ updateDirection ();
156180}
157181
158182void ImuAccVisual::setFramePosition (const Ogre::Vector3& position)
@@ -165,4 +189,23 @@ void ImuAccVisual::setFrameOrientation(const Ogre::Quaternion& orientation)
165189 frame_node_->setOrientation (orientation);
166190}
167191
192+ bool ImuAccVisual::checkQuaternionValidity (
193+ const sensor_msgs::msg::Imu::ConstSharedPtr msg)
194+ {
195+ // REP-145: orientation_covariance[0] == -1 signals "not estimated".
196+ if (msg->orientation_covariance [0 ] == -1.0 )
197+ {
198+ return false ;
199+ }
200+ double x = msg->orientation .x , y = msg->orientation .y ,
201+ z = msg->orientation .z , w = msg->orientation .w ;
202+ // Near-zero length indicates the default (0, 0, 0, 0) quaternion,
203+ // which would silently zero out any vector multiplication.
204+ if (std::sqrt (x * x + y * y + z * z + w * w) < 0.0001 )
205+ {
206+ return false ;
207+ }
208+ return true ;
209+ }
210+
168211} // namespace rviz_imu_plugin
0 commit comments