Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Archived knowledge] Is your Simulink controller running real time? #67

Closed
gabrielenava opened this issue Jul 8, 2019 · 4 comments
Closed
Assignees

Comments

@gabrielenava
Copy link
Collaborator

gabrielenava commented Jul 8, 2019

I am having a lot of interesting discussions here in LAAS with Simulink users about Simulink real-time performances. Here it is what I understood so far, I hope it will be useful for finally clarify some open questions we had also at IIT.

1) I am using the yarp real time synchronizer. Is my Simulink controller running real time?

It means that most of the time your Simulink controller will conclude each iteration, i.e. it will read input measurements and it will provide an output, around the specified user-defined fixed time step.

If you require Simulink to run at 0.01 [s], this means that every iteration will actually last more or less 0.01 [s], as there may be some jittering (i.e., one step may be 0.011 [s] and the next may be 0.0099 [s]), but this is physiological and in general is not a big issue.

HOWEVER, yarp DOES NOT HAVE "sudo" powers on Simulink processes, this means that if Simulink has something important to do during the current iteration that takes more than the time step you specified (e.g. update the Simulink GUI), it will do it regardless the request of the synchronizer. What is the result?, well, from the Simulink point of view, nothing actually happened! Every time step lasts as the user requested. But from the real time point of view, that from now on we can assume is the time provided by Yarp, there is one Simulink iteration that lasted much more than the required time step! In this plot we see what I mean:

44842049-1e8bcf00-ac45-11e8-80fe-71a31f40bb65

It is clear from the figure above that at a certain point there is a Simulink iteration that took much longer than 0.01 [s], but Simulink did not note it. However, the longer iteration is visible when looking at the Yarp time.

2) Ok, but does this problem affects the performances of my controller?

I think the correct answer is: IT DEPENDS. Assume for example we want to implement a simple joints velocity controller for set point control on iCub on the pole. Then, our Simulink model will contain the following elements:

  • A block for retrieving the iCub joints positions at the current time step;

  • The desired, constant joints position references (it is a set point control);

  • A simple control law of the form: qDot = -KP(q-qDes); Then, qDot is the Simulink output at the current time step.

Such Simulink controller uses only information related to the CURRENT time step. The effect of the delay in this controller is that while the control loop should run at a constant frequency of, let's say, 100 Hz, actually the controller sometimes provides references at a lower frequency. BUT THE REFERENCE PROVIDED BY THE CONTROLLER IS CORRECT! Just, Simulink thinks to be at a different time instant! But inside my simple Simulink controller only the current time instant is used, so who cares. For example, let's assume I am expecting Simulink to run at 100 Hz but it actually always run at 50 Hz. Then, internally the controller "thinks" to run at 100 Hz, but it takes measurements and provide references to the robot at 50 Hz. But this does not mean necessarily that the controller is not working properly! It depends on the system to which I am applying it. Does the system have a really fast dynamics? then maybe 50 Hz are not sufficient for stabilizing it. If the system has instead a slow dynamics, maybe a controller that runs at 50 Hz will work perfectly. Really, it depends on the application. Off course it is not really nice to have a controller that runs at 50 Hz while expecting it to run at a much higher frequency. But nothing is wrong in the control input you are providing to the system.

BUT PAY ATTENTION! This is true for a controller that uses only the current time step for doing all the operations. Unfortunately, this only seldom happens!!! Does your Simulink model contain one of this blocks?

Screenshot from 2019-07-08 23-42-15

Or maybe you implemented something similar to this inside some Matlab user-defined function:

persistent time;

...my fancy code where I use time ...

time = time + timeStep;

In these cases, not only the controller is sometimes running at a frequency different than the expected one, but it is most likely also doing wrong calculations when the iteration with delay occurs. Let's do an example. Let's assume we are given with the simple velocity controller implemented before, and that we want to add an integral feedback of the form: -KI int(q-qDes). To calculate the integral of q, intq, we apply Euler forward integration as follows:

persistent intq_previous

intq = intq_previous + timeStep*q

% update intq at previous step
intq_previous = intq;

Then, I guess that after the long discussion I did you can easily spot what is wrong here: the variable "timeStep" from Simulink is constant (assume 0.01 [s]), but the measured q during the iteration with delays actually is the "q" happening after a much longer time step than 0.01 [s], therefore this integrator is doing something wrong when the delay occurs.

3) Isn't the synchronizer doing something for this?

yes, it is worsening the issue! As far as I know there are to possible actions of the synchronizer when a delay occurs: catchup delay and skip delay. Yarp synchronizer only implements the catchup delay solution, but GenoM pacer instead allows the user to choose among the two. I think the behaviors of the synchronizer can be clearly understood looking at these two pictures:

catchup delay

44842049-1e8bcf00-ac45-11e8-80fe-71a31f40bb65

skip delay

Screenshot from 2019-07-08 23-56-31

In catchup delay mode, the synchronizer will shorten the Simulink iterations right after the delay: they will last less than the user defined time step. This means that your simple integrator
will provide wrong measurements not only for the iteration at which the delay occurred, but also for some next iteartions. In skip delay mode, the synchonizer will continue as if nothing actually happened after the iteration with delay. By doing so, only that iteration will provide wrong estimations, but Simulink time and real time will diverge!. So if for example you are using the Simulink clock block something wrong may happen after you run your controller for a while.

4) But I saw iCub performing the fast Yoga demo! How is it possible?

I think in the end the Yoga demo uses very few information that do not depend only on the current time step, and not for crucial operations. Also, the wrong steps induced by the catchup with delay mode are not many, and maybe they just act as a disturbance on the controller w.r.t which the controller is actually robust enough. Or maybe we were just lucky.

5) So I am doomed. What can I do?

In general, it may be better if you instead of using the Simulink time you take the Yarp time from the proper WBToolbox block:

Screenshot from 2019-07-08 23-58-37

and use it for any operation involving more than the current time step. This also means that you should implement e.g. your own Euler integrator rather than using the Simulink one.

Also, USE THE STATIC GUI! it is composed of two elements (https://github.com/robotology/whole-body-controllers/blob/master/library/matlab-gui/simulinkStaticGUI.fig, https://github.com/robotology/whole-body-controllers/blob/master/library/matlab-gui/simulinkStaticGUI.m), that you just have to copy-paste inside a path visible when running your controller. It requires literally 3 configuration functions (https://github.com/robotology/whole-body-controllers/blob/master/controllers/floating-base-balancing-torque-control/startModelWithStaticGui.m, https://github.com/robotology/whole-body-controllers/blob/master/controllers/floating-base-balancing-torque-control/src-static-gui/closeModel.m, https://github.com/robotology/whole-body-controllers/blob/master/controllers/floating-base-balancing-torque-control/src-static-gui/compileModel.m) that can be easily adapted to any controller, and if you want to do things really in a proper way you may have a look at the callbacks in the Yoga controller. It has been verified that at least for the iCub use case the static GUI solved the Simulink delay problem.

6) But my controller is working already, I will not spend time on this.

As you wish, but did it ever happened to you to say something like:

It seems its working more or less, but there are some tracking issues that I don't really understand?

Then, this may be one of the reasons.

@gabrielenava
Copy link
Collaborator Author

gabrielenava commented Jul 8, 2019

cc Simulink users @Yeshasvitvs @diegoferigo @lrapetti @Giulero @VenusPasandi I just wrote this to organize a bit the idea as I am now working with Simulink on a system with much more time precision required than iCub. If you have time and patience for reading it it may be useful for you also :-)

@VenusPasandi
Copy link

@gabrielenava it is a really nice report! ❤️

I am a bit in doubt about the synchronizer! As I checked here, when the Simulink is slower than the real time, the synchronizer does nothing! Actually, the synchronizer works for the cases that the Simulink is so fast! Am I right?

@gabrielenava
Copy link
Collaborator Author

gabrielenava commented Jul 9, 2019

I am a bit in doubt about the synchronizer! As I checked here, when the Simulink is slower than the real time, the synchronizer does nothing! Actually, the synchronizer works for the cases that the Simulink is so fast! Am I right?

Yes exactly, this is what I meant saying that the Synchronizer has "no sudo powers" over Simulink: the synchronizer works under the assumption that Simulink is able to perform all the calculations faster that the user-defined time step. If Simulink actually at some iteration takes longer, there will be a delay.

Note that the synchronizer in catchup delay mode is not forcing Simulink to run faster than the user defined time step: this functionality only works because your specific Simulink model naturally takes less at concluding one iteration than the time step you specified, and the synchronizer simply asks Simulink to perform shorter steps in order to catch up with yarp time. But if you have a Simulink model that at every "normal" iteration naturally takes exactly your time step to perform all the calculations, there will be totally no differences between the Synchronizer in catchup delay and the synchronizer in skip delay mode: they will both behave as the skip delay one.

@traversaro
Copy link
Member

traversaro commented Jul 29, 2019

It may be worth to also add a link to this relevant issue: robotology/wb-toolbox#160 (in this way this issue is also linked back there).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants