`ode45`和tspan错误尝试访问

时间:2015-03-24 05:36:42

标签: matlab ode

我正在使用ode45来解决二阶微分方程。时间跨度是根据txt文件中的数量确定的,因此,时间跨度定义如下

i    = 1;
t(i) = 0;
dt   = 0.1;
numel(theta_d)
while ( i < numel(theta_d) )
   i = i + 1;
   t(i) = t(i-1) + dt;
end

现在时间元素不应超过txt的大小(即numel(theta_d))。在main.m,我有

x0 = [0; 0];
options= odeset('Reltol',dt,'Stats','on');
[t, x] = ode45('ODESolver', t, x0, options);

ODESolver.m标题是

function dx = ODESolver(t, x)

如果我运行代码,我收到此错误

Attempted to access theta_d(56); index out of bounds because numel(theta_d)=55.

Error in ODESolver (line 29)
theta_dDot  = ( theta_d(i) - theta_dPrev ) / dt;

为什么ode45没有按时间跨度修复?


编辑:这是整个代码

main.m

clear all
clc

global error theta_d dt;
error = 0;


theta_d = load('trajectory.txt');




i    = 1;
t(i) = 0;
dt   = 0.1;
numel(theta_d)
while ( i < numel(theta_d) )
  i = i + 1;
  t(i) = t(i-1) + dt;
end

x0 = [pi/4; 0];
options= odeset('Reltol',dt,'Stats','on');
[t, x] = ode45(@ODESolver, t, x0, options);

 %e = x(:,1) - theta_d; % Error theta


plot(t, x(:,2), 'r', 'LineWidth', 2);
title('Tracking Problem','Interpreter','LaTex');
xlabel('time (sec)');
ylabel('$\dot{\theta}(t)$', 'Interpreter','LaTex');
grid on

ODESolver.m

function dx = ODESolver(t, x)

persistent i theta_dPrev

if isempty(i)
    i = 1;
    theta_dPrev = 0;
end

global error theta_d dt ; 

dx = zeros(2,1);

%Parameters:
m = 0.5;       % mass (Kg)
d = 0.0023e-6; % viscous friction coefficient
L = 1;         % arm length (m)
I = 1/3*m*L^2; % inertia seen at the rotation axis. (Kg.m^2)
g = 9.81;      % acceleration due to gravity m/s^2


% PID tuning
Kp = 5;
Kd = 1.9;
Ki = 0.02;

% theta_d first derivative
theta_dDot  = ( theta_d(i) - theta_dPrev ) / dt;
theta_dPrev = theta_d(i);


% u: joint torque
u = Kp*(theta_d(i) - x(1)) + Kd*( theta_dDot - x(2)) + Ki*error;
error = error + (theta_dDot - x(1));

dx(1) = x(2);
dx(2) = 1/I*(u - d*x(2) - m*g*L*sin(x(1)));

i = i + 1;
end

这是错误

Attempted to access theta_d(56); index out of bounds because numel(theta_d)=55.

Error in ODESolver (line 28)
theta_dDot  = ( theta_d(i) - theta_dPrev ) / dt;

Error in ode45 (line 261)
    f(:,2) = feval(odeFcn,t+hA(1),y+f*hB(:,1),odeArgs{:});

Error in main (line 21)
[t, x] = ode45(@ODESolver, t, x0, options);

1 个答案:

答案 0 :(得分:2)

这里的问题是因为您在离散时间点有数据,但ode45需要能够在您的时间范围内的任何时间点计算导数。解决问题后,它会将结果插回到您想要的时间点。因此,它会比您指定的时间点计算衍生品的次数多倍,因此您的i计数器根本不起作用。

由于您拥有离散数据,因此继续ode45的唯一方法是将theta_d插入任何时间t。您有一个与时间theta_d对应的值0:dt:(dt*(numel(theta_d)-1))列表,因此要插入特定时间t,请使用interp1(0:dt:(dt*(numel(theta_d)-1)),theta_d,t),然后将其转换为匿名函数在给定时间theta_p

t的插值

然后你的衍生函数看起来像

function dx = ODESolver(t, x,thetaI)

dx = zeros(2,1);

%Parameters:
m = 0.5;       % mass (Kg)
d = 0.0023e-6; % viscous friction coefficient
L = 1;         % arm length (m)
I = 1/3*m*L^2; % inertia seen at the rotation axis. (Kg.m^2)
g = 9.81;      % acceleration due to gravity m/s^2

% PID tuning
Kp = 5;
Kd = 1.9;
Ki = 0.02;

% theta_d first derivative
dt=1e-4;
theta_dDot  = (thetaI(t) - theta(I-dt)) / dt;
%// Note thetaI(t) is the interpolated theta_d values at time t

% u: joint torque
u = Kp*(thetaI(t) - x(1)) + Kd*( theta_dDot - x(2)) + Ki*error;
error = error + (theta_dDot - x(1));

dx=[x(2);  1/I*(u - d*x(2) - m*g*L*sin(x(1)))];    
end

,在使用thetaI=@(t) interp1(0:dt:(dt*(numel(theta_d)-1)),theta_d,t);致电ode45之前,您必须先定义[t, x] = ode45(@(t,x) ODESolver(t,x,thetaI, t, x0, options);

我从ODESolver中移除了一些内容,并更改了导数的计算方法。

注意我无法测试这个,但它应该让你在路上。