ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

Robot Localization repeatability

asked 2021-04-27 02:40:00 -0500

xaru8145 gravatar image

updated 2021-04-27 02:42:08 -0500

Hi all,

I am using robot_localization and navsat_transform to fuse RTK gps (dual antenna so we have orientation) and imu data. The issue that I am seeing is that when I run a bagfile twice with the same recorded input topics, I get slightly different outputs. Since the inputs are the same and the parameters for the EKF are the same, I would expect the output being exactly the same. Does anyone have any idea why might this be happening?

Thanks so much!


Results

I am attaching 3 images that show this behavior. The position in x and y are the odometry components from the output (/odometry/filtered/global) of the EKF. I use it for an application that requires cm level accuracy so accurate repeatability is really important. I am seeing difference of +-1cm average between 2 reprocessed sessions. Note that the robot starts moving at around sequence=10000, where the error increases. Even the timestamps of the messages are slightly different. I have tried to use f=50 and predict_to_current_time = false but same result. IMU is publishing at 50Hz, gps at 10Hz, heading at 5Hz.

image description image description image description


Launch file

I use use_sime_time = true and --clock arg when using rosbag play.

<launch>
<node pkg="tf2_ros" type="static_transform_publisher" name="map_odom" args="0 0 0 0 0 0 map odom" />
<node pkg="robot_localization" type="ekf_localization_node" name="ekf_global_localization">
    <rosparam command="load" file="$(find earth_rover_localization)/cfg/ekf_global_rover_localization.yaml" />
    <remap from="/odometry/filtered" to="/odometry/filtered/global"/>
</node>
<node pkg="robot_localization" type="navsat_transform_node" name="navsat_transform" respawn="true" output="screen">
    <param name="frequency" value="30"/>
    <param name="delay" value="3.0"/>
    <param name="magnetic_declination_radians" value="0.0"/>
    <param name="yaw_offset" value="0"/>
    <param name="zero_altitude" value="false"/>
    <param name="broadcast_utm_transform" value="true"/>
    <param name="publish_filtered_gps" value="true"/>
    <param name="use_odometry_yaw" value="false"/>
    <param name="wait_for_datum" value="true"/>
    <rosparam command="load" file="$(find earth_rover_localization)/cfg/datum.yaml" />
    <remap from="/odometry/filtered" to="/odometry/filtered/global"/>
    <remap from="/gps/fix" to="/piksi_receiver/navsatfix_best_fix"/>
    </node>
 </launch>

cfg file:

The /heading topic comes from having a dual antenna RTK GPS.

frequency: 60
sensor_timeout: 0.1
two_d_mode: true
transform_time_offset: 0.0
transform_timeout: 0.0
print_diagnostics: true
map_frame: map              
odom_frame: odom            
base_link_frame: scouting_base_link  
world_frame: odom
predict_to_current_time: true
odom0: /odometry/gps
odom0_config: [true,  true,  true,
               false, false, false,
               false, false, false,
               false, false, false,
               false, false, false]
odom0_queue_size: 0
odom0_nodelay: false
odom0_differential: false
odom0_relative: false
imu0: /imu
imu0_config: [false, false, false,
              true,  true,  false,
              false, false, false,
              true,  true,  true,
              true, false, false]
imu0_nodelay: false
imu0_differential: false
imu0_relative: false
imu0_queue_size: 5
imu0_remove_gravitational_acceleration: true

imu1: /heading
              false, false, true,
              false, false, false,
              false, false, false,
              false, false, false]
imu1_nodelay: false
imu1_differential: false
imu1_relative: false
imu1_queue_size: 0
imu1_remove_gravitational_acceleration: true
use_control: false
process_noise_covariance: [0.05, 0.05, 0.06, 0.03, 0.03, 0.06, 0.025, 0.025, 0.04, 0.01, 0.01, 0.02, 0.01, 0.01, 0.015] #diagonal
initial_estimate_covariance: [1e-6, 1e-6 ...
(more)
edit retag flag offensive close merge delete

Comments

Also, I'm forgetting: does a queue size of 0 mean infinite for ROS subs? I'd just set those to a reasonable value (as many messages as you'd expect from that sensor in the time delta between updates).

Tom Moore gravatar image Tom Moore  ( 2021-04-27 05:15:45 -0500 )edit

Okay, I will do that. The EKF frequency is 60Hz and the highest sensor frequency is 50Hz so I think with a value of 2, it should be more than enough.

xaru8145 gravatar image xaru8145  ( 2021-04-27 08:59:28 -0500 )edit

1 Answer

Sort by » oldest newest most voted
1

answered 2021-04-27 05:10:42 -0500

Tom Moore gravatar image

You can't guarantee that the filter is receiving the exact same messages in every run. I'm guessing you are seeing something like this:

Run 1

  • Node begins initializing
  • Bag starts playing
  • Node finishes subscribing to topics after 0.10 seconds
  • First messages received in callbacks

Run 2

  • Node begins initializing
  • Bag starts playing
  • Node finishes subscribing to topics after 0.15 seconds
  • First messages received in callbacks. These messages are not the same as in Run 1.

The timing of the messages coming in, combined with when the node actually completes initialization, will mean that you will definitely see some variation from run to run. Moreover, an EKF's prediction step involves linearizing its transfer function around the current state. That linearization process introduces small errors (it's the price you pay for nonlinear state estimation in this case), so if you aren't linearizing around the _exact_ same state between two runs, you'll see some small differences there as well.

Anyway, the short version is that there's going to be variability in each run, just owing to small differences in timing between each run. If you could guarantee that the exact same callbacks would fire in the exact same order with the exact same messages between every run, you might be able to get the exact same output between runs. But I don't think you should expect to achieve that with this setup.

edit flag offensive delete link more

Comments

Thanks a lot for your quick response Tom, I really appreciate it. Would there be any way to reduce this variability? I understand it is really hard to eliminate due to the nature of a linearized filter but maybe there is a way to wait a fix amount of time to subscribe to the topics and then process the first messages or tune certain parameters.

xaru8145 gravatar image xaru8145  ( 2021-04-27 09:03:25 -0500 )edit

You can move to ROS 2, which has lifecycle management. Then you can ensure everything is running in the order you want it. This is a ROS issue, rather than an r_l issue. Messages get published by sensors or rosbag, and all of that plumbing getting the messages from their source to r_l isn't going to be deterministic.

In this setup, if you are playing back from a bag, you can try using some of rosbag's features to help bring down the variability. Are you launching the bag replay, or doing it manually? Look at rosbag play --help and you will see some helpful options, like --delay, --pause, and --wait-for-subscribers.

Tom Moore gravatar image Tom Moore  ( 2021-06-22 04:02:21 -0500 )edit

Question Tools

3 followers

Stats

Asked: 2021-04-27 02:40:00 -0500

Seen: 323 times

Last updated: Apr 27 '21