Skip to content

Commit

Permalink
Update control interface: add nacelle IMU, method to kill discon (WIS…
Browse files Browse the repository at this point in the history
…DEM#42)

* Update control interface: add nacelle IMU, method to kill discon

* Set openfast install to 2.5.0
  • Loading branch information
dzalkind authored May 12, 2021
1 parent 381ae28 commit b7ef93e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CI_rosco-toolbox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
# Install OpenFAST
- name: Install OpenFAST
run: |
conda install openfast
conda install openfast==2.5.0
# Run examples
- name: Run examples
Expand Down
46 changes: 39 additions & 7 deletions ROSCO_toolbox/control_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

from ctypes import byref, cdll, c_int, POINTER, c_float, c_char_p, c_double, create_string_buffer, c_int32
from ctypes import byref, cdll, c_int, POINTER, c_float, c_char_p, c_double, create_string_buffer, c_int32, c_void_p
import numpy as np
from numpy.ctypeslib import ndpointer

Expand All @@ -35,19 +35,31 @@ class ControllerInterface():
"""

def __init__(self, lib_name, param_filename='DISCON.IN'):
def __init__(self, lib_name, param_filename='DISCON.IN', **kwargs):
"""
Setup the interface
"""
self.lib_name = lib_name
self.param_name = param_filename

# Temp fixed parameters
# Set default parameters
# PARAMETERS
self.DT = 0.1
self.num_blade = 3
self.char_buffer = 500
self.avr_size = 500
self.sim_name = 'simDEBUG'

# Set kwargs, like DT
for (k, w) in kwargs.items():
try:
setattr(self, k, w)
except:
pass

self.init_discon()

def init_discon(self):

# Initialize
self.pitch = 0
Expand All @@ -56,10 +68,12 @@ def __init__(self, lib_name, param_filename='DISCON.IN'):
self.discon = cdll.LoadLibrary(self.lib_name)
self.avrSWAP = np.zeros(self.avr_size)

# Define some avrSWAP parameters
# Define some avrSWAP parameters, NOTE: avrSWAP indices are offset by -1 from Fortran
self.avrSWAP[2] = self.DT
self.avrSWAP[60] = self.num_blade
self.avrSWAP[20] = 1 # HARD CODE initial rot speed = 1 rad/s
self.avrSWAP[19] = 1.0 # HARD CODE initial gen speed = 1 rad/s
self.avrSWAP[20] = 1.0 # HARD CODE initial rot speed = 1 rad/s
self.avrSWAP[82] = 0 # HARD CODE initial nacIMU = 0
self.avrSWAP[26] = 10 # HARD CODE initial wind speed = 10 m/s


Expand All @@ -76,7 +90,7 @@ def __init__(self, lib_name, param_filename='DISCON.IN'):
self.aviFAIL = c_int32() # 1
self.accINFILE = self.param_name.encode('utf-8')
# self.avcOUTNAME = create_string_buffer(1000) # 'DEMO'.encode('utf-8')
self.avcOUTNAME = 'simDEBUG.dbg'.encode('utf-8')
self.avcOUTNAME = (self.sim_name + '.RO.dbg').encode('utf-8')
self.avcMSG = create_string_buffer(1000)
self.discon.DISCON.argtypes = [POINTER(c_float), POINTER(c_int32), c_char_p, c_char_p, c_char_p] # (all defined by ctypes)

Expand All @@ -103,7 +117,7 @@ def call_discon(self):
self.avrSWAP = data


def call_controller(self,t,dt,pitch,torque,genspeed,geneff,rotspeed,ws):
def call_controller(self,t,dt,pitch,torque,genspeed,geneff,rotspeed,ws,NacIMU_FA_Acc=0):
'''
Runs the controller. Passes current turbine state to the controller, and returns control inputs back
Expand All @@ -123,6 +137,9 @@ def call_controller(self,t,dt,pitch,torque,genspeed,geneff,rotspeed,ws):
rotor speed, (rad/s)
ws: float
wind speed, (m/s)
NacIMU_FA_Acc : float
nacelle IMU accel. in the nodding dir. , (m/s**2)
default to 0 (fixed-bottom, simple 1-DOF sim does not include it, but OpenFAST linearizations do)
'''

# Add states to avr
Expand All @@ -136,6 +153,7 @@ def call_controller(self,t,dt,pitch,torque,genspeed,geneff,rotspeed,ws):
self.avrSWAP[19] = genspeed
self.avrSWAP[20] = rotspeed
self.avrSWAP[26] = ws
self.avrSWAP[82] = NacIMU_FA_Acc

# call controller
self.call_discon()
Expand All @@ -152,3 +170,17 @@ def show_control_values(self):
'''
print('Pitch',self.pitch)
print('Torque',self.torque)

def kill_discon(self):
'''
Unload the dylib from memory: https://stackoverflow.com/questions/359498/how-can-i-unload-a-dll-using-ctypes-in-python
This is unix-specific, but there seems to be a windows solution as well
'''

print('Shutting down {}'.format(self.lib_name))
handle = self.discon._handle
dlclose_func = self.discon.dlclose
dlclose_func.argtypes = [c_void_p]

del self.discon
dlclose_func(handle)

0 comments on commit b7ef93e

Please sign in to comment.