同步操作将从 Qingwen/PythonRobotics 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
# Copyright (c) 2020 Jeff Irion and contributors## This file originated from the `graphslam` package:## https://github.com/JeffLIrion/python-graphslamr"""A ``Graph`` class that stores the edges and vertices required for Graph SLAM."""import warningsfrom collections import defaultdictfrom functools import reduceimport matplotlib.pyplot as pltimport numpy as npfrom scipy.sparse import SparseEfficiencyWarning, lil_matrixfrom scipy.sparse.linalg import spsolvewarnings.simplefilter("ignore", SparseEfficiencyWarning)warnings.filterwarnings("ignore", category=SparseEfficiencyWarning)# pylint: disable=too-few-public-methodsclass _Chi2GradientHessian:r"""A class that is used to aggregate the :math:`\chi^2` error, gradient, and Hessian.Parameters----------dim : intThe compact dimensionality of the posesAttributes----------chi2 : floatThe :math:`\chi^2` errordim : intThe compact dimensionality of the posesgradient : defaultdictThe contributions to the gradient vectorhessian : defaultdictThe contributions to the Hessian matrix"""def __init__(self, dim):self.chi2 = 0.self.dim = dimself.gradient = defaultdict(lambda: np.zeros(dim))self.hessian = defaultdict(lambda: np.zeros((dim, dim)))@staticmethoddef update(chi2_grad_hess, incoming):r"""Update the :math:`\chi^2` error and the gradient and Hessian dictionaries.Parameters----------chi2_grad_hess : _Chi2GradientHessianThe ``_Chi2GradientHessian`` that will be updatedincoming : tuple"""chi2_grad_hess.chi2 += incoming[0]for idx, contrib in incoming[1].items():chi2_grad_hess.gradient[idx] += contribfor (idx1, idx2), contrib in incoming[2].items():if idx1 <= idx2:chi2_grad_hess.hessian[idx1, idx2] += contribelse:chi2_grad_hess.hessian[idx2, idx1] += np.transpose(contrib)return chi2_grad_hessclass Graph(object):r"""A graph that will be optimized via Graph SLAM.Parameters----------edges : list[graphslam.edge.edge_odometry.EdgeOdometry]A list of the vertices in the graphvertices : list[graphslam.vertex.Vertex]A list of the vertices in the graphAttributes----------_chi2 : float, NoneThe current :math:`\chi^2` error, or ``None`` if it has not yet been computed_edges : list[graphslam.edge.edge_odometry.EdgeOdometry]A list of the edges (i.e., constraints) in the graph_gradient : numpy.ndarray, NoneThe gradient :math:`\mathbf{b}` of the :math:`\chi^2` error, or ``None`` if it has not yet been computed_hessian : scipy.sparse.lil_matrix, NoneThe Hessian matrix :math:`H`, or ``None`` if it has not yet been computed_vertices : list[graphslam.vertex.Vertex]A list of the vertices in the graph"""def __init__(self, edges, vertices):# The vertices and edges listsself._edges = edgesself._vertices = vertices# The chi^2 error, gradient, and Hessianself._chi2 = Noneself._gradient = Noneself._hessian = Noneself._link_edges()def _link_edges(self):"""Fill in the ``vertices`` attributes for the graph's edges."""index_id_dict = {i: v.id for i, v in enumerate(self._vertices)}id_index_dict = {v_id: v_index for v_index, v_id inindex_id_dict.items()}# Fill in the vertices' `index` attributefor v in self._vertices:v.index = id_index_dict[v.id]for e in self._edges:e.vertices = [self._vertices[id_index_dict[v_id]] for v_id ine.vertex_ids]def calc_chi2(self):r"""Calculate the :math:`\chi^2` error for the ``Graph``.Returns-------floatThe :math:`\chi^2` error"""self._chi2 = sum((e.calc_chi2() for e in self._edges))return self._chi2def _calc_chi2_gradient_hessian(self):r"""Calculate the :math:`\chi^2` error, the gradient :math:`\mathbf{b}`, and the Hessian :math:`H`."""n = len(self._vertices)dim = len(self._vertices[0].pose.to_compact())chi2_gradient_hessian = reduce(_Chi2GradientHessian.update,(e.calc_chi2_gradient_hessian()for e in self._edges),_Chi2GradientHessian(dim))self._chi2 = chi2_gradient_hessian.chi2# Fill in the gradient vectorself._gradient = np.zeros(n * dim, dtype=float)for idx, cont in chi2_gradient_hessian.gradient.items():self._gradient[idx * dim: (idx + 1) * dim] += cont# Fill in the Hessian matrixself._hessian = lil_matrix((n * dim, n * dim), dtype=float)for (row_idx, col_idx), cont in chi2_gradient_hessian.hessian.items():x_start = row_idx * dimx_end = (row_idx + 1) * dimy_start = col_idx * dimy_end = (col_idx + 1) * dimself._hessian[x_start:x_end, y_start:y_end] = contif row_idx != col_idx:x_start = col_idx * dimx_end = (col_idx + 1) * dimy_start = row_idx * dimy_end = (row_idx + 1) * dimself._hessian[x_start:x_end, y_start:y_end] = \np.transpose(cont)def optimize(self, tol=1e-4, max_iter=20, fix_first_pose=True):r"""Optimize the :math:`\chi^2` error for the ``Graph``.Parameters----------tol : floatIf the relative decrease in the :math:`\chi^2` error between iterations is less than ``tol``, we will stopmax_iter : intThe maximum number of iterationsfix_first_pose : boolIf ``True``, we will fix the first pose"""n = len(self._vertices)dim = len(self._vertices[0].pose.to_compact())# Previous iteration's chi^2 errorchi2_prev = -1.# For displaying the optimization progressprint("\nIteration chi^2 rel. change")print("--------- ----- -----------")for i in range(max_iter):self._calc_chi2_gradient_hessian()# Check for convergence (from the previous iteration); this avoids having to calculate chi^2 twiceif i > 0:rel_diff = (chi2_prev - self._chi2) / (chi2_prev + np.finfo(float).eps)print("{:9d} {:20.4f} {:18.6f}".format(i, self._chi2, -rel_diff))if self._chi2 < chi2_prev and rel_diff < tol:returnelse:print("{:9d} {:20.4f}".format(i, self._chi2))# Update the previous iteration's chi^2 errorchi2_prev = self._chi2# Hold the first pose fixedif fix_first_pose:self._hessian[:dim, :] = 0.self._hessian[:, :dim] = 0.self._hessian[:dim, :dim] += np.eye(dim)self._gradient[:dim] = 0.# Solve for the updatesdx = spsolve(self._hessian, -self._gradient)# Apply the updatesfor v, dx_i in zip(self._vertices, np.split(dx, n)):v.pose += dx_i# If we reached the maximum number of iterations, print out the final iteration's resultsself.calc_chi2()rel_diff = (chi2_prev - self._chi2) / (chi2_prev + np.finfo(float).eps)print("{:9d} {:20.4f} {:18.6f}".format(max_iter, self._chi2, -rel_diff))def to_g2o(self, outfile):"""Save the graph in .g2o format.Parameters----------outfile : strThe path where the graph will be saved"""with open(outfile, 'w') as f:for v in self._vertices:f.write(v.to_g2o())for e in self._edges:f.write(e.to_g2o())def plot(self, vertex_color='r', vertex_marker='o', vertex_markersize=3,edge_color='b', title=None):"""Plot the graph.Parameters----------vertex_color : strThe color that will be used to plot the verticesvertex_marker : strThe marker that will be used to plot the verticesvertex_markersize : intThe size of the plotted verticesedge_color : strThe color that will be used to plot the edgestitle : str, NoneThe title that will be used for the plot"""plt.figure()for e in self._edges:e.plot(edge_color)for v in self._vertices:v.plot(vertex_color, vertex_marker, vertex_markersize)if title:plt.title(title)plt.show()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。