Your robot's position in the world is the transform between its base_link
frame and a world-referenced frame, such as odom
or map
. According to REP105, the robot's position in the odom
frame should always be continuous. GPS data is discontinuous, so therefore it should not be fused into a robot_localization
instance for odom
. If you want to integrate GPS data, the most common way is to run a second instance of robot_localization
and set it's world frame to map
. So you now have two estimates of your robot's position in the world: one in the odom
frame and one in map
. The transforms for these estimates would be published with the parent frame as the world frame, and the child frame as base_link
. However, and this is the important part: a frame can only ever have one parent! Publishing the two transforms odom -> base_link
and map -> base_link
would violate this rule. So, to get around this, robot_localization will publish map -> odom
and odom -> base_link
in a way such that the map -> base_link
transform is still correct.
Since map
is world fixed, and map -> odom
has a non-zero transform, it may seem like this implies that the odom
frame is moving in the world, but it isn't! The map -> odom
transform is simply the difference in your robot's position estimate between the two state estimation nodes. The map
estimate is more accurate in the long term, but the odom
estimate is continuous and is best used for navigation. The magnitude of the transform can be thought of as a measure of the accumulated drift error in the odom
estimate, due to it not having any absolute referencing data inputs such as GPS.
TLDR: You can't have two parent frames for one child frame, so odom
is the tf
parent of base_link
and map
is the tf
parent of odom
.