Robot_localization configuration (GPS, IMU, Odometry)
Hello,
I try to use the robot_localization package for a project where we have the following sensors:
IMU
Odometry by wheel encoders
GPS
After I have read the robot_localization documentation and seen the ROSCON presentation of Tom Moore I have the following setup:
ekf localization node with input of navsattransformnode (odometry/gps), IMU and odom
navsat_transform node with input from ekf localization node (odometry/filtered) and IMU
My frame configuration is the following:
odom_frame: odom
baselinkframe: base_link
world_frame: odom
I have read in the "ekftemplate.yaml" of the robotlocalization package that I should set the worldframe to map when fusing a global absolute position and get the odom->baselink transform from somewhere else (another estimation node for example but I shouldn't fuse global data there).
In my configuration I am using the global position in both nodes (input for navsattransformnode and the output of the node into ekflocalizationnode)
Do I need to create a second ekflocalizationnode with just continous data input and use the data output of this node as input into the first ekflocalizationnode which just fuses two odometry sources (from navsattransformnode and second ekflocalizationnode) then?
Is the output of the first ekflocalizationnode or the navsattransformnode the most reliable then to use the pose for distance measuring or calculation of circle radius for example?
Thank you guys in advance!
EDIT:
We have the following configuration for ekf_localization_node
(at the moment):
frequency: 30
sensor_timeout: 0.1
two_d_mode: false
transform_time_offset: 0.0
transform_timeout: 0.0
print_diagnostics: true
debug: false
debug_out_file: robot_localization_debug.txt
publish_tf: true
publish_acceleration: false
odom_frame: odom # Defaults to "odom" if unspecified
base_link_frame: base_link # Defaults to "base_link" if unspecified
world_frame: odom # Defaults to the value of odom_frame if unspecified
odom0: /odom
odom0_config: [false, false, false,
false, false, false,
true, true, false,
false, false, true,
false, false, false]
odom0_queue_size: 2
odom0_nodelay: false
odom0_differential: false
odom0_relative: false
odom0_pose_rejection_threshold: 5
odom0_twist_rejection_threshold: 1
odom1: /odometry/gps
odom1_config: [true, true, true,
false, false, false,
false, false, false,
false, false, false,
false, false, false]
odom1_differential: false
odom1_relative: true
odom1_queue_size: 2
odom1_pose_rejection_threshold: 2
odom1_twist_rejection_threshold: 0.2
odom1_nodelay: false
imu0: /imu/data
imu0_config: [false, false, false,
false, false, true,
false, false, false,
false, false, true,
true, false, false]
imu0_nodelay: false
imu0_differential: false
imu0_relative: true
imu0_queue_size: 5
imu0_pose_rejection_threshold: 0.8
imu0_twist_rejection_threshold: 0.8
imu0_linear_acceleration_rejection_threshold: 0.8
imu0_remove_gravitational_acceleration: true
use_control: false
stamped_control: false
control_timeout: 0.2
control_config: [true, false, false, false, false, true]
acceleration_limits: [1.3, 0.0, 0.0, 0.0, 0.0, 3.4]
deceleration_limits: [1.3, 0.0, 0.0, 0.0, 0.0, 4.5]
acceleration_gains: [0.8, 0.0, 0.0, 0.0, 0.0, 0.9]
deceleration_gains: [1.0, 0.0, 0.0, 0.0, 0.0, 1.0]
process_noise_covariance: [0.05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0.05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0.06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0.03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0.03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0.06, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0.025, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0.025, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0.04, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.02, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.015]
initial_estimate_covariance: [1e-9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1e-9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1e-9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1e-9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1e-9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1e-9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1e-9, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1e-9, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1e-9, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1e-9, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1e-9, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1e-9, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1e-9, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1e-9, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1e-9]
We have the following configuration for navsat_transform_node
:
frequency: 30
delay: 3.0
magnetic_declination_radians: 0
yaw_offset: 1.5707963
zero_altitude: false
broadcast_utm_transform: false
broadcast_utm_transform_as_parent_frame: false
publish_filtered_gps: false
use_odometry_yaw: false
wait_for_datum: false
datum: [55.944904, -3.186693, 0.0]
Our launch file:
<launch>
<node pkg="robot_localization" type="ekf_localization_node" name="ekf_se" clear_params="true">
<rosparam command="load" file="$(find robot_localization_specfic)/params/ekf_template.yaml" />
</node>
<node pkg="robot_localization" type="navsat_transform_node" name="navsat_transform_node" clear_params="true">
<rosparam command="load" file="$(find robot_localization_specfic)/params/navsat_transform_template.yaml" />
</node>
</launch>
This our configuration at the moment:
Would you suggest a solution like this now (from what I have understood from your answer)?
Or is the configuration different?
I have found the dual_ekf_navsat_example
in robot_localization
, is that the one I should stick to?
If we would have a second odometry source do we have to fuse the odometry in ekf_localization_node 2
too with the first one?
We want to drive outdoors in terrain without many features (like a meadow) and use the most accurate odometry (from robot localization) for 3D mapping.
Thank you very much in advance!
Asked by ce_guy on 2018-06-18 07:26:58 UTC
Answers
Please post your configuration and launch files. It makes answering such questions easier.
I can say that this is a typical setup for GPS data:
EKF1: world frame is odom, fuse IMU and wheel encoders.
EKF2: world frame is map, fuse GPS, IMU, and wheel encoders
navsat_transform_node
should listen to the output of EKF2.
As to which output to use, it doesn't really make sense to use the output of navsat_transform_node
, unless you want to plot it in Google Earth or something. The output of EKF2 will be the most accurate pose, but is obviously subject to discontinuities from the GPS.
EDIT: your second solution is more in line with what I was thinking, yes. The example in the package isn't prescriptive; that is, I don't encourage you to stick to it necessarily, but it gives an idea of what's required to work with GPS data.
What is your second odometry source? The odom_gps
data? Or another one?
I'll give you the same advice I give everyone: get your filters working with just IMU and wheel encoders. When that's done, add the GPS data.
I'm not sure how well this will work in a mapping context, but I know nothing about your setup.
Asked by Tom Moore on 2018-06-19 05:40:39 UTC
Comments
Thank you very much for your answer! I have updated the question now with the configuration and launch files.
Asked by ce_guy on 2018-06-25 05:00:40 UTC
Comments