Tom Moore's answer is correct, however for others like me who are relatively new to ROS I'll restate everything a bit more explicitly with instructions. In this instance I am referring to the frame /odom
as created by an instance of ekf_localization
from the robot_localization
package, so my explanation relates to that package. The problem and solution may be different if you are using some other part of the navigation stack to track odometry. I'm also assuming that this is a ground based robot with IMU and odometry data.
Problem
You want to know how the frame /odom is initialized and how you can manually re-set it or control it's initialization.
Cause
In short: The origin of /odom
initializes to the current position of the robot. The orientation of /odom
initializes to whatever your IMU thinks is magnetic North (the heading at which your IMU reads 0.0).
In full: The frame /odom
is created by an instance of ekf_localization
when the node is launched. By default, the origin of /odom
is set equal to the origin of /base_link
- i.e. the current position of your robot. The ekf_localization
node requires an IMU data stream as an input (default source is /imu/data
). This data stream dictates the orientation of /odom
. When ekf_localization
is launched it will read the IMU data and set the orientation of /odom
to whatever heading your IMU will read 0.0 at. If your IMU data is earth-referenced, it will (typically) read 0.0 when pointing to magnetic North. So, your /odom
frame will initialize with its orientation pointing to magnetic North.
However, you may want to re-set /odom
or otherwise control its pose...
Solution
There are three things you can do to set the origin and orientation of /odom
:
- Initialize
/odom
to match the origin and orientation of /base_link
at launch. - Manually re-set the origin and orientation of
/odom
by publishing a geometry_msgs/PoseWithCovarianceStamped to the /set_pose
topic. - Use the
SetPose
service to set the origin and orientation.
(There may be more options that I don't know about yet so feel free to correct me)
Setting /odom
at launch
This is as simple as setting a single parameter in the launch file for your robot_localization
instance that is creating /odom
. Find your launch file and add the line:
<param name="imu0_relative" value="true"/>
To override the IMU data and match the orientations. The origin of /odom
should already match.
Re-setting /odom
by publishing to /set_pose
At any time you can publish a geometry_msgs/PoseWithCovarianceStamped message to the /set_pose
topic. The topic likely won't appear using rostopic list
until you publish to it. Type this into a terminal:
rostopic pub /set_pose geometry_msgs/PoseWithCovarianceStamped '{header: {stamp: now, frame_id: "odom"}, pose: {pose: {position: {x: 1.0, y: 1.0, z: 0.0}, orientation: {w: 1.0} }, covariance: [1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0 ...
(more)