diff --git a/_images/Figure_11.png b/_images/Figure_11.png deleted file mode 100644 index 539854ac..00000000 Binary files a/_images/Figure_11.png and /dev/null differ diff --git a/_images/approx_and_curvature.png b/_images/approx_and_curvature.png new file mode 100644 index 00000000..49f260bb Binary files /dev/null and b/_images/approx_and_curvature.png differ diff --git a/_images/approximation1.png b/_images/approximation1.png new file mode 100644 index 00000000..d5f00551 Binary files /dev/null and b/_images/approximation1.png differ diff --git a/_images/basis_functions.png b/_images/basis_functions.png new file mode 100644 index 00000000..65075c80 Binary files /dev/null and b/_images/basis_functions.png differ diff --git a/_images/bspline_path_planning.png b/_images/bspline_path_planning.png new file mode 100644 index 00000000..a3c1e621 Binary files /dev/null and b/_images/bspline_path_planning.png differ diff --git a/_images/curvature_plot.png b/_images/curvature_plot.png new file mode 100644 index 00000000..891d3008 Binary files /dev/null and b/_images/curvature_plot.png differ diff --git a/_images/interp_and_curvature.png b/_images/interp_and_curvature.png new file mode 100644 index 00000000..54e29174 Binary files /dev/null and b/_images/interp_and_curvature.png differ diff --git a/_images/interpolation1.png b/_images/interpolation1.png new file mode 100644 index 00000000..fb280343 Binary files /dev/null and b/_images/interpolation1.png differ diff --git a/_modules/PathPlanning/BSplinePath/bspline_path.html b/_modules/PathPlanning/BSplinePath/bspline_path.html new file mode 100644 index 00000000..91712a46 --- /dev/null +++ b/_modules/PathPlanning/BSplinePath/bspline_path.html @@ -0,0 +1,278 @@ + + + + + + PathPlanning.BSplinePath.bspline_path — PythonRobotics documentation + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • »
  • +
  • Module code »
  • +
  • PathPlanning.BSplinePath.bspline_path
  • +
  • +
  • +
+
+
+
+
+ +

Source code for PathPlanning.BSplinePath.bspline_path

+"""
+
+Path Planner with B-Spline
+
+author: Atsushi Sakai (@Atsushi_twi)
+
+"""
+import sys
+import pathlib
+sys.path.append(str(pathlib.Path(__file__).parent.parent.parent))
+
+import numpy as np
+import matplotlib.pyplot as plt
+import scipy.interpolate as interpolate
+
+from utils.plot import plot_curvature
+
+
+
[docs]def approximate_b_spline_path(x: list, + y: list, + n_path_points: int, + degree: int = 3, + s=None, + ) -> tuple: + """ + Approximate points with a B-Spline path + + Parameters + ---------- + x : array_like + x position list of approximated points + y : array_like + y position list of approximated points + n_path_points : int + number of path points + degree : int, optional + B Spline curve degree. Must be 2<= k <= 5. Default: 3. + s : int, optional + smoothing parameter. If this value is bigger, the path will be + smoother, but it will be less accurate. If this value is smaller, + the path will be more accurate, but it will be less smooth. + When `s` is 0, it is equivalent to the interpolation. Default is None, + in this case `s` will be `len(x)`. + + Returns + ------- + x : array + x positions of the result path + y : array + y positions of the result path + heading : array + heading of the result path + curvature : array + curvature of the result path + + """ + distances = _calc_distance_vector(x, y) + + spl_i_x = interpolate.UnivariateSpline(distances, x, k=degree, s=s) + spl_i_y = interpolate.UnivariateSpline(distances, y, k=degree, s=s) + + sampled = np.linspace(0.0, distances[-1], n_path_points) + return _evaluate_spline(sampled, spl_i_x, spl_i_y)
+ + +
[docs]def interpolate_b_spline_path(x, y, + n_path_points: int, + degree: int = 3) -> tuple: + """ + Interpolate x-y points with a B-Spline path + + Parameters + ---------- + x : array_like + x positions of interpolated points + y : array_like + y positions of interpolated points + n_path_points : int + number of path points + degree : int, optional + B-Spline degree. Must be 2<= k <= 5. Default: 3 + + Returns + ------- + x : array + x positions of the result path + y : array + y positions of the result path + heading : array + heading of the result path + curvature : array + curvature of the result path + + """ + return approximate_b_spline_path(x, y, n_path_points, degree, s=0.0)
+ + +def _calc_distance_vector(x, y): + dx, dy = np.diff(x), np.diff(y) + distances = np.cumsum([np.hypot(idx, idy) for idx, idy in zip(dx, dy)]) + distances = np.concatenate(([0.0], distances)) + distances /= distances[-1] + return distances + + +def _evaluate_spline(sampled, spl_i_x, spl_i_y): + x = spl_i_x(sampled) + y = spl_i_y(sampled) + dx = spl_i_x.derivative(1)(sampled) + dy = spl_i_y.derivative(1)(sampled) + heading = np.arctan2(dy, dx) + ddx = spl_i_x.derivative(2)(sampled) + ddy = spl_i_y.derivative(2)(sampled) + curvature = (ddy * dx - ddx * dy) / np.power(dx * dx + dy * dy, 2.0 / 3.0) + return np.array(x), y, heading, curvature, + + +def main(): + print(__file__ + " start!!") + # way points + way_point_x = [-1.0, 3.0, 4.0, 2.0, 1.0] + way_point_y = [0.0, -3.0, 1.0, 1.0, 3.0] + n_course_point = 50 # sampling number + + plt.subplots() + rax, ray, heading, curvature = approximate_b_spline_path( + way_point_x, way_point_y, n_course_point, s=0.5) + plt.plot(rax, ray, '-r', label="Approximated B-Spline path") + plot_curvature(rax, ray, heading, curvature) + + plt.title("B-Spline approximation") + plt.plot(way_point_x, way_point_y, '-og', label="way points") + plt.grid(True) + plt.legend() + plt.axis("equal") + + plt.subplots() + rix, riy, heading, curvature = interpolate_b_spline_path( + way_point_x, way_point_y, n_course_point) + plt.plot(rix, riy, '-b', label="Interpolated B-Spline path") + plot_curvature(rix, riy, heading, curvature) + + plt.title("B-Spline interpolation") + plt.plot(way_point_x, way_point_y, '-og', label="way points") + plt.grid(True) + plt.legend() + plt.axis("equal") + plt.show() + + +if __name__ == '__main__': + main() +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/_modules/PathPlanning/CubicSpline/cubic_spline_planner.html b/_modules/PathPlanning/CubicSpline/cubic_spline_planner.html index f629a583..e72c6a7b 100644 --- a/_modules/PathPlanning/CubicSpline/cubic_spline_planner.html +++ b/_modules/PathPlanning/CubicSpline/cubic_spline_planner.html @@ -64,6 +64,7 @@
  • Aerial Navigation
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • diff --git a/_modules/PathPlanning/DubinsPath/dubins_path_planner.html b/_modules/PathPlanning/DubinsPath/dubins_path_planner.html index ce58f495..f0105149 100644 --- a/_modules/PathPlanning/DubinsPath/dubins_path_planner.html +++ b/_modules/PathPlanning/DubinsPath/dubins_path_planner.html @@ -64,6 +64,7 @@
  • Aerial Navigation
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • diff --git a/_modules/index.html b/_modules/index.html index 2400b22f..7212f6d2 100644 --- a/_modules/index.html +++ b/_modules/index.html @@ -64,6 +64,7 @@
  • Aerial Navigation
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • @@ -92,8 +93,10 @@

    All modules for which code is available

    -
    diff --git a/_modules/utils/plot.html b/_modules/utils/plot.html new file mode 100644 index 00000000..0d9053b8 --- /dev/null +++ b/_modules/utils/plot.html @@ -0,0 +1,212 @@ + + + + + + utils.plot — PythonRobotics documentation + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +

    Source code for utils.plot

    +"""
    +Matplotlib based plotting utilities
    +"""
    +import math
    +import matplotlib.pyplot as plt
    +import numpy as np
    +
    +
    +def plot_arrow(x, y, yaw, arrow_length=1.0,
    +               origin_point_plot_style="xr",
    +               head_width=0.1, fc="r", ec="k", **kwargs):
    +    """
    +    Plot an arrow or arrows based on 2D state (x, y, yaw)
    +
    +    All optional settings of matplotlib.pyplot.arrow can be used.
    +    - matplotlib.pyplot.arrow:
    +    https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.arrow.html
    +
    +    Parameters
    +    ----------
    +    x : a float or array_like
    +        a value or a list of arrow origin x position.
    +    y : a float or array_like
    +        a value or a list of arrow origin y position.
    +    yaw : a float or array_like
    +        a value or a list of arrow yaw angle (orientation).
    +    arrow_length : a float (optional)
    +        arrow length. default is 1.0
    +    origin_point_plot_style : str (optional)
    +        origin point plot style. If None, not plotting.
    +    head_width : a float (optional)
    +        arrow head width. default is 0.1
    +    fc : string (optional)
    +        face color
    +    ec : string (optional)
    +        edge color
    +    """
    +    if not isinstance(x, float):
    +        for (i_x, i_y, i_yaw) in zip(x, y, yaw):
    +            plot_arrow(i_x, i_y, i_yaw, head_width=head_width,
    +                       fc=fc, ec=ec, **kwargs)
    +    else:
    +        plt.arrow(x, y,
    +                  arrow_length * math.cos(yaw),
    +                  arrow_length * math.sin(yaw),
    +                  head_width=head_width,
    +                  fc=fc, ec=ec,
    +                  **kwargs)
    +        if origin_point_plot_style is not None:
    +            plt.plot(x, y, origin_point_plot_style)
    +
    +
    +
    [docs]def plot_curvature(x_list, y_list, heading_list, curvature, + k=0.01, c="-c", label="Curvature"): + """ + Plot curvature on 2D path. This plot is a line from the original path, + the lateral distance from the original path shows curvature magnitude. + Left turning shows right side plot, right turning shows left side plot. + For straight path, the curvature plot will be on the path, because + curvature is 0 on the straight path. + + Parameters + ---------- + x_list : array_like + x position list of the path + y_list : array_like + y position list of the path + heading_list : array_like + heading list of the path + curvature : array_like + curvature list of the path + k : float + curvature scale factor to calculate distance from the original path + c : string + color of the plot + label : string + label of the plot + """ + cx = [x + d * k * np.cos(yaw - np.pi / 2.0) for x, y, yaw, d in + zip(x_list, y_list, heading_list, curvature)] + cy = [y + d * k * np.sin(yaw - np.pi / 2.0) for x, y, yaw, d in + zip(x_list, y_list, heading_list, curvature)] + + plt.plot(cx, cy, c, label=label) + for ix, iy, icx, icy in zip(x_list, y_list, cx, cy): + plt.plot([ix, icx], [iy, icy], c)
    +
    + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/_sources/index_main.rst.txt b/_sources/index_main.rst.txt index 15175928..67bd9889 100644 --- a/_sources/index_main.rst.txt +++ b/_sources/index_main.rst.txt @@ -44,6 +44,7 @@ See this paper for more details: modules/aerial_navigation/aerial_navigation modules/bipedal/bipedal modules/control/control + modules/utils/utils modules/appendix/appendix how_to_contribute diff --git a/_sources/modules/path_planning/bspline_path/bspline_path_main.rst.txt b/_sources/modules/path_planning/bspline_path/bspline_path_main.rst.txt index d3523a19..e734352e 100644 --- a/_sources/modules/path_planning/bspline_path/bspline_path_main.rst.txt +++ b/_sources/modules/path_planning/bspline_path/bspline_path_main.rst.txt @@ -1,14 +1,146 @@ B-Spline planning ----------------- -.. image:: Figure_1.png +.. image:: bspline_path_planning.png -This is a path planning with B-Spline curse. +This is a B-Spline path planning routines. If you input waypoints, it generates a smooth path with B-Spline curve. -The final course should be on the first and last waypoints. +This codes provide two types of B-Spline curve generations: -Ref: +1. Interpolation: generate a curve that passes through all waypoints. + +2. Approximation: generate a curve that approximates the waypoints. (Not passing through all waypoints) + +Bspline basics +~~~~~~~~~~~~~~ + +BSpline (Basis-Spline) is a piecewise polynomial spline curve. + +It is expressed by the following equation. + +:math:`\mathbf{S}(x)=\sum_{i=k-p}^k \mathbf{c}_i B_{i, p}(x)` + +here: + +* :math:`S(x)` is the curve point on the spline at x. +* :math:`c_i` is the representative point generating the spline, called the control point. +* :math:`p+1` is the dimension of the BSpline. +* :math:`k` is the number of knots. +* :math:`B_{i,p}(x)` is a function called Basis Function. + +The the basis function can be calculated by the following `De Boor recursion formula `_: + +:math:`B_{i, 0}(x):= \begin{cases}1 & \text { if } \quad t_i \leq x`_. + +.. code-block:: python + + from scipy.interpolate import BSpline + + def B_orig(x, k, i, t): + if k == 0: + return 1.0 if t[i] <= x < t[i + 1] else 0.0 + if t[i + k] == t[i]: + c1 = 0.0 + else: + c1 = (x - t[i]) / (t[i + k] - t[i]) * B(x, k - 1, i, t) + + if t[i + k + 1] == t[i + 1]: + c2 = 0.0 + else: + c2 = (t[i + k + 1] - x) / (t[i + k + 1] - t[i + 1]) * B(x, k - 1, i + 1, t) + return c1 + c2 + + + def B(x, k, i, t): + c = np.zeros_like(t) + c[i] = 1 + return BSpline(t, c, k)(x) + + + def main(): + k = 3 # degree of the spline + t = [0, 1, 2, 3, 4, 5] # knots vector + + x = np.linspace(0, 5, 1000, endpoint=False) + t = np.r_[[np.min(t)]*k, t, [np.max(t)]*k] + + n = len(t) - k - 1 + for i in range(n): + y = np.array([B(ix, k, i, t) for ix in x]) + plt.plot(x, y, label=f'i = {i}') + + plt.title(f'Basis functions (k = {k}, knots = {t})') + plt.show() + +Bspline interpolation planning +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:meth:`PathPlanning.BSplinePath.bspline_path.interpolate_b_spline_path` generates a curve that passes through all waypoints. + +This is a simple example of the interpolation planning: + +.. image:: interpolation1.png + +This figure also shows curvatures of each path point using :ref:`utils.plot.plot_curvature `. + +The default spline degree is 3, so curvature changes smoothly. + +.. image:: interp_and_curvature.png + +API +++++ + +.. autofunction:: PathPlanning.BSplinePath.bspline_path.interpolate_b_spline_path + + +Bspline approximation planning +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:meth:`PathPlanning.BSplinePath.bspline_path.approximate_b_spline_path` +generates a curve that approximates the waypoints, which means that +the curve might not pass through waypoints. + +Users can adjust path smoothness by the smoothing parameter `s`. If this +value is bigger, the path will be smoother, but it will be less accurate. +If this value is smaller, the path will be more accurate, but it will be +less smooth. + +This is a simple example of the approximation planning: + +.. image:: approximation1.png + +This figure also shows curvatures of each path point using :ref:`utils.plot.plot_curvature `. + +The default spline degree is 3, so curvature changes smoothly. + +.. image:: approx_and_curvature.png + +API +++++ + +.. autofunction:: PathPlanning.BSplinePath.bspline_path.approximate_b_spline_path + + +References +~~~~~~~~~~ - `B-spline - Wikipedia `__ +- `scipy.interpolate.UnivariateSpline `__ \ No newline at end of file diff --git a/_sources/modules/utils/plot/plot_main.rst.txt b/_sources/modules/utils/plot/plot_main.rst.txt new file mode 100644 index 00000000..b5fef0c4 --- /dev/null +++ b/_sources/modules/utils/plot/plot_main.rst.txt @@ -0,0 +1,16 @@ +.. _plot_utils: + +Plotting Utilities +------------------- + +This module contains a number of utility functions for plotting data. + +.. _plot_curvature: + +plot_curvature +~~~~~~~~~~~~~~~ + +.. autofunction:: utils.plot.plot_curvature + +.. image:: curvature_plot.png + diff --git a/_sources/modules/utils/utils_main.rst.txt b/_sources/modules/utils/utils_main.rst.txt new file mode 100644 index 00000000..ff79a262 --- /dev/null +++ b/_sources/modules/utils/utils_main.rst.txt @@ -0,0 +1,12 @@ +.. _utils: + +Utilities +========== + +Common utilities for PythonRobotics. + +.. toctree:: + :maxdepth: 2 + :caption: Contents + + plot/plot diff --git a/genindex.html b/genindex.html index a60e9636..11fc2e7b 100644 --- a/genindex.html +++ b/genindex.html @@ -64,6 +64,7 @@
  • Aerial Navigation
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • @@ -96,10 +97,20 @@

    Index

    - C + A + | C + | I | P
    +

    A

    + + +
    +

    C

      @@ -126,10 +137,22 @@
    +

    I

    + + +
    +

    P

    +
    diff --git a/getting_started.html b/getting_started.html index c50d8e56..7dcaf6be 100644 --- a/getting_started.html +++ b/getting_started.html @@ -72,6 +72,7 @@
  • Aerial Navigation
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • diff --git a/how_to_contribute.html b/how_to_contribute.html index 0bd794e1..23a1d42c 100644 --- a/how_to_contribute.html +++ b/how_to_contribute.html @@ -66,6 +66,7 @@
  • Aerial Navigation
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • +
  • Utilities +
  • Appendix diff --git a/modules/aerial_navigation/drone_3d_trajectory_following/drone_3d_trajectory_following.html b/modules/aerial_navigation/drone_3d_trajectory_following/drone_3d_trajectory_following.html index 9a125cb0..94e2f948 100644 --- a/modules/aerial_navigation/drone_3d_trajectory_following/drone_3d_trajectory_following.html +++ b/modules/aerial_navigation/drone_3d_trajectory_following/drone_3d_trajectory_following.html @@ -71,6 +71,7 @@
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • diff --git a/modules/aerial_navigation/rocket_powered_landing/rocket_powered_landing.html b/modules/aerial_navigation/rocket_powered_landing/rocket_powered_landing.html index ae0609cb..a76fd0ba 100644 --- a/modules/aerial_navigation/rocket_powered_landing/rocket_powered_landing.html +++ b/modules/aerial_navigation/rocket_powered_landing/rocket_powered_landing.html @@ -77,6 +77,7 @@
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • diff --git a/modules/appendix/Kalmanfilter_basics.html b/modules/appendix/Kalmanfilter_basics.html index bcc69835..5b8aa6ec 100644 --- a/modules/appendix/Kalmanfilter_basics.html +++ b/modules/appendix/Kalmanfilter_basics.html @@ -68,6 +68,7 @@
  • Aerial Navigation
  • Bipedal
  • Control
  • +
  • Utilities
  • Appendix diff --git a/modules/bipedal/bipedal_planner/bipedal_planner.html b/modules/bipedal/bipedal_planner/bipedal_planner.html index 82825033..961bcf99 100644 --- a/modules/bipedal/bipedal_planner/bipedal_planner.html +++ b/modules/bipedal/bipedal_planner/bipedal_planner.html @@ -70,6 +70,7 @@
  • Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • diff --git a/modules/control/control.html b/modules/control/control.html index 14879c42..b426685f 100644 --- a/modules/control/control.html +++ b/modules/control/control.html @@ -71,6 +71,7 @@
  • Move to a Pose Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • diff --git a/modules/control/inverted_pendulum_control/inverted_pendulum_control.html b/modules/control/inverted_pendulum_control/inverted_pendulum_control.html index b5a79d7f..faa99121 100644 --- a/modules/control/inverted_pendulum_control/inverted_pendulum_control.html +++ b/modules/control/inverted_pendulum_control/inverted_pendulum_control.html @@ -77,6 +77,7 @@
  • Move to a Pose Control
  • +
  • Utilities
  • Appendix
  • How To Contribute
  • diff --git a/modules/control/move_to_a_pose_control/move_to_a_pose_control.html b/modules/control/move_to_a_pose_control/move_to_a_pose_control.html index e4cc461b..934c6976 100644 --- a/modules/control/move_to_a_pose_control/move_to_a_pose_control.html +++ b/modules/control/move_to_a_pose_control/move_to_a_pose_control.html @@ -21,7 +21,7 @@ - + @@ -88,6 +88,7 @@ +
  • Utilities
  • Appendix
  • How To Contribute
  • @@ -301,7 +302,7 @@ p102