rtabmap_ros: "GTSAM exception caught: Indeterminant linear system detected while working near variable" then crash

Hi everyone, I’m working in a project with ROS1 in which we use Rtabmap for localization in a previously mapped environment. I’m using the localization_pose to feed my localization stack. Recently I have experienced problems with GTSAM which warns for “inderteminant linear systems”. Eventually, it also crashes with the following FATAL ERROR.

FATAL] (2023-10-27 09:25:31.539) Transform.cpp:184::inverse() Condition (invertible) not met! [This transform is not invertible! xyz=inf,inf,0.000000 rpy=0.000000,0.000000,-1.267575 
[0.298596 0.954380 0.000000 inf;
 -0.954380 0.298596 -0.000000 inf;
 -0.000000 0.000000 1.000000 0.000000;
 0 0 0 1]]
terminate called after throwing an instance of 'UException'
  what():  [FATAL] (2023-10-27 09:25:31.539) Transform.cpp:184::inverse() Condition (invertible) not met! [This transform is not invertible! xyz=inf,inf,0.000000 rpy=0.000000,0.000000,-1.267575 
[0.298596 0.954380 0.000000 inf;
 -0.954380 0.298596 -0.000000 inf;
 -0.000000 0.000000 1.000000 0.000000;
 0 0 0 1]]

By setting the “–udebug --logconsole” arguments I was able to see some information about the problem. However something very strange took my attemption, which are the following debug messages:

[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2946::process() Constraint -8->-8 (type=PosePrior)
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2948::process() Constraint 1058->-8 (type=Landmark, var = 0.001000 0.010000)
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2946::process() Constraint 875->875 (type=PosePrior)
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2948::process() Constraint 1058->875 (type=LocalSpaceClosure, var = 0.000003 0.002736)
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2946::process() Constraint 876->876 (type=PosePrior)
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2948::process() Constraint 1058->876 (type=GlobalClosure, var = 0.000002 0.001697)
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2946::process() Constraint 1033->1033 (type=PosePrior)
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2948::process() Constraint 1058->1033 (type=LocalSpaceClosure, var = 0.000027 0.007702)
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2952::process() Pose -8 xyz=0.851523,-0.041897,0.404141 rpy=0.085773,0.006991,1.561444
[DEBUG] (2023-10-27 09:25:31.535) Rtabmap.cpp:2952::process() Pose 875 xyz=0.319759,-0.040769,0.000000 rpy=0.000000,-0.000000,0.013201
[DEBUG] (2023-10-27 09:25:31.536) Rtabmap.cpp:2952::process() Pose 876 xyz=0.297985,-0.013632,0.000000 rpy=0.000000,0.000000,-0.039805
[DEBUG] (2023-10-27 09:25:31.536) Rtabmap.cpp:2952::process() Pose 1033 xyz=0.240514,-0.004088,0.000000 rpy=0.000000,-0.000000,0.023084
[DEBUG] (2023-10-27 09:25:31.536) Rtabmap.cpp:2952::process() Pose 1058 xyz=-197.406799,29.594700,0.000000 rpy=0.000000,0.000000,-3.107898

The above logs, show the constraints used in the optmization. However the last line took my attemption. In the referred line we can see that the pose of the node 1058 is very distant (in terms of xyz) from the other nodes of the graph. Then, I was looking in the code and found these debug messages in the Rtabmap library. I noticed that the odom pose is not being transformed to the same frame of the graph nodes before optimization, as shown in the following lines:

https://github.com/introlab/rtabmap_ros/blob/3293f2b51a42cdcd4f531576e3d787f149ac2e1b/rtabmap_slam/src/CoreWrapper.cpp#L2026C6-L2030

Based in my knowledge of optimization, I thought it would be better for the optimization problem (in terms of speed and accuracy) if the initial guess was near to the minimum. I understand that the mapCorrection output is being used to generate the mapToOdom information. However, in my point of view, it would be better for the optimization problem, if the odom pose was transformed to the map frame with the last map->odom transform before passing it to the optimizer. Then the mapCorrection output could be used to correct the last map->odom TF from /tf.

I would appreciate any comments and clarifications on this. Thank you!

About this issue

  • Original URL
  • State: closed
  • Created 8 months ago
  • Comments: 16 (9 by maintainers)

Commits related to this issue

Most upvoted comments

I updated the code with a change for landmark constraints in localization mode that could help with your issue (see https://github.com/introlab/rtabmap/pull/1156). You may give a try. If the issue is still there, you may increase this new parameter called RGBD/LocalizationPriorError to 0.01 or 0.1.

Hi, I have some updates again.

I made the tests with the commit above and finally the issue was solved. The system is working perfectly and everything is great.

Thanks for the help and explanations about this awesome package/library.

The odometry topic covariance looks fine, but if you are using odom_frame_id, those parameters are used:

~odom_tf_linear_variance (double, default: 0.001) When odom_frame_id is used, the first 3 values of the diagonal of the 6x6 covariance matrix are set to this value.

~odom_tf_angular_variance (double, default: 0.001) When odom_frame_id is used, the last 3 values of the diagonal of the 6x6 covariance matrix are set to this value.

which should not cause that issue with those default values.

In the commit above, I updated the code to remove the last argument of getConnectedGraph() so this would fix the current issue. I won’t “fix” the problem of switching Reg/Force3DoF from true to false or vice-versa when the map contains landmarks, as the changes would be quite deep to do and I think the current code is more efficient in its current state.

I removed the last argument of that function and simplified the code. I think I reproduced the issue of switching from a map created with Reg/Force3DoF=true, then try to localize with Reg/Force3DoF=false, this make the robot flips upside down. It is because the tags were transformed for 3DoF optimization, which is not the real pose for 6DoF. Here are two examples of the same tag when mapping with Reg/Force3DoF=true and Reg/Force3DoF=false respectively (the real orientation is the second one, with z axis perpendicular to the tag): Screenshot from 2023-11-15 22-35-49 Screenshot from 2023-11-15 22-37-04

To make 2D optimization working, as it optimizes only x,y, and yaw, the orientation of the tag should have z-axis up. The bug is that after optimization, we don’t flip back the correct orientation of the tag, so if we switch to 6DoF in localization, the robot will think the tag is flipped 90 deg. I need to dig more into this in the next days.

I will try to reproduce the issue that this commit was fixing, I don’t remember on top of my head what was the issue addressed there. In your case, if I understand, if you change this line by:

_graphOptimizer->getConnectedGraph(signature->id(), poses, constraints, posesOut, edgeConstraintsOut);

Would it fix your issue?

Just confirming that even if odometry pose is large, GTSAM should be able to converge correctly. Here I reset odometry to x=10000 and y=8000:

[ INFO] (2023-11-01 14:31:20.381) Rtabmap.cpp:2979::process() timeAddLoopClosureLink=0.000003s
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3055::process() RGB-D SLAM mode: 1
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3056::process() Incremental: 0
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3057::process() Loop hyp: 9
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3058::process() Last prox: 9
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3059::process() Reduced ids: 0
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3060::process() Has prior: 0 (prior ignored=1)
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3061::process() Has gravity: 1 (sigma=0.300000, odomGravity=0, refined=0)
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3062::process() Has virtual link: 0
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3063::process() Prox Time: 0
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3064::process() Landmarks: 0
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3065::process() Retrieved: 0
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3066::process() Not self ref links: 1
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3150::process() Constraint 184->184 (type=Gravity, var = 1.000000 1.000000)
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3148::process() Constraint 9->9 (type=PosePrior)
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3150::process() Constraint 184->9 (type=GlobalClosure, var = 0.000223 0.003220)
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3154::process() Pose 9 xyz=-0.291190,-0.002876,-0.033898 rpy=0.183713,0.389845,-2.646930
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3154::process() Pose 184 xyz=10000.000000,8000.000000,0.000000 rpy=0.177814,0.359494,-2.979261
[DEBUG] (2023-11-01 14:31:20.381) Rtabmap.cpp:3161::process() priorsIgnored was true
[DEBUG] (2023-11-01 14:31:20.381) Optimizer.cpp:196::getConnectedGraph() IN: fromId=184 poses=2 links=3 priorsIgnored=0 landmarksIgnored=0
[DEBUG] (2023-11-01 14:31:20.381) Optimizer.cpp:301::getConnectedGraph() OUT: poses=2 links=3
[DEBUG] (2023-11-01 14:31:20.381) OptimizerGTSAM.cpp:101::optimize() Optimizing graph...
[DEBUG] (2023-11-01 14:31:20.381) OptimizerGTSAM.cpp:163::optimize() fill poses to gtsam... rootId=0 (priorsIgnored=0 landmarksIgnored=0)
[DEBUG] (2023-11-01 14:31:20.381) OptimizerGTSAM.cpp:223::optimize() fill edges to gtsam...
[DEBUG] (2023-11-01 14:31:20.381) OptimizerGTSAM.cpp:495::optimize() create optimizer
[DEBUG] (2023-11-01 14:31:20.381) OptimizerGTSAM.cpp:520::optimize() GTSAM optimizing begin (max iterations=20, robust=0)
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:604::optimize() iteration 1 error =3529.759225
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:604::optimize() iteration 2 error =0.318584
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:604::optimize() iteration 3 error =0.271166
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:604::optimize() iteration 4 error =0.271165
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:614::optimize() Stop optimizing, not enough improvement (0.000001 < 0.000010)
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:633::optimize() GTSAM optimizing end (4 iterations done, error=0.271165 (initial=84492982519949.375000 final=0.271165), time=0.000274 s)
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:697::optimize() Computing marginals...
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:701::optimize() Computed marginals = 0.000040s (key=184)
[DEBUG] (2023-11-01 14:31:20.382) OptimizerGTSAM.cpp:750::optimize() Optimizing graph...end!
[DEBUG] (2023-11-01 14:31:20.382) Rtabmap.cpp:3170::process() Opt  9 xyz=-0.291190,-0.002876,-0.033898 rpy=0.183711,0.389845,-2.646930
[DEBUG] (2023-11-01 14:31:20.382) Rtabmap.cpp:3170::process() Opt  184 xyz=-0.217603,0.092621,-0.115117 rpy=0.218768,0.354219,-2.363997
[ INFO] (2023-11-01 14:31:20.382) Rtabmap.cpp:3180::process() Compute max graph errors...

Maybe the tag detection is too wrong to correctly converge.