Matlab `ode45`和tspan错误试图访问

Matlab `ode45`和tspan错误试图访问,matlab,ode,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 并且ODESolver.m头是 function dx = ODESolver(t, x) 如果我运行代码,我会得到这个错误 Attempted to acc

我用
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
并且
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
这就是错误所在

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);

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

由于您有离散数据,继续执行
ode45
的唯一方法是将
theta\u d
插值到任何时间
t
。您有一个与时间
0:dt:(dt*(numel(theta\ud)-1))
对应的值列表
theta\ud
,因此要插值到特定时间
t
,请使用
interp1(0:dt:(dt*(numel(theta\ud)-1)),theta\ud,t)
,我把它转换成一个匿名函数,给出给定时间
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中删除了一些内容,并更改了导数的计算方式


注意:我不能测试这个,但它应该会让你上路。

什么是
theta\u d
?值的向量?尝试
t=0:st:numel(theta\u d)
而不是
while
循环。@David,是的,它是值的向量。
t=0:st:numel(theta\u d)
不正确。它将创建比
txt
大小更多的样本。您可以将
theta\u d
生成为
theta\u d=rand(5,1)
是的,抱歉,请尝试以下操作:
0:dt:(dt*(numel(theta\u d)-1))
这解决了您的问题吗?还是集成仍然会带来麻烦?您提供了一条错误消息,但您提供的代码中没有一行会产生错误(错误消息提供了有用的信息)。此外,除非您使用的是10年前的Matlab版本,否则应使用匿名函数指定积分函数:`ode45(@ODESolver,t,x0,options);`。
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);
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