文章目录
Python库中三次样条不同形式使用比较
Python库中三次样条不同形式使用比较
python">import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate as spi
from IPython import embed
data = [[0, 0],
[1, 1],
[5, 2],
[10, 3],
[20, 4],
[40, 5],
[100, 6],
[101, 7],
[101, 8],
[101, 9],
[60, 10],
[40, 11],
[-100, 12],
[40, 13],
[50, 14],
[60, 15],
[70, 16],
[80, 17],
[90, 18],
[100, 19],
[110, 20],
[100, 21],
[90, 22],
[50, 23],
[10, 24],
[0, 25]]
Y = [row[0] for row in data]
X = [row[1] for row in data]
time_list = np.arange(0, X[-1],0.001)
# 1:三次样条: 自然边界,边界点的二阶导为0
# 2:三次样条: 固定边界,边界点导数给定
# 3:三次样条: 非节点边界,使边界点的三阶导与这两边界端点的邻近点的三阶导相等
# 4:三次样条: 预测,需要 Y的第一个点和最后一个点一直,否则会报错c1_i_f = spi.CubicSpline(X, Y, bc_type= 'natural')
## 这两个结果是一样的,指定起点和终点的二阶导数为 0
# c1_i_f = spi.CubicSpline(X, Y, bc_type=((2, 0), (2, 0)))
c1_pos = c1_i_f(time_list)
c1_vel = np.dot(np.diff(c1_pos), 1000)
c1_acc = np.dot(np.diff(c1_vel), 1000)c2_i_f = spi.CubicSpline(X, Y, bc_type= 'clamped')
## 这两个结果是一样的,指定起点和终点的一阶导数为 0
# c2_i_f = spi.CubicSpline(X, Y, bc_type=((1, 0), (1, 0)))
c2_pos = c2_i_f(time_list)
c2_vel = np.dot(np.diff(c2_pos), 1000)
c2_acc = np.dot(np.diff(c2_vel), 1000)c3_i_f = spi.CubicSpline(X, Y, bc_type= 'not-a-knot')
c3_pos = c3_i_f(time_list)
c3_vel = np.dot(np.diff(c3_pos), 1000)
c3_acc = np.dot(np.diff(c3_vel), 1000)c4_i_f = spi.CubicSpline(X, Y, bc_type= 'periodic')
c4_pos = c4_i_f(time_list)
c4_vel = np.dot(np.diff(c4_pos), 1000)
c4_acc = np.dot(np.diff(c4_vel), 1000)plt.figure()
plt.plot(X, Y, 'ro', label='given pos')
plt.plot(time_list, c1_pos, label='cubic natural')
plt.plot(time_list, c2_pos, label='cubic clamped')
plt.plot(time_list, c3_pos, label='cubic not-a-knot')
plt.plot(time_list, c4_pos, label='cubic periodic')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()plt.figure()
plt.plot(time_list[:-1], c1_vel, label='cubic natural')
plt.plot(time_list[:-1], c2_vel, label='cubic clamped')
plt.plot(time_list[:-1], c3_vel, label='cubic not-a-knot')
plt.plot(time_list[:-1], c4_vel, label='cubic periodic')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()plt.figure()
plt.plot(time_list[:-2], c1_acc, label='cubic natural')
plt.plot(time_list[:-2], c2_acc, label='cubic clamped')
plt.plot(time_list[:-2], c3_acc, label='cubic not-a-knot')
plt.plot(time_list[:-2], c4_acc, label='cubic periodic')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()
位置比较示意图
速度比较示意图
加速度比较示意图
介绍如何使用三次样条的预测功能实现一个画圆的功能
python">import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate as spi
from IPython import embed
## 介绍如何使用三次样条的预测功能实现一个画圆的功能
## 为了增加轨迹精度,需要提供更多的轨迹点
theta = 2 * np.pi * np.linspace(0, 1, 5)
y = np.c_[np.cos(theta), np.sin(theta)]
cs_1 = spi.CubicSpline(theta, y, bc_type='natural')
cs_2 = spi.CubicSpline(theta, y, bc_type='clamped')
cs_3 = spi.CubicSpline(theta, y, bc_type='not-a-knot')
cs_4 = spi.CubicSpline(theta, y, bc_type='periodic')
print("ds/dx={:.1f} ds/dy={:.1f}".format(cs_4(0, 1)[0], cs_4(0, 1)[1]))
xs = 2 * np.pi * np.linspace(0, 1, 100)
fig, ax = plt.subplots(figsize=(6.5, 4))
ax.plot(y[:, 0], y[:, 1], 'o', label='data')
ax.plot(np.cos(xs), np.sin(xs), label='true')
ax.plot(cs_1(xs)[:, 0], cs_1(xs)[:, 1], label='natural')
ax.plot(cs_2(xs)[:, 0], cs_2(xs)[:, 1], label='clamped')
ax.plot(cs_3(xs)[:, 0], cs_3(xs)[:, 1], label='not-a-knot')
ax.plot(cs_4(xs)[:, 0], cs_4(xs)[:, 1], label='periodic')
ax.axes.set_aspect('equal')
ax.legend(loc='center')
plt.show()
从这个图中可以看出,只有 periodic 得出的轨迹和实际的圆轨迹比较接近,这还是在只有4个插值点的情况下。
当把插值点增加100个的时候,得到的轨迹就很接近一个圆了。
提供一阶或者二阶导致来对轨迹进行精确拟合功能
python">import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate as spi
from IPython import embed
# 拟合 y = x^3 的曲线
# x = 0, y = 0, dy = 0, ddy = 0
# x = 1, y = 1, dy = 3, ddy = 6
# bc_type 中第一个数组对应着轨迹起点的一阶导致以及对应的导数值,或者二阶导数以及对应的导数值
# bc_type 中第二个数组对应着轨迹终点的一阶导致以及对应的导数值,或者二阶导数以及对应的导数值
# bc_type=((1, 0), (1, 3)
# 表示起点的一阶导数为0, 终点的一阶导致为3
# bc_type=((2, 0), (2, 6)
# 表示起点的二阶导数为0, 终点的二阶导致为6
cs_1 = spi.CubicSpline([0, 1], [0, 1], bc_type=((1, 0), (1, 3)))
cs_2 = spi.CubicSpline([0, 1], [0, 1], bc_type=((1, 0), (2, 6)))
x = np.linspace(0, 1, 10)
np.allclose(x**3, cs_1(x))
plt.plot(x, x**3, label='true')
plt.plot(x, cs_1(x), label='cubic 1')
plt.plot(x, cs_2(x), label='cubic 2')
plt.legend(loc='center')
plt.show()
提供两个点位数据
python">import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate as spi
from IPython import embed# y = x**3 + 2 * x**2 + 3 * x + 4
cs_1= spi.CubicSpline([0, 1], [4, 10], bc_type='natural')
cs_2 = spi.CubicSpline([0, 1], [4, 10], bc_type=((1, 3), (1, 10)))
cs_3 = spi.CubicSpline([0, 1], [4, 10], bc_type=((2, 4), (2, 10)))
x = np.linspace(0, 1, 10)
np.allclose(x**3 + 2 * x**2 + 3 * x + 4, cs_1(x))
plt.plot(x, x**3 + 2 * x**2 + 3 * x + 4, label='true')
plt.plot(x, cs_1(x), label='cubic natural')
# plt.plot(x, cs_2(x), label='cubic 1')
# plt.plot(x, cs_3(x), label='cubic 2')
plt.legend(loc='center')
plt.show()plt.plot(x, x**3 + 2 * x**2 + 3 * x + 4, label='true')
# plt.plot(x, cs_1(x), label='cubic natural')
plt.plot(x, cs_2(x), label='cubic 1')
plt.plot(x, cs_3(x), label='cubic 2')
plt.legend(loc='center')
plt.show()
提供三个点位数据
python">import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate as spi
from IPython import embed# y = x**3 + 2 * x**2 + 3 * x + 4
cs_1= spi.CubicSpline([0, 1, 10], [4, 10, 1234], bc_type='natural')
cs_2 = spi.CubicSpline([0, 1, 10], [4, 10, 1234], bc_type=((1, 3), (1, 343)))
cs_3 = spi.CubicSpline([0, 1, 10], [4, 10, 1234], bc_type=((2, 4), (2, 64)))
x = np.linspace(0, 10, 20)
np.allclose(x**3 + 2 * x**2 + 3 * x + 4, cs_1(x))
plt.plot(x, x**3 + 2 * x**2 + 3 * x + 4, label='true')
plt.plot(x, cs_1(x), label='cubic natural')
# plt.plot(x, cs_2(x), label='cubic 1')
# plt.plot(x, cs_3(x), label='cubic 2')
plt.legend(loc='center')
plt.show()plt.plot(x, x**3 + 2 * x**2 + 3 * x + 4, label='true')
# plt.plot(x, cs_1(x), label='cubic natural')
plt.plot(x, cs_2(x), label='cubic 1')
plt.plot(x, cs_3(x), label='cubic 2')
plt.legend(loc='center')
plt.show()
python"># y = x**3 + 2 * x**2 + 3 * x + 4
cs_1= spi.CubicSpline(X, Y, bc_type='clamped')
cs_2 = spi.CubicSpline(X, Y, bc_type=((1, 0), (1, 0)))c1_pos= spi.CubicSpline(X, Y, bc_type='natural')
c2_pos = spi.CubicSpline(X, Y, bc_type=((2, 0), (2, 0)))c1_vel = np.dot(np.diff(c1_pos(time_list)), 1000)
c1_acc = np.dot(np.diff(c1_vel), 1000)
c2_vel = np.dot(np.diff(c2_pos(time_list)), 1000)
c2_acc = np.dot(np.diff(c2_vel), 1000)plt.figure()
plt.plot(time_list, c1_pos(time_list), label='cubic natural')
plt.plot(time_list, c2_pos(time_list), label='cubic bc type')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()plt.figure()
plt.plot(time_list[:-1], c1_vel, label='cubic natural')
plt.plot(time_list[:-1], c2_vel, label='cubic bc type')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()plt.figure()
plt.plot(time_list[:-2], c1_acc, label='cubic natural')
plt.plot(time_list[:-2], c2_acc, label='cubic bc type')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()# y = x**3 + 2 * x**2 + 3 * x + 4
c1_pos= spi.CubicSpline(X, Y, bc_type='clamped')
c2_pos = spi.CubicSpline(X, Y, bc_type=((1, 0), (1, 0)))c1_vel = np.dot(np.diff(c1_pos(time_list)), 1000)
c1_acc = np.dot(np.diff(c1_vel), 1000)
c2_vel = np.dot(np.diff(c2_pos(time_list)), 1000)
c2_acc = np.dot(np.diff(c2_vel), 1000)plt.figure()
plt.plot(time_list, c1_pos(time_list), label='cubic clamped')
plt.plot(time_list, c2_pos(time_list), label='cubic bc type')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()plt.figure()
plt.plot(time_list[:-1], c1_vel, label='cubic clamped')
plt.plot(time_list[:-1], c2_vel, label='cubic bc type')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()plt.figure()
plt.plot(time_list[:-2], c1_acc, label='cubic clamped')
plt.plot(time_list[:-2], c2_acc, label='cubic bc type')
plt.grid('on')
plt.legend(loc='upper right')
plt.xlabel('time[s]')
plt.show()