NREL / ROSCO

A Reference Open Source Controller for Wind Turbines
https://rosco.readthedocs.io/en/latest/
Apache License 2.0
116 stars 93 forks source link

Feature: expand wfc_zmq_server to allow wind farm controllers to access past measurements and measurements from other turbines #353

Closed Bartdoekemeijer closed 5 months ago

Bartdoekemeijer commented 5 months ago

Description of feature

First of all, I wanted to extend my appreciation to @abhineet-gupta and @dzalkind for the tremendous efforts on the ZeroMQ interface. It's been working without issues for me in FAST.Farm runs, all across a single network port. Thank you!

Now, I raise this feature request because I was trying to implement more advanced wind farm controllers through the interface. The wfc_zmq_server in rosco.toolbox is very useful for this. It requires users to define a wfc_controller(id, current_time, measurements) function -- very useful for implementing look-up table approaches and open-loop control. This is exemplified in Examples 17a_zeromq_simple.py and 17b_zeromq_multi_openfast.py.

def wfc_controller(id,current_time,measurements):
        if current_time <= 10.0:
            yaw_setpoint = 0.0
        else:
            yaw_setpoint = DESIRED_YAW_OFFSET

        # Pitch offset
        if current_time >= 10.0:
            col_pitch_command = np.deg2rad(2) * np.sin(0.1 * current_time) + np.deg2rad(2) # Implement dynamic induction control
        else:
            col_pitch_command = 0.0

        # Send new setpoints back to ROSCO
        setpoints = {}
        setpoints['ZMQ_TorqueOffset'] = 0.0
        setpoints['ZMQ_YawOffset'] = yaw_setpoint
        setpoints['ZMQ_PitOffset(1)'] = col_pitch_command
        setpoints['ZMQ_PitOffset(2)'] = col_pitch_command
        setpoints['ZMQ_PitOffset(3)'] = col_pitch_command
        return setpoints

However, the problem with this implementation is that the wfc_controller() function is called once for each turbine, and the only available information passed to this function are that turbine's measurements at the current time. There is no way to access measurements from the past (e.g., the last 10 seconds) and there is no way to access measurements from the other turbines. This can quickly become a limiting factor, e.g., you often want to assign yaw angles for T2 based on measurements at T1. You may also want to apply a lowpass filter on the measured conditions before interpolating a wake steering offset lookup table. This can become a bit difficult in the current set-up.

Potential solution

The solution would be to turn the wfc_controller function into a class, which allows internal memory/variables. It only requires a couple lines of code to change, and allows much greater freedom in wind farm controller design.

I will open a Pull Request with the proposed changes for you to review.