New mobile robot example using Python interface
changed documentation and included python header files
Version 2.3.3 (enable find_package(grampc), add interface ProblemDescription suitable for Python bindings)
Replaced memcpy by for-loop since memcpy is undefined for null pointers.
Version 2.3.2 (fix compile errors with GCC 15.2.1)
Version 2.3.1 (fix minor issues)
GRAMPC v2.3
Version 2.3 (Update of Sourceforge repository)
Dear Krysten, I would not say that the input delay is only enforced for the first N steps. If you have a time delay, then your current input does not influence the current state but instead a future state. The forward integration in GRAMPC automatically predicts what the future state after the time delay will be. However, the respective part of the control trajectory is already in the process of execution and can therefore no longer be changed. This is achieved by setting all gradients to zero in...
Dear Krysten, our preferred approach to handling a time delay is described in Section 4.2 of the paper https://www.sciencedirect.com/science/article/pii/S0957415824000552#sec4. The strategy is to set all gradients to zero for times below the delay. We have tested this experimentally with multiple systems and it generally works quite well. The post on the time delay system may be older, I think we never tried to implement this approach. Best regards, Andreas Völz
Dear Krysten, I tested with the BallOnPlate example where Nu is 1 and Nhor is 10. In mdlInitializeSizes I have /*Output ports*/ if (!ssSetNumOutputPorts(S, 9)) return; /* number of output ports */ ssSetOutputPortWidth(S, 0, Nx); /* no. of outputs at output port 0 (xnext) */ ssSetOutputPortWidth(S, 1, MAX(Nu, 1)); /* no. of outputs at output port 2 (unext) */ ssSetOutputPortWidth(S, 2, MAX(Np, 1)); /* no. of outputs at output port 3 (pnext) */ ssSetOutputPortWidth(S, 3, 1); /* no. of outputs at output...
Dear Krysten, I don't think that you need any modifications to .c- and .h-files except for grampc_run_Sfct_Cmex.c. For my tests I added the new output port in mdlInitializeSizes just like you did. Then I modified mdlOutputs with a line typeRNum *rws_u = (typeRNum *)ssGetOutputPortRealSignal(S, 7); and after the call to grampc_run I added another line MatCopy(rws_u, grampc->rws->u, grampc->opt->Nhor, grampc->param->Nu); I connected the respective signal in Simulink to a scope and what it displayed...
Dear Krysten, I am sorry, but I am not a Simulink expert. After changing the code of the S-function, I opened the Simulink model, performed "Compile the toolbox", "Compile probfct", "Init grampc" and then "Run". This lead to an error that one of the output ports is not connected and it turned out that inside the MPC-subsystem the new output port has appeared. I am not sure whether all those steps are really necessary, but it seemed that I had to run the model so that Simulink recognized that there...
Dear Krysten, I think that you should change the number 8 in the if-clause with ssSetNumOutputPorts to 9 since you added one more output port. Can you please try this? Best regards, Andreas Völz
Dear Karthik, was thinking whether the same will be applicable for a rocket example with depleting mass ?. So GRAMPC is not applicable here too ? Sorry for the confusion. If the dynamics can be formulated as ordinary differential equation or index-1 differential algebraic equation, GRAMPC should be applicable. For most systems this is probably the case. However, I can't tell for sure without more details about the actual system. Also even if we use ABA, GRAMPC software may be of less help for the...
Dear Karthik, for this paper I had reimplemented the core algorithm of GRAMPC in C++ in order to keep it as simple as possible and to tailor it to the special case of rigid body dynamics. In principle it would also be possible to implement the same algorithm within GRAMPC but it would be quite a lot of effort and I doubt that enough people would use this special variant to justify the effort. However, GRAMPC can still be used for MPC of systems with rigid body dynamics. It just requires using forward...
Dear Karthik, I guess that you can ignore the warnings. After all, this file is only relevant for the RODAS integrator and it is not very likely that you will use RODAS in an embedded MPC application. Best regards, Andreas Völz
Dear Ethan, In my model, Thor=6, Nhor=61, dt=0.02 In this case GRAMPC discretizes the horizon Thor=6 with Nhor=61 sampling points, which means they have a spacing of 6/(61-1) = 0.1, that is, grampc.rws.t is the vector [0, 0.1, 0.2, 0.3, ..., 5.7, 5.8, 5.9, 6.0] Now, it would be sufficient to pass the predicted disturbances at these 61 sampling points to GRAMPC, in which case you would need (t-t0)/0.1 to compute the index into the userparam array. On the other hand, your MPC is running with the sampling...
Dear Ethan, (1): I would expect Thor/(Nhor-1) but you have programmed it. What are the specific values of Thor, Nhor and dt in your case? The MHE example in GRAMPC chooses them in such a way that the sampling time along the prediction horizon corresponds to the sampling time of the controller. This definitely simplifies such tasks where you want to take predicted values into account. Otherwise, setting the values in userparam before calling grampc_run is just a little bit more complex. (2): You can...
Dear Karthik, since there exist so many different microcontrollers, it is impossible for us to provide examples or tutorials for each of them. The manufacturer of your controller probably provides some minimal examples for running own programs on the controller. I would take these as starting points and then integrate GRAMPC. If you need more help, then you should at least share such a minimal example. Best regards, Andreas Völz
Hi, I am a PhD student in optimization based control and would like to evaluate GRAMPC for implementing NMPC. I had setup the tool in my PC and able to run few examples. I had gone through documentation and some published papers also and tried PYGRAMPC also. I would like to know the compilation steps of GRAMPC for a RISC-V micro-controller. I understand its already implemented for dSpace, RH850 etc. Is there any tutorial for implementation on embedded controller (similar to the PC implementation...
Dear Krysten, I don't think I have ever seen the penalties explode so fast to PenaltyMax. Maybe the error is related to wrong gradients of the constraint, but this is really just a guess. I am now on vacation during the next weeks and won't have time to look into this problem. Maybe you can reduce it to a minimal working example (probfct,c, initData.m and startMPC.m) that still shows the behaviour and then share it with me? Best regards, Andreas Völz
Dear Bilal, the closest example is the double_integrator_OCP that is also described in the GRAMPC manual in Section 6.2.1. It also includes a free end time, terminal equality constraints and inequality constraints. For your use case you would have to extend it to a triple integrator and then adjust the constraints. In order to minimize with respect to time all you have to do is weight the time in the cost functional and set the option OptimTime to on. Note however that GRAMPC may not be the ideal...
Dear Carlos, in the C++ interface the problem description is implemented as a class and the userparam field is used to store the pointer to the instance of this class. See the code in grampc/cpp/src/problem_description.cpp where the actual probfct interface is implemented. Therefore, userparam is no longer available in the C++ interface. However, it is also no longer necessary since in C++ you can store data in attributes of the class and then access it from all methods. In the C variant this was...
Dear Genc, it is out of scope to explain the whole algorithm behind GRAMPC. We have done this in the journal paper in Optimization and Engineering and also in the documentation that comes along with the code. * First, all trajectories are stored in discretized manner. * Each gradient iteration performs a forward integration of the system dynamics, * then a backward integration of the adjoint dynamics (involves partial derivatives of cost and system dynamics with respect to the states x), * then an...
Dear Genc, Now, if I want to incorporate an output y = f(x, u) into my cost function in order to follow an output reference ydes, in my understanding I can define ydes with userparam. Is it possible to define the output inside the function lfct, depending on x and u? Is there anything special, besides the "normal" structure of GRAMPC I need to be aware of? The cost functions can be arbitrary nonlinear functions depending on t, x, u and p so there is nothing special to consider when using some transformed...
Dear Genc, In my understanding grampc.sol.xnext is the same as the first x in grampc.rws.x. This seems to be wrong, as it is dependent from Nhor at whch position rws.x and sol.xnext are the same. Why is that? If I set Nhor to 401, rws.x at position 101 corresponds to sol.xnext The first element in the workspace grampc.rws.x is always equal to grampc.param.x0, that is, the initial state from which the integration starts. The value of grampc.sol.xnext is an estimate of the predicted trajectory x(dt)...
Dear Krysten, thanks for sharing the minimal example. Using GRAMPC to optimize over feedback gains instead of control inputs is a quite interesting usecase that we probably have not tested so far. Our initial motivation to add the parameter optimization was rather to enable moving horizon estimation. It took me a while to debug your problem, but I think I found at least one main issue. GRAMPC passes the global time t0+t (running from t0 to t0+Thor) to ffct, dfdx_vec, dfdu_vec, dfdp_vec while it passes...
Dear Genc Yavuz, can you share the code or at least the relevant parts of it? Note that the estim_penmin function internally calls grampc_run which then calls your problem functions so it is important that the userparameters are correctly initialized before the call of estim_penmin. Maybe you extend the userparam vector after estim_penmin? In this case it could happen that your problem function reads from an invalid memory location. Best regards, Andreas Völz
Dear Krysten, it is quite difficult to help here with always only a part of the code available. If you get different results with each run, the reason is typically that you read from the wrong memory locations. This can happen in C, for example when variables are not initialized properly or when you read with pointers (or arrays) beyond your allocated memory. One option would be that you reduce your code to a minimal working example that still shows the problematic behaviour or I can try to create...
Your should add a line break to all your printf statements, so printf("%s\n",("We're now in dl/dx")). Currently you get everything in one line but I also saw "evaluateCost" which maybe your output in the lfct.
Debugging using a simpler example is always good. So what is the output of your simpler program? Does it compile? Can you see messages printed?
Dear Krysten, the code pSys[t/d_t] does not compile because t/d_t is of floating point type but array access requires integer types. With int step = t/d_t; you perform an implicit type cast from floating point to integer. Alternatively you could use pSys[(int)(t/d_t)] with an explicit type cast. In principle it is possible to use a debugger to go through the code step by step. While this is easy if you run GRAMPC as pure C code, it is more involved if you start it from Matlab and probably even more...
Dear Krysten, this definitely goes into the right direction. You should take care that if you want to cover a horizon Thor=1.0s with sampling points every 0.1s then you need Nhor=11 because the sampling time along the horizon is Thor/(Nhor-1). You should also take care that Matlab starts counting from 1 whereas C code starts counting from 0. The element pSys[13] is thus the 14th element in the Matlab vector. Your first step is 0 for t=0 and therefore your first xd is selected from pSys[13+2*0+0]...
Dear Krysten Lambeth, yes, xdes and udes have always been parameters of size Nx and Nu that were simply passed to the cost functions and their derivatives. In order to take time-varying references into account, you always had to work with userparam (or pCost in v1.0 and v1.1). However, we generally see this as advantage since one can realize arbitrary complex usecases with the userparam field. Do you need help with implementing your usecase via userparam? Best regards, Andreas Völz
Dear Krysten Lambeth, thank you for your interest in GRAMPC. You are right that xdes is assumed constant over the prediction horizon, it is just a convenience parameter for the typical setpoint stabilization tasks. Trajectory tracking should be implemented via the userparam field depending on the problem-specific representation (e.g. discrete sampling points along the horizon or a polynomial trajectory). To get started, see for example the past questions: https://sourceforge.net/p/grampc/discussion/general/thread/7add8e634f/...
Dear Marta Lom, thank you for your interest in GRAMPC. Where do you think a discrete-time problem is used internally? Of course the trajectories are discretized, but the numerical solution works by iterative forward and backward integration of the differential equations. The good news is that we have already implemented a "discrete" integrator that allows to implement discrete-time systems in the probfct. The bad news is that it is not yet public and is planned for version 2.3. Can you give some...
Dear Raahul, if it is only a MATLAB+GCC issue without relation to GRAMPC, then you better ask for help in another place. However, if it is clearly related to GRAMPC, we can of course help you here. To this end, you should describe in detail what you have done and what are the error messages that you get. Best regards, Andreas Völz
Dear Wong, as I have said, grampc_estim_penmin internally calls grampc_run which requires that the userparameters are well defined. In your case, the disturbance-related fields are only set in the Simulink model but not within initData prior to the call of grampc_estim_penmin. You should change line 98 of initData.m to something like Wf = zeros(1, user.opt.Nhor); userparam = [ pSys , pCost , boxz, Wf ] ; and then the call of [grampc, ~] = CmexFiles.grampc_estim_penmin_Cmex(grampc,1); should work...
Dear Mengke, do you use a version control system (e.g. Git)? If yes, you could check which files have been changed between now and the last time it worked. Otherwise, if it previously worked well and only failed now, I would try to delete all build-related files (i.e. clean the whole workspace) and attempt a full rebuild of all project-related files. You could also check whether you can compile GRAMPC and your probfct on its own, that is, without using Simulink. Best regards, Andreas Völz
Dear Wong, it is difficult to help with the few information available. My first guess would be that grampc_estim_penmin (typically called from initData.m) computes an invalid value for your problem (maybe inf or nan). Please remove the call of grampc_estim_penmin_Cmex in initData to check this. Note that this function internally calls grampc_run, which requires that the problem is well-defined after the initialization. If your problem relies on some user parameters that are only set in the MPC loop...
Dear Wong, the actual / true disturbance should be added to the simulation. For example, in startMPC.m when integrating the system to obtain the next state. If you can measure the current disturbance and assume that it remains constant over the prediction horizon, you can store it within the MPC loop in a userparam field and consider it in the ffct and possibly dfdx_vec, dfdu_vec. This is what you should test first. If you have a prediction model for the disturbance, meaning that you can get estimates...
Dear Haig, if "indirect function calls" also includes the usage of function pointers, then there are some spots in GRAMPC that need to be modified: - function evaluate_sys in grampc_run.c (line 595) to directly call the integrator - function evaluate_adjsys in grampc_run.c (line 625) to directly call the integrator - function evaluate_cost in grampc_run.c (line 1262) to directly call the integrator None of these is difficult to change, since the usage of function pointers is not strictly needed here....
Dear Haig, if I understand you correctly, using functions from stdlib.h, stdio.h, math.h and string.h is not a problem, because the HLS generates appropriate code, right? I have seen in your list of warnings that you have included the file problem_description.hpp from GRAMPC's C++ interface. This could be the reason for the linker error if you compile the C++ interface together with the probfct_QUADROTOR.c since then you have two implementations of the probfct interface (one in probfct_QUADROTOR.c...
Dear Haig, Sadly (unless I am missing some hidden errors), this should be the whole error message that is produced (see attachments). Maybe there is some option (like --verbose) that can be activated to get more detailed error messages? In addition the Console is issuing a lot of warnings about unused parameters in the problem_description.hpp, probfct_QUADROTOR.c. and some other files. Maybe the problem lies there? Unused parameters do not lead to linker errors, so this should not be the problem....
Dear Haig, I think that you have not posted the complete error message of the linker. A linker error typically includes something like "undefined reference to function ..." or "multiple definition of ...", where the name of the function is an important hint on how to fix the error. A common reason for such linker errors is that not all relevant source or library files are included in the linking process. Best regards, Andreas Völz
Dear Yifan Zhang, basically, you should still be able to use the Matlab/Simulink-interface of GRAMPC. However, depending on your modifications to the C-code of GRAMPC you also have to modify some parts of the mex-interface. From your error messages it appears that you have changed the interface of grampc_init, which then requires that you also change the function calls of grampc_init in all of the mex-files. If possible, I would suggest to keep the changes to the function definitions of GRAMPC as...
Dear Bin Zhong, I have tested your code and think the main problem was that your trajectory is not feasible for the system. In the attached code I have modified the desired trajectory, the initial state and removed the wrong lines in startMPC. With these changes, the first state follows the trajectory as expected. To further improve the result, the desired control value should be adapted in such a way that exact tracking has zero cost. Best regards, Andreas Völz
Dear Bin Zhong, you need to set the respective entry of userparam to the current time before the call to grampc_run, that is like grampc.userparam(11) = vec.t(i); [grampc,vec.CPUtime(i)] = CmexFiles.grampc_run_Cmex(grampc); See also https://sourceforge.net/p/grampc/discussion/general/thread/cd2e89b28f/#cf73/f55d where the same is done in C code. Best regards, Andreas Völz
Dear WenChao, yes, I meant that, use the MPC for the mechanical system and a low-level controller for the electrical subsystem. If the electrical system is fast enough and the controller well-tuned, you won't see any difference in the resulting system behaviour. Best regards, Andreas Völz
Dear WenChao, thanks for the more detailed information. Given that the electrical subsystem is typically much faster than the mechanical subsystem, you should honestly ask yourself whether it is of advantage to include the voltage-current dynamics in the MPC. You would probably have to decrease the sampling time, increase the number of discretization steps, or shorten the prediction horizon. However, if the horizon is too short, you could get problems with stabilizing the mechanical subsystem. Therefore,...
Can you maybe state the dynamical equations of the system that you want to control?
Dear WenChao, what do you mean by "the discretization of the dynamic model will fail"? Can you please explain the problem in more detail? Note that GRAMPC's integrator "ruku45" is a method with variable step size that should work for most problems. Besides, you could test "rodas", which uses a variable step size, too. However, I am not convinced that this is truly the source of your problems. If the MPC without additional integrator worked with "heun", then the MPC with additional integrator should...
Dear WenChao Xu, another idea would be to test the rate limits first for the simpler task of setpoint stabilization. That is, replace the reference trajectory with constant desired values and see whether you can tune the MPC for exponentially decreasing cost. Best regards, Andreas Völz
Dear WenChao Xu, thanks for sharing the code and the plots. I guess that you also implemented dhdx_vec and not only hfct although you didn't show it. The problem may be either an implementation error (although I saw no obvious one) or a matter of tuning, which is clearly more difficult with the additional integrator. From the plots it seems that it may be impossible for the system to follow the trajectory with these input rate limits. Since the system is too slow, it lags behind the reference, which...
Dear WenChao Xu, if you set udes to unext, the result will be a damping of the control updates. The higher the weighting, the closer the next "unext" will be to the previous "unext". However, my point was that this "unext" is the same along the whole prediction horizon, that is, for all t \in [0, Thor], the difference of u(t) to unext is weighted. This is different from weighting \dot u(t) or the discrete approximation u(t) - u(t + \delta t). Both is feasible of course and it depends on what you...
Dear WenChao Xu, if you set unext as udes, this is some kind of regularization but not a weighting of the control input rate. The typical approach would be to use the time derivative of your true input as virtual input in GRAMPC and add an integrator to the model to obtain the true input as integral of the virtual input. Then you can use umax and umin to limit the control input rate. Note however, that the constraints on the true input must then be realized as state constraint via hfct. Best regards,...
Dear WenChao Xu, I think we have no experience with this specific chip, but GRAMPC had been implemented and tested on a Renesas RH850/P1M microcontroller which seems to have similar performance (CPU frequency of 160 MHz, 2 MB program flash and 128 kB RAM), see the journal paper in Optimization&Engineering. GRAMPC does not use code generation, but is a standalone program/library written in pure C code with no external dependencies. Therefore, if you have a C compiler for this chip available, then...
Dear WenChao Xu, thanks for the positive feedback. Some more complex examples (e.g. trajectory tracking, C++ interface, ...) are still on the "to do list" for the next update of GRAMPC. Best regards, Andreas Völz
Dear WenChao Xu, looks like it is basically working. The next step would be to check the influence of different parameters (weighting factors, number of iterations, ...) on the tracking performance. Furthermore, I am not sure if your reference trajectory is feasible with respect to the system dynamics, that is, whether perfect tracking would be possible at all. Best regards, Andreas Völz
Dear WenChao Xu, your basic approach seems correct to me. However, I guess that typeRNum xref = coeff[0] * sin(t0 + t) + coeff[1] * sin(t0 + 2*t) + coeff[2]; should be changed into typeRNum xref = coeff[0] * sin(t0 + t) + coeff[1] * sin(2 * (t0 + t)) + coeff[2]; Furthermore, you need to update the global time in each MPC step, that is, the MPC loop should be modified as userparam[9] = t; grampc_run(grampc); Please try this and report on the results. Best regards, Andreas Völz
Dear WenChao Xu, the parameters xdes and udes are just offered as convenience for the frequent case of setpoints that are constant over the prediction horizon. With help of userparam, arbitrary complex scenarios can be realized on top of GRAMPC. Actually, this is described quite well in the thread that you have linked. Therefore, I would ask what have you tried and what were the results? Important to note is that the time argument in the cost functions and constraints is the internal prediction time...
Dear Marc, do you have multiple ships with differently fast dynamics in one MPC problem or do you want to tune one MPC approach for multiple ships? In the former case, one could think of a problem-specific integrator that uses a different number of integration steps for each of the ships. Regarding the latter case, note that in GRAMPC, the parameters Thor, Nhor and dt are partially independent. Thor defines the length of the prediction horizon and Nhor the number of sampling steps along this horizon....
Dear Marc, why is it not acceptable for you to increase the number of sampling points Nhor if you need smaller time steps for the integration? The computational effort and the memory of GRAMPC scale linearly with Nhor. Regarding the forward and backward integrations of the system and the adjoint system, the effort would be the same with higher Nhor or more intermediate integration steps. The only differences would be less evaluations of the constraints and the gradients w.r.t. u, p, T, which are...
Dear Ali Naderi, if I understand you correctly, you want to penalize only u(0) in the integral cost function and not u(t) for t in [0, Thor]. This is possible by adding if-statements in lfct, dldx, dldu, for example void lfct(typeRNum *out, ctypeRNum t, ctypeRNum *x, ctypeRNum *u, ctypeRNum *p, ctypeRNum *xdes, ctypeRNum *udes, typeUSERPARAM *userparam) { ctypeRNum* param = (ctypeRNum*)userparam; out[0] = (param[0] * POW2(x[0] - xdes[0]) + param[1] * POW2(x[1] - xdes[1]) / 2; if(t == 0) { out[0]...
Dear Zhidong Guo, as I have said, I don't know an approach for handling discrete-valued control variables in GRAMPC. Would it be possible to keep a continuous-valued control, but still include the effects of the PWM in the dynamics or cost function? Besides, are you sure that the "errors" are really caused by the neglected PWM in the MPC formulation? Best regards, Andreas Völz
Dear Zhidong Guo, I don't think that you can model variables with a discrete value set in GRAMPC. I would approach the problem by formulating the control as a continuous variable, which is realized via PWM when applying the MPC solution to the plant. Or is it really necessary to include the switching PWM dynamics in the MPC formulation? Best regards, Andreas Völz
Dear xiaolou, I am glad to hear that you were able to get it running as desired. If you noticed some critical steps, that could also be of help to other users of GRAMPC, feel free to share your experience. Best regards, Andreas Völz
Dear xiaolou, thank you for the update, this looks already better, but also more complicated. It seems to me that your are computing the slope h and the change of slope delt_h using numerical differentiation of the altitude a, although the altitude is given as an analytical function. Is this correct? Then, why don't you compute slope and change of slope also analytically? Let's say the position is s=x[0], and you have an altitude function a(s), where the slope is defined is h(s)=da(s) / ds and the...
Dear xiaolou, thanks for the code. First of all, the slope h is not used in the cost functions, so no predictive impact here. Then, the slope h (equal to param[14]) is used in the dynamics ffct and its derivative delt_h (equal to param[15]) is used in dfdx_vec. However, you only have one slope parameter that is used for the complete prediction horizon, i.e. it is independent of the actual position / displacement. What you need to pass in via userparam is a representation of the slope depending on...
Dear xiaolou, with this information, it is still difficult to help you. Can you share your implementation of the probfct_TEMPLATE.c, a subset of it or provide a minimal working example that reproduces the problem? Best regards, Andreas Völz
Dear xiaoloujiang, thank you for your interest in the GRAMPC toolbox. Unfortunately, your problem description is not detailed enough for targeted help. Exploiting the predictive character of MPC as you intend is definitely possible and has been demonstrated in many publications using GRAMPC. However, based on the limited information, all I can say is that you need the future values (e.g. road slope depending on position) in the problem functions (often lfct, dldx, Vfct, dVdx). Typically, userparam...
Dear Artur, can you share some insights on the tuning process, which would be of help to other GRAMPC users? For example, which settings turned out to be crucial for your problem? Which values did you finally choose for these options and which performance did you finally reach? Best regards, Andreas Völz
Dear Hoomaan, I'm sorry, but when I said "if t == 0" I did not consider that ffct, dfdx_vec, and dfdu_vec receive as argument the global time "grampc->param->t0 + t" instead of the prediction time "t" as in the other problem functions. This might be the reason why GRAMPC still updates the first element of the control vector. You could check this by not updating t0 in the S-function in line 327. Please report back if this works as intended. Best regards, Andreas Völz
Dear Artur, nice to hear that your were able to stabilize the pendulum. If the weights were given, then they are hopefully already tuned for good control performance and not just some initial guesses. Having a small sampling time for an unstable system like the double pendulum is of huge advantage, since faster feedback allows to counteract disturbances faster. If the sampling time of 0.01 s is also a requirement given to you, then I would proceed as follows: - Solve the problem with high accuracy...
Vesion 2.2 (Update of Sourceforge repository)
Dear Artur, thank you for your detailed problem description. The double pendulum is a system that is difficult to control and requires some effort in MPC tuning. I would start with a rather short horizon, for example 0.3 sec or 0.5 sec as you have done already. It suffices to simulate the system for 3 seconds. Once it works, you can simulate it for longer time intervals. I would deactivate scaling at first, set dt = 0.001 s, MaxGradIter = 10, MaxMultIter = 1, Nhor = 50. Start without state constraints,...
Dear Hoomaan, if you want to fix the first control u[0], i.e. not optimize it, then the best approach is to set the gradient dfdu_vec to zero if t==0 and manually set grampc.rws.u[0] = userparam[0] to your desired value before the call to grampc_run(...). Regards, Andreas Völz
Dear Hoomaan, what do you mean by dual variables? Are you interested in the adjoint states related to the dynamics or in the Lagrangian multipliers related to the constraints? In both cases, you have to modify grampc_run_Sfct.c. You can find the definition of the output ports in the function mdlInitializeSizes and the setting of the outputs in mdlOutputs. Regarding the second question, userparam is already passed to the S-function via a dynamically-sized input port. If you want to adjust the inital...
Dear Hoomann, I am not sure what you mean with the hardware mode of Simulink. However, your error message indicates that the S-function is not found by the linker. The solution could be to perform the same steps that are required for using the S-Function with DSpace real-time systems. This is described at the end of Section 5.2.2 of the GRAMPC documentation: "Furthermore, the S-function grampc run Sfct.c satisfies the additional restrictions of the Matlab code generator. Therefore, the block can...
Hello xiaolou, thanks for reporting that you finally came up with a solution. However, I doubt that your description is detailed enough to help other GRAMPC users who face a similar problem. I guess that it would be more helpful if GRAMPC would include some examples with more advanced usecases that new users can use as starting points. Regards, Andreas Völz
Hello xiaolou, the initData-function should be the same for startMPC and for Simulink. I thought your problem was how to update the t0-entry within userparam in each time step of the Simulink simulation. Now, I'm not an expert in Simulink, but I thought it should be possible to manipulate the userparam vector directly in Simulink using Mux, Demux, and/or Concatenate Vector blocks. Alternatively, you could write a small block that calls e.g. an m-function that updates the userparam vector. It should...
Hello xiaolou, userparam is an input to the MPC-subsystem (S-function), which allows to update the user parameters in each simulation step. The current time step t0 is generated by a clock, converted to the required data type and forwarded to the input tk of the MPC-subsystem. If t0 is the first element of your userparam vector, you can add a Vector Concatenate Block that combines t0 from the clock and userparam(2:end) and forwards this to the MPC-subsystem and the sysfct. An alternative would be...
Hello xiaolou, nice to hear that you could solve your problem. If you need further help in implementing or tuning the performance of your MPC, please ask. Kind regards, Andreas Völz
Hello xiaolou, the error in your code is that you cast userparam to a typeRNum (usually double) although it should be a pointer to typeRNum, see the code below: typeRNum* trajparam = (typeRNum*)userparam; typeRNum t0 = trajparam[0]; typeRNum* coeff = trajparam + 1; typeRNum xref = coeff[0] * (t0 + t) * (t0 + t) + coeff[1] * (t0 + t) + coeff[2]; Furthermore, in your MPC-loop (e.g. in startMPC.m) you have to update the value of userparam(1) (that is trajparam[0] in your C code) in each MPC step, e.g....
Hello xiaolou, since you have not described the problem formulation and the excepted result in detail, I can only guess. Have you considered that the variable t, that is passed to the constraint functions, is the internal prediction time of the MPC (ranging from 0 to Thor) and not the global simulation time (ranging from 0 to Tsim)? This is also described in the GRAMPC manual, see equations (3.1) and the following text on page 5. If you need the global time, you should pass grampc->param->t0 via...
Is the problem solved if you use the correct indices x[0] and x[1]? Otherwise, I need more information, e.g. the complete probfct.
Hello Vaishali, did you consider that array indices start with zero in C code? If the states x are position and velocity, then you probably want out[0] = x[1]; out[1] = -98.1 * sin(x[0]) - 0.2 * x[1] + u[0] Otherwise, what is x[0], x[1], x[2] and why is there no out[2]? Regards, Andreas
Hello Max, the lfct and the weighting_function looks good to me. That is exactly the type of curve that I had in mind. Did you also consider the derivatives of the weighting function in dldx? Furthermore, you could compare the variants with and without weighting_function for different values of the coefficient (1, 0.1, 0.01) to see if it has an effect on the solution. Regards, Andreas
Hello Gustav, the usage of the C++ interface is mostly identical to the C interface. Instead of implementing all functions in a probfct_TEMPLATE.c-file, one derives from grampc::ProblemDescription, i.e. class TemplateProblemDescription : public grampc::ProblemDescription { public: virtual void ocp_dim(typeInt *Nx, typeInt *Nu, typeInt *Np, typeInt *Ng, typeInt *Nh, typeInt *NgT, typeInt *NhT) override { *Nx = 2; *Nu = 1; *Np = 0; *Ng = 0; *Nh = 0; *NgT = 0; *NhT = 0; } // ... }; Of advantage is that...
Hello Max, if you really want to restrict the control signal to the three values -5%, 0 and 5%, you arrive at a combinatorial optimization problem, which is also known as finite control set MPC. In this case, GRAMPC would not be the preferred option, since it applies methods from continuous optimization. Nonetheless, if you set the control limits to -5% and 5% and use a low weight on the control in the cost function, the controller will probably compute control signals close to the limits instead...
Hi Simone, don't know why you have edited your last message, but I could still read the original one, since I receive them additionally as emails. If I have understood you correctly, the differences occured when you changed the sampling time of the Simulink model and used triggered function calls to keep the original sampling rate for the MPC. Now, I'm not an expert on the Simulink issues and the S-function has been programmed by one of my colleagues. However, as I have skimmed through the code of...
(1) What are your recommended best practices for running multirate simulations in which the two rates are particularly different? Actually, we do not have much experience using GRAMPC in multirate simulations. As I already said in my first short answer, one should interpolate the control trajectory if the sampling time is relatively long. Beyond that, one should validate that the MPC is well-tuned, e.g. smooth decrease of the cost function, reasonable state and control trajectories, state constraints...
Dear Simone, short answer first, longer answer will follow. GRAMPC internally uses a piecewise linear control trajectory, i.e. the control u(t) is interpolated linearly between the Nhor discretization points. However, the MATLAB template handles the control trajectory as piecewise constant, i.e. the control u(t) is held constant during the sampling interval dt. This difference has negligible effect if the sampling time dt is short compared to the prediction horizon Thor, which is the case for most...
Dear Matteo, thank you for your interest in GRAMPC. First of all, let me say that I have no experience with Xilinx Vitis platform. From a short internet search I found https://www.xilinx.com/html_docs/xilinx2020_1/vitis_doc/oyw1565072992738.html and https://www.xilinx.com/html_docs/xilinx2020_1/vitis_doc/creatinglibrar_project.html#ipa1565072992673 which describe how to build a library for Vitis. Since GRAMPC consists of pure C-code without external dependencies except the standard libraries, it...
Dear Kexianshen, from reading sections 5.1.2 and 5.1.3 in the documentation, I infer that your are using GRAMPC directly in C. In this case, note that the grampc structure only stores a pointer to userparam, which is then passed on to each of the problem functions (ffct, dfdx_vec, dfdu_vec, lfct, ...). The user is responsible for memory allocation and deallocation of whatever is behind userparam, for example an array of doubles or a struct with multiple fields. This means that you can simply modify...
Hello Leticia, I have referred to the following paragraph in Section 3.1 in the GRAMPC manual The terminal cost V as well as the integral cost l and all constraints (g, g T , h, h T ) contain an explicit time dependency with regard to the internal time t. In addition, the system dynamics (3.1b) features an explicit time dependency. Note that in the context of MPC, the initial time t 0 and initial state x 0 correspond to the sampling instant t k that is incremented by the sampling time ∆t > 0 in each...
Hello Leticia, the role of t depends on the function. Typically, it is the prediction time of the MPC with the range [0, Thor]. That is the case in the cost function, which is why you have to use (t0 + t) if the desired trajectory depends on the "global" time. The exception is the system model ffct, where t is the global time. If one needs the prediction time in the system model, one has to use (t - t0). These details are also explained in the GRAMPC documentation in the section problem formulation....
Hello Leticia, second question: the reference for the vehicle model is given in our journal paper https://link.springer.com/article/10.1007%2Fs11081-018-9417-2 as Werling M, Reinisch P, Gresser K (2012) Kombinierte Brems-Ausweich-Assistenz mittels nichtlinearer modellprädiktiver Trajektorienplanung für den aktiven Fußgängerschutz. Tagungsband des 8. Work-shop Fahrerassistenzsysteme, pp 68–77 These proceedings are available online under https://www.uni-das.de/images/pdf/fas-workshop/2012/FAS2012_Tagungsband.pdf...
Dear Sophie, thanks for reporting this issue. We are aware of this problem in the MHE example and guess that it is related to incorrect setting of the past controls in grampc.rws.u. I have attached a modified version of startMHE.m that solved the problem for one of our developers. Could you please test whether it solves the problem on your system too and report it here? Regards, Andreas Völz