Not a member yet? Why not Sign up today
Create an account  

  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 
Electric engine output control

#1
One of the recent updates added some new functions to self awareness API which allows us to get info about vehicle's power state, so I tried to use them to optimize electric engine throttle. Seems to work fine.

This script controls throttle of all electric engines present on vehicle according to the following algorithm:

  1. When battery charge is above minimum level (default is 80%), output is set to generate just enough power to fully satisfy vehicle's demand.
  2. When battery charge is below minimum level, the output is limited to "balanced" value (do not consume more than generated), preventing battery from charge stall.
The idea is to minimize battery drain when the vehicle is idle (set output as low as possible to satisfy power demand), and when it is fully (or over-) loaded with LAMS and stuff, allow it to drain battery to certain level and then enter "economical" mode, limiting it from draining more.

That way, for instance, vehicle with limited power can shoot large initial volley of missiles using acceptable amount of battery charge, and then rapidly recharge batteries. It should be quite more efficient then setting some "balanced" value manually once in designer, wasting battery recharge rate in calm periods of battle and limiting vehicle's systems output in crirical moments.


I have been testing this script on my RTG-only destroyer (will probably upload it to workshop soon), should work fine with other battery charge generation methods as long as they provide more or less constant recharge rate.

Battery capacity and recharge rate should be put into the script manually at the moment. It would be great if somebody will point out how to calculate vehicle's battery generation and storage capacity automatically, I can't even find means to enumerate battery or RTG blocks as they don't have any components associated with them.

The script is available at github along with small Wolfram Mathematica file with some simple math used in this script.
Dublicating code here (will try to keep this updated), formatting is slightly broken:

Code:
UPDATE_INTERVAL              = 10  -- Update every %number% frame

-- Currently, I cannot find any means to automatically calculate vehicle battery capacity and battery generation
-- (can't even enumerate RTG's and batteries), so you have to enter these values manually here

BATTERY_CAPACITY             = PUT_YOUR_NUMBER_HERE -- Battery capacity of your ship
BATTERY_GENERATION           = PUT_YOUR_NUMBER_HERE -- Battery generation of your ship

-- The level to which we can drain battery before limiting throttle to prevent battery stall.
-- For example, useful for maximizing LAMS power agains first, most dangerous, missile swarms at the beginning of the battle
ACCEPTABLE_BATTERY_FRACTION  = 0.8

------------------------------------------------------------------------------------------------------------------------

ELECTRIC_ENGINE              = 35   -- ID of electric engine component
NEEDED_POWER_OUTPUT_OVERHEAD = 0.005 -- Min needed output addition to end up with small amount of spare power

_currentTick                 = 0
_currentPowerOutput          = 1

function Update(I)
    _currentTick = _currentTick + 1

    if _currentTick == 0 then
        ApplyElectricEngineOutput(I, 1.0)
        return
    end

    if _currentTick % UPDATE_INTERVAL == 0 then
        return
    end

    local batteryFraction         = I:GetEnergyFraction()
    local electricPowerFraction   = I:GetElectricPowerFraction()

    local batteryCapacity         = GetBatteryCapacity(I)
    local batteryGeneration       = GetBatteryGeneration(I)
    local batteryCharge           = batteryCapacity * batteryFraction
    local acceptableBatteryCharge = batteryCapacity * ACCEPTABLE_BATTERY_FRACTION

    -- doesn't seem to be a way to get requested power directly, so we have to calculate it
    local powerNeeded             = (1 - electricPowerFraction) * GetPowerGeneratedForGivenOutputLevel(batteryCapacity, _currentPowerOutput)
    if (electricPowerFraction == 0) then
        powerNeeded = 0x7FFFFFFF -- if for some reason we have no power available, set it to some large number
    end
    local neededOutput = GetMinOutputToSatisfyPowerDemand(batteryCharge, powerNeeded)

    local balancedOutputLevel
    if (batteryCharge > acceptableBatteryCharge) then
        -- No restrictions for battery draw
        balancedOutputLevel = 1
    else
        -- Try to keep battery charge at acceptable level
        balancedOutputLevel = GetBalancedOutputLevel(acceptableBatteryCharge, batteryGeneration)
    end

    local newPowerOutput = math.min(balancedOutputLevel, neededOutput)

    I:ClearLogs();
    I:Log('battery charge ' .. batteryCharge .. ' (' .. batteryFraction .. ')');
    I:Log('optimal output ' .. balancedOutputLevel);
    I:Log('needed electric power ' .. powerNeeded);
    I:Log('needed output level ' .. neededOutput);

    ApplyElectricEngineOutput(I, newPowerOutput)
end

function GetBatteryCapacity(I)
    -- TODO: autoate
    return BATTERY_CAPACITY
end

function GetBatteryGeneration(I)
    -- TODO: automate
    return BATTERY_GENERATION
end

function GetPowerGeneratedForGivenOutputLevel(batteryCapacity, outputLevel)
    return batteryCapacity * outputLevel / 25
end

function GetBalancedOutputLevel(batteryCapacity, batteryGeneration)
    return (math.sqrt((batteryCapacity + 200 * batteryGeneration) / batteryCapacity) - 1) / 2
end

function GetMinOutputToSatisfyPowerDemand(batteryCapacity, powerNeeded)
    return math.min(NEEDED_POWER_OUTPUT_OVERHEAD + 25 * powerNeeded / batteryCapacity, 1)
end

function ApplyElectricEngineOutput(I, outputLevel)
    for i = 0, I:Component_GetCount(ELECTRIC_ENGINE) - 1 do
        I:Component_SetFloatLogic(ELECTRIC_ENGINE, i, outputLevel)
    end

    _currentPowerOutput = outputLevel
end

First time I wrote something on lua, so it might contain some noob mistakes.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)