ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
1 | initial version |
In the meantime we implemented a modified version of the gazebo_ros_imu plugin in our hector_gazebo_plugins package (http://www.ros.org/wiki/hector_gazebo_plugins). The sensor controller can be configured with independent Gaussian noise and a low-frequency drifting behavior for all six IMU channels (angular_velocity and linear_acceleration). Orientation is derived from the simulated acceleration/gravity measurement and an additional error model for the heading.
So here are some answers to my own questions:
An acceleration sensors measures the acceleration acting on a probe mass relative to the sensor's body frame. Gravity is acting on both, the probe mass and the sensor frame and therefore has to be handled separately from other forces. All other external forces are acting on the frame only and therefore produce a measurable relative acceleration. As a result, the sensor output is the sum of all forces minus the gravity (or vice-versa depending on the point of view). When the platform is not accelerated, e.g. standing on the ground, the sensor output corresponds to the inverse gravity vector.
The Entity::GetRelativeLinearAccel() and Entity::GetWorldLinearAccel() member functions are indeed unusable for IMU simulation as their result is dependent on the order in which controllers are executed. Looking at Gazebo's current implementation of the ODEBody::SetForce() and ODEBody::SetTorque() method reveals that forces and torques are accumulated within each simulation step and the getter functions for forces and linear accelerations just return the current value of the accumulator. Forces added at a later time are ignored. Furthermore gravity and contact forces seem to be handled differently and the returned acceleration vector is zero for a platform standing on the ground and during free fall. So looking at the linear velocities and differentiating them manually is a valuable solution for determining the overall acceleration during the previous time step. GetRelativeAngularVel()/GetWorldAngularVel() functions are not affected by this issue, but sometimes return illegal NaN values. Calculating the angular velocity from the quaternion rate between two subsequent time steps works flawlessly.
As expected the return values of Body::GetRelativeXXX() and Body::GetWorldXXX() functions just differ by the true orientation of the platform in the world frame. Our implementation of the hector_gazebo_ros_imu plugin uses the GetRelativeLinearVel() function directly to calculate the accelerations in body coordinates. The roll and pitch components of the orientation quaternion are derived from the "measured" gravity vector affected by noise, offset and drift, much like a real AHRS would do in the static case. Errors in orientation are a consequence of the drift error in gravity measurement and therefore not independent of the orientation like in the standard implementation of the IMU plugin.