2014-09-27 7 views
0

Мне нужно построить эту функцию в Matlab: Участок функции в Matlab

Линии должны быть соединены, я имею в виду в конце убывающей линии, увеличивая один должен начинаться и т.д. Это выглядит так:

enter image description here

enter image description here

Любая идея? Мне нужно это на каком-то широком интервале, например, t идет от нуля до 10

+0

Вы уверены, что ожидаемый график будет выглядеть ваш рисунок? Если функция определена только для t от 0 до 0,2, то какая она есть при t> 0,2? –

+0

@etf - Причина, по которой он не работает должным образом, заключается в том, что, поскольку вы перемещаете строки каждый раз, равный «0.1s», вы не учитываете 'y'-перехват. Я напишу ответ на этот вопрос. – rayryeng

+0

Вот мой график для 0 etf

ответ

1

Причина, по которой он не работает должным образом, потому что для каждой кривой вы рисуете между краями 0.1 секунд, y -перехват не является и поэтому кривые не располагаются в правильном месте. Для первой части вашей кривой, y = -57.5t, y -перехват находится в начале координат, поэтому ваша кривая y = -57.5t, как и ожидалось. Однако, когда вы достигнете 0.1 секунд, вам нужно решить для y -перехватить эту новую линию с новым уклоном, так как он переместился. В частности:

y = 42.5t + b 

Мы знаем, что в t = 0.1 секунды, y = -5.75 учитывая предыдущую кривую. Решение для y -intercept дает нам:

-5.75 = (42.5)(0.1) + b 
b = -10 

как таковой, между 0.1s <= t <= 0.2s, ваше уравнение линии на самом деле:

y = 42.5t - 10 

Теперь, повторяя ту же процедуру в t = 0.2s, у нас есть новый уравнение линии, даже если она имеет такой же наклон, как и происхождение:

y = -57.5t + b 

из предыдущей кривой, мы KNO w, что при t = 0.2 секундах, y = (42.5)(0.2) - 10 = -1.5. Поэтому, отсекаемый отрезок для этой новой кривой:

-1.5 = -(57.5)(0.2) + b 
b = 10 

Поэтому y = -57.5t + 10 является кривой между 0.2s <= t <= 0.3s. Если вы продолжите повторять эти вычисления, вы увидите, что следующий y -перехват - -20, затем для следующего - 20, затем следующий после -30 и так далее. Для этих вычислений вы видите красивое кратное 10 шаблонов, и вы увидите, что кривая с положительным наклоном всегда имеет отрицательный y -перехват, который кратен 10, а кривая с отрицательным наклоном имеет положительный наклон с a y -перехват, который кратен -10.

Это шаблон, который мы должны иметь в виду при построении этой кривой. Потому что, когда вы рисуете в MATLAB, мы должны начертить точки дискретно, вы хотите определить выборку , определяющую временное разрешение между каждой точкой. Поскольку это линейные кривые, вам не нужно это маленькое время выборки, но давайте сделаем для этого просто 0.01 секунд. Это означает, что мы будем иметь 10 точек между каждой новой кривой.

Таким образом, для каждых 10 пунктов в нашем графике мы будем нарисовать другую кривую с другим значением y -перехвата для каждой кривой. Поскольку вы хотите нарисовать очки между 0 до 10 секунд, это означает, что нам понадобятся (100)(10) = 1000 баллов. Однако это не включает происхождение, поэтому вам действительно нужно баллов. Таким образом, вы бы определить свой t вектор, как это:

t = linspace(0,10,1001); 

Теперь за каждые 10 очков, мы должны постоянно менять нашу y перехватывать. В первом сегменте перехват y равен 0, второй сегмент - перехват y - 10 и так далее. Теперь многие пуристы MATLAB расскажут вам, что петли for являются табу, но когда дело доходит до операций индексирования, петли for являются одними из самых быстрых по времени по сравнению с другими более векторными решениями. Например, take a look at this post, где я реализую решение с петлей for, и это был самый быстрый среди других предлагаемых решений.

Сначала давайте определим массив склонов, где каждый элемент сообщает нам наклон на сегмент. Поскольку у нас есть сегменты на 10 секунд, и каждый сегмент имеет длину 0.1 секунд, в том числе у источника 101 сегмент. В начале координат у нас есть наклон -57.5. После этого наши склоны чередуются между 42.5 и -57.5. Фактически, это чередует 50 раз. Для того, чтобы создать этот массив, мы делаем:

m = [-57.5 repmat([42.5 -57.5], 1, 50)]; 

Я использую repmat повторить [42.5 -57.5] матрицу 50 раз в общей сложности 100 раз, плюс -57.5 в нуле.

Теперь давайте определим вектор y -intercept, который сообщает нам, что перехват y находится в каждом сегменте.

y = zeros(1,101); 
y(2:2:101) = 1; 
y = 10*cumsum(y); 
y(2:2:101) = -y(2:2:101); 

Приведенный выше код будет генерировать y -intercept вектор таким образом, что она начинается в 0, то есть коэффициенты -10, 10, то -20, 20 и т.д. Трюк с этим кодом является то, что я сначала генерировать последовательность [0 1 0 1 0 1 0 1 0 1...]. После этого я использую cumsum, который выполняет кумулятивное суммирование, где для каждой точки вашего массива он добавляет значения от начала до этой точки. Поэтому, если бы мы сделали cumsum в этой двоичной последовательности, это дало бы нам [0 1 1 2 2 3 3 4 4...]. Когда мы умножим это на 10, получим [0 10 10 20 20 30 30 40 40...]. Наконец, чтобы завершить склоны, мы просто отрицаем любое четное местоположение в этом массиве, и поэтому мы наконец получаем [0 -10 10 -20 20 -30 30 -40 40...].

Теперь вот код, который мы собираемся использовать для генерации нашей кривой. Мы собираемся проходить через каждый сегмент и генерировать наши выходные значения с учетом y -intercept. Сначала нам нужно выделить выходной массив, который будет хранить наши значения, тогда мы будем заполнять значения для каждого сегмента. Нам также необходимо отслеживать, какие значения времени мы собираемся получить, чтобы вычислить наши выходные значения.

Как таковой:

%// Define time vector 
t = linspace(0,10,1001); 

%// Define slopes 
m = [-57.5 repmat([42.5 -57.5], 1, 50)]; 

%// Define y-intercepts 
y = zeros(1,101); 
y(2:2:101) = 1; 
y = 10*cumsum(y); 
y(2:2:101) = -y(2:2:101); 

%// Calculate the output curves for each segment 
out = zeros(1, numel(t)); 
for idx = 1 : numel(y)-1 
    %// Compute where in the time array and output array 
    %// we need to write to 
    vals_to_access = (idx - 1)*10 + 1 : idx*10; 

    %// Create the curve for this segment 
    out(vals_to_access) = m(idx)*t(vals_to_access) + y(idx); 
end 

%// Copy second last value over to last value 
out(end) = out(end-1); 

%// Plot the curve 
plot(t,out); 
axis tight; 

Трюк с петлей for, чтобы знать, где для доступа к значениям времени для каждого сегмента, и где писать эти ценности.Это цель vals_to_access. Также обратите внимание, что цикл for заполняет только заполненные значения в массиве от первого индекса до индекса 1000th, но не вычисляет элемент 1001th. Чтобы все было просто, мы просто скопируем элемент со второй последней точки до последней точки, поэтому out(end) = out(end-1); есть. Вышеприведенный код также будет отображать кривую и гарантирует, что оси жестко связаны. Таким образом, это то, что я получаю:

enter image description here

+1

Ничего себе! Большое спасибо!!! – etf

+0

@etf - Мое удовольствие! Это была интересная проблема для решения ... Я просто должен был дать ответ :) Удачи, и спасибо за принятие моего ответа! – rayryeng

Смежные вопросы