Closed ojura closed 7 years ago
We are also investigating the same problem at the moment. The orientation becomes very strange when use_odometry=true
.
BTW, bisecting is really made difficult by the fact that there are two separate repos. I know it's a long shot, but would you be willing to consider moving everything to one repo? In the very probable case that you won't, in order to facilitate bisecting, I was thinking of making a script that would prepare a "zipped" linear repo with commits from both cartographer
and cartographer_ros
ordered by time of commiting.
Edit: I did exactly that, a mirror repo is located at larics/cartographer_combined. Here is the post on Google Groups.
@jihoonl have you reached any conclusions? I still haven't looked into it in detail, but I have one clue which might be useful. In the InsertionResult
returned from AddAccumulatedRangeData
, I have replaced the gravity_alignment.rotation()
with an identity quaternion (Eigen::Quaterniond::Identity()
).
The reasoning for trying this out was that I am doing flat 2D vehicle slam, so I don't really need the estimation of gravity. And, in my case, changing this single line of code immediately stopped this from happening.
The conclusion is that the passed gravity alignment wrecks chaos in the sparse pose graph for some reason. That's all I know at this moment.
Here is a log of the gravity alignment quaternion. It should be close to the identity quaternion the whole time. It is oscillating in yaw: https://gist.github.com/ojura/6fc7dd0f2fad8ae46b5c9fab03e89c74
Gravity only constrains 2 degrees of freedom, not yaw. The quaternions all seem to be rotations around the z axis. This part seems okay to me.
Obviously the question is whether the yaw component of this quaternion is handled correctly, i.e. odometry is taken into account once in the correct direction.
Why would the gravity alignment quaternion have a yaw component at all? I am a bit confused about its role.
Gravity orientation is updated by integrating angular velocities and there is nothing that would remove the yaw component and also no reason to.
@ojura I'm not sure if i got you right, but in commit https://github.com/googlecartographer/cartographer/commit/3948943b6491ad07dd4c6ba8e71cb4d03b27a5bf, the one of #499 gravity_alignment.rotation()
isn't part of the insertion result...? Or do you mean you replaced gravity_alignment
with sth. like transform::Rigid3d(gravity_alignment.translation(), Eigen::Quaterniond::Identity())
this did not improve the result in our case.
Other than the only thing we found out so far was that if use_odometry=false
the problem does not occur.
@Mofef, @wohe changed this a bit in #500, where he passes gravity_alignment.rotation()
instead of gravity_alignment
. I have been experimenting with the current head.
Gravity orientation is updated by integrating angular velocities and there is nothing that would remove the yaw component and also no reason to.
@wohe this is where you have me confused about what the role of gravity_alignment
is. Previously, we had tracking_to_tracking_2d
, which was accompanied with the following comment:
// Computes the rotation without yaw, as defined by GetYaw().
In #500, you wrote: In 2D this [gravity_alignment] replaces the 'tracking_to_tracking_2d' transform.
So that's why I thought that this quaternion should not contain any yaw. And the fact that setting gravity_alignment
to an identity quaternion (effectively removing that yaw) unbroke my SLAM reinforced that interpretation. Can you please clarify?
The breakage can be prevented when you set odometry_available in optimization_problem.cc to false. So, I assume that we have to double check the logic of TransformInterpolationBuffer::Lookup or logic that computes relative_pose when odometry_available=true
.
Too sad that I will be in the train and cannot attend the open house meeting.
There were a couple of changes:
tracking_to_tracking_2d
was only a rotation, even though stored as a rigid transform. We now store gravity_alignment
(which has replaced it) as a quaternion since we know there is no translational part.GetYaw()
part was possible because we earlier had the assumption that the tracking frame is approximately gravity aligned. Now we don't make this assumption anymore, so removing the yaw is not easily possible and the code that was there would not work if the tracking frame is oriented orthogonal to the gravity aligned frame. In the absence of bugs (entirely possible of course) this should not matter, the gravity aligned frame just has an arbitrary rotation around the z axis now.pose
stored in each trajectory node is now the complete pose, even in 2D.I see, thanks on the explanation. Well, the good news is that I have published pose_estimate
directly from the local trajectory builder and it looks okay (it follows the right trajectory). It's just that something later in the SPG makes the optimized poses (and the optimized submap origins) go crazy.
So @jihoonl I disagree that the problem is in the local trajectory builder, or the pose extrapolator / interpolation buffer. Something is broken in SPG optimization, and passing just an identity gravity alignment quaternion to the SPG in the insertion result prevents this from happening (@Mofef oddly this "fix" doesn't work in #499, but it works in #500). @wohe do you have an idea where the problem could lie? My head gets a little dizzy when I try to follow what you're doing with the pose and the gravity alignment in the sparse pose graph and constraint builder :-)
@ojura I reproduced, that the "fix" improves the result after #500, but for us the result is still way worse than before #499
@ojura Thanks for pointing out that the issue could be in the pose graph optimization, I have an idea what is wrong: we have 2D poses in this optimization problem which are from the gravity_alignment
frame to the map frame. Odometry poses are in tracking frame and optimization_problem.cc
is not correctly transforming them into the gravity_alignment
frame.
Thanks on the suggestion, @wohe. Based on it, I followed how the local trajectory builder applies the gravity alignment to rangefinder data and did a similar thing with odometry data passed to SPG. From your description, I thought that I would need to multiply the odometry pose with gravity_alignment
in order to achieve what we need, but it turned out to be that it needed to be multiplied with its inverse! Go figure. At least on my data, this restores pre-#499 behaviour, so @Mofef @jihoonl you might want to try it out (check out PR #532).
Fixing this should actually improve quality over the behavior before #499. The bug already existed before and only was exposed by #499. Earlier, the missing transformations just happened to be approximately identity if the tracking frame was kept approximately gravity aligned.
Thanks everyone for helping to get this resolved!
For us its solved. Thank you :)
This is using the same dataset as in #453, which was another regression that caused a drastic decrease in quality on that dataset.
I did a git bisect:
Here's with e3b6f0a:
...and with 3948943:
Here is the updated
pioneer-cartographer.lua
(please use this one instead of the one in #453). Also, please usecartographer_ros
with rangefinder decimation (if it doesn't get merged by the time you are reading this): googlecartographer/cartographer_ros@e8962a7.