-
Notifications
You must be signed in to change notification settings - Fork 9
/
discretetf.py
127 lines (105 loc) · 3.73 KB
/
discretetf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import ctypes
import os
import platform
import pandas as pd
from rtwtypes import real_T
class DiscreteTF:
def __init__(self, model="discrete_tf"):
self.model = model
if platform.system() == "Linux":
self.dll_path = os.path.abspath(f"{model}.so")
self.dll = ctypes.cdll.LoadLibrary(self.dll_path)
elif platform.system() == "Windows":
self.dll_path = os.path.abspath(f"{model}_win64.dll")
self.dll = ctypes.windll.LoadLibrary(self.dll_path)
else:
raise Exception("System Not Supported")
# Model entry point functions
self.__initialize = getattr(self.dll, f"{model}_initialize")
self.__step = getattr(self.dll, f"{model}_step")
self.__model_terminate = getattr(self.dll, f"{model}_terminate")
# Model signals
self._output = real_T.in_dll(self.dll, "OutputSignal")
self._time = real_T.in_dll(self.dll, "SimTime")
# Model Parameters
self._input_signal = real_T.in_dll(self.dll, "InputSignal")
self._num = (real_T * 2).in_dll(self.dll, "num")
self._den = (real_T * 2).in_dll(self.dll, "den")
def initialize(self):
"""Initialize the Model."""
self.__initialize()
self.step_num = -1
def step(self):
"""Step through the model Model."""
self.__step()
self.step_num += 1
def terminate(self):
"""Terminate the model Model."""
self.__model_terminate()
def init_log(self):
"""Create an empty datalog and intialize the model."""
self.data = dict()
self.data["input"] = list()
self.data["output"] = list()
self.data["time"] = list()
self.initialize()
def step_log(self):
"""Step the data and log it."""
self.step()
self.data["input"].append(self.input_signal)
self.data["output"].append(self.output)
self.data["time"].append(self.time)
@property
def dataframe(self):
return pd.DataFrame(self.data)
def plot(self):
self.dataframe.plot(x="time", y=["input", "output"])
# Signals
@property
def output(self):
# Model output, return a Python datatype
return float(self._output.value)
@property
def time(self):
# Model time, return a Python datatype
return float(self._time.value)
# Parameters
# Use setters/getters to make it as pythonic as possible
@property
def num(self):
# Convert the ctypes Array to a python list.
return list(self._num)
@num.setter
def num(self, value):
# This size was specified at compile time and does
# need the library to be recompiled to change.
assert len(value) in [1, 2]
if len(value) == 2:
self._num[0] = float(value[0])
self._num[1] = float(value[1])
else:
self._num[0] = float(0)
self._num[1] = float(value[0])
@property
def den(self):
return list(self._den)
@den.setter
def den(self, value):
# This size was specified at compile time and does
# need the library to be recompiled to change.
assert len(value) in [1, 2]
if len(value) == 2:
self._den[0] = float(value[0])
self._den[1] = float(value[1])
else:
self._den[0] = float(0)
self._den[1] = float(value[0])
@property
def input_signal(self):
return float(self._input_signal.value)
@input_signal.setter
def input_signal(self, value):
self._input_signal.value = float(value)
# 'Pretty' Display for IPython/Notebooks.
def __repr__(self):
return f"{self.model}<{self.time}, {self.input_signal}, {self.output}>"