How to get the solution to a GIVEN input VECTOR using ode45 solver
古いコメントを表示
Hi everyone!
I already posted my problem here, but unfortunately we did not come to a proper solution, so I've decided to reformulate my problem in an easier way, hoping it to be clear enough.
In the code below, you'll find the variable u_opt which represents the imput u of my system of equations.
u in function calc_only_f is a single scalar number, not a vector.
u_opt is a 50x1 double vector I obtained from a previous calculation as a solution of an optimal control problem (THIS INFO IS NOT RELEVANT). What I want to acheive is using u_opt as the imput of the ode45 solver and get for EACH component of this vector (50x1 i.e. for 50 different values) a 4x1 double solution as output.
After N=50 interation I would like to have a 50x4 double solution (aka trajectory) for those 50x1 double inputs of vector u_opt
As You can see below (represented by an arrow <-- in second to last line) I obtain for EACH component (i.e. value) of the input vector u_opt a 50x4 double solution. So for N=50 interations, I get 50 of these 50x4 double trajectoies, which are given as 1x50 double cell array.
Is there possibility to acheive exactly what I'm looking for, so getting a 50x4 double solution for those 50x1 double inputs? I spent a lot of hours in finding a solution, but unfortunately I'm still stuck on this problem.
........... calcf .........
% System of equations x' = f(t,x,u)
function f = calc_only_f(t,x,u,param)
% Parameter of the systems given as a struct
M = param.M;
g = param.g;
L = param.L;
m = param.m;
d = param.d;
Sx = sin(x(3)); % sin(x)
Cx = cos(x(3)); % cos(x)
N = M + m*(1-Cx^2); % denominator
K = N*L; % L*(M + m*(1-Cx^2))
f = [x(2); (1/N)*(-m*g*Cx*Sx + m*L*x(4)^2*Sx - d*x(2)+ u); x(4); (1/(N*L))*((m+M)*g*Sx -Cx*(m*L*x(4)^2*Sx - d*x(2)) - Cx*u)];
end
% +++++++++++++++++++++++++++++++++++++++++++++++++++
% -------------------- MAIN -------------------------
% +++++++++++++++++++++++++++++++++++++++++++++++++++
N=50; sizeu=1; tf= 5;
u_opt = rand(N*sizeu,1,'double'); % only for the implementation ... dimension of u_opt should be a 50x1 double
x0 = [0;0;pi;0]; % start point 4x1 double ... x0_1 position x0_2 velocity x0_3 angle x0_4 angular velocity
param.m = 1.5;
param.M = 27;
param.L = 2;
param.g = -9.80665;
param.d = 1.2;
param.N = 50;
param.timePart = linspace(t0,tf,N);
tspan = param.timePart;
for k = 1:numel(u_opt)
[t_ode{k},x_ode{k}] = ode45(@(t,x)calc_only_f(t,x,u_opt(k),param),tspan,x0); % <-- I get a 1x50 double cell array
end
I appreciate any help!
Cheers !
6 件のコメント
J. Alex Lee
2020 年 7 月 31 日
It is clearer than in your last question that you expect "a 4x1 double solution as output" of ode45 for any given value of u in u_opt. But it's still (maybe more so) unclear what you really want. Are you looking for just the terminal value of each variable, at time = tf?
By the way it doesn't help you that you happen to have 50 time steps and also u_opt happens to be 50.
J. Alex Lee
2020 年 7 月 31 日
As far as I understand, it's a non-starter as soon as you assert you want ode45 to return a [4x1] matrix upon giving it a 1x50 sized time (domain) vector.
ode45 has to return something at least 2 elements long and M-elements tall, where M is the number of equations you specify in your odefun (or the transpose, i'm continually confused about how matlab likes to return columns and rows).
If you can revise this part, maybe the community can invest a bit more in understanding what you actaully want (which I am afraid I still cannot grasp).
Ivan
2020 年 8 月 1 日
J. Alex Lee
2020 年 8 月 1 日
Your original post:
"What I want to acheive is using u_opt as the imput of the ode45 solver and get for EACH component of this vector (50x1 i.e. for 50 different values) a 4x1 double solution as output."
It sounds to me that you do want each of 50 calls to ode45 (using a single value of u drawn from some vector, which in your words are irrelevant details to the problem) to produce a 4x1 solution. It's going to give you solutions at all the time steps you requested in tSpan, which in this case is 50 long. Do you want to choose some specific time step to pick out of the 4x50 solution that it will give you, as you hinted above with t_c? Which one? What does it mean to let ode45 "choose"?
Ivan
2020 年 8 月 2 日
回答 (1 件)
J. Alex Lee
2020 年 8 月 2 日
If you're just looking for code to extract some element out of your ode45 solution:
tAll = nan(1,length(u_opt));
xAll = nan(4,length(u_opt));
idx = 50; % or whatever index of tspan you want
for k = 1:numel(u_opt)
[t,x] = ode45(@(t,x)calc_only_f(t,x,u_opt(k),param),tspan,x0);
tAll(k) = t(idx);
xAll(:,k) = x(:,idx);
end
and just change idx to whatever you want. If you want t_c to be "half of tspan", and you have defined tspan with linspace, then let idx=25, for example.
5 件のコメント
Walter Roberson
2020 年 8 月 3 日
x(idx, :)
J. Alex Lee
2020 年 8 月 3 日
編集済み: J. Alex Lee
2020 年 8 月 3 日
I mistakenly thought ode45 returns rows rather than columns (I think because I've started using the struct output, and therein the solutions are returned as rows...thanks TMW for making things easy). Your transposition and Walter's fix partially makes sense, I guess you want
xAll(k,:) = x(idx,:)
By the way, my case-in-point about the confusion of the equality of lengths of your time vector and u_opt vector is evident here...there is no reason to want (and I think you have admitted as much) idx==k.
Ivan
2020 年 8 月 3 日
J. Alex Lee
2020 年 8 月 3 日
Ok, glad it gets you closer to what you want.
But for would-be consumers of this "solution", be warned that in my understanding this was essentially a long protracted discussion about how to extract elements from a matrix, so that is all this answer purports to provide.
カテゴリ
ヘルプ センター および File Exchange で App Building についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!