Skip to content
Snippets Groups Projects
control.py 4.62 KiB
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 04 09:24:51 2016

@author: tlbl
"""


import numpy as np


class Control(object):

    def torque_controller_tuning(self, r0, lambda_opt, ksi_pole_part,
                                 omega_pole_part, j_dt):
        """THIS IS A WIP
        """

        # TODO: THIS IS STILL A WIP

        i12, i23, i34 = self.select_regions()

        # Compute K factor for optimal CP tracking in region 1 as
        # K=0.5*rho*A*Cp_opt*R^3/lambda_opt^3

        # HAWCStab2/Computation_LIB/compute_controller_input_mod.f90:83-88

        # Compute K factor for optimal CP tracking in region 1 as
        # K=0.5*rho*A*Cp_opt*R^3/lambda_opt^3
        # pi_torque_controller%kfactor=0.d0
        # do i=1,iregion2-iregion1-1
        # !kfactor=kfactor+0.85d0*kfactor_fit(i)*substructure(3)
        #   pi_torque_controller%kfactor
        #   = pi_torque_controller%kfactor
        #   + kfactor_fit(i)*substructure(3)%opstate(i+iregion1)%r0**3/lambda_opt**3
        # enddo

        # HAWCStab2/Computation_LIB/compute_controller_input_mod.f90:89
        # pi_torque_controller%kfactor =
        #   pi_torque_controller%kfactor/max(dfloat(iregion2-iregion1-1), 1.d0)

        Qg = (r0*r0*r0)/(lambda_opt*lambda_opt*lambda_opt)

        # PI generator torque controller in region 2 (constant speed, variable power)
        # HAWCStab2/Computation_LIB/compute_controller_input_mod.f90:104-105
        # pi_torque_controller%kp = 2.d0*ksi_pole_part*omega_pole_part*j_dt
        # pi_torque_controller%ki = omega_pole_part**2*j_dt
        pgTorque = 2.0*ksi_pole_part*omega_pole_part*j_dt
        igTorque = omega_pole_part**2*j_dt

        return Qg, pgTorque, igTorque


    def pitch_controller_tuning(self, pitch, I, dQdt, P, Omr, om, csi):
        """

        Function to compute the gains of the pitch controller of the Basic DTU
        Wind Energy Controller with the pole placement technique implemented
        in HAWCStab2.

        Parameters
        ----------
        pitch: array
            Pitch angle [deg]. The values should only be those of the full load
            region.
        I: array
            Drivetrain inertia [kg*m**2]
        dQdt: array
            Partial derivative of the aerodynamic torque with respect to the
            pitch angle [kNm/deg]. Can be computed with HAWCStab2.
        P: float
            Rated power [kW]. Set to zero in case of constant torque regulation
        Omr: float
            Rated rotational speed [rpm]
        om: float
            Freqeuncy of regulator mode [Hz]
        csi: float
            Damping ratio of regulator mode

        Returns
        -------
        kp: float
            Proportional gain [rad/(rad/s)]
        ki: float
            Intagral gain [rad/rad]
        K1: float
            Linear term of the gain scheduling [deg]
        K2: float
            Quadratic term of the gain shceduling [deg**2]


        """
        pitch = pitch * np.pi/180.
        I = I * 1e-3
        dQdt = dQdt * 180./np.pi
        Omr = Omr * np.pi/30.
        om = om * 2.*np.pi

        # Quadratic fitting of dQdt
        A = np.ones([dQdt.shape[0], 3])
        A[:, 0] = pitch**2
        A[:, 1] = pitch
        b = dQdt
        ATA = np.dot(A.T, A)
        iATA = np.linalg.inv(ATA)
        iATAA = np.dot(iATA, A.T)
        x = np.dot(iATAA, b)

        kp = -(2*csi*om*I[0] - P/(Omr**2))/x[2]
        ki = -(om**2*I[0])/x[2]

        K1 = x[2]/x[1]*(180./np.pi)
        K2 = x[2]/x[0]*(180./np.pi)**2

        return kp, ki, K1, K2

    def K_omega2(V, P, R, TSR):

        Va = np.array(V)
        Pa = np.array(P)
        Ra = np.array(R)
        TSRa = np.array(TSR)
        K = Ra**3 * np.mean(Pa/(TSRa*Va)**3)

        return K

    def select_regions(self, pitch, omega, power):
        """Find indices at wich point the controller should switch between the
        different operating mode regions.

        Parameters
        ----------



        Returns
        ------

        i12 : int

        123 : int

        134 : int

        """

        i12 = 0

        n = len(pitch)

        for i in range(n-1):
            if (abs(power[i]/power[i+1] - 1.) > 0.01):
                if (abs(omega[i] / omega[i+1] - 1.) > 0.01):
                    i12 = i
                    break
        i23 = n-1
        for i in range(i12, n-1):
            if (abs(omega[i] / omega[i+1] - 1.) < 0.01):
                i23 = i
                break

        i34 = i23
        for i in range(i23, n-1):
            if (abs(power[i]/power[i+1] - 1.) > 0.01):
                if (abs(omega[i] / omega[i+1] - 1.) < 0.01):
                    i34 = i+1

        return i12, i23, i34


if __name__ == '__main__':

    pass