From af456c70b0ec336442b0b32c5aab1a220aefaf74 Mon Sep 17 00:00:00 2001 From: Surabhi Gupta <103124390+SurabhiGupta17@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:42:31 +0530 Subject: [PATCH] Implement Catmull-Rom Spline with test and documentation (#1085) --- .../blending_functions.py | 34 ++++++ .../catmull_rom_spline_path.py | 86 +++++++++++++++ .../catmull_rom_spline/blending_functions.png | Bin 0 -> 41129 bytes .../catmull_rom_path_planning.png | Bin 0 -> 33505 bytes .../catmull_rom_spline_main.rst | 103 ++++++++++++++++++ tests/test_catmull_rom_spline.py | 16 +++ 6 files changed, 239 insertions(+) create mode 100644 PathPlanning/Catmull_RomSplinePath/blending_functions.py create mode 100644 PathPlanning/Catmull_RomSplinePath/catmull_rom_spline_path.py create mode 100644 docs/modules/path_planning/catmull_rom_spline/blending_functions.png create mode 100644 docs/modules/path_planning/catmull_rom_spline/catmull_rom_path_planning.png create mode 100644 docs/modules/path_planning/catmull_rom_spline/catmull_rom_spline_main.rst create mode 100644 tests/test_catmull_rom_spline.py diff --git a/PathPlanning/Catmull_RomSplinePath/blending_functions.py b/PathPlanning/Catmull_RomSplinePath/blending_functions.py new file mode 100644 index 0000000000..f3ef5dd323 --- /dev/null +++ b/PathPlanning/Catmull_RomSplinePath/blending_functions.py @@ -0,0 +1,34 @@ +import numpy as np +import matplotlib.pyplot as plt + +def blending_function_1(t): + return -t + 2*t**2 - t**3 + +def blending_function_2(t): + return 2 - 5*t**2 + 3*t**3 + +def blending_function_3(t): + return t + 4*t**2 - 3*t**3 + +def blending_function_4(t): + return -t**2 + t**3 + +def plot_blending_functions(): + t = np.linspace(0, 1, 100) + + plt.plot(t, blending_function_1(t), label='b1') + plt.plot(t, blending_function_2(t), label='b2') + plt.plot(t, blending_function_3(t), label='b3') + plt.plot(t, blending_function_4(t), label='b4') + + plt.title("Catmull-Rom Blending Functions") + plt.xlabel("t") + plt.ylabel("Value") + plt.legend() + plt.grid(True) + plt.axhline(y=0, color='k', linestyle='--') + plt.axvline(x=0, color='k', linestyle='--') + plt.show() + +if __name__ == "__main__": + plot_blending_functions() \ No newline at end of file diff --git a/PathPlanning/Catmull_RomSplinePath/catmull_rom_spline_path.py b/PathPlanning/Catmull_RomSplinePath/catmull_rom_spline_path.py new file mode 100644 index 0000000000..79916330c9 --- /dev/null +++ b/PathPlanning/Catmull_RomSplinePath/catmull_rom_spline_path.py @@ -0,0 +1,86 @@ +""" +Path Planner with Catmull-Rom Spline +Author: Surabhi Gupta (@this_is_surabhi) +Source: http://graphics.cs.cmu.edu/nsp/course/15-462/Fall04/assts/catmullRom.pdf +""" + +import sys +import pathlib +sys.path.append(str(pathlib.Path(__file__).parent.parent.parent)) + +import numpy as np +import matplotlib.pyplot as plt + +def catmull_rom_point(t, p0, p1, p2, p3): + """ + Parameters + ---------- + t : float + Parameter value (0 <= t <= 1) (0 <= t <= 1) + p0, p1, p2, p3 : np.ndarray + Control points for the spline segment + + Returns + ------- + np.ndarray + Calculated point on the spline + """ + return 0.5 * ((2 * p1) + + (-p0 + p2) * t + + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t**2 + + (-p0 + 3 * p1 - 3 * p2 + p3) * t**3) + + +def catmull_rom_spline(control_points, num_points): + """ + Parameters + ---------- + control_points : list + List of control points + num_points : int + Number of points to generate on the spline + + Returns + ------- + tuple + x and y coordinates of the spline points + """ + t_vals = np.linspace(0, 1, num_points) + spline_points = [] + + control_points = np.array(control_points) + + for i in range(len(control_points) - 1): + if i == 0: + p1, p2, p3 = control_points[i:i+3] + p0 = p1 + elif i == len(control_points) - 2: + p0, p1, p2 = control_points[i-1:i+2] + p3 = p2 + else: + p0, p1, p2, p3 = control_points[i-1:i+3] + + for t in t_vals: + point = catmull_rom_point(t, p0, p1, p2, p3) + spline_points.append(point) + + return np.array(spline_points).T + + +def main(): + print(__file__ + " start!!") + + way_points = [[-1.0, -2.0], [1.0, -1.0], [3.0, -2.0], [4.0, -1.0], [3.0, 1.0], [1.0, 2.0], [0.0, 2.0]] + n_course_point = 100 + spline_x, spline_y = catmull_rom_spline(way_points, n_course_point) + + plt.plot(spline_x,spline_y, '-r', label="Catmull-Rom Spline Path") + plt.plot(np.array(way_points).T[0], np.array(way_points).T[1], '-og', label="Way points") + plt.title("Catmull-Rom Spline Path") + plt.grid(True) + plt.legend() + plt.axis("equal") + plt.show() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/docs/modules/path_planning/catmull_rom_spline/blending_functions.png b/docs/modules/path_planning/catmull_rom_spline/blending_functions.png new file mode 100644 index 0000000000000000000000000000000000000000..928946df46c7f14524247d675697d81e049c9a86 GIT binary patch literal 41129 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

tE>;rj18uQ$r_-%kmJ0~e2j$!iQ~wUR=gX9pvB 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 O%hb^P{1biW*nb0@J+h|& literal 0 HcmV?d00001 diff --git a/docs/modules/path_planning/catmull_rom_spline/catmull_rom_path_planning.png b/docs/modules/path_planning/catmull_rom_spline/catmull_rom_path_planning.png new file mode 100644 index 0000000000000000000000000000000000000000..1d0ff001e60bbe01787ab8f134768a6558542ad7 GIT binary patch literal 33505 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 literal 0 HcmV?d00001 diff --git a/docs/modules/path_planning/catmull_rom_spline/catmull_rom_spline_main.rst b/docs/modules/path_planning/catmull_rom_spline/catmull_rom_spline_main.rst new file mode 100644 index 0000000000..4d8d3bdefe --- /dev/null +++ b/docs/modules/path_planning/catmull_rom_spline/catmull_rom_spline_main.rst @@ -0,0 +1,103 @@ +Catmull-Rom Spline Planning +----------------- + +.. image:: catmull_rom_path_planning.png + +This is a Catmull-Rom spline path planning routine. + +If you provide waypoints, the Catmull-Rom spline generates a smooth path that always passes through the control points, +exhibits local control, and maintains 𝐶1 continuity. + + +Catmull-Rom Spline Fundamentals +~~~~~~~~~~~~~~ + +Catmull-Rom splines are a type of cubic spline that passes through a given set of points, known as control points. + +They are defined by the following equation for calculating a point on the spline: + +:math:`P(t) = 0.5 \times \left( 2P_1 + (-P_0 + P_2)t + (2P_0 - 5P_1 + 4P_2 - P_3)t^2 + (-P_0 + 3P_1 - 3P_2 + P_3)t^3 \right)` + +Where: + +* :math:`P(t)` is the point on the spline at parameter :math:`t`. +* :math:`P_0, P_1, P_2, P_3` are the control points surrounding the parameter :math:`t`. + +Types of Catmull-Rom Splines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are different types of Catmull-Rom splines based on the choice of the **tau** parameter, which influences how the curve +behaves in relation to the control points: + +1. **Uniform Catmull-Rom Spline**: + The standard implementation where the parameterization is uniform. Each segment of the spline is treated equally, + regardless of the distances between control points. + + +2. **Chordal Catmull-Rom Spline**: + This spline type takes into account the distance between control points. The parameterization is based on the actual distance + along the spline, ensuring smoother transitions. The equation can be modified to include the chord length :math:`L_i` between + points :math:`P_i` and :math:`P_{i+1}`: + + .. math:: + \tau_i = \sqrt{(x_{i+1} - x_i)^2 + (y_{i+1} - y_i)^2} + +3. **Centripetal Catmull-Rom Spline**: + This variation improves upon the chordal spline by using the square root of the distance to determine the parameterization, + which avoids oscillations and creates a more natural curve. The parameter :math:`t_i` is adjusted using the following relation: + + .. math:: + t_i = \sqrt{(x_{i+1} - x_i)^2 + (y_{i+1} - y_i)^2} + + +Blending Functions +~~~~~~~~~~~~~~~~~~ + +In Catmull-Rom spline interpolation, blending functions are used to calculate the influence of each control point on the spline at a +given parameter :math:`t`. The blending functions ensure that the spline is smooth and passes through the control points while +maintaining continuity. The four blending functions used in Catmull-Rom splines are defined as follows: + +1. **Blending Function 1**: + + .. math:: + b_1(t) = -t + 2t^2 - t^3 + +2. **Blending Function 2**: + + .. math:: + b_2(t) = 2 - 5t^2 + 3t^3 + +3. **Blending Function 3**: + + .. math:: + b_3(t) = t + 4t^2 - 3t^3 + +4. **Blending Function 4**: + + .. math:: + b_4(t) = -t^2 + t^3 + +The blending functions are combined in the spline equation to create a smooth curve that reflects the influence of each control point. + +The following figure illustrates the blending functions over the interval :math:`[0, 1]`: + +.. image:: blending_functions.png + +Catmull-Rom Spline API +~~~~~~~~~~~~~~~~~~~~~~~ + +This section provides an overview of the functions used for Catmull-Rom spline path planning. + +API +++++ + +.. autofunction:: PathPlanning.Catmull_RomSplinePath.catmull_rom_spline_path.catmull_rom_point + +.. autofunction:: PathPlanning.Catmull_RomSplinePath.catmull_rom_spline_path.catmull_rom_spline + + +References +~~~~~~~~~~ + +- `Catmull-Rom Spline - Wikipedia `__ +- `Catmull-Rom Splines `__ \ No newline at end of file diff --git a/tests/test_catmull_rom_spline.py b/tests/test_catmull_rom_spline.py new file mode 100644 index 0000000000..41a73588c3 --- /dev/null +++ b/tests/test_catmull_rom_spline.py @@ -0,0 +1,16 @@ +import conftest +from PathPlanning.Catmull_RomSplinePath.catmull_rom_spline_path import catmull_rom_spline + +def test_catmull_rom_spline(): + way_points = [[0, 0], [1, 2], [2, 0], [3, 3]] + num_points = 100 + + spline_x, spline_y = catmull_rom_spline(way_points, num_points) + + assert spline_x.size > 0, "Spline X coordinates should not be empty" + assert spline_y.size > 0, "Spline Y coordinates should not be empty" + + assert spline_x.shape == spline_y.shape, "Spline X and Y coordinates should have the same shape" + +if __name__ == '__main__': + conftest.run_this_test(__file__)