From 821c4ed006980bf87b179d07dfc4d9343d946064 Mon Sep 17 00:00:00 2001 From: ShisatoYano Date: Wed, 28 Aug 2024 14:57:03 +0000 Subject: [PATCH] calculate yaw angle by first derivative --- .../course/cubic_spline_course/cubic_spline.py | 10 ++++++++++ .../cubic_spline_course/cubic_spline_2d.py | 7 +++++++ .../course/cubic_spline/cubic_spline_2d_plot.py | 9 +++++++++ .../cubic_spline/cubic_spline_yaw_angle.png | Bin 0 -> 26468 bytes 4 files changed, 26 insertions(+) create mode 100644 src/simulations/course/cubic_spline/cubic_spline_yaw_angle.png diff --git a/src/components/course/cubic_spline_course/cubic_spline.py b/src/components/course/cubic_spline_course/cubic_spline.py index b634ad4..c0488bd 100644 --- a/src/components/course/cubic_spline_course/cubic_spline.py +++ b/src/components/course/cubic_spline_course/cubic_spline.py @@ -46,6 +46,16 @@ def calculate_position(self, x): return y + def calculate_first_derivative(self, x): + if x < self.x_points[0]: return None + elif x > self.x_points[-1]: return None + + i_x = self._search_segment_index(x) + dx = x - self.x_points[i_x] + dy = self.b[i_x] + 2.0 * self.c[i_x] * dx + 3.0 * self.d[i_x] * dx ** 2.0 + + return dy + def _search_segment_index(self, x): return bisect.bisect(self.x_points, x) - 1 diff --git a/src/components/course/cubic_spline_course/cubic_spline_2d.py b/src/components/course/cubic_spline_course/cubic_spline_2d.py index aef5805..02a3ced 100644 --- a/src/components/course/cubic_spline_course/cubic_spline_2d.py +++ b/src/components/course/cubic_spline_course/cubic_spline_2d.py @@ -5,6 +5,7 @@ """ import numpy as np +import math from cubic_spline import CubicSpline @@ -26,6 +27,12 @@ def calc_interpolated_xy(self, s): interpolated_y = self.sy.calculate_position(s) return interpolated_x, interpolated_y + + def calc_yaw_angle(self, s): + dx = self.sx.calculate_first_derivative(s) + dy = self.sy.calculate_first_derivative(s) + yaw_angle = math.atan2(dy, dx) + return yaw_angle def _calc_base_points(self, x_points, y_points): dx = np.diff(x_points) diff --git a/src/simulations/course/cubic_spline/cubic_spline_2d_plot.py b/src/simulations/course/cubic_spline/cubic_spline_2d_plot.py index 37def8e..3f24527 100644 --- a/src/simulations/course/cubic_spline/cubic_spline_2d_plot.py +++ b/src/simulations/course/cubic_spline/cubic_spline_2d_plot.py @@ -42,6 +42,7 @@ def main(): i_x, i_y = cs.calc_interpolated_xy(i_s) xs.append(i_x) ys.append(i_y) + yaws.append(cs.calc_yaw_angle(i_s)) plt.subplots(1) plt.plot(x_points, y_points, "xb", label="Input points") @@ -53,6 +54,14 @@ def main(): plt.legend() if show_plot: plt.savefig("cubic_spline_2d.png") + plt.subplots(1) + plt.plot(s, [np.rad2deg(yaw) for yaw in yaws], "-r", label="Yaw angle") + plt.grid(True) + plt.xlabel("Line length[m]") + plt.ylabel("Yaw angle[deg]") + plt.legend() + if show_plot: plt.savefig("cubic_spline_yaw_angle.png") + if __name__ == "__main__": main() diff --git a/src/simulations/course/cubic_spline/cubic_spline_yaw_angle.png b/src/simulations/course/cubic_spline/cubic_spline_yaw_angle.png new file mode 100644 index 0000000000000000000000000000000000000000..2dbfb6253a09253e18ed73191cef344c5fcf2d79 GIT binary patch literal 26468 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 literal 0 HcmV?d00001