TinyMPC icon indicating copy to clipboard operation
TinyMPC copied to clipboard

Why is it ineffective to impose constraints on state variables?

Open Chen-MP opened this issue 1 year ago • 6 comments

Hello, thank you very much for your open source work, which has given me a lot of inspiration. Here are some questions I would like to ask. This is the state equation and parameters of the inverted pendulum of the small car.

const double M = 0.5f; const double m = 0.5f; const double l = 0.3f; const double g = 9.81f;

double A_data[NUM_STATES * NUM_STATES] = {0, 0, 1, 0, 0, 0, 0, 1, 0, m * g / M, 0, 0, 0, (m * g + M * g) / (M * l), 0, 0}; double B_data[NUM_STATES * NUM_INPUTS] = { 0, 0, 1 / M, 1 / (M * l)};

The constraints are as follows:

StateVector xMax;
xMax << 10.0, 9.0, 8.0, 7.0;
StateVector xMin;
xMin << -3.0, -2.0, -2.1, -2.5;

InputVector uMax;
uMax << 10.0;
InputVector uMin;
uMin << -12.0;

The output result of TinyMPC is as follows:

2024-10-16 20-32-02 的屏幕截图

The output result of OSQP is as follows:

2024-10-16 20-33-23 的屏幕截图

It is evident that the input variable u can be constrained, but the state variable qDot has exceeded the lower limit of the constraint. Why is this?

Chen-MP avatar Oct 16 '24 12:10 Chen-MP

Hi, Thanks for reaching out. Have you tried to tune rho? What are your termination tolerance and maximum number of iterations? It'd be easier to check if you can upload your program.

xkhainguyen avatar Oct 18 '24 14:10 xkhainguyen

This is the code I wrote based on open source code https://github.com/Chen-MP/CopyTinyMPC.git

According to the results of the cartpole example used in open source, my code should have no errors. In addition, I have also tried adjusting the parameter rho, but I think this is actually modifying the weights.

Chen-MP avatar Oct 22 '24 02:10 Chen-MP

This is the code I wrote based on open source code https://github.com/Chen-MP/CopyTinyMPC.git

According to the results of the cartpole example used in open source, my code should have no errors. In addition, I have also tried adjusting the parameter rho, but I think this is actually modifying the weights.

I also found this problem, have you solved it?

Broad-sky avatar Nov 12 '24 09:11 Broad-sky

Hello, thank you very much for your open source work, which has given me a lot of inspiration. Here are some questions I would like to ask. This is the state equation and parameters of the inverted pendulum of the small car.

const double M = 0.5f; const double m = 0.5f; const double l = 0.3f; const double g = 9.81f;

double A_data[NUM_STATES * NUM_STATES] = {0, 0, 1, 0, 0, 0, 0, 1, 0, m * g / M, 0, 0, 0, (m * g + M * g) / (M * l), 0, 0}; double B_data[NUM_STATES * NUM_INPUTS] = { 0, 0, 1 / M, 1 / (M * l)};

The constraints are as follows:

StateVector xMax;
xMax << 10.0, 9.0, 8.0, 7.0;
StateVector xMin;
xMin << -3.0, -2.0, -2.1, -2.5;

InputVector uMax;
uMax << 10.0;
InputVector uMin;
uMin << -12.0;

The output result of TinyMPC is as follows:

2024-10-16 20-32-02 的屏幕截图

The output result of OSQP is as follows:

2024-10-16 20-33-23 的屏幕截图

It is evident that the input variable u can be constrained, but the state variable qDot has exceeded the lower limit of the constraint. Why is this?

I also found this problem, have you solved it?

Broad-sky avatar Nov 12 '24 09:11 Broad-sky

Hello, thank you very much for your open source work, which has given me a lot of inspiration. Here are some questions I would like to ask. This is the state equation and parameters of the inverted pendulum of the small car. const double M = 0.5f; const double m = 0.5f; const double l = 0.3f; const double g = 9.81f; double A_data[NUM_STATES * NUM_STATES] = {0, 0, 1, 0, 0, 0, 0, 1, 0, m * g / M, 0, 0, 0, (m * g + M * g) / (M * l), 0, 0}; double B_data[NUM_STATES * NUM_INPUTS] = { 0, 0, 1 / M, 1 / (M * l)}; The constraints are as follows:

StateVector xMax;
xMax << 10.0, 9.0, 8.0, 7.0;
StateVector xMin;
xMin << -3.0, -2.0, -2.1, -2.5;

InputVector uMax;
uMax << 10.0;
InputVector uMin;
uMin << -12.0;

The output result of TinyMPC is as follows: 2024-10-16 20-32-02 的屏幕截图 The output result of OSQP is as follows: 2024-10-16 20-33-23 的屏幕截图 It is evident that the input variable u can be constrained, but the state variable qDot has exceeded the lower limit of the constraint. Why is this?

I also found this problem, have you solved it?

Sorry, I haven't found a solution either. The following is my personal guess, there may be some errors.

图片 According to the formula, Kk is the gain of LQR, which is constant and can make the input variable u converge within the constraint range of the state variable x, which may be the variable pk. Perhaps we can multiply it by a coefficient? I haven't practiced it myself either.

In addition, in the admm.cpp code if (solver->settings->en_state_bound) { solver->work->vnew = solver->work->x_max.cwiseMin(solver->work->x_min.cwiseMax(solver->work->vnew)); } solver->solution->x = solver->work->vnew; solver->solution->u = solver->work->znew; Solver ->solution ->x has converged within the constraint range.

https://osqp.org/docs/examples/mpc.html https://robotology.github.io/osqp-eigen/md_pages_mpc.html Referring to the two examples above, both OSQP libraries are based on the ADMM algorithm and are basically in sparse form, while solving for state variables and input variables within the constraint range.

But still, I cannot guarantee that my statement is correct because I am not good at mathematics either.

Chen-MP avatar Nov 12 '24 09:11 Chen-MP

Hello, thank you very much for your open source work, which has given me a lot of inspiration. Here are some questions I would like to ask. This is the state equation and parameters of the inverted pendulum of the small car. const double M = 0.5f; const double m = 0.5f; const double l = 0.3f; const double g = 9.81f; double A_data[NUM_STATES * NUM_STATES] = {0, 0, 1, 0, 0, 0, 0, 1, 0, m * g / M, 0, 0, 0, (m * g + M * g) / (M * l), 0, 0}; double B_data[NUM_STATES * NUM_INPUTS] = { 0, 0, 1 / M, 1 / (M * l)}; The constraints are as follows:

StateVector xMax;
xMax << 10.0, 9.0, 8.0, 7.0;
StateVector xMin;
xMin << -3.0, -2.0, -2.1, -2.5;

InputVector uMax;
uMax << 10.0;
InputVector uMin;
uMin << -12.0;

The output result of TinyMPC is as follows: 2024-10-16 20-32-02 的屏幕截图 The output result of OSQP is as follows: 2024-10-16 20-33-23 的屏幕截图 It is evident that the input variable u can be constrained, but the state variable qDot has exceeded the lower limit of the constraint. Why is this?

I also found this problem, have you solved it?

Sorry, I haven't found a solution either. The following is my personal guess, there may be some errors.

图片 According to the formula, Kk is the gain of LQR, which is constant and can make the input variable u converge within the constraint range of the state variable x, which may be the variable pk. Perhaps we can multiply it by a coefficient? I haven't practiced it myself either.

In addition, in the admm.cpp code if (solver->settings->en_state_bound) { solver->work->vnew = solver->work->x_max.cwiseMin(solver->work->x_min.cwiseMax(solver->work->vnew)); } solver->solution->x = solver->work->vnew; solver->solution->u = solver->work->znew; Solver ->solution ->x has converged within the constraint range.

https://osqp.org/docs/examples/mpc.html https://robotology.github.io/osqp-eigen/md_pages_mpc.html Referring to the two examples above, both OSQP libraries are based on the ADMM algorithm and are basically in sparse form, while solving for state variables and input variables within the constraint range.

But still, I cannot guarantee that my statement is correct because I am not good at mathematics either.

Recently, I have also been looking at the formulas and derivations of the parts you marked, and I also have some doubts. In addition, did you use osqp-eigen to verify the inverted pendulum model? If so, can you post the code you wrote using osqp-eigen?

Broad-sky avatar Nov 12 '24 14:11 Broad-sky

Hi all, I think the real challenge you are having here is that you are trying to use TinyMPC for any general optimal control problem and expecting good convergence. Unfortunately, that is not going to be the case. TinyMPC is designed to be very computationally efficient (fast) and as such trades off accuracy for speed and needs to be highly tuned to ensure good convergence. In this case, my guess is that your issue is that we use a fixed rho parameter for the whole solve, while OSQP has a sophisticated mechanism to update rho to balance primal and dual convergence during solver iterations. This makes it much more accurate on general problems but would introduce significant computational complexity issues in our approach. We are currently working on some new mathematical approaches to try to find ways to efficiently update rho and hope to be able to support such features in the next few months but at this time you likely will need to highly tune such hyperparameters to get stable convergence. Hope that helps!

plancherb1 avatar Nov 19 '24 14:11 plancherb1

Hi @Broad-sky @Chen-MP we have introduced a mechanism to adapt rho. This is where you can enable/disable the setting - https://github.com/TinyMPC/TinyMPC/blob/7cecb25e450e888cbd431b446e1b14baf8c139d6/src/tinympc/tiny_api.cpp#L367.

You can try playing with this to see if that helps your problem. I am closing this issue for now, but feel free to open new ones!

ishaanamahajan avatar Jul 13 '25 17:07 ishaanamahajan