{{ network:menu-icon-curves.png?nolink&60|}}
======Curves======
=====Introduction=====
{{ :curve:function_machine2.png?nolink&200|}}
Curve is a way to define output value from a pre-defined pair table of a discrete set of known data points. Such as standard or desired value.
Curve can be represented as a function f, which is a blackbox, where is some **INPUT x** have corresponding **OUTPUT y** = f(x)
Curve is using a piecewise linear interpolation, is a curve fitting which is a allow to using linear polynomials to construct new data points within the range of a discrete set of known data points.
Curves can :
* be edited at any time.
* have a static register for storing it.
* be read from string register.
* be copied to another string register using dashboard element.
To create a curve you need to define Y and X value for known points using visual editor or digital input form.
There are several options for using curve:
* The dependence of Y on X (function) is given by the table of pairs.
* The function should be empirical defined.
* There is strict algebraic function and value should be calculated.
* The function should be sequentually or time-to-time changed.
To define curve algebraically, it is linear interpolation between two known points for every piece used. Its string reprentation is a JSON formatted linear polynomial factor "**k**", syllable "**b**" and function definition domain "**range**" values for every piece of a curve, so that inside the **range** of **INPUT x** value **OUTPUT y** value can be calculated as\\ ''y = **k**⋅x + **b**''
For example:\\
At minimum it can be two points.\\
{{ :curve:c1.png?direct&600 |}}\\
Binary logic function.\\
{{ :curve:c2.png?direct&600 |}}\\
Table parameter definition\\
{{ :curve:c3.png?direct&600 |}}\\
Saturation function\\
{{ :curve:c4.png?direct&600 |}}\\
Algebraic defined calculated function. For example sin(x) with 6 points approximation.\\
{{ :curve:c5.png?direct&600 |}}\\
=====New curve creation=====
Let's create a new curve. \\
Click on "New curve" button.\\
{{ :curve:curve_new.png?direct&600 |}}\\
Type in a Title and go on the next tab ''Curve''\\
{{ :curve:curve_tab.png?direct&600 |}}\\
Optionally, you can check "Use the existing String register to store the curve parameters" to store it all the time in this register if you will.
{{ :curve:c1_start.png?direct&600 |}}
Here is a curve editor. There is a domain of a function definition, range of a function and every point X and Y coordinates.\\
{{ :curve:curve_new_start.png?direct&600 |}}\\
To create a new point click twice on a line. To remove it click with holding Alt button.\\
{{ :curve:curve_new_click.png?direct&600 |}}\\
Then you can both move point or specify its value using form in the right.\\
{{ :curve:curve_new_move.png?direct&600 |}}\\
At the end, when all the rest of parameters set let's look at the result . In our example it would more precise approximation of sin(x) with 7 point defined\\
{{ :curve:c6.png?direct&600 |}}\\
=====Select a curve to put in register=====
To get the value you need:
- Have a curve
- Have a string register for dashboard element to put selected curve in it
- Optionally, have yet another string register for store that curve all the time
Now, it is time to create a register with value type "String" for dashboard element.
Then, create a new dashboard.
{{ :curve:no_dashb.png?direct&600 |}}
Click the "Add dashboard".
{{ :curve:dash.png?direct&600 |}}
Type in the Title and go on.
{{ :curve:dash_vis_editor.png?direct&600 |}}
Go to a visual editor.
To do this, there is a dashboard element "Curve".
{{ :curve:dash_element.png?direct&600 |}}
Drag'n'drop it to create a new one.
{{ :curve:dash_element_created.png?direct&600 |}}
Pick a register to be used later in Lua script to get value.
{{ :curve:dash_element_reg.png?direct&600 |}}
Let's test it.
Now, you need to put the curve to string register via dashboard.
{{ :curve:dash_element_view_no_select.png?direct&600 |}}
Click and select the one you want to pick. There is a icon for open curve editor.
{{ :curve:dash_element_view_selector.png?direct&600 |}}
There is a picked one.
{{ :curve:dash_element_view_curve_1.png?direct&600 |}}
Let's check the register.
{{ :curve:reg_filled_with_equat.png?direct&600 |}}
=====Get value from the curve via Lua =====
To get the **OUTPUT y value** from existing(pre-created) curve, you need:
- a Lua script to work with string register and
- include a Lua lib, which will provide access to that function.
- create a register for dashboard element.
- create a dashboard, with "curve" element, where you can select which curve will be stored in the bound register.
- Call a GetCurveValue function and pass to it this ''**register**'' and INPUT ''**x**''.
--[[
The function does curve conversion f(inputValue) = outputValue
Example of a curve, having multiple ranges of kx + b, set in a register of a String type with Json
[{"k":4.167,"b":0,"range":[0,3]},{"k":0,"b":12.5,"range":[3,27]},{"k":-4.167,"b":125,"range":[27,30]}]
--]]
function getCurveValue (curveReg, inputValue)
local s, e = 1, 2 -- start & end indexes of the subranges
local tab = cjson.decode( R(curveReg) )
local outputValue, stickOutflag
for _, sub_ in ipairs(tab) do
if ( (sub_.range[s] <= inputValue) and (inputValue < sub_.range[e]) ) then
return (inputValue * sub_.k + sub_.b), nil -- normal sequence
end
end
-- edge cases
if (inputValue < tab[s].range[s]) then
outputValue = tab[s].range[s] * tab[s].k + tab[s].b
stickOutflag = 1
elseif (inputValue > tab[#tab].range[e]) then
outputValue = tab[#tab].range[e] * tab[#tab].k + tab[#tab].b
stickOutflag = #tab
end
return outputValue, stickOutflag
end
Example of usage:
include "curves.lib"
function main (userId)
local SAFE_VALUE = 10
local curHour = tonumber( os.date("*t", os.time()).hour )
INFO("curHour " .. curHour)
local y, valueOutOfRange = getCurveValue("curve_for_curHour", curHour)
if (not valueOutOfRange) then
W("value_for_curHour", y) -- WriteReg
else
W("value_for_curHour", SAFE_VALUE)
end
end
Of course, you can fork a your own lib or use the given one.