Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rover_global_localization

ROS 2 package for global GPS-based localization of a rover using robot_localization.

This package adds the global localization layer required to publish the transform:

map -> odom

It is designed to work together with an existing local EKF that already publishes:

odom -> base_link

Purpose

The local EKF usually fuses wheel or track odometry with IMU data to produce a smooth local odometry estimate. This local estimate is continuous, but it can drift over time.

This package uses GPS data with navsat_transform_node and a second EKF to correct that drift in a global map frame.

Final TF tree:

map -> odom -> base_link

Architecture

Existing local localization:

/odom + /imu/raw
        |
        v
Local EKF
        |
        v
/odometry/filtered
TF: odom -> base_link

Global localization added by this package:

/gps/fix + /imu/raw + /odometry/filtered
        |
        v
navsat_transform_node
        |
        v
/odometry/gps
        |
        v
Global EKF
        |
        v
/odometry/global
TF: map -> odom

Input Topics

This package expects the following topics:

/odometry/filtered   nav_msgs/msg/Odometry
/imu/raw             sensor_msgs/msg/Imu
/gps/fix             sensor_msgs/msg/NavSatFix

/odometry/filtered should come from the local EKF.

/imu/raw should contain IMU data. Ideally, the IMU message should include a valid orientation.

/gps/fix should contain GPS data as sensor_msgs/msg/NavSatFix.

Output Topics

This package publishes:

/odometry/gps        nav_msgs/msg/Odometry
/odometry/global     nav_msgs/msg/Odometry

It also publishes the TF:

map -> odom

Required Existing TF

Before launching this package, the robot should already have:

odom -> base_link

Usually this is published by the local EKF.

The robot should also have static transforms for its sensors, for example:

base_link -> imu_link
base_link -> gps_link

Dependencies

This package depends on:

robot_localization
nav_msgs
sensor_msgs
tf2_ros
rclpy

Install robot_localization:

sudo apt update
sudo apt install ros-jazzy-robot-localization

If you are not using ROS 2 Jazzy, replace jazzy with your ROS 2 distribution name.

Package Structure

rover_global_localization
├── config
│   ├── ekf_global.yaml
│   └── navsat.yaml
├── launch
│   └── global_localization.launch.py
├── rover_global_localization
│   └── __init__.py
├── resource
│   └── rover_global_localization
├── package.xml
├── setup.cfg
├── setup.py
└── README.md

Configuration

navsat.yaml

navsat_transform_node converts GPS latitude/longitude into a local odometry message.

Important parameters:

use_odometry_yaw: false
zero_altitude: true
wait_for_datum: false
publish_filtered_gps: true

If the IMU does not provide a valid orientation, use_odometry_yaw may need to be set to true.

ekf_global.yaml

The global EKF fuses:

/odometry/filtered
/odometry/gps
/imu/raw

The important frame configuration is:

map_frame: map
odom_frame: odom
base_link_frame: base_link
world_frame: map
publish_tf: true

The key parameter is:

world_frame: map

This makes the global EKF publish:

map -> odom

Build

From the ROS 2 workspace:

cd ~/ros2_ws
colcon build --packages-select rover_global_localization
source install/setup.bash

Run

First, launch the local EKF and sensor drivers.

The following topics should already exist:

ros2 topic list | grep -E "imu|gps|odom"

Expected topics include:

/imu/raw
/gps/fix
/odom
/odometry/filtered

Then launch the global localization package:

ros2 launch rover_global_localization global_localization.launch.py

Verification

Check the GPS fix:

ros2 topic echo /gps/fix --once

Check the IMU:

ros2 topic echo /imu/raw --once

Check the local EKF output:

ros2 topic echo /odometry/filtered --once

Check the GPS odometry output from navsat_transform_node:

ros2 topic echo /odometry/gps --once

Check the global EKF output:

ros2 topic echo /odometry/global --once

Check the local transform:

ros2 run tf2_ros tf2_echo odom base_link

Check the global transform:

ros2 run tf2_ros tf2_echo map odom

Check the full transform chain:

ros2 run tf2_ros tf2_echo map base_link

RViz

Launch RViz:

rviz2

Set:

Fixed Frame = map

Recommended displays:

TF
Odometry: /odometry/filtered
Odometry: /odometry/global
NavSatFix: /gps/fix

Expected TF tree:

map
└── odom
    └── base_link
        ├── imu_link
        └── gps_link

Notes

Only one node should publish each TF.

Recommended setup:

Local EKF  -> odom -> base_link
Global EKF -> map -> odom

The odometry node should not publish odom -> base_link if the local EKF already does it.

The global EKF should not replace the local EKF. The local EKF provides smooth short-term motion, while the global EKF corrects drift using GPS.

Troubleshooting

/odometry/gps is not publishing

Check that all required inputs exist:

ros2 topic echo /gps/fix --once
ros2 topic echo /imu/raw --once
ros2 topic echo /odometry/filtered --once

Also check that the IMU orientation is valid.

If the IMU orientation is invalid, try setting:

use_odometry_yaw: true

in navsat.yaml.

No map -> odom transform

Check that the global EKF is running:

ros2 node list

Check the global odometry output:

ros2 topic echo /odometry/global --once

Check the TF:

ros2 run tf2_ros tf2_echo map odom

Make sure the global EKF has:

world_frame: map
publish_tf: true

Wrong IMU topic name

If your IMU topic is /imu/data instead of /imu/raw, replace /imu/raw with /imu/data in:

config/ekf_global.yaml
launch/global_localization.launch.py

License

MIT

About

ROS 2 package for GPS-based global localization of a rover using robot_localization. It combines local odometry, IMU data, and GPS fixes to generate global odometry and publish the map -> odom transform, completing the TF chain map -> odom -> base_link.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages