TL; DR
Очевидно, scipy
не предоставляет метод, аналогичный MATLAB spapi
, который позволяет устанавливать производные только в указанных точках c, , обеспечивая плавные переходы по всему интерполированному сплайну. Я хотел бы найти способ сделать это в Python.
В целом
Моя цель - выполнить сплайн-интерполяцию с использованием Python 3, но задавать нужные производные только в указанных c баллов. Например, скажем, массив X определяет положение объекта, точка-точка, я бы хотел, чтобы сплайн представлял допустимую траекторию, но также гарантировал, что скорость (первая производная) равна нулю как в начальной, так и в конечной точках, в других точках. не имеет ограничений на производные. В этом примере я мог бы также пожелать, чтобы ускорение (вторая производная) равнялось нулю в тех же точках.
То, что я хочу, это, другими словами, реализация сплайн-интерполяции, аналогичная MATLAB spapi
функция, на которую ссылаются здесь :
spline = spapi(knots,x,y)
возвращает сплайн f (если есть) порядка
k = length(knots) - length(x)
с узлами последовательности узлов, для которых
(*) f(x(j)) = y(:,j), all j.
Если некоторые из записей x
совпадают, то это берется в осцилляторе смысл , т. е. в том смысле, что Dm(j)f(x(j)) = y(:, j)
, с m(j) : = #{ i < j : x(i) = x(j) }
и Dmf
mth
производной f . Таким образом, r-кратное повторение сайта z
в x
соответствует заданному значению и первым r – 1
производным f при z
.
То, что я пробовал
Я знаю метод from_derivatives
класса BPoly
класса scipy.interpolate
, но это создает критическую проблему, заключающуюся в том, что, когда производные не указаны в любой точке, алгоритм не гарантирует плавного перехода, как отмечено здесь . Я также попробовал то, что было предложено здесь , но, как и ожидалось, возникает та же проблема.
Итак, затем я представлю простые репродукции того, чего я пытаюсь достичь, успешно или нет.
spapi
без производных
Здесь, например, с использованием метода spapi
, в MATLAB, без установки каких-либо производных. Не так, как я хочу, так как производные высокие в начальной и конечной точках:
xi = linspace(0, 10, 6);
xnew = linspace(0, 10, 100);
yi = [0 2 1 4 2 0];
knots = optknt(xi, order);
ref_spline = spapi(knots, xi, yi);
spline = fnval(xnew, ref_spline);
der_spline = gradient(spline);
И соответствующий график контрольных точек вместе с интерполированным сплайном: spapi">
А вот производная 1-го порядка этого сплайна:
spapi
с производными
Здесь, например, с использованием метода spapi
в MATLAB , установка производных как 0
в начальной и конечной точках. Точно ожидаемый результат, с плавными переходами по всему сплайну и производными, равными 0
в начальной и конечной точках:
xi = linspace(0, 10, 6);
xnew = linspace(0, 10, 100);
xder = [0 xi 10];
yi = [0 2 1 4 2 0];
ynew = [0 yi 0];
knots = optknt(xder, order);
ref_spline = spapi(knots, xder, ynew);
spline = fnval(xnew, ref_spline);
der_spline = gradient(spline);
И график исходных точек вместе со сплайном: spapi">
А вот производная 1-го порядка этого сплайна:
BPoly.from_derivatives
с производными
Вот пример используя BPoly.from_derivatives
, устанавливая производные как 0
в начальной и конечной точках. Неудачно, даже если производные 0
в начале и в конце, плавный переход не гарантируется вдоль сплайна:
ref_points = [0, 2, 1, 4, 2, 0]
time_vector = np.linspace(0, 10, 100)
time_points = np.linspace(0, 10, 6)
ref_complete = [[ref_points[j] if (i == 0) else 0 for i in range(2)] if (
(j == 0) or (j == len(ref_points) - 1)) else [ref_points[j]] for j in range(len(ref_points))]
ref_spline = BPoly.from_derivatives(time_points, ref_complete)
spline = ref_spline(time_vector)
der_spline = ref_spline.derivative(1)
der_y = der_spline(time_vector)
Для пояснения, строка, которая определяет ref_complete
, просто заменяет первый и последний элементы ref_points
массивом, содержащим исходное значение в индексе 0
, и 0
в индексе 1
:
>>> ref_points
[0, 2, 1, 4, 2, 0]
>>> ref_complete
[[0, 0], [2], [1], [4], [2], [0, 0]]
И график опорных точек вместе со сплайном: BPoly.from_derivatives">
А вот производная 1-го порядка этого сплайна: