def control(self,
                currentCV: np.ndarray,
                voltageCV: np.ndarray,
                idq0SP: np.ndarray = np.zeros(3),
                **kwargs):
        """
        Performs the calculations for a discrete step of the controller
        Droop-control is started if Vgrid_rms exceeds 200 V, to avoid oscillation with the grid forming inverter

        :param currentCV: 1d-array with 3 entries, one for each phase. The feedback values for current
        :param voltageCV:  1d-array with 3 entries, one for each phase. The feedback values for voltage
        :param idq0SP: The peak current setpoints in the dq0 frame (Additional power output to droop, if == 0, than
            only droop is applied

        :return: Modulation indices for the current sourcing inverter in ABC
        """
        # Calulate P&Q for slave
        instPow = -inst_power(voltageCV, currentCV)
        instQ = -inst_reactive(voltageCV, currentCV)

        Vinst = inst_rms(voltageCV)
        # Get current phase information from the voltage measurement
        self._prev_cossine, self._prev_freq, self._prev_theta = self._pll.step(
            voltageCV)

        # Transform the current feedback to the DQ0 frame
        self._lastIDQ = abc_to_dq0_cos_sin(currentCV, *self._prev_cossine)

        droop = np.zeros(2)
        if Vinst > self.lower_droop_voltage_threshold:
            # Determine the droop power setpoints
            droopPI = (self._PdroopController.step(self._prev_freq) /
                       inst_rms(voltageCV))

            # Determine the droop reactive power set points
            droopQI = (self._QdroopController.step(Vinst) / Vinst)
            droop = np.array([
                droopPI, droopQI
            ]) / 3  # devide by 3 due to here dq, but we want to set the e.g.
            # d-setpoint in the sum of the phases abc

            droop = droop * 1.4142135623730951  # RMS to Peak
            droop = np.clip(droop, -self._i_limit, self._i_limit)

        idq0SP = idq0SP + np.array([-droop[0], +droop[1], 0])
        # Calculate the control applied to the DQ0 currents
        # action space is limited to [-1,1]

        MVdq0 = self._currentPI.step(idq0SP, self._lastIDQ)
        # Transform the outputs from the controllers (dq0) to abc
        # also divide by SQRT(2) to ensure the transform is limited to [-1,1]

        MVabc = dq0_to_abc_cos_sin(MVdq0, *self._prev_cossine)
        self._last_meas = [
            self._prev_theta, instPow, instQ, self._prev_freq, *self._lastIDQ,
            *idq0SP, *MVdq0, *MVabc
        ]
        return MVabc
    def control(self, currentCV: np.ndarray, voltageCV: np.ndarray, **kwargs):
        """
        Performs the calculations for a discrete step of the controller

        :param currentCV: 1d-array with 3 entries, one for each phase in abc. The feedback values for current
        :param voltageCV:  1d-array with 3 entries, one for each phase in abc. The feedback values for voltage

        :return: Modulation index for the inverter in abc
        """

        instPow = -inst_power(voltageCV, currentCV)
        freq = self._PdroopController.step(instPow)
        # Get the next phase rotation angle to implement
        self.phase = phase = self._phaseDDS.step(freq)

        instQ = -inst_reactive(voltageCV, currentCV)
        voltage = self._QdroopController.step(instQ)

        # Transform the feedback to the dq0 frame
        CVIdq0 = abc_to_dq0(currentCV, phase)
        CVVdq0 = abc_to_dq0(voltageCV, phase)

        # If available, calulate load current using observer
        iabc_out_etimate = np.empty(N_PHASE)
        if self._observer is None:
            iabc_out_etimate = np.zeros(N_PHASE)
        else:
            for j in range(N_PHASE):
                iabc_out_etimate[j] = self._observer[j].cal_estimate(
                    y=[currentCV[j], voltageCV[j]], u=self._lastMabc[j])

        i_dq0_out_estimat = abc_to_dq0(iabc_out_etimate, phase)

        # Voltage controller calculations
        VSP = voltage
        # Voltage SP in dq0 (static for the moment)
        SPVdq0 = np.array([VSP, 0, 0])
        SPVabc = dq0_to_abc(SPVdq0, phase)
        SPIdq0 = self._voltagePI.step(SPVdq0, CVVdq0, i_dq0_out_estimat)

        SPIabc = dq0_to_abc(SPIdq0, phase)

        # Current controller calculations
        MVdq0 = self._currentPI.step(SPIdq0, CVIdq0)
        MVabc = dq0_to_abc(MVdq0,
                           phase)  # Transform the MVs back to the abc frame
        self._lastMabc = MVabc
        # Add intern measurment
        self._last_meas = [
            phase, instPow, instQ, freq, *SPVdq0, *SPVabc, *SPIdq0, *SPIabc,
            *CVVdq0, *CVIdq0, *i_dq0_out_estimat, *iabc_out_etimate, *MVdq0,
            *MVabc
        ]

        return MVabc
    def calculate(self):
        super().calculate()
        instPow = -inst_power(self.v, self.i)
        freq = self.pdroop_ctl.step(instPow)
        # Get the next phase rotation angle to implement
        phase = self.dds.step(freq)

        instQ = -inst_reactive(self.v, self.i)
        v_refd = self.qdroop_ctl.step(instQ)
        v_refdq0 = np.array([v_refd, 0, 0]) * self.v_ref

        return dict(i_ref=dq0_to_abc(self.i_ref, phase), v_ref=dq0_to_abc(v_refdq0, phase))
    def control(self, currentCV: np.ndarray, voltageCV: np.ndarray, **kwargs):
        instPow = -inst_power(voltageCV, currentCV)
        freq = self._PdroopController.step(instPow)
        # Get the next phase rotation angle to implement
        phase = self._phaseDDS.step(freq)

        instQ = -inst_reactive(voltageCV, currentCV)
        voltage = self._QdroopController.step(instQ)

        VSP = voltage * 1.732050807568877
        # Voltage SP in dq0 (static for the moment)
        SPVdq0 = np.array([VSP, 0, 0])

        # Get the voltage SPs in abc vector
        # print("SPVdq0: {}, phase: {}".format(SPVdq0,phase))
        SPV = dq0_to_abc(SPVdq0, phase)

        # print("QInst: {}, Volt {}".format(instQ,VSP))
        SPI = self._voltagePI.step(SPV, voltageCV)

        # Average voltages from modulation indices created by current controller
        return self._currentPI.step(SPI, currentCV)
    def control(self, currentCV: np.ndarray, voltageCV: np.ndarray, **kwargs):
        """
        Performs the calculations for a discrete step of the controller

        :param currentCV: 1d-array with 3 entries, one for each phase in abc. The feedback values for current
        :param voltageCV:  1d-array with 3 entries, one for each phase in abc. The feedback values for voltage

        :return: Modulation index for the inverter in abc
        """

        instPow = -inst_power(voltageCV, currentCV)
        freq = self._PdroopController.step(instPow)
        # Get the next phase rotation angle to implement
        phase = self._phaseDDS.step(freq)

        instQ = -inst_reactive(voltageCV, currentCV)
        voltage = self._QdroopController.step(instQ)

        # Transform the feedback to the dq0 frame
        CVIdq0 = abc_to_dq0(currentCV, phase)
        CVVdq0 = abc_to_dq0(voltageCV, phase)

        # Voltage controller calculations
        VSP = voltage
        # Voltage SP in dq0 (static for the moment)
        SPVdq0 = np.array([VSP, 0, 0])
        SPIdq0 = self._voltagePI.step(SPVdq0, CVVdq0)

        # Current controller calculations
        MVdq0 = self._currentPI.step(SPIdq0, CVIdq0)

        # Add intern measurment
        self.history.append([
            phase, *SPVdq0, *SPIdq0, *CVVdq0, *CVIdq0, *MVdq0, instPow, instQ,
            freq
        ])

        # Transform the MVs back to the abc frame
        return dq0_to_abc(MVdq0, phase)