diff --git a/_images/grid_clustering.png b/_images/grid_clustering.png new file mode 100644 index 00000000..c5359028 Binary files /dev/null and b/_images/grid_clustering.png differ diff --git a/_images/ndt_map1.png b/_images/ndt_map1.png new file mode 100644 index 00000000..1f34b9a6 Binary files /dev/null and b/_images/ndt_map1.png differ diff --git a/_images/ndt_map2.png b/_images/ndt_map2.png new file mode 100644 index 00000000..b9970629 Binary files /dev/null and b/_images/ndt_map2.png differ diff --git a/_images/raw_observations.png b/_images/raw_observations.png new file mode 100644 index 00000000..c1a0dd47 Binary files /dev/null and b/_images/raw_observations.png differ diff --git a/_modules/Mapping/ndt_map/ndt_map.html b/_modules/Mapping/ndt_map/ndt_map.html new file mode 100644 index 00000000..cd4b16ee --- /dev/null +++ b/_modules/Mapping/ndt_map/ndt_map.html @@ -0,0 +1,268 @@ + + + + + + Mapping.ndt_map.ndt_map — PythonRobotics documentation + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • »
  • +
  • Module code »
  • +
  • Mapping.ndt_map.ndt_map
  • +
  • +
  • +
+
+
+
+
+ +

Source code for Mapping.ndt_map.ndt_map

+"""
+Normal Distribution Transform (NDTGrid) mapping sample
+"""
+import matplotlib.pyplot as plt
+import numpy as np
+from collections import defaultdict
+
+from Mapping.grid_map_lib.grid_map_lib import GridMap
+from utils.plot import plot_covariance_ellipse
+
+
+
[docs]class NDTMap: + """ + Normal Distribution Transform (NDT) map class + + :param ox: obstacle x position list + :param oy: obstacle y position list + :param resolution: grid resolution [m] + """ + +
[docs] class NDTGrid: + """ + NDT grid + """ + + def __init__(self): + #: Number of points in the NDTGrid grid + self.n_points = 0 + #: Mean x position of points in the NDTGrid cell + self.mean_x = None + #: Mean y position of points in the NDTGrid cell + self.mean_y = None + #: Center x position of the NDT grid + self.center_grid_x = None + #: Center y position of the NDT grid + self.center_grid_y = None + #: Covariance matrix of the NDT grid + self.covariance = None + #: Eigen vectors of the NDT grid + self.eig_vec = None + #: Eigen values of the NDT grid + self.eig_values = None
+ + def __init__(self, ox, oy, resolution): + #: Minimum number of points in the NDT grid + self.min_n_points = 3 + #: Resolution of the NDT grid [m] + self.resolution = resolution + width = int((max(ox) - min(ox))/resolution) + 3 # rounding up + right and left margin + height = int((max(oy) - min(oy))/resolution) + 3 + center_x = np.mean(ox) + center_y = np.mean(oy) + self.ox = ox + self.oy = oy + #: NDT grid index map + self.grid_index_map = self._create_grid_index_map(ox, oy) + + #: NDT grid map. Each grid contains NDTGrid object + self._construct_grid_map(center_x, center_y, height, ox, oy, resolution, width) + + def _construct_grid_map(self, center_x, center_y, height, ox, oy, resolution, width): + self.grid_map = GridMap(width, height, resolution, center_x, center_y, self.NDTGrid()) + for grid_index, inds in self.grid_index_map.items(): + ndt = self.NDTGrid() + ndt.n_points = len(inds) + if ndt.n_points >= self.min_n_points: + ndt.mean_x = np.mean(ox[inds]) + ndt.mean_y = np.mean(oy[inds]) + ndt.center_grid_x, ndt.center_grid_y = \ + self.grid_map.calc_grid_central_xy_position_from_grid_index(grid_index) + ndt.covariance = np.cov(ox[inds], oy[inds]) + ndt.eig_values, ndt.eig_vec = np.linalg.eig(ndt.covariance) + self.grid_map.data[grid_index] = ndt + + def _create_grid_index_map(self, ox, oy): + grid_index_map = defaultdict(list) + for i in range(len(ox)): + grid_index = self.grid_map.calc_grid_index_from_xy_pos(ox[i], oy[i]) + grid_index_map[grid_index].append(i) + return grid_index_map
+ + +def create_dummy_observation_data(): + ox = [] + oy = [] + # left corridor + for y in range(-50, 50): + ox.append(-20.0) + oy.append(y) + # right corridor 1 + for y in range(-50, 0): + ox.append(20.0) + oy.append(y) + # right corridor 2 + for x in range(20, 50): + ox.append(x) + oy.append(0) + # right corridor 3 + for x in range(20, 50): + ox.append(x) + oy.append(x/2.0+10) + # right corridor 4 + for y in range(20, 50): + ox.append(20) + oy.append(y) + ox = np.array(ox) + oy = np.array(oy) + # Adding random noize + ox += np.random.rand(len(ox)) * 1.0 + oy += np.random.rand(len(ox)) * 1.0 + return ox, oy + + +def main(): + print(__file__ + " start!!") + + ox, oy = create_dummy_observation_data() + grid_resolution = 10.0 + ndt_map = NDTMap(ox, oy, grid_resolution) + + # plot raw observation + plt.plot(ox, oy, ".r") + + # plot grid clustering + [plt.plot(ox[inds], oy[inds], "x") for inds in ndt_map.grid_index_map.values()] + + # plot ndt grid map + [plot_covariance_ellipse(ndt.mean_x, ndt.mean_y, ndt.covariance, color="-k") for ndt in ndt_map.grid_map.data if ndt.n_points > 0] + + plt.axis("equal") + plt.show() + + +if __name__ == '__main__': + main() +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/index.html b/_modules/index.html index 81a1db08..f5dff4f9 100644 --- a/_modules/index.html +++ b/_modules/index.html @@ -100,7 +100,8 @@

All modules for which code is available

-
diff --git a/_sources/modules/mapping/mapping_main.rst.txt b/_sources/modules/mapping/mapping_main.rst.txt index 1c02c75c..a98acaaf 100644 --- a/_sources/modules/mapping/mapping_main.rst.txt +++ b/_sources/modules/mapping/mapping_main.rst.txt @@ -7,6 +7,7 @@ Mapping :caption: Contents gaussian_grid_map/gaussian_grid_map + ndt_map/ndt_map ray_casting_grid_map/ray_casting_grid_map lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial point_cloud_sampling/point_cloud_sampling diff --git a/_sources/modules/mapping/ndt_map/ndt_map_main.rst.txt b/_sources/modules/mapping/ndt_map/ndt_map_main.rst.txt new file mode 100644 index 00000000..bfc39363 --- /dev/null +++ b/_sources/modules/mapping/ndt_map/ndt_map_main.rst.txt @@ -0,0 +1,53 @@ +.. _ndt_map: + +Normal Distance Transform (NDT) map +------------------------------------ + +This is a NDT mapping example. + +Normal Distribution Transform (NDT) is a map representation that uses normal distribution for observation point modeling. + +Normal Distribution +~~~~~~~~~~~~~~~~~~~~~ + +Normal distribution consists of two parameters: mean :math:`\mu` and covariance :math:`\Sigma`. + +:math:`\mathbf{X} \sim \mathcal{N}(\boldsymbol{\mu}, \boldsymbol{\Sigma})` + +In the 2D case, :math:`\boldsymbol{\mu}` is a 2D vector and :math:`\boldsymbol{\Sigma}` is a 2x2 matrix. + +In the matrix form, the probability density function of thr normal distribution is: + +:math:`X=\frac{1}{\sqrt{(2 \pi)^2|\Sigma|}} \exp \left\{-\frac{1}{2}^t(x-\mu) \sum^{-1}(x-\mu)\right\}` + +Normal Distance Transform mapping steps +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  + +NDT mapping consists of two steps: + +When we have a new observation like this: + +.. figure:: raw_observations.png + +First, we need to cluster the observation points. +This is done by using a grid based clustering algorithm. + +The result is: + +.. figure:: grid_clustering.png + +Then, we need to fit a normal distribution to each grid cluster. + +Black ellipse shows each NDT grid like this: + +.. figure:: ndt_map1.png + +.. figure:: ndt_map2.png + +API +~~~~~ + +.. autoclass:: Mapping.ndt_map.ndt_map.NDTMap + :members: + :class-doc-from: class + diff --git a/genindex.html b/genindex.html index b4428940..93263535 100644 --- a/genindex.html +++ b/genindex.html @@ -107,10 +107,13 @@ A | C | D + | E | F + | G | I | L | M + | N | P | R | V @@ -139,11 +142,17 @@
  • (PathPlanning.CubicSpline.cubic_spline_planner.CubicSpline2D method)
  • - - + +

    E

    + + + +
    +

    F

      @@ -174,6 +195,14 @@
    +

    G

    + + +
    +

    I

    - +
    diff --git a/index.html b/index.html index 19478fa4..0cbb9763 100644 --- a/index.html +++ b/index.html @@ -146,6 +146,7 @@ algorithms (Mapping