Smearing / Ghosting of laser scan in move_base costmap
Hello ROS Community,
I'm seeing a problem where laser scans are exhibiting rotational "smearing" when marking the move_base costmaps. This results in "ghost" obstacles in both the global and local maps, and these have the potential to cause path planning to fail. Typically, these smearing effects are cleared out when subsequent scans detect free space, and so the issue does not always cause navigation to fail. However, it does sometimes cause sub-optimal behavior, such as a need to re-plan.
The robot spec:
- Kobuki base
- Raspberry Pi 2, running ROS Indigo / Ubuntu ARM
- Rhoeby Dynamics R2D LiDAR (@ 3 Hz scan rate)
- Navigation stack (gmapping, move_base)
In the below screenshot: observe the accumulated LaserScans (in white), the local costmap marked areas (in yellow), and the inflated obstacles (in blue). Notice the ghosting of the walls in the top-left part of the costmap (in yellow).
If I set "Decay Time" on the LaserScan topic in RViz to accumulate the scans, and then observe the LaserScan plot over the same time period as when the costmap smearing occurs: I see that there is no such smearing in the decayed LaserScan plot. So the errors in rotation only show up in the costmap, and not on the LaserScans themselves. How/why would that be happening? How is it possible for this difference to exist?
Another observation about this phenomenon is that the problem only occurs when the rotational velocity of the robot is a non-constant, eg. when beginning turning from stopped, or when slowing down from a turn which is in progress. So the problem is a transient one that occurs during theta acceleration. Also of note is the fact that there are no similar smearing effects in translation (robot accelerating along x/y).
The problem is:
- unique to theta
- only occurs during theta acceleration (or deceleration)
- does not seem to affect LaserScans themselves (as plotted in RViz)
- only appears on the move_base costmaps (global and local costmap)
The fact that theta acceleration must be non-zero, leads me to think the problem could be due to delays in the odom TF, perhaps with a root cause in the Kobuki. Is the Kobuki just slow to reflect changes in it's rotation? Perhaps the odom transform lags the actual robot rotation?
But why would this not also affect the "decayed" LaserScan data as plotted in RViz?
The fact that the LaserScan plot is not affected, leads me to think the error could be rooted in move_base, although I doubt it. Perhaps there is some delay in the uptake of changes in the TF? But why only on rotation?
Thanks for any comment.
ADDENDUM:
I've checked the TF frames, and it seems to look reasonable:
The frames utilized are:
The topic /laser_data is published in tf frame: base_laser (rigidly attached to base_footprint)
The topic /move_base/local_costmap/costmap is published in tf frame: odom
The Global frame is: map
local_costmap:
global_frame: odom robot_base_frame: /base_footprint
global_costmap:
global_frame: /map
robot_base_frame: /base_footprint
ADDENDUM 2:
I made the following change ...
Have you tried mapping a priori using
gmapping
and then pairingmove_base
withamcl
on the (now) known map? I'm asking because your costmap configuration might be assuming a static map, not one generated online using SLAM. Conversely, check your costmap configuration.Yes, I've done that, ie. taking a previously built map (and then using amcl), but it shows exactly the same behavior. Note: mapping and navigation are essentially work fine, modulo this transient rotational issue.
I see, OK. Then yeah, the next logical suspects are the Odometry messages and the odom TF. Have you checked/ran
tf view_frames
,tf tf_monitor
,roswtf
,rostopic echo odom
, etc.? Anything suspicious?I've checked the TF frames, and it seems to look reasonable (see ADDENDUM:). Appreciate your input.
The plot thickens. What are the values of your
global_costmap/robot_base_frame
,global_costmap/global_frame
,local_costmap/robot_base_frame
, andlocal_costmap/global_frame
parameters? (You've already mentioned a few of these in your addendum; just getting the full picture.)local_costmap: global_frame: odom robot_base_frame: /base_footprint
global_costmap: global_frame: /map robot_base_frame: /base_footprint