Throbol Reference Manual
Overview
Throbol is a time-domain spreadsheet. Like a spreadsheet, every cell has a name and formula, and cells can refer to each other by name. The recalculation engine automatically figures out what order to calculate them in. Unlike most spreadsheets, each cell's value is a time series. You can refer to a cell's current value as foo
, and its previous value as foo[-dt]
.
Throbol can be used in 3 modes:
- controlling live robot hardware.
- controlling a simulated robot.
- a pure spreadsheet.
When controlling a live robot, runs must be started with ⌘L. With a simulated robot, it will re-run the simulation whenever a formula or parameter changes.
Throbol formula language quick reference
-
Types and literals:
float
like3.0
complex
like3.0 + 4.2im
vec3
like[1, 2, 3]
: a column vector. Any size works.mat2
like[[1, 2], [3, 4]]
: a square matrix with columns[1,2]
and[3,4]
. Any size works.mat23x42
: a rectangular matrix. Any size worksstring
like"foo"
SymbolSet
like'foo
or'mode.start | 'mode.run
-
Parameters:
value~range
like6.2~10
: a float parameter with a current value of 6.2 and a range of -10 .. +10expr~range
like[1.1, 2.2, 3.3]~5
: all numeric values in expr become parameters
-
Arithmetic:
a + b
: scalar, complex, vector, or matrix additiona - b
: as expecteda * b
: as expected for scalar. Matmul semantics for mat * mat or mat * veca / b
: as expected, but matrices and vectors can only be divided by a scalara .+ b
,a .- b
,a .* b
,a ./ b
: Elementwise arithmetica ^ b
: exponentiation
-
Math functions:
sin(a)
,cos(a)
,tan(a)
,sinh(a)
,cosh(a)
,tanh(a)
,exp(a)
,log(a)
: as in Csqrt(a)
,sqr(a)
,cbrt(a)
,cube(a)
: as in C, or usea^0.5
,a^2
,a^(1/3)
,a^3
lerp(a, b, c)
: interpolate between a & b, equivalent toa + c * (b - a)
-
Randomness:
random()
uniform in [0..1]randomNormal()
from clamped to [-3..3]
-
Comparison:
bool(a)
: likea >= 0.5 ? 1.0 : 0.0
a == b
: exact equalitya ~~ b
: true ifa
andb
are similar (within 0.1%)a ~~~ b
: signal an error ifa
andb
aren't similar. Either way, returna
-
Sets:
a | b
: union of sets a and ba & b
: intersection
-
Misc:
repr(a)
: string representation
-
Functions:
foo{a=1, b=2}
: the value of cellfoo
with cellsa
andb
(which must exist) having the values provided.
-
Control Theory:
lpfilter1(period, input)
: a single pole low-pass filterlpfilter2(period, q, input)
: a double pole low-pass filtervel(a)
: the time derivative of a, calculated as(a - a[-dt])/dt
lookahead(t, a)
: a prediction of the value ofa
int
seconds, calculated asa + vel(a)*t
-
Stateful functions:
duration(a)
: the time (in seconds) thata
has been continuously true for.duration(a, 'foo|'bar)
: the time that behavior treea
has run either'foo
or'bar
latch(a)
: true ifa
was ever truelatch(a, b)
: becomes true whena
is true, or false whenb
is false. If both are true, returns false.hysteresis(a)
: becomes 1 whenevera > 0.5
, or -1 whenevera < -0.5
clampslew(a, ratelo, ratehi)
: follows a, but changes at a rate clamped betweenratelo
andratehi
.
-
Geometry:
length(a)
: norm2 of a vectordistance(a, b)
: length of a-bmat4.rotx(a)
,mat4.roty(a)
,mat4.rotz(a)
: 4x4 rotation matrix around an axis.mat4.rotxderiv(a)
,mat4.rotyderiv(a)
,mat4.rotzderiv(a)
: the derivative of above matrices WRT amat4.scale(a)
: 4x4 scale matrixmat4.translate(a)
,mat4.translate(x, y, z)
: translation by a∊vec3 or x, y, z.mat3.rotx(a)
,mat3.roty(a)
,mat3.rotz(a)
: 3x3 rotation around an axismat3.scale(a)
ormat3.scale(x, y, z)
: 3x3 scale matrixmat2.rot(a)
: 2x2 rotation matrixmat2.scale(a)
ormat2.scale(x, y)
: 2x2 scale matrixnormangle(a)
: modulo 2pi, within -pi to +pinormalize(a)
: likea/length(a)
-
Complex:
3.0 + 4.2im
: complex number. Equivalent to3.0 + 4.2*im
polar(length, angle)
: complex number from length & angle.conj(a)
: complex conjugatereal(a)
,imag(a)
: get real or imaginary componentarg(a)
: get angleabs(a)
: get magnitudemat2(a)
: same as[[real(a), -imag(a)], [imag(a), real(a)]]
-
Cells:
- Every cells has a name, consisting of alphanumerics and
.
. - You can refer to the value of a cell by name like
foo
, or the previous value withfoo[-dt]
, or a value at some past time withfoo[-0.5]
. References to times before 0 return a zero or null value (generally safe to work with). - Any number of expressions terminated by semicolons can preceed the cell value. It's useful for binding cell-local variables, like
a=2; b=3; a + b
yields 5.
- Every cells has a name, consisting of alphanumerics and
-
Graphics:
line(p0 ∊ vec2|3|4, p1 ∊ same)
: a line from p0 to p1linePlot(x, y)
orlinePlot(x, y, z)
- Add axis labels:
linePlot(volume, pressure){labelX="V", labelY="P"}
- Set ranges:
linePlot(volume, pressure){rangeX=[0, 100], rangeY=[0, 800]}
- Add axis labels:
scatterPlot(x, y)
orscatterPlot(x, y, z)
: as above but with dots- Add a linear regression line with
scatterPlot(x, y){regressionLine=1}
- Add a linear regression line with
spline(controlPoints ∊ mat3xN, thickness)
disk(center, size)
text(pos, size, str)
withsize
∊ float is the font size. 0.05 is common.solid(filename)
: a solid loaded from an STL filedial(value, range)
ordial(center, radius, value, range)
- One or more
label(value, str)
s can be attached to mark points on the dial
- One or more
arcArrow(center, rx, ry, up)
:- Set color by adding
{color=#ff0000ff}
or{color=graphColor(12)}
.- The syntax
#RRGGBBAA
results in avec4
of RGBA values in[0..1]
graphColor(index)
: returns a pleasing color for each integer index,
- The syntax
- Multiple graphics can be combined (overlaid) with
|
. They're drawn in left-to-right order, although you should mostly use the Z axis to determine layering - You can transform graphics by pre-multiplying with a mat4.
- See the Stirling engine sheet for an example of graphs, or the Solo12 for an example of 3D rendering.
-
Optimization:
minimize.lbfgsb(target, params...)
: apply an L-BFGS-B optimizer to minimize the target value. Parameters aren't directly changed; this cell returns a graphical object you can click on to inspect suggested parameter changes or apply them.minimize.newton
,minimize.grad
,minimize.cgrad
,minimize.bfgs
,minimize.lbfgs
: Like the above using other algorithms from Minpack.minimize.particle(target, params...)
: particle search minimize