Menu

Is there a way to enforce bang-bang behavior?

2021-03-08
2021-03-16
  • Max Herrmann

    Max Herrmann - 2021-03-08

    I’m trying to implement a model-predictive controller for a system in the lower input signal range [0..5%].

    Since the dead-band is [0..1%], I’m looking for a way to parameterize the controller s.t. control actions are always larger than 1%.

    If there is a way to enforce bang-bang behavior, i.e. having the input signal switch between -5%, 0, and 5%, this would be the preferred option.

    Thanks a lot!

    Max

     
  • Andreas Völz

    Andreas Völz - 2021-03-08

    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 of close to 0. Furthermore, you could design a nonlinear cost function that penalizes control signals between zero and 1%. Maybe something involving the second derivative of exp(-x^2).

    Regards,
    Andreas

     
    👍
    1
  • Max Herrmann

    Max Herrmann - 2021-03-08

    Hello Andreas,

    thanks a lot for your quick reply, and the promising hints!

    I will definitely give it a try with GRAMPC, using your proposed methods, and I will post the results in this thread. While I think that finite control set MPC tends towards over-engineering the system we are currently dealing with, it sounds like an interesting research area in its own right. Is there a must-read on it?

    Max

     
  • Max Herrmann

    Max Herrmann - 2021-03-15

    I implemented it this way in lfct():

    out[0] = (xdes[0] - x[0]) * (xdes[0] - x[0]) + 0.01 * weighting_function(u[0]);

    where weighting function() is a function based on the second derivative of exp(-x^2). It puts a penalty on input values which are not |4|:

    typeRNum weighting_function (typeRNum x) {
    
        typeRNum xm, ym, xs;
    
        xm = sqrt(3/2);
        ym = 4*exp(-3/2);
        xs = x*xm/4;
    
        return -(-2*exp(-(xs * xs))+4*(xs * xs)*exp(-(xs * xs)) - ym);
    
    }
    

    Honestly, I don't know if the weighting function has much of an effect. While the weighting function's coefficient 0.01 definitely has.

     
  • Andreas Völz

    Andreas Völz - 2021-03-16

    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

     
  • Max Herrmann

    Max Herrmann - 2021-03-16

    I didn't consider the derivatives of the weighting function in dldx, since the weighting function exclusively depends on the input u. But I put its derivative into dldu:

    typeRNum weighting_function_derived_with_respect_to_u(typeRNum u) {
    
        typeRNum um, us;
    
        um = sqrt(3/2);
        us = u*um/4;
    
        return -12*us*exp(-(us * us))+8*(us * us * us)*exp(-(us * us));
    
    }
    

    I tried different values for the weighting function's coefficient. For my purposes, 0.001 turned out to be the degree of aggression that I needed.

    While the closed loop is now eventually stable, the performance of the controlled system is still not good. But for the time being, I blame it on model deficiencies.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.