Using robot_localization, how can I calculate the GPS coordinates of any point on my robot?
The Problem (TL;DR)
I want to calculate the GPS coordinates of a random hardpoint on my robot, both directly from the GPS and via sensor fusion (EKFs).
The Problem (in full)
This is a conceptual question about the "best practice" for calculating the GPS coordinates of any random hardpoint on my robot using the robot_localization package. I already have something that works, I just want to see if there is a better/more accurate way.
I'm using a Clearpath Robotics "Jackal" with a GPS mounted on top. So far I've been using the excellent robot_localization package to localize the robot using two EKFs. This diagram below shows a simplified version of my frame tree. The first "local" EKF generates the /odom
-> /base_link
link. The second "global" EKF generates the /map
-> /odom
link. An instance of navsat_transform generates the /map
-> /utm
link (note that the /utm frame is located at the 0,0 point of the real UTM grid). The remaining links are set up in the robot URDF. The blue frames are fixed and do not move. The orange frames are fixed relative to the other orange frames but move with the robot and move relative to /map, /odom etc. I want to calculate the GPS coordinates of /hardpoint
anywhere on my robot, could be the nose or a mounting point for a manipulator, the exact location isn't critical. The coordinates themselves could be in WGS84 or UTM although UTM is preferred because it's easier for frame transforms.
I would like to calculate the coordinates in both of the following ways:
- Directly from the GPS, i.e.
/auxgps
(so if the EKFs go nuts I still know where/hardpoint
is) - Via the EKFs (so if I lose GPS lock briefly I still have coordinates for
/hardpoint
)
I currently have several possible ways of doing this:
- [GPS Direct Option 1] Use the
/auxgps
->/hardpoint
. This is more complicated than it sounds because the result has to be relative to the UTM grid. I.e. the/auxgps
->/hardpoint
transform by itself is meaningless because it just gives the location of/hardpoint
relative to/auxgps
, which I already know because I set it in the URDF. I'm a little unsure how to practically achieve this in code (python TF2 documentation isn't great) - [GPS Direct Option 2] Calculate the difference between the translational components of the
/utm
->/auxgps
and/utm
->/hardpoint
frame transforms. This will give you a difference in Nth/Est/Elv relative to the UTM grid Subtracting this from the UTM coordinates of/auxgps
gives you the UTM coordinates of/hardpoint
. Because this uses the difference between frame transforms, any error in the absolute position of/utm
should come out in the wash. This method is dirty and more than a little hacky but it's easier to implement than option 1 above. - [Via EKF Option 1] Modify the source code of navsat_transform. Navsat_transform publishes a topic called
/gps/fix
, which is normally the position ...