Дані вимірювання положення, як оцінити швидкість і прискорення


11

Думаю, це просто, але мій наївний підхід призвів до дуже галасливих результатів. Я маю цей зразок разів і позиції у файлі з назвою t_angle.txt:

0.768 -166.099892
0.837 -165.994148
0.898 -165.670052
0.958 -165.138245
1.025 -164.381218
1.084 -163.405838
1.144 -162.232704
1.213 -160.824051
1.268 -159.224854
1.337 -157.383270
1.398 -155.357666
1.458 -153.082809
1.524 -150.589943
1.584 -147.923012
1.644 -144.996872
1.713 -141.904221
1.768 -138.544807
1.837 -135.025749
1.896 -131.233063
1.957 -127.222366
2.024 -123.062325
2.084 -118.618355
2.144 -114.031906
2.212 -109.155006
2.271 -104.059753
2.332 -98.832321
2.399 -93.303795
2.459 -87.649956
2.520 -81.688499
2.588 -75.608597
2.643 -69.308281
2.706 -63.008308
2.774 -56.808586
2.833 -50.508270
2.894 -44.308548
2.962 -38.008575
3.021 -31.808510
3.082 -25.508537
3.151 -19.208565
3.210 -13.008499
3.269 -6.708527
3.337 -0.508461
3.397 5.791168
3.457 12.091141
3.525 18.291206
3.584 24.591179
3.645 30.791245
3.713 37.091217
3.768 43.291283
3.836 49.591255
3.896 55.891228
3.957 62.091293
4.026 68.391266
4.085 74.591331
4.146 80.891304
4.213 87.082100
4.268 92.961502
4.337 98.719368
4.397 104.172363
4.458 109.496956
4.518 114.523888
4.586 119.415550
4.647 124.088860
4.707 128.474464
4.775 132.714500
4.834 136.674385
4.894 140.481148
4.962 144.014626
5.017 147.388458
5.086 150.543938
5.146 153.436089
5.207 156.158638
5.276 158.624725
5.335 160.914001
5.394 162.984924
5.463 164.809685
5.519 166.447678

і хочете оцінити швидкість і прискорення. Я знаю, що прискорення є постійним, в цьому випадку близько 55 градусів / сек ^ 2, поки швидкість не буде приблизно 100 градусів / сек, тоді Акк дорівнює нулю, а константа швидкості. В кінці прискорення дорівнює -55 град / сек ^ 2. Ось код scilab, який дає дуже шумні та непридатні оцінки особливо прискорення.

clf()
clear
M=fscanfMat('t_angle.txt');
t=M(:,1);
len=length(t);
x=M(:,2);
dt=diff(t);
dx=diff(x);
v=dx./dt;
dv=diff(v);
a=dv./dt(1:len-2);
subplot(311), title("position"),
plot(t,x,'b');
subplot(312), title("velocity"),
plot(t(1:len-1),v,'g');
subplot(313), title("acceleration"),
plot(t(1:len-2),a,'r');

Я думав використовувати натомість фільтр кальмана, щоб отримати кращі оцінки. Чи доречно тут? Не знаєте, як сформувати рівняння філера, не дуже досвідчені з фільтрами кальмана. Я думаю, що вектор стану - це швидкість, прискорення, а сигнал - це положення. Або є більш простий метод, ніж KF, який дає корисні результати.

Всі пропозиції вітаються! введіть тут опис зображення


1
Це відповідне застосування фільтра Калмана. Стаття Вікіпедії про фільтри Кальмана має приклад, дуже схожий на ваш. Він лише оцінює положення і швидкість, але якщо ви розумієте цей приклад, його просто також можна продовжити до прискорення.
Джейсон R

1
У Scipy це може бути корисним < docs.scipy.org/doc/scipy-0.16.1/reference/generated/… >
Майк

Відповіді:


12

Одним із підходів було б поставити проблему як згладжування найменших квадратів. Ідея полягає в тому, щоб локально помістити поліном з рухомим вікном, а потім оцінити похідне від многочлена. Ця відповідь про фільтрацію Савіцкого-Голая має деяке теоретичне підґрунтя щодо того, як вона працює для неоднорідного відбору проб.

У цьому випадку код, ймовірно, є більш освітленим щодо переваг / обмежень методики. Наступний сценарій numpy обчислить швидкість і прискорення заданого позиційного сигналу на основі двох параметрів: 1) розмір вікна згладжування та 2) порядок наближення локального полінома.

# Example Usage:
# python sg.py position.dat 7 2

import math
import sys

import numpy as np
import numpy.linalg
import pylab as py

def sg_filter(x, m, k=0):
    """
    x = Vector of sample times
    m = Order of the smoothing polynomial
    k = Which derivative
    """
    mid = len(x) / 2        
    a = x - x[mid]
    expa = lambda x: map(lambda i: i**x, a)    
    A = np.r_[map(expa, range(0,m+1))].transpose()
    Ai = np.linalg.pinv(A)

    return Ai[k]

def smooth(x, y, size=5, order=2, deriv=0):

    if deriv > order:
        raise Exception, "deriv must be <= order"

    n = len(x)
    m = size

    result = np.zeros(n)

    for i in xrange(m, n-m):
        start, end = i - m, i + m + 1
        f = sg_filter(x[start:end], order, deriv)
        result[i] = np.dot(f, y[start:end])

    if deriv > 1:
        result *= math.factorial(deriv)

    return result

def plot(t, plots):
    n = len(plots)

    for i in range(0,n):
        label, data = plots[i]

        plt = py.subplot(n, 1, i+1)
        plt.tick_params(labelsize=8)
        py.grid()
        py.xlim([t[0], t[-1]])
        py.ylabel(label)

        py.plot(t, data, 'k-')

    py.xlabel("Time")

def create_figure(size, order):
    fig = py.figure(figsize=(8,6))
    nth = 'th'
    if order < 4:
        nth = ['st','nd','rd','th'][order-1]

    title = "%s point smoothing" % size
    title += ", %d%s degree polynomial" % (order, nth)

    fig.text(.5, .92, title,
             horizontalalignment='center')

def load(name):
    f = open(name)    
    dat = [map(float, x.split(' ')) for x in f]
    f.close()

    xs = [x[0] for x in dat]
    ys = [x[1] for x in dat]

    return np.array(xs), np.array(ys)

def plot_results(data, size, order):
    t, pos = load(data)
    params = (t, pos, size, order)

    plots = [
        ["Position",     pos],
        ["Velocity",     smooth(*params, deriv=1)],
        ["Acceleration", smooth(*params, deriv=2)]
    ]

    create_figure(size, order)
    plot(t, plots)

if __name__ == '__main__':
    data = sys.argv[1]
    size = int(sys.argv[2])
    order = int(sys.argv[3])

    plot_results(data, size, order)
    py.show()

Ось кілька прикладних графіків (використовуючи надані вами дані) для різних параметрів.

3-кратне згладжування, многочлен 2-го ступеня Згладжування 7pt, многочлен 2-го ступеня Згладжування 11pt, многочлен 2-го ступеня Згладжування 11pt, многочлен 4-го ступеня Згладжування 11pt, многочлен 10-го ступеня

Зауважте, як кусково-постійний характер прискорення стає менш очевидним із збільшенням розміру вікна, але їх можна певною мірою відновити, використовуючи поліноми вищого порядку. Звичайно, інші варіанти передбачають застосування першого похідного фільтра двічі (можливо, різних замовлень). Інша річ, яка має бути очевидною - це те, як цей тип фільтрації Савіцького-Голая, оскільки він використовує середину вікна, все більше і більше обрізає кінці згладжених даних із збільшенням розміру вікна. Існують різні способи вирішення цієї проблеми, але один з кращих описаний у наступній роботі:

П. А. Горрі, загальне згладжування та диференціація загальних найменших квадратів методом згортки (Савіцький-Голай), анал. Хім. 62 (1990) 570–573. ( google )

Інший документ того ж автора описує більш ефективний спосіб згладити неоднорідні дані, ніж простий метод у прикладі коду:

П. А. Горрі, загальне згладжування найменших квадратів та диференціювання даних, що не є рівномірно розташованими, методом згортки, анал. Хім. 63 (1991) 534–536. ( google )

Нарешті, ще один документ, який варто прочитати в цій галузі, - Персон і Странг :

П.П. Персон, Г. Странг, Згладжування Фільтрів Савіцького – Голая та Легенда, ком. Склад. Фінанси 13 (2003) 301–316. ( посилання в PDF )

Він містить значно більше фонової теорії та зосереджений на аналізі помилок для вибору розміру вікна.


Приємний аналіз! +1
Пітер К.

Я ціную цю відповідь!
південний захід

@Iqwest Звичайно, сподіваюся, що це допоможе!
datageist

Якщо дані розподілені рівномірно, наприклад, dt = 0,1, то відповідні функції фільтра.
lgwest

Тоді коефіцієнти фільтра будуть постійними, тому ви можете просто зателефонувати sg_filter один раз (і помножити фільтр на фактор похідної k - 2 для присвоєння). Дивіться першу частину цієї відповіді .
datageist

2

Ви повинні , ймовірно , просто робити те ж саме, що і в цьому питанні і відповідь .

Редагувати: видалено посилання на двовимірні; код фактично використовує лише одне (інше - змінна часу).

Однак, здається, що зразки вашого часу не розташовані рівномірно. Це більше питання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.