-
Notifications
You must be signed in to change notification settings - Fork 411
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
Constrained MPC: Differences to MATLAB and Numeric Issues for different OS #929
Comments
Thanks for your comments! The
It's odd that the results seem to be very different from MATLAB, since they should be solving the same underlying optimization problem (though with different solvers). One thing to try might be using different solvers (using the
We have seen in some unit testing that different builds can sometimes have convergence issues (see, for example, #838, #918). These seems to come from different choices of BLAS and other routines. Can you use
I think the only way to do this right now is to explicitly create a discrete time nonlinear I/O system. If someone wanted to add a |
Thank you Professor Murray for your quick response.
I have tried all solvers available to scipy.optimize.minize on the Mac with ARM and Linux systems. Results here: Scipy_optimization_solver.zip No method produced results the same as MATLAB. Several solver types returned "Method %s cannot handle constraints.", or returned an error requiring the Jacobian function directly as an input. I am intrigued to notice that the optimization results change based on the OS/architecture, see for example 'TNC' or 'Powell' methods. This result indicates to me that the underlying optimization problem is not the same. Perhaps this difference in the underlying optimization problem comes from the use of the trapezoidal integration of the cost function over the prediction horizon in
Please see numpy.show_config() on four platforms (Windows-intel, Mac-intel, Mac-arm, Linux): numpy_configs.zip
I am concerned that scipy.optimize.minimize and numpy appear to return different numeric results depending on OS or system architecture! Additionally, for teaching purposes we intended to use JupyterLab hosted on our university's HPC. Our HPC runs openSUSE OS and has both Intel and non-Intel CPU nodes, thus making it an 'exotic' platform in the sense of #838. |
I took a look at this example. A couple of comments:
I don't have MATLAB on my computer, so I can't yet sort out why the MATLAB solution to the fixed horizon problem is (quite) different than the python-control version. Since this is a discrete time system, the trapezoidal rule is not being used (the code lines mentioned above only gets used if I'll keep looking at this, but wanted to post some initial observations. |
I did a bit more looking into this, trying to understand the difference in the results from MATLAB versus those computed using I used the following code to compute the cost of the trajectory associated with the inputs returned by MATLAB (as reported above):
This returns a cost of 569.2907752964345. The result of the same computation applied to the results from the optimal cost returned by A possibility is that MATLAB is including the terminal point of the trajectory in the cost calculation (whereas
yields
and a cost of 628.2607745091476. The MATLAB optimal trajectory with the added terminal cost gives total cost of 628.9253400095968, so still not optimal. Conclusion based on these data: MATLAB seems to be solving a different problem than @JMK593: If you have any thoughts/insights, please post here. |
Thank you @murrayrm for your continued investigation. I have done some further analysis. Second, following your most recent post I investigated the For clarity I have outlined my dynamics and finite horizon cost function here: Python_Control_Testing_Issue_929.pdf Note:
Python and updated MATLAB Code here: Code.zip In MATLAB I implemented the simplified cost function (equation (4)) using the To provide a fair comparison, I implemented this same simplified cost function in
Control Sequence: The result is almost the same as MATLAB! (Difference in cost appears to be smaller than single floating point error tolerance.) Consider a direct implementation of the cost function using the dynamics. This is implementation of equation (3).
Control Sequence: The result is almost the same sequence as above, and is almost the same as MATLAB (both sequence and cost)! Now let us try with the
Control sequence: Intriguingly, the result is now different, but is similar to the output in your recent response. As you noted the cost is also smaller than the output from MATLAB. Let us inspect whether Terminal output (state dynamics directly): terminaloutput_direct.txt Terminal output ( Confirmed it does not! Given the control sequence Now including the final state value
Control sequence: This confirms the original suspicion that the I have not found anything yet to suggest that platform (OS/CPU architecture) influenced the output from Final note, in the above I used the linear constraints computed in the form
If the constriants in |
Thanks for all of this extra information @JMK593. I think it is now clear what is going on and indeed the problem that was solved in MATLAB is different than the one solved by As with MATLAB, The optimal control computation in With the current code, if you want to get the same optimal control problem that you passed to “mpcActiveSetSolver” in MATLAB, then the function call needs to look like this:
This returns the input
which is the same one you reported above for the manually constructed optimization. However, I believe that the proper implementation of With that change (not yet implemented), then the original function call
should work just fine. Making this change in the code will cause inconsistencies for anyone relying on the current behavior for |
Thank you @murrayrm. I now see the underlying issue. I look forward to testing version 0.10.0 with the revised Regarding MATLAB's As an improvement to python-control over this misleading MATLAB usage, in the case of a discrete-time system, if given an intial condition (x_0) with associated time (t_0) and a control sequence of length N, is it necessary to also require an input of the time points? Would it not be easy to compute the output times associated with the state sequence? Then given an initial state condition and control sequence of length N, the output sequence would be the appropriate length of N+1 for that control sequence of length N. |
I played around a bit more with implementing the change I described above and decided that the way we have it is actually the most clear (and of course maintains backward compatibility). The main reason for sticking with the current implementation is that all sorts of things get complicated when you start returning inputs and states that are a different length than the list of time points that you specified (which I found out by seeing how many unit tests I started having to modify, as well as the number of examples that broke). So for now the current behavior is as follows: for a discrete time system if you give a list of time points Following that documentation (see PR #930), if you want to have the stage cost applied to all points include the last one, you should use a call of the form
To see why this makes sense, suppose represent the value of the This may all seem odd, but to me it makes more sense when you think about the fact that |
Thank you @murrayrm for considering my suggestion. I further explored the current work around for The current workaround to achieve the same cost function as a finite horizon of length N, is to add For optimal control problem
and dynamics simulated by
intriguingly the final value (N+1, the extra output from I further explored by removing the
The final value of the sequence does remain at zero but the applied control is considerably different. Finally, I created a new terminal cost with
The final value of the control sequence remains at zero as desired. The applied control action is still different. While the workaround and potential solution posed in the earlier answers is sufficient to produce the same optimization problem for the initial condition with the same optimization output, the solution does not work for subsequent state values. This includes different choices for the terminal cost. The issue remains and cannot be closed. Additionally, in my initial post, I raised a second issue where the use of
and comparing the control actions to a simulation using the optimal control problem at each time
with dynamics computing the next state at each time
By my limited understanding of the how Finally, for Linux and Mac platforms the resulting simulation is still constraint violating. In my analysis (see the above comments), when |
It will take me a while to look through all of that, but one quick comment:
This is not correct. The output of the If you want to create a system that has both the outputs from the system and the inputs from the controller, you need to use
which will have output given by [system states, control output]. (I added this functionality while debugging because having to use interconnect was a pain.) |
Thank you for the quick response. I stated incorrectly that I used the outputs from I found that the As suggested I have re-run the loop simulation using the updated functions
Please see the difference between the extracted applied control action from Computing the difference between what I assumed was the control action and the output from Also for clarity here is the difference in control action between using the loop from Updated code here: Code_V3.zip |
In the context of a masters course on constrained optimal control, we were looking to implement the classic cart-pendulum example, with a hard state constraint on the angle of the pendulum. Our implementation followed the constrained MPC aircraft model example.
During our implementation we observed that the output control sequences from the “optimal.solve_ocp” were different than from MATLAB’s “mpcActiveSetSolver” for the same model, stage cost, and prediction horizon. The following are the control sequences at time 0:
solve_ocp: 8.085e-01 1.464e-02 4.912e-01 7.621e-01 5.672e-01 5.080e-01 4.151e-01 2.398e-01 0.000e+00 0.000e+00
MATLAB: 0.8750 -0.1281 0.6964 0.7551 0.7363 0.7937 0.6934 0.6644 0.6041 0.4130
We also observed that the output from “input_output_response” simulation differed based on platform (Windows vs Linux/MacOS). On Linux/MacOS the optimiser would fail to meet the state constraints, while this behaviour does not occur on Windows.
I have included an implementation of our code in both Python and in JupyterLab, environment package lists, plots of the constrained state, and a comparison version in MATLAB: MPC_PythonControl_Analysis.zip
Are there any plans for classic MPC implementation for the cost function to directly compute the state predictions using the discrete-time linear dynamics rather than numerically computed using the trapezoid rule (line 311-322 in optimal.py)?
Are you able to provide any advice or guidance on why the numeric simulation result is different between OS versions?
The text was updated successfully, but these errors were encountered: