88
99"""
1010
11-
11+ import warnings
1212from collections import defaultdict
1313from functools import reduce
14- import warnings
1514
15+ import matplotlib .pyplot as plt
1616import numpy as np
1717from scipy .sparse import SparseEfficiencyWarning , lil_matrix
1818from scipy .sparse .linalg import spsolve
19- import matplotlib .pyplot as plt
20-
2119
2220warnings .simplefilter ("ignore" , SparseEfficiencyWarning )
2321warnings .filterwarnings ("ignore" , category = SparseEfficiencyWarning )
@@ -44,6 +42,7 @@ class _Chi2GradientHessian:
4442 The contributions to the Hessian matrix
4543
4644 """
45+
4746 def __init__ (self , dim ):
4847 self .chi2 = 0.
4948 self .dim = dim
@@ -59,7 +58,6 @@ def update(chi2_grad_hess, incoming):
5958 chi2_grad_hess : _Chi2GradientHessian
6059 The ``_Chi2GradientHessian`` that will be updated
6160 incoming : tuple
62- TODO
6361
6462 """
6563 chi2_grad_hess .chi2 += incoming [0 ]
@@ -100,6 +98,7 @@ class Graph(object):
10098 A list of the vertices in the graph
10199
102100 """
101+
103102 def __init__ (self , edges , vertices ):
104103 # The vertices and edges lists
105104 self ._edges = edges
@@ -117,14 +116,16 @@ def _link_edges(self):
117116
118117 """
119118 index_id_dict = {i : v .id for i , v in enumerate (self ._vertices )}
120- id_index_dict = {v_id : v_index for v_index , v_id in index_id_dict .items ()}
119+ id_index_dict = {v_id : v_index for v_index , v_id in
120+ index_id_dict .items ()}
121121
122122 # Fill in the vertices' `index` attribute
123123 for v in self ._vertices :
124124 v .index = id_index_dict [v .id ]
125125
126126 for e in self ._edges :
127- e .vertices = [self ._vertices [id_index_dict [v_id ]] for v_id in e .vertex_ids ]
127+ e .vertices = [self ._vertices [id_index_dict [v_id ]] for v_id in
128+ e .vertex_ids ]
128129
129130 def calc_chi2 (self ):
130131 r"""Calculate the :math:`\chi^2` error for the ``Graph``.
@@ -144,22 +145,34 @@ def _calc_chi2_gradient_hessian(self):
144145 """
145146 n = len (self ._vertices )
146147 dim = len (self ._vertices [0 ].pose .to_compact ())
147- chi2_gradient_hessian = reduce (_Chi2GradientHessian .update , (e .calc_chi2_gradient_hessian () for e in self ._edges ), _Chi2GradientHessian (dim ))
148+ chi2_gradient_hessian = reduce (_Chi2GradientHessian .update ,
149+ (e .calc_chi2_gradient_hessian ()
150+ for e in self ._edges ),
151+ _Chi2GradientHessian (dim ))
148152
149153 self ._chi2 = chi2_gradient_hessian .chi2
150154
151155 # Fill in the gradient vector
152- self ._gradient = np .zeros (n * dim , dtype = np . float64 )
153- for idx , contrib in chi2_gradient_hessian .gradient .items ():
154- self ._gradient [idx * dim : (idx + 1 ) * dim ] += contrib
156+ self ._gradient = np .zeros (n * dim , dtype = float )
157+ for idx , cont in chi2_gradient_hessian .gradient .items ():
158+ self ._gradient [idx * dim : (idx + 1 ) * dim ] += cont
155159
156160 # Fill in the Hessian matrix
157- self ._hessian = lil_matrix ((n * dim , n * dim ), dtype = np .float64 )
158- for (row_idx , col_idx ), contrib in chi2_gradient_hessian .hessian .items ():
159- self ._hessian [row_idx * dim : (row_idx + 1 ) * dim , col_idx * dim : (col_idx + 1 ) * dim ] = contrib
161+ self ._hessian = lil_matrix ((n * dim , n * dim ), dtype = float )
162+ for (row_idx , col_idx ), cont in chi2_gradient_hessian .hessian .items ():
163+ x_start = row_idx * dim
164+ x_end = (row_idx + 1 ) * dim
165+ y_start = col_idx * dim
166+ y_end = (col_idx + 1 ) * dim
167+ self ._hessian [x_start :x_end , y_start :y_end ] = cont
160168
161169 if row_idx != col_idx :
162- self ._hessian [col_idx * dim : (col_idx + 1 ) * dim , row_idx * dim : (row_idx + 1 ) * dim ] = np .transpose (contrib )
170+ x_start = col_idx * dim
171+ x_end = (col_idx + 1 ) * dim
172+ y_start = row_idx * dim
173+ y_end = (row_idx + 1 ) * dim
174+ self ._hessian [x_start :x_end , y_start :y_end ] = \
175+ np .transpose (cont )
163176
164177 def optimize (self , tol = 1e-4 , max_iter = 20 , fix_first_pose = True ):
165178 r"""Optimize the :math:`\chi^2` error for the ``Graph``.
@@ -189,8 +202,10 @@ def optimize(self, tol=1e-4, max_iter=20, fix_first_pose=True):
189202
190203 # Check for convergence (from the previous iteration); this avoids having to calculate chi^2 twice
191204 if i > 0 :
192- rel_diff = (chi2_prev - self ._chi2 ) / (chi2_prev + np .finfo (float ).eps )
193- print ("{:9d} {:20.4f} {:18.6f}" .format (i , self ._chi2 , - rel_diff ))
205+ rel_diff = (chi2_prev - self ._chi2 ) / (
206+ chi2_prev + np .finfo (float ).eps )
207+ print (
208+ "{:9d} {:20.4f} {:18.6f}" .format (i , self ._chi2 , - rel_diff ))
194209 if self ._chi2 < chi2_prev and rel_diff < tol :
195210 return
196211 else :
@@ -207,7 +222,7 @@ def optimize(self, tol=1e-4, max_iter=20, fix_first_pose=True):
207222 self ._gradient [:dim ] = 0.
208223
209224 # Solve for the updates
210- dx = spsolve (self ._hessian , - self ._gradient ) # pylint: disable=invalid-unary-operand-type
225+ dx = spsolve (self ._hessian , - self ._gradient )
211226
212227 # Apply the updates
213228 for v , dx_i in zip (self ._vertices , np .split (dx , n )):
@@ -216,7 +231,8 @@ def optimize(self, tol=1e-4, max_iter=20, fix_first_pose=True):
216231 # If we reached the maximum number of iterations, print out the final iteration's results
217232 self .calc_chi2 ()
218233 rel_diff = (chi2_prev - self ._chi2 ) / (chi2_prev + np .finfo (float ).eps )
219- print ("{:9d} {:20.4f} {:18.6f}" .format (max_iter , self ._chi2 , - rel_diff ))
234+ print ("{:9d} {:20.4f} {:18.6f}" .format (
235+ max_iter , self ._chi2 , - rel_diff ))
220236
221237 def to_g2o (self , outfile ):
222238 """Save the graph in .g2o format.
@@ -234,7 +250,8 @@ def to_g2o(self, outfile):
234250 for e in self ._edges :
235251 f .write (e .to_g2o ())
236252
237- def plot (self , vertex_color = 'r' , vertex_marker = 'o' , vertex_markersize = 3 , edge_color = 'b' , title = None ):
253+ def plot (self , vertex_color = 'r' , vertex_marker = 'o' , vertex_markersize = 3 ,
254+ edge_color = 'b' , title = None ):
238255 """Plot the graph.
239256
240257 Parameters
0 commit comments