- added generic tracer class

- create tracer for TC
- tracer task runs TC-Tracer
This commit is contained in:
jens
2021-10-18 17:57:40 +02:00
parent 236c33d8d6
commit 54f2322c07
5 changed files with 138 additions and 7 deletions
+13 -1
View File
@@ -9,6 +9,7 @@ from components.pid import PidFactory
from components.plant import Pot from components.plant import Pot
from components.actor import HeaterFactory, StirrerFactory from components.actor import HeaterFactory, StirrerFactory
from tasks import TaskManager, TempSensorTask, HeaterTask, PotTask, TcTask, StirrerTask, TracerTask from tasks import TaskManager, TempSensorTask, HeaterTask, PotTask, TcTask, StirrerTask, TracerTask
from tracer import Tracer
if __name__ == '__main__': if __name__ == '__main__':
config = json.load(open("config.json")) config = json.load(open("config.json"))
@@ -40,13 +41,24 @@ if __name__ == '__main__':
tc_task = TcTask(tc, DT_TASK, dispatcher.msgio_get("TempCtrl")) tc_task = TcTask(tc, DT_TASK, dispatcher.msgio_get("TempCtrl"))
taskmgr.add(tc_task) taskmgr.add(tc_task)
tc_trace_vars = [
{'variable': 'theta_ist_plant', 'name': 'theta_ist_plant', 'unit': ''},
{'variable': 'dtheta_ist_plant', 'name': 'dtheta_ist_plant', 'unit': ''},
{'variable': 'theta_ist_model', 'name': 'theta_ist_model', 'unit': ''},
{'variable': 'dtheta_ist_model', 'name': 'dtheta_ist_model', 'unit': ''},
{'variable': 'theta_ist_model_delay', 'name': 'theta_ist_model_delay', 'unit': ''},
{'variable': 'dtheta_ist_model_delay', 'name': 'dtheta_ist_model_delay', 'unit': ''}
]
trace_tc = Tracer(tc, tc_trace_vars, name='tc_trace')
# Stirrer # Stirrer
stirrer = StirrerFactory.create(config['Controller']['stirrer_name'], DT, config['Stirrer']) stirrer = StirrerFactory.create(config['Controller']['stirrer_name'], DT, config['Stirrer'])
stirrer_task = StirrerTask(stirrer, DT_TASK, dispatcher.msgio_get("Stirrer")) stirrer_task = StirrerTask(stirrer, DT_TASK, dispatcher.msgio_get("Stirrer"))
taskmgr.add(stirrer_task) taskmgr.add(stirrer_task)
# Tracer # Tracer
taskmgr.add(TracerTask(sensor, heater, tc, DT_TASK_TRACER, dispatcher.msgio_get("Tracer"))) taskmgr.add(TracerTask(sensor, heater, tc, trace_tc, DT_TASK_TRACER, dispatcher.msgio_get("Tracer")))
# Assign data flow # Assign data flow
tc.set_on_changed("y", heater_task.actor) tc.set_on_changed("y", heater_task.actor)
+3 -3
View File
@@ -100,9 +100,9 @@ class TempController(APid):
self.heatrate_soll = self.heatrate_soll_set * self.pid_hold.get_y() self.heatrate_soll = self.heatrate_soll_set * self.pid_hold.get_y()
print ("Model : T_ist={:2.2f}, dT_ist={:2.2f}".format(theta_ist_model, heatrate_ist_model)) # print ("Model : T_ist={:2.2f}, dT_ist={:2.2f}".format(theta_ist_model, heatrate_ist_model))
print ("Model*z-1: T_ist={:2.2f}, dT_ist={:2.2f}".format(theta_ist_model_delay, dtheta_ist_model_delay)) # print ("Model*z-1: T_ist={:2.2f}, dT_ist={:2.2f}".format(theta_ist_model_delay, dtheta_ist_model_delay))
print ("Plant : T_ist={:2.2f}, dT_ist={:2.2f}".format(theta_ist_plant, heatrate_ist_plant)) # print ("Plant : T_ist={:2.2f}, dT_ist={:2.2f}".format(theta_ist_plant, heatrate_ist_plant))
if 0: if 0:
theta_err = self.theta_soll_set - (theta_ist_plant - theta_ist_model_delay + theta_ist_model) theta_err = self.theta_soll_set - (theta_ist_plant - theta_ist_model_delay + theta_ist_model)
else: else:
+45
View File
@@ -0,0 +1,45 @@
## Copyright (C) 2020 Jens
##
## This program is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see
## <https://www.gnu.org/licenses/>.
## -*- texinfo -*-
## @deftypefn {} {@var{retval} =} results (@var{input1}, @var{input2})
##
## @seealso{}
## @end deftypefn
## Author: Jens <jens@orion>
## Created: 2020-12-20
function retval = results_tc()
load ('logs/tc_trace.mat')
close all;
figure(1)
set(0, "defaultlinelinewidth", 1.5);
subplot(2,1,1)
plot(time, theta_ist_plant, time, theta_ist_model, theta_ist_model_delay); grid
title("Temperature [°C]")
legend("Plant","Model","Model*z")
subplot(2,1,2)
plot(time, dtheta_ist_plant, time, dtheta_ist_model, dtheta_ist_model_delay); grid
title("Heatrate [°C/min]")
legend("Plant","Model","Model*z")
endfunction
+10 -3
View File
@@ -5,6 +5,7 @@ from ws.message import MsgIo
from components import ATemperatureSensor from components import ATemperatureSensor
from components import AHeater from components import AHeater
from components import APid from components import APid
from tracer import Tracer
import numpy as np import numpy as np
import scipy.io import scipy.io
@@ -12,7 +13,7 @@ import os
class TracerTask(ATask): class TracerTask(ATask):
def __init__(self, sensor: ATemperatureSensor, heater: AHeater, temp_ctrl: APid, interval, msg_handler: MsgIo, path= './logs'): def __init__(self, sensor: ATemperatureSensor, heater: AHeater, temp_ctrl: APid, tracer: Tracer, interval, msg_handler: MsgIo, path= './logs'):
ATask.__init__(self, interval) ATask.__init__(self, interval)
if not os.path.exists(path): if not os.path.exists(path):
os.makedirs(path) os.makedirs(path)
@@ -23,6 +24,7 @@ class TracerTask(ATask):
self.sensor = sensor self.sensor = sensor
self.heater = heater self.heater = heater
self.temp_ctrl = temp_ctrl self.temp_ctrl = temp_ctrl
self.tracer = tracer
self.path = path self.path = path
async def recv(self, data): async def recv(self, data):
@@ -44,8 +46,13 @@ class TracerTask(ATask):
_tc_dtemp_soll = np.empty(0) _tc_dtemp_soll = np.empty(0)
_tc_dtemp_commanded = np.empty(0) _tc_dtemp_commanded = np.empty(0)
filename = os.path.join(self.path, '') + "brewpi." + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".mat" name = 'brewpi'
filename = os.path.join(self.path, '') + name + ".mat"
filename_full = os.path.join(self.path, '') + name + "." + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".mat"
while True: while True:
self.tracer.process()
_timestamp = np.append(_timestamp, timestamp) _timestamp = np.append(_timestamp, timestamp)
_sensor_temp = np.append(_sensor_temp, self.sensor.temperature()) _sensor_temp = np.append(_sensor_temp, self.sensor.temperature())
_heater_power = np.append(_heater_power, self.heater.get_power()) _heater_power = np.append(_heater_power, self.heater.get_power())
@@ -57,8 +64,8 @@ class TracerTask(ATask):
data = {'time': _timestamp, 'sensor_temp': _sensor_temp, 'heater_power': _heater_power, 'tc_temp_ist': _tc_temp_ist, 'tc_dtemp_ist': _tc_dtemp_ist, 'tc_temp_soll': _tc_temp_soll, 'tc_dtemp_soll': _tc_dtemp_soll, 'tc_dtemp_commanded': _tc_dtemp_commanded} data = {'time': _timestamp, 'sensor_temp': _sensor_temp, 'heater_power': _heater_power, 'tc_temp_ist': _tc_temp_ist, 'tc_dtemp_ist': _tc_dtemp_ist, 'tc_temp_soll': _tc_temp_soll, 'tc_dtemp_soll': _tc_dtemp_soll, 'tc_dtemp_commanded': _tc_dtemp_commanded}
scipy.io.savemat('brewpi.mat', data)
scipy.io.savemat(filename, data) scipy.io.savemat(filename, data)
scipy.io.savemat(filename_full, data)
timestamp += 1 timestamp += 1
await asyncio.sleep(self.interval) await asyncio.sleep(self.interval)
+67
View File
@@ -0,0 +1,67 @@
from typing import TypedDict
import numpy as np
import scipy.io
import os
import time
class Entry(TypedDict):
variable: str
name: str
unit: str
class Tracer:
def __init__(self, obj, var_list: Entry, name='default', path='./logs'):
if not os.path.exists(path):
os.makedirs(path)
self.obj = obj
self.var_list = var_list
self.timestamp = 0
self.timestamp_data = np.empty(0)
self.filename_full = os.path.join(path, '') + name + "." + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".mat"
self.filename = os.path.join(path, '') + name + ".mat"
self.data_list = {}
for var in self.var_list:
self.data_list[var['name']] = np.empty(0)
def process(self):
data = {}
self.timestamp_data = np.append(self.timestamp_data, self.timestamp)
data['time'] = self.timestamp_data
for var in self.var_list:
key_name = var['name']
key_variable = var['variable']
self.data_list[key_name] = np.append(self.data_list[key_name], self.obj.__getattribute__(key_variable))
data[key_name] = self.data_list[key_name]
scipy.io.savemat(self.filename, data)
scipy.io.savemat(self.filename_full, data)
self.timestamp += 1
class Test:
def __init__(self):
self.a = 0
self.b = 0
def process(self):
self.a += 1
self.b += 10
@staticmethod
def get_entry():
a: Entry = [{'variable': 'a', 'name' : 'v_a', 'unit': 'u_a'}]
b: Entry = [{'variable': 'b', 'name' : 'v_b', 'unit': 'u_b'}]
return a + b
if __name__ == '__main__':
test = Test()
dut = Tracer(test, Test.get_entry(), name='TracerTest')
for i in range(0, 10):
dut.process()
test.process()