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

Feature request: off-diagonal elements for feedback controllers #128

Open
ryancoe opened this issue Sep 2, 2022 · 1 comment · May be fixed by #281
Open

Feature request: off-diagonal elements for feedback controllers #128

ryancoe opened this issue Sep 2, 2022 · 1 comment · May be fixed by #281
Assignees
Labels
enhancement New feature or request

Comments

@ryancoe
Copy link
Collaborator

ryancoe commented Sep 2, 2022

Feedback controllers for multi-DOF systems can use off diagonal elements (see, e.g., https://github.com/SNL-WaterPower/fbWecCntrl/blob/master/src/mimoPi.m). @dtgaebe is implementing this for a one-off case, but in the future we should incorporate this fully. I believe this code is fully general for creating these gain matrices with/without symmetry enforced and with/without the off-diagonal elements.

import numpy as np

n_dof = 3
n_gains = 1

def number_of_gains(n_dof, n_gains, sym=True, diag=False):
    
    if diag is True:
        mat = np.eye(n_dof) * n_gains
    else:
        if sym is True:
            mat = np.triu(n_gains * np.ones((n_dof,n_dof)))
        elif sym is False:
            mat = np.ones((n_dof,n_dof)) * n_gains
        
    print(mat)
    return int(np.sum(mat))


def make_gain_matrix(n_dof, gains=None, sym=True, diag=False):
    
    n_tot = number_of_gains(n_dof=n_dof,n_gains=1,sym=sym,diag=diag)

    if gains is None:
        gains = np.arange(n_tot)+1
    else:
        if len(gains) != n_tot:
            raise ValueError(f"Length of gains is {len(gains)}, should be {n_tot}")

    if diag is True:
        whole_sym = np.diag(gains)
    else:
        if sym is True:
            inds = np.triu_indices(n_dof)
            gain_mat = np.zeros((n_dof,n_dof))
            gain_mat[inds] = gains
            
            diag = np.diag(np.diag(gain_mat))
            upper_tri = np.triu(gain_mat,1)
            lower_tri = np.tril(np.transpose(gain_mat),-1)
            
            whole_sym = diag + upper_tri + lower_tri
        elif sym is False:
            whole_sym = np.reshape(gains,(n_dof,n_dof))
    
    return whole_sym

make_gain_matrix(n_dof=n_dof, 
                #  gains=[1,2,3,4,5,6],
                 sym=True,
                 diag=False)
@ryancoe ryancoe added the enhancement New feature or request label Sep 2, 2022
@cmichelenstrofer
Copy link
Member

This does not require any changes to the core, just an additional (or modified) example controller in the pto module.

@cmichelenstrofer cmichelenstrofer self-assigned this Oct 10, 2023
@cmichelenstrofer cmichelenstrofer linked a pull request Oct 19, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants