1

I'm trying to interpolate a set of points using the UnivariateSpline function, but I'm getting the usual big oscillations in the limits of the set, do you know any way to solve this?

My code looks like this:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

x=pd.read_csv('thrustlaw.txt')
x1=x['Time(sec)']
y1=x['Thrust(N)']

def splines(x1,y1):
    from scipy.interpolate import UnivariateSpline

    si = UnivariateSpline(x1,y1,s=0, k=3)

    xs = np.linspace(0, x1[len(x1)-1], 10000)
    ys = si(xs)

    plt.plot(x1,y1,'go')
    plt.plot(xs, ys)
    plt.ylabel("Thrust[N]")
    plt.xlabel("Time[sec]")
    plt.title("Thrust curve (splines)")
    plt.grid()
    plt.show()

splines(x1,y1)

Result:

screenshot

mkrieger1
  • 19,194
  • 5
  • 54
  • 65

1 Answers1

4

Fitting high-degree polynomials to noisy data tends to do this. An interpolation method that doesn't have this problem is the (unique) piecewise cubic polynomial that, for each pair of successive points i, i+1:

  • goes through x_i, y_i
  • goes through x_{i+1}, y_{i+1}
  • at x_i, has slope (y_{i+1} - y_{i-1}) / (x_{i+1} - x_{i-1})
  • at x_{i+1}, has slope (y_{i+2} - y_i) / (x_{i+2} - x_i)

So the tangent at each point is parallel to the straight line segment from the previous point to the next. This forces the derivative to be "somewhat similar" to the original data, so it doesn't oscillate wildly.

If I'm not mistaken, this is a Catmull-Rom spline, a particular case of a cubic Hermite spline. Maybe this question will help you implement it in scipy, or to find another interpolation method to your liking.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • (+1) yup, can DIY a CR interpolator or use already-implemented PCHIP or Akima schemes. The latter are guaranteed to be C1-smooth which may or may not be relevant depending what the curve is used for. And implementing all of these is easy now that scipy.interpolare provides tge CubicHermiteSpline class – ev-br Aug 28 '20 at 20:31