【问题标题】:Plot of function in MatlabMatlab中的函数图
【发布时间】:2014-09-27 23:44:51
【问题描述】:

我需要在 Matlab 中绘制这个函数:

线必须连接,我的意思是在减少线的末端,增加一个必须开始等。它看起来像这样:

有什么想法吗?我需要它在很宽的间隔内,例如 t 从零到 10

【问题讨论】:

  • 你确定预期的情节会像你的画吗?如果函数只为 0 到 0.2 之间的 t 定义,那么当 t > 0.2 时是什么?
  • @etf - 它不能按预期工作的原因是因为当您在 0.1s 的每个倍数处移动行时,您没有考虑到 y-intercept。我会写一个答案来说明这一点。
  • 这是我的 0
  • @etf - 没关系 :) 你只需要一点数学知识。这是一个有趣的问题,我已经提供了答案。祝你好运!

标签: matlab function graph


【解决方案1】:

它没有按预期工作的原因是因为对于您在0.1 秒的倍数之间绘制的每条曲线,y-intercept 没有被正确计算,因此曲线没有放在右边地点。对于曲线的第一部分,y = -57.5ty-intercept 位于原点,因此您的曲线是 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

从前面的曲线,我们知道在t = 0.2 秒,y = (42.5)(0.2) - 10 = -1.5。因此,这条新曲线的截距为:

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

因此,y = -57.5t + 100.2s <= t <= 0.3s 之间的曲线。如果你不断重复这些计算,你会看到下一个y-intercept 是-20,然后下一个是20,然后下一个是-30,以此类推。对于这些计算,您会看到一个很好的 10 倍数模式,并且您会看到具有正斜率的曲线始终具有负的 y-intercept,它是 10 的倍数,而具有负斜率的曲线具有正斜率,y-intercept 是-10 的倍数。

这是我们在绘制这条曲线时需要记住的模式。因为当您在 MATLAB 中绘图时,我们必须离散地绘制点,您需要定义一个 采样 时间来定义每个点之间的时间分辨率。因为这些是线性曲线,所以您不需要那么短的采样时间,但为了简单起见,我们选择0.01 秒。这意味着我们将在每条新曲线之间有 10 个点。

因此,对于绘图中的每 10 个点,我们将绘制一条不同的曲线,并为每条曲线使用不同的y-intercept。因为你想在010 秒之间画点,这意味着我们需要(100)(10) = 1000 点。但是,这不包括原点,因此您实际上需要 1001 点。因此,您可以像这样定义 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); 存在的原因。上面的代码还将绘制曲线并确保轴紧密结合。因此,这就是我得到的:

【讨论】:

  • @etf - 我的荣幸!这是一个需要解决的有趣问题......我只需要提供一个答案 :) 祝你好运,感谢您接受我的回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-06
相关资源
最近更新 更多