I’m experimenting with ode45 in Matlab. I’ve learned how to pass parameters to the ode function but I still have a question. Let’s suppose that I want to compute the trajectory (speed profile) of a Car and I have a function, e.g. getAcceleration, that gives me the acceleration of the car but also the right gear: [acceleration, gear] = getAcceleration(speed,modelStructure) where modelStructure represents the model of the car.
The ode function would be:
function [dy] = car(t,y,modelStructure)
dy = zeros(2,1);
dy(1) = y(2);
[dy(2),gear] = getAcceleration(y(1),modelStructure);
Then I call the Ode45 integrator in this way:
tInit = 0;
tEnd = 5,
[t,y] = ode45(@car,[tInit tEnd], [speedInitial,accelerationInitial],options,modelStructure);
The problem is: how do I get the vector storing gears? Should I have something like [t,y,gear]=ode45(....) or should gear be within the y vector?
I’ve been working on my code and using the events function I’m now able to get the car ‘gears’ changes (as events).
Now I have a new problem related to the same code.
Imagine that when I evaluate de ‘dy’ vector I’m able to get a further value Z which let me to have a massive speed up calling the acceleration computation (getAcceleration):
function [dy] = car(t,y,modelStructure)
dy = zeros(2,1);
dy(1) = y(2);
[dy(2),Z(t)] = getAcceleration(y(1),modelStructure,Z(t-1));
and suppose that I’m also able to compute Z at the initial condition. The problem is that I’m not able to compute the Z derivative.
Is there a way to pass Z value throw the stepping without integrating it?
Thanks guys.
First off: why are the initial values to the differential equation the initial speed (
speedInitial) and the initial acceleration (accelerationInitial)? That means that the differential equationcarwill be computing the acceleration (y(1)) and the jerk (y(2)), the time-derivative of the acceleration, at each timet. That seems incorrect…I would say the initial values should be the initial position (positionInitial) and the initial speed (speedInitial). But, I don’t know your model, I could be wrong.Now, getting the
gearin the solution directlty: you can’t, not without hackingode45. This is also logical; you also cannot getdyat all times directly, can you? That’s just not howode45is set up.There’s two ways out I see here:
Global variable
DISCLAIMER: don’t use this method. It’s only here to show what most people would do as a first attempt.
You can store
gearin a global variable. It’s probably the least amount of coding, but also the least convenient outcome:But, due to the nature of
ode45, this will get you an array of timestsand associatedgearwhich contains intermediate points and/or points that got rejected byode45. So, you’ll have to filter for those afterwards:I’ll say it again: this is NOT the method I’d recommend. Only use global variables when testing or doing some quick-n-dirty stuff, but always very quickly shift towards other solutions. Also, the global variables grow at each (sub-)iteration of
ode45, which is an unacceptable performance penalty.It’s better to use the next method:
Post-solve call
This is also not too hard for your case, and the way I’d recommend you to go. First, modify the differential equation as below, and solve as normal:
and then after
ode45completes, do this:That will get you all the gears the car would have at times
t.The only drawback that I can see here is that you’ll have many more function evaluations of
carthanode45would use by itself. But this is only a real problem if each evaluation ofcartakes in the order of seconds or longer, which I suspect is not the case in your setup.