@@ -15,7 +15,6 @@ namespace cv
15
15
{
16
16
namespace kinfu
17
17
{
18
-
19
18
bool PoseGraph::isValid () const
20
19
{
21
20
int numNodes = int (nodes.size ());
@@ -34,7 +33,7 @@ bool PoseGraph::isValid() const
34
33
{
35
34
int currNodeId = nodesToVisit.back ();
36
35
nodesToVisit.pop_back ();
37
-
36
+ std::cout << " Visiting node: " << currNodeId << " \n " ;
38
37
// Since each node does not maintain its neighbor list
39
38
for (int i = 0 ; i < numEdges; i++)
40
39
{
@@ -49,20 +48,20 @@ bool PoseGraph::isValid() const
49
48
{
50
49
nextNodeId = potentialEdge.getSourceNodeId ();
51
50
}
52
-
51
+ std::cout << " Next node: " << nextNodeId << std::endl;
53
52
if (nextNodeId != -1 )
54
53
{
55
- if (nodesVisited.count (currNodeId) == 0 )
54
+ if (nodesVisited.count (currNodeId) == 0 )
56
55
{
57
56
nodesVisited.insert (currNodeId);
57
+ nodesToVisit.push_back (nextNodeId);
58
58
}
59
- nodesToVisit.push_back (nextNodeId);
60
59
}
61
60
}
62
61
}
63
62
64
63
isGraphConnected = (int (nodesVisited.size ()) == numNodes);
65
-
64
+ std::cout << " IsGraphConnected: " << isGraphConnected << std::endl;
66
65
bool invalidEdgeNode = false ;
67
66
for (int i = 0 ; i < numEdges; i++)
68
67
{
@@ -81,26 +80,37 @@ float PoseGraph::createLinearSystem(BlockSparseMat<float, 6, 6>& H, Mat& B)
81
80
{
82
81
int numEdges = int (edges.size ());
83
82
84
- float residual = 0 ;
83
+ float residual = 0 . 0f ;
85
84
86
- // ! Lmabda to calculate error jacobian for a particular constraint
85
+ // Lambda to calculate the error Jacobians w.r.t source and target poses
87
86
auto calcErrorJacobian = [](Matx66f& jacSource, Matx66f& jacTarget, const Affine3f& relativePoseMeas,
88
- const Affine3f& sourcePose, const Affine3f& targetPose) -> void {
87
+ const Affine3f& sourcePose, const Affine3f& targetPose) -> void
88
+ {
89
89
const Affine3f relativePoseMeas_inv = relativePoseMeas.inv ();
90
90
const Affine3f targetPose_inv = targetPose.inv ();
91
91
for (int i = 0 ; i < 6 ; i++)
92
92
{
93
93
Affine3f dError_dSource = relativePoseMeas_inv * targetPose_inv * cv::Affine3f (generatorJacobian[i]) * sourcePose;
94
- Vec3f rot = dError_dSource.rvec ();
95
- Vec3f trans = dError_dSource.translation ();
96
- jacSource.col (i) = Vec6f (rot (0 ), rot (1 ), rot (2 ), trans (0 ), trans (1 ), trans (2 ));
94
+ Vec3f rot = dError_dSource.rvec ();
95
+ Vec3f trans = dError_dSource.translation ();
96
+ jacSource.val [i + 6 *0 ] = rot (0 );
97
+ jacSource.val [i + 6 *1 ] = rot (1 );
98
+ jacSource.val [i + 6 *2 ] = rot (2 );
99
+ jacSource.val [i + 6 *3 ] = trans (0 );
100
+ jacSource.val [i + 6 *4 ] = trans (1 );
101
+ jacSource.val [i + 6 *5 ] = trans (2 );
97
102
}
98
103
for (int i = 0 ; i < 6 ; i++)
99
104
{
100
105
Affine3f dError_dSource = relativePoseMeas_inv * targetPose_inv * cv::Affine3f (-generatorJacobian[i]) * sourcePose;
101
- Vec3f rot = dError_dSource.rvec ();
102
- Vec3f trans = dError_dSource.translation ();
103
- jacTarget.col (i) = Vec6f (rot (0 ), rot (1 ), rot (2 ), trans (0 ), trans (1 ), trans (2 ));
106
+ Vec3f rot = dError_dSource.rvec ();
107
+ Vec3f trans = dError_dSource.translation ();
108
+ jacTarget.val [i + 6 *0 ] = rot (0 );
109
+ jacTarget.val [i + 6 *1 ] = rot (1 );
110
+ jacTarget.val [i + 6 *2 ] = rot (2 );
111
+ jacTarget.val [i + 6 *3 ] = trans (0 );
112
+ jacTarget.val [i + 6 *4 ] = trans (1 );
113
+ jacTarget.val [i + 6 *5 ] = trans (2 );
104
114
}
105
115
};
106
116
@@ -117,35 +127,50 @@ float PoseGraph::createLinearSystem(BlockSparseMat<float, 6, 6>& H, Mat& B)
117
127
// ! Edge transformation is source to target. (relativeConstraint should be identity if no error)
118
128
Affine3f poseConstraint = currEdge.transformation .inv () * relativeSourceToTarget;
119
129
120
- Vec6f error;
130
+ std::cout << " RelativeSourceToTarget: \n " << relativeSourceToTarget.matrix << " \n " ;
131
+ std::cout << " PoseConstraint: \n " << poseConstraint.matrix << " \n " ;
132
+
133
+ Matx61f error;
121
134
Vec3f rot = poseConstraint.rvec ();
122
135
Vec3f trans = poseConstraint.translation ();
123
136
124
- error[0 ] = rot[0 ];
125
- error[1 ] = rot[1 ];
126
- error[2 ] = rot[2 ];
127
- error[3 ] = trans[0 ];
128
- error[4 ] = trans[1 ];
129
- error[5 ] = trans[2 ];
137
+ error.val [0 ] = rot[0 ];
138
+ error.val [1 ] = rot[1 ];
139
+ error.val [2 ] = rot[2 ];
140
+ error.val [3 ] = trans[0 ];
141
+ error.val [4 ] = trans[1 ];
142
+ error.val [5 ] = trans[2 ];
143
+
144
+ std::cout << " Error vector: " << error << std::endl;
130
145
131
146
Matx66f jacSource, jacTarget;
132
147
calcErrorJacobian (jacSource, jacTarget, currEdge.transformation , sourcePose, targetPose);
148
+ std::cout << " Source Jacobian: \n " << jacSource << std::endl;
149
+ std::cout << " Target Jacobian: \n " << jacTarget << std::endl;
133
150
134
151
Matx16f errorTransposeInfo = error.t () * currEdge.information ;
135
152
Matx66f jacSourceTransposeInfo = jacSource.t () * currEdge.information ;
136
153
Matx66f jacTargetTransposeInfo = jacTarget.t () * currEdge.information ;
137
154
138
- residual += (errorTransposeInfo * error)[0 ];
155
+ std::cout << " errorTransposeInfo: " << errorTransposeInfo << " \n " ;
156
+ std::cout << " jacSourceTransposeInfo: " << jacSourceTransposeInfo << " \n " ;
157
+ std::cout << " jacTargetTransposeInfo: " << jacTargetTransposeInfo << " \n " ;
158
+
159
+ float res = (errorTransposeInfo * error).val [0 ];
160
+ residual += res;
139
161
162
+ std::cout << " sourceNodeId: " << sourceNodeId << " targetNodeId: " << targetNodeId << std::endl;
140
163
H.refBlock (sourceNodeId, sourceNodeId) += jacSourceTransposeInfo * jacSource;
141
164
H.refBlock (targetNodeId, targetNodeId) += jacTargetTransposeInfo * jacTarget;
142
165
H.refBlock (sourceNodeId, targetNodeId) += jacSourceTransposeInfo * jacTarget;
143
166
H.refBlock (targetNodeId, sourceNodeId) += jacTargetTransposeInfo * jacSource;
144
167
145
- B.rowRange (6 * sourceNodeId, 6 * (sourceNodeId + 1 )) += errorTransposeInfo * jacSource;
146
- B.rowRange (6 * targetNodeId, 6 * (targetNodeId + 1 )) += errorTransposeInfo * jacTarget;
168
+
169
+ B.rowRange (6 * sourceNodeId, 6 * (sourceNodeId + 1 )) += (errorTransposeInfo * jacSource).reshape <6 , 1 >();
170
+ B.rowRange (6 * targetNodeId, 6 * (targetNodeId + 1 )) += (errorTransposeInfo * jacTarget).reshape <6 , 1 >();
147
171
}
148
172
173
+ std::cout << " Residual value: " << residual << std::endl;
149
174
return residual;
150
175
}
151
176
@@ -194,27 +219,34 @@ void Optimizer::optimizeGaussNewton(const Optimizer::Params& params, PoseGraph&
194
219
{
195
220
// ! ApproxH = Approximate Hessian = J^T * information * J
196
221
BlockSparseMat<float , 6 , 6 > ApproxH (numNodes);
197
- Mat B (6 * numNodes, 1 , CV_32F);
222
+ Mat B = cv::Mat::zeros (6 * numNodes, 1 , CV_32F);
198
223
199
224
float currentResidual = poseGraph.createLinearSystem (ApproxH, B);
200
-
225
+ std::cout << " Number of non-zero blocks in H: " << ApproxH. nonZeroBlocks () << " \n " ;
201
226
Mat delta (6 * numNodes, 1 , CV_32F);
202
227
bool success = sparseSolve (ApproxH, B, delta);
203
228
if (!success)
204
229
{
205
230
CV_Error (Error::StsNoConv, " Sparse solve failed" );
206
231
return ;
207
232
}
233
+ std::cout << " delta update: " << delta << " \n " ;
208
234
// ! Check delta
235
+ std::cout << " Current residual: " << currentResidual << " Prev residual: " << prevResidual << " \n " ;
209
236
210
237
// ! TODO: Improve criterion and allow small increments in residual
211
- if ((currentResidual - prevResidual) > params.maxAcceptableResIncre )
238
+ if ((currentResidual - prevResidual) > params.maxAcceptableResIncre )
239
+ {
240
+ std::cout << " Current residual increased from prevResidual by at least " << params.maxAcceptableResIncre << std::endl;
212
241
break ;
242
+ }
213
243
if ((currentResidual - params.minResidual ) < 0 .00001f )
244
+ {
245
+ std::cout << " Gauss newton converged \n " ;
214
246
converged = true ;
247
+ }
215
248
216
249
poseGraph = poseGraph.update (delta);
217
- std::cout << " Current residual: " << currentResidual << " Prev residual: " << prevResidual << " \n " ;
218
250
219
251
prevResidual = currentResidual;
220
252
0 commit comments