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

Matlab S-function freeze #29

Closed
stribor14 opened this issue Jul 30, 2019 · 5 comments
Closed

Matlab S-function freeze #29

stribor14 opened this issue Jul 30, 2019 · 5 comments

Comments

@stribor14
Copy link

Hello.

I've hit a roadblock of sorts with this library. Usecase is following, I've implemented an MPC controller as a library and tested it with an ideal plant written in C++ (no noise, ideal delay, etc), and everything works fine. But for a more real use-case, we have a Simulink model so I've written s-function level 2 wrapper for the MPC controller. Every time I run the simulation, it works fine, but for some reason, Matlab hangs at the end of the simulation (or earlier if I hit stop). No error is given and the only way to recover is to kill the Matlab process and run everything from begging.

After a few hours of trying to find the source of the problem by commenting out everything and then block by block uncommenting and testing, I've narrowed it down to two lines:

solver.updateHessianMatrix(P_);
solver.updateLinearConstraintsMatrix(A_);

If I comment out both of them, Matlab behaves normally (except, MPC is useless without them)

P.S. updating bounds does not result in freeze:

solver.updateBounds(lo_bound_, up_bound_);

P.P.S.
we have already implemented and tested similar things with osqp and Matlab, but now we wanted to use Eigen wrapper since a lot of our data is in Eigen classes

@traversaro
Copy link
Member

traversaro commented Jul 30, 2019

Hi @stribor14 ,

  • On which operating system are you experiencing this problem?
  • With which osqp/osqp-eigen/Eigen commit?
  • With which MATLAB version?

Just a curiosity: do you have a Short, Self Contained and Compilable Example for your problem that you can share?

@stribor14
Copy link
Author

  • Ubuntu 18.04.2
  • osqp is on commit 8949e67
  • osqp-eigen is on current master
  • Eigen is from 18.04.2 official repo (eigen3 v3.3.4-4)
  • Matlab R2019a

Sadly, I cannot share an example, but If I don't figure this out, I'll try to create a new one (which might also help me if I figure out how to produce this behavior)

Tomorrow I'll try running Matlab in gdb and see if there is an infinite loop occurring

@stribor14
Copy link
Author

stribor14 commented Jul 31, 2019

Hi @traversaro ,

I think I found the problem, but I would like your thoughts on it. All matrices I give to update functions are class members variables (not pointers):

solver.updateHessianMatrix(P_);
solver.updateLinearConstraintsMatrix(A_);
solver.updateBounds(lo_bound_, up_bound_);

After debugging, I noticed that Matlab hangs when trying to clean up memory, so I removed P-value delete (intentionally introduced memory leak). Now everything works as intended.

My reasoning is that when I call updateSomeMatrix(Mat), osqp-eigen or osqp takes ownership of it and frees that memory before class destructor tries to free the same memory. (#16 )

P.S. This all sounds fishy because Valgrind gives 0 errors and memory leaks with c++ plant. I only have problem with Matlab. So far experience with osqp-eigen is great and straightforward (Kudos!)

@stribor14
Copy link
Author

Problem solved :)

In MPC class constructor, I had solver initialization (it should be noted that all of the matrices are initialized but still empty at this point):

    solver.settings()->setVerbosity(false);
    solver.settings()->setWarmStart(true);
    solver.data()->setNumberOfVariables((N__ + 1) * n_x__ + N__ * n_u__);
    solver.data()->setNumberOfConstraints(2 * (N__ + 1) * n_x__ + N__ * n_u__);
    solver.data()->setHessianMatrix(P_);
    solver.data()->setGradient(q_);
    solver.data()->setLinearConstraintsMatrix(A_);
    solver.data()->setUpperBound(up_bound_);
    solver.data()->setLowerBound(lo_bound_);
    solver.initSolver();

Then, in function call to get a new solution, I recalculate new matrices and update solver with them:

solver.updateHessianMatrix(P_);
solver.updateLinearConstraintsMatrix(A_);
solver.updateBounds(lo_bound_, up_bound_);

But, when this function is called first time, sparsity pattern changes and osqp-eigen has to create new solver. On all other subsequent calls, it only updates values in osqp (since later sparsity pattern doesn't change). This works without any problem with normal C++ application.

When writing Matlab S-function, this doesn't seem to work, so I tried to avoid creating new solver because of sparsity pattern change. I removed initialization from class constructor to function call after all of the matrices are calculated:

  static bool first_pass = true;
  if (first_pass)
  {
    first_pass = false;
    solver.settings()->setVerbosity(false);
    solver.settings()->setWarmStart(true);
    solver.data()->setNumberOfVariables((N__ + 1) * n_x__ + N__ * n_u__);
    solver.data()->setNumberOfConstraints(2 * (N__ + 1) * n_x__ + N__ * n_u__);
    solver.data()->setHessianMatrix(P_);
    solver.data()->setGradient(q_);
    solver.data()->setLinearConstraintsMatrix(A_);
    solver.data()->setUpperBound(up_bound_);
    solver.data()->setLowerBound(lo_bound_);
    solver.initSolver();
  }
  else {
    solver.updateHessianMatrix(P_);
    solver.updateLinearConstraintsMatrix(A_);
    solver.updateBounds(lo_bound_, up_bound_);
  }

I doubt that Matlab should crash because of that, maybe this is only a workaround for a bug, but it works.

@traversaro
Copy link
Member

Thanks @stribor14 ! Given that you found your solution, I think we can close the issue.

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

No branches or pull requests

2 participants