Fusing two odoms (VO) using robot_localization
Hi,
I am fairly new to using robot_localization
. I am trying to fuse odometry from two visual odometry sources (i.e. stereo cameras) in my robot’s reference frame. The setup is drawn here
I have drawn the tf tree here
I am not sure as to how I should proceed to fuse the two odometry sources as there is no tf base_link-->odom1
and base_link-->odom2
I can work out the static tf between base_link-->base1
and base_link-->base2
, but then baselink becomes the parent to base1 and base2 and I lose the `baselink-->odom1and
base_link-->odom2` tf
I have searched for an answer among similar posts, but haven’t been able to get a solution. I am pretty sure I am missing something very basic, but I can't point it out. Kindly advise.
Asked by Equaltrace on 2020-09-11 15:14:14 UTC
Answers
Following on from the comments:
When it comes to taking in sensor data, the filter is primarily concerned with two coordinate frames: the value of the world_frame
parameter (typically odom or map) and the value of the base_link_frame
parameter (typically base_link or base_footprint).
When you provide a nav_msgs/Odometry
message as a sensor input, there are two coordinate frames represented in that. The frame_id
in the message refers to the pose data, and the child_frame_id
refers to the twist (velocity) data.
All velocity data will get transformed from the child_frame_id
of the odometry message to the base_link_frame
of your EKF, so you need to provide that transform, or make sure both frames are the same.
All pose data will get transformed from the frame_id
of the odomety message to the world_frame
of your EKF, so you need to provide that transform, or make sure both frames are the same.
The EKF itself will generate a transform from world_frame
->base_link_frame
.
In your case, I'd recommend fusing just velocity data from one source. Get it working the way you want, and then add a new source.
Asked by Tom Moore on 2020-10-07 04:28:33 UTC
Comments
Your tree should look like map->odom_filtered->base_link->... not base_link->odomX. Take the odometry message of source1 (I asume its camera centered, so frame_ID would be "camera1_base") fuse it in robot_localization ekf (link text with odom2 and output the fused data (ekf output) in odom_filtered frame.
Asked by Dragonslayer on 2020-09-11 16:55:10 UTC
@Dragonslayer Hi. I fell asleep before I could tag you and you beat me to it. So welcome to the post. I am starting from the basics. My config file for robot_localization is below. But I am still confused what needs to go in for
odom_frame, base_link_frame, map_frame, world_frame
?For the sake of simplicity, the frame names for camera1 are
cam1_odom->cam1_base->cam1_optical...
and the frame names for camera2 arecam2_odom->cam2_base->cam2_optical...
and the PC is thebase_link
Asked by Equaltrace on 2020-09-11 19:24:26 UTC
Asked by Dragonslayer on 2020-09-12 09:02:52 UTC
@Dragonslayer: I get the following warning messages repeatedly when I run the localization node with the frames set to
Warnings:
In a way I would expect these errors because there are no tf which would establish a relation between cam1 tree, cam2 tree, and base_link. :/
Asked by Equaltrace on 2020-09-12 15:05:47 UTC
You dont need the cam1 and cam2 tree. just a urdf for the robot model, base_link up to the frame the cams odometries are in reference to (camera_linkX or cam1_base or whatever its called).
Asked by Dragonslayer on 2020-09-12 16:46:11 UTC
@Dragonslayer So, I turned off the tf between the
camX_odom --> camX_base
. I then modified the robot urdf to publishbase_link --> camX_base
urdfs. Now my tf tree looks like this.And now when I try to run robot_localization, I get the following warn message repeatedly:
This I would expect too, since there is no tf to relate cam1_odom to any other frames. Do I need to manually publish the inverse tf from camX_base --> camX_odom?
Asked by Equaltrace on 2020-09-12 22:43:57 UTC
Are you sure its ekf node that sends the warn? What does your /camera1/odom message look like (frame_ID)? Likely somewhere in your setup some node is looking for cam1_odom but your odom frame now is odom or odom_filtered whatever you put in the ekf parameter odom_frame. You dont get a cam2_odom warning?
Asked by Dragonslayer on 2020-09-13 09:19:40 UTC
@Dragonslayer The warning messages only start when I start the ekf node and in the same window where ekf is running. The
odom_frame
in ekf config is set toodom
. Here is the config-file for ekf node. If I change the order of odom in config i.e. putodom0: /camera2/odom
andodom1: /camera1/odom
, the warning message change to cam2_odom warnings instead of cam1_odom warnings:This is what the /camera1/odom message looks like:
Asked by Equaltrace on 2020-09-13 10:01:54 UTC
Get /odom to be the frame_id in the odom messages, I would suggest. Or for a quick try set odom_frame in ekf to cam1_odom and see what happens.
Asked by Dragonslayer on 2020-09-13 10:12:03 UTC
@Dragonslayer I tried the latter suggestion. I changed the
odom_frame: cam1_odom
and the warnings went away. The data /odometry/filtered has the frame_id: cam1_odom, child_frame_id: base_linkBut this means that the ekf output is in cam1_odom. The cam1_odom originates at the cam1_base start location. This would be different from the odom frame which should originate from the base_link start location?
Asked by Equaltrace on 2020-09-13 10:44:11 UTC
Yes, to make it really work you have to get odom to be frame_ID in the cam1 odom message. My first suggestion so to speak.
Iam not sure how your odometry node works. You should visualize the transforms in rviz to see if this is really the case, after all ekf should place its odom frame (which in the test is cam1_odom) in a the base_link relation.
Asked by Dragonslayer on 2020-09-13 13:12:37 UTC
@Dragonslayer The cam node does allow me to change the name of the odometry frame via. param file. But I don't think just changing the name from "cam1_odom" to "odom" would be the right way to go about. I would need to somehow add a
odom->cam1_odom
tf to indicate the relation between the two odometry frames. I have been trying to figure out if that is a possibility but it doesn't seems so.The other way I can think of is to keep using the
cam1_odom
frame as the fusion frame. And then use a custom node to transform the fused odometry data fromcam1_odom
frame toodom
frame and publish both the tf and the odometry msg. Bothcam1_odom
andodom
are stationary, so doing the above should make sense. What do you think ?Asked by Equaltrace on 2020-09-13 13:51:24 UTC
What in the code makes you think this again and again, I absolutely dont understand? You never prove your point. Why dont you just try?
Asked by Dragonslayer on 2020-09-13 14:25:31 UTC
@Dragonslayer Sorry at times I get confused myself. My understanding is that, I should not directly change the odometry frame name in the camera param file from "cam1_odom" to "odom" because cam1_odom represents the odometry frame that has its origin located at the starting location of the cam1 (i.e. cam1_base) in 3D space. Whereas "odom" is supposed to be the odometry frame with its origin located at the starting physical location of the robot/pc (i.e. the base_link). Now, if I were to change the name of the camera odometry frame in the param file directly from "cam1_odom" to "odom", it would mean that the camera is outputting odometry messages in the "odom" frame and that the odom frame's origin is located at the physical starting point of camera1. This contradict the notion that odom needs to have its origin located at the physical start point of the robot/pc (i.e. the base_link).
Moreover if I do the same for camera2, it becomes even more contradictory. Is my understanding valid?
Asked by Equaltrace on 2020-09-13 17:07:03 UTC
@Dragonslayer Also, sorry for the delay in trying out things. I am working on it remotely and don't have access to the setup over the weekend. Therefore, before I tend to make modifications, I try to reason it out in my head. Really sorry about it all and I really appreciate your patience with me.
Asked by Equaltrace on 2020-09-13 17:20:54 UTC
Have you tried it?
Asked by Dragonslayer on 2020-09-15 14:02:46 UTC
@Dragonslayer Not yet. Apparently my fellow student lab mates think that I was hogging the system over the weekend so I had to relinquish it for a bit. But I have it reserved for tonight. Will update as soon as I have tried it out!
Asked by Equaltrace on 2020-09-15 15:03:58 UTC
@Dragonslayer I was able to run it. Both camera1 and camera2
frame_id
are set to "odom" to match theodom_frame = world_frame = "odom"
in robot_localizationAnd it works without any warnings or errors. Thank you for the help getting here! I have been able to test it out while the setup was stationary. I will be doing further tests by moving the setup around to check the estimate.However, can you help me understand why this worked? It seems my understanding of the basics is wrong for odometry frames. I thought that since camera1 and camer2 generate their own VO independently, they have their own odom frames, centered at the camera start position. Whereas the odom frame has base_link at its origin. Something like this. So when we set both camera1 and camera2 odometry frame_id to "odom", doesn't it imply that they are publishing in the same "odom" frame, whereas their original frames were separate?
Asked by Equaltrace on 2020-09-16 09:38:35 UTC
Glad to hear. The issue is that tf takes care of the relation of the frames to each other (frames are simply said joint-link "pairs"). Odometry just says "I moved forward 1 meter", seen from frame_ID/child_frame_ID. What this means for the robot in map space is "figured out" by tf, via its knowledge of the relation of the frames to each other (tf free, kinematics). It takes in data and frame_ID (where the data is in reference to) and outputs pose. Pose is taking all other related frames into account. The problem with your cam-odometry is that its already a running system including tf-publishing and odome_frame and all, but then you tried to put it as is into another system. There might actually be a way to get this to work...it would only be work for nothing.
Asked by Dragonslayer on 2020-09-16 14:37:09 UTC
@Dragonslayer sorry for the delay in getting back to you. I had a couple of exams to get through which kept my mind tied up. Just want to thank you for your help and explanation: Thank you! I will be giving the system a try while moving it around. I have one more exam to get through and then I should be able to play with the system again. Stationary it was working fine. Will let you know if I run into something that confuses me regarding this issue! Thanks once again!
Asked by Equaltrace on 2020-09-19 23:10:34 UTC