#366 idling and charge level PD gain changes

This commit is contained in:
Mikayla Fischler 2024-04-09 22:23:43 -04:00
parent 4fcd375ee2
commit 65d43d55c7
3 changed files with 85 additions and 16 deletions

View File

@ -50,9 +50,9 @@ local START_STATUS = {
BLADE_MISMATCH = 2
}
local charge_Kp = 0.275
local charge_Kp = 0.15
local charge_Ki = 0.0
local charge_Kd = 4.5
local charge_Kd = 0.6
local rate_Kp = 2.45
local rate_Ki = 0.4825
@ -225,6 +225,14 @@ function facility.new(num_reactors, cooling_conf)
return unallocated, false
end
-- set idle state of all assigned reactors
---@param idle boolean idle state
local function _set_idling(idle)
for i = 1, #self.prio_defs do
for _, u in pairs(self.prio_defs[i]) do u.auto_set_idle(idle) end
end
end
-- PUBLIC FUNCTIONS --
---@class facility
@ -325,8 +333,9 @@ function facility.new(num_reactors, cooling_conf)
--#region
local avg_charge = self.avg_charge.compute()
local avg_inflow = self.avg_inflow.compute()
local avg_charge = self.avg_charge.compute()
local avg_inflow = self.avg_inflow.compute()
local avg_outflow = self.avg_outflow.compute()
local now = util.time_s()
@ -390,6 +399,7 @@ function facility.new(num_reactors, cooling_conf)
-- disable reactors and disengage auto control
for _, u in pairs(self.prio_defs[i]) do
u.disable()
u.auto_set_idle(false)
u.auto_disengage()
end
end
@ -460,6 +470,9 @@ function facility.new(num_reactors, cooling_conf)
self.last_error = 0
self.accumulator = 0
-- enabling idling on all assigned units
_set_idling(true)
self.status_text = { "CHARGE MODE", "running control loop" }
log.info("FAC: CHARGE mode starting PID control")
elseif self.last_update ~= charge_update then
@ -475,9 +488,9 @@ function facility.new(num_reactors, cooling_conf)
local integral = self.accumulator
local derivative = (error - self.last_error) / (now - self.last_time)
local P = (charge_Kp * error)
local I = (charge_Ki * integral)
local D = (charge_Kd * derivative)
local P = charge_Kp * error
local I = charge_Ki * integral
local D = charge_Kd * derivative
local output = P + I + D
@ -486,7 +499,10 @@ function facility.new(num_reactors, cooling_conf)
self.saturated = output ~= out_c
-- log.debug(util.sprintf("CHARGE[%f] { CHRG[%f] ERR[%f] INT[%f] => OUT[%f] OUT_C[%f] <= P[%f] I[%f] D[%d] }",
-- stop idling early if the output is zero, we are at or above the setpoint, and are not losing charge
_set_idling(not ((out_c == 0) and (error <= 0) and (avg_outflow < avg_inflow)))
-- log.debug(util.sprintf("CHARGE[%f] { CHRG[%f] ERR[%f] INT[%f] => OUT[%f] OUT_C[%f] <= P[%f] I[%f] D[%f] }",
-- runtime, avg_charge, error, integral, output, out_c, P, I, D))
_allocate_burn_rate(out_c, true)
@ -544,9 +560,9 @@ function facility.new(num_reactors, cooling_conf)
local integral = self.accumulator
local derivative = (error - self.last_error) / (now - self.last_time)
local P = (rate_Kp * error)
local I = (rate_Ki * integral)
local D = (rate_Kd * derivative)
local P = rate_Kp * error
local I = rate_Ki * integral
local D = rate_Kd * derivative
-- velocity (rate) (derivative of charge level => rate) feed forward
local FF = self.gen_rate_setpoint / self.charge_conversion

View File

@ -21,7 +21,7 @@ local supervisor = require("supervisor.supervisor")
local svsessions = require("supervisor.session.svsessions")
local SUPERVISOR_VERSION = "v1.3.5"
local SUPERVISOR_VERSION = "v1.3.6"
local println = util.println
local println_ts = util.println_ts

View File

@ -8,9 +8,6 @@ local logic = require("supervisor.unitlogic")
local plc = require("supervisor.session.plc")
local rsctl = require("supervisor.session.rsctl")
---@class reactor_control_unit
local unit = {}
local WASTE_MODE = types.WASTE_MODE
local WASTE = types.WASTE_PRODUCT
local ALARM = types.ALARM
@ -55,6 +52,14 @@ local AISTATE = {
---@field id ALARM alarm ID
---@field tier integer alarm urgency tier (0 = highest)
-- burn rate to idle at
local IDLE_RATE = 0.01
-- time (ms) to idle
local IDLE_TIME = 15000
---@class reactor_control_unit
local unit = {}
-- create a new reactor unit
---@nodiscard
---@param reactor_id integer reactor unit number
@ -83,6 +88,9 @@ function unit.new(reactor_id, num_boilers, num_turbines)
emcool_opened = false,
-- auto control
auto_engaged = false,
auto_idle = false,
auto_idling = false,
auto_idle_start = 0,
auto_was_alarmed = false,
ramp_target_br100 = 0,
-- state tracking
@ -578,6 +586,23 @@ function unit.new(reactor_id, num_boilers, num_turbines)
end
end
-- set automatic control idling mode to change behavior when given a burn rate command of zero<br>
-- - enabling will hold the reactor at 0.01 mB/t for a period before disabling when commanded zero
-- - disabling will stop the reactor when commanded zero
---@param idle boolean true to enable, false to disable and stop right away
function public.auto_set_idle(idle)
if not (idle and self.auto_idle) then
self.auto_idling = false
self.auto_idle_start = 0
end
if idle ~= self.auto_idle then
log.debug(util.c("UNIT ", self.r_id, ": idling mode changed to ", idle))
end
self.auto_idle = idle
end
-- get the actual limit of this unit<br>
-- if it is degraded or not ready, the limit will be 0
---@nodiscard
@ -597,7 +622,35 @@ function unit.new(reactor_id, num_boilers, num_turbines)
if self.auto_engaged then
if self.plc_i ~= nil then
log.debug(util.c("UNIT ", self.r_id, ": commit br100 of ", self.db.control.br100, " with ramp set to ", ramp))
self.plc_i.auto_set_burn(self.db.control.br100 / 100, ramp)
local rate = self.db.control.br100 / 100
if self.auto_idle then
if rate <= IDLE_RATE then
if self.auto_idle_start == 0 then
self.auto_idling = true
self.auto_idle_start = util.time_ms()
log.info(util.c("UNIT ", self.r_id, ": started idling at ", IDLE_RATE, " mB/t"))
rate = IDLE_RATE
elseif (util.time_ms() - self.auto_idle_start) > IDLE_TIME then
if self.auto_idling then
self.auto_idling = false
log.info(util.c("UNIT ", self.r_id, ": completed idling period"))
end
else
log.debug(util.c("UNIT ", self.r_id, ": continuing idle at ", IDLE_RATE, " mB/t"))
rate = IDLE_RATE
end
else
self.auto_idling = false
self.auto_idle_start = 0
end
end
self.plc_i.auto_set_burn(rate, ramp)
if ramp then self.ramp_target_br100 = self.db.control.br100 end
end
end