Components
Components are C++ classes that use store objects for input/output/parameters/control. This let’s you easily tune and debug an application.
The instances of these classes are tuned at compile-time to reflect the objects in the store. Especially, no resources are used for (optional) fields that do not exist in the store, and all store lookups in the directory are done at compile-time. You need C++14 (or later), though.
Check out the components
and control
examples.
stored::Amplifier
-
template<typename Container, unsigned long long flags = 0, typename T = float>
class Amplifier An offset/gain amplifier, based on store variables.
This class comes in very handy when converting ADC inputs to some SI-value. It includes an override field to force inputs to some test value.
To use this class, add a scope to your store, like:
{ float input bool=true enable float=1 gain float=0 offset float=-inf low float=inf high float=nan override float output } amp
All fields are optional. All variables of type
float
can be any other type, as long as it matches the template parameterT
.When not all fields are in the store, names may become ambiguous. For example, if override and output are not there, the store’s directory may resolve
o
to any of the three fields. In this case, you have to specify which fields are to be processed. For this, use the following ids:field
id
input
I
enable
e
gain
g
offset
o
low
l
high
h
override
F
output
O
The amplifier basically does:
if(override is nan) output = min(high, max(low, input * gain + offset)) else output = override
Then, instantiate the amplifier like this:
// Construct a compile-time object, which resolves all fields in your store. constexpr auto amp_o = stored::Amplifier<stored::YourStore>::objects("/amp/"); // Instantiate an Amplifier, tailored to the available fields in the store. stored::Amplifier<stored::YourStore, amp_o.flags()> amp{amp_o, yourStore};
Or, for example when you know there are only the offset and gain fields in the store, and ambiguity must be resolved:
// Construct a compile-time object, which resolves only two fields in your store. constexpr auto amp_o = stored::Amplifier<stored::YourStore>::objects<'o','g'>("/amp/"); stored::Amplifier<stored::YourStore, amp_o.flags()> amp{amp_o, yourStore};
Calling
amp()
now uses theinput
and produces the value inoutput
. Alternatively, or when theinput
field is absent in the store, callamp(x)
, wherex
is the input.Public Types
Public Functions
-
constexpr Amplifier() noexcept = default
Default ctor.
Use this when initialization is postponed. Do not access or run the Amplifier instance, as it does not hold proper references to a store. You can just assign another Amplifier instance.
-
inline constexpr Amplifier(AmplifierObjects<Container, type> const &o, Container &container)
Initialize the Amplifier, given a list of objects and a container.
-
inline void disable() noexcept
Disable the Amplifier.
Ignored when the
enable
object is not available.
-
inline void enable(bool value = true) noexcept
Enable (or disable) the Amplifier.
Ignored when the
enable
object is not available.
-
inline bool enabled() const noexcept
Return the
enable
value, which istrue
when not available.
-
inline decltype(auto) enableObject() const noexcept
Return the
enable
object.
-
inline decltype(auto) enableObject() noexcept
Return the
enable
object.
-
inline decltype(auto) gainObject() const noexcept
Return the
gain
object.
-
inline decltype(auto) gainObject() noexcept
Return the
gain
object.
-
inline decltype(auto) highObject() const noexcept
Return the
high
object.
-
inline decltype(auto) highObject() noexcept
Return the
high
object.
-
inline decltype(auto) inputObject() const noexcept
Return the
input
object.
-
inline decltype(auto) inputObject() noexcept
Return the
input
object.
-
inline decltype(auto) lowObject() const noexcept
Return the
low
object.
-
inline decltype(auto) lowObject() noexcept
Return the
low
object.
-
inline decltype(auto) offsetObject() const noexcept
Return the
offset
object.
-
inline decltype(auto) offsetObject() noexcept
Return the
offset
object.
-
inline type operator()() noexcept
Compute the Amplifier output, given the input as stored in the store.
-
inline decltype(auto) outputObject() const noexcept
Return the
output
object.
-
inline decltype(auto) outputObject() noexcept
Return the
output
object.
-
inline decltype(auto) overrideObject() const noexcept
Return the
override
object.
-
inline decltype(auto) overrideObject() noexcept
Return the
override
object.
-
constexpr Amplifier() noexcept = default
stored::FirstOrderFilter
-
template<typename Container, bool LowPass, unsigned long long flags = 0, typename T = float>
class FirstOrderFilter First-order low- or high-pass filter, based on store variables.
To use this class, add a scope to your store, like:
{ (float) sample frequency (Hz) float input float cutoff frequency (Hz) bool=true enable bool reset float=nan override float output } filter
Only
sample frequency
andcutoff frequency
are mandatory. All variables of typefloat
, except forsample frequency
, can be any other type, as long as it matches the template parameterT
.Then, instantiate the controller like this:
// Construct a compile-time object, which resolves all fields in your store. constexpr auto filter_o = stored::LowPass<stored::YourStore>::objects("/filter/"); // Instantiate the filter, tailored to the available fields in the store. stored::LowPass<stored::YourStore, filter_o.flags()> filter{filter_o, yourStore}; // ...or use HighPass instead of LowPass.
The cutoff frequency can be changed while running (by setting
reset
totrue
). It will applied smoothly; the output will gradually take the new cutoff frequency into account.Public Types
Public Functions
-
constexpr FirstOrderFilter() noexcept = default
Default ctor.
Use this when initialization is postponed. You can assign another instance later on.
-
inline constexpr FirstOrderFilter(FirstOrderFilterObjects<Container, type> const &o, Container &container)
Initialize the filter, given a list of objects and a container.
-
inline decltype(auto) cutoffFrequencyObject() const noexcept
Return the
cutoff frequency
object.
-
inline decltype(auto) cutoffFrequencyObject() noexcept
Return the
cutoff frequency
object.
-
inline void disable() noexcept
Disable the pulse wave.
Ignored when the
enable
object is not available.
-
inline void enable(bool value = true) noexcept
Enable (or disable) the pulse wave.
Ignored when the
enable
object is not available.
-
inline bool enabled() const noexcept
Return the
enable
value, ortrue
when not available.
-
inline decltype(auto) enableObject() const noexcept
Return the
enable
object.
-
inline decltype(auto) enableObject() noexcept
Return the
enable
object.
-
inline decltype(auto) inputObject() const noexcept
Return the
input
object.
-
inline decltype(auto) inputObject() noexcept
Return the
input
object.
-
inline decltype(auto) outputObject() const noexcept
Return the
output
object.
-
inline decltype(auto) outputObject() noexcept
Return the
output
object.
-
inline decltype(auto) overrideObject() const noexcept
Return the
override
object.
-
inline decltype(auto) overrideObject() noexcept
Return the
override
object.
-
inline void recomputeCoefficients()
Recompute alpha after changed filter parameters.
-
inline bool reset() const noexcept
Return the
reset
value, orfalse
when not available.
-
inline decltype(auto) resetObject() const noexcept
Return the
reset
object.
-
inline decltype(auto) resetObject() noexcept
Return the
reset
object.
-
inline float sampleFrequency() const noexcept
Return the sample frequency.
-
inline decltype(auto) sampleFrequencyObject() const noexcept
Return the
sample frequency
object.
-
constexpr FirstOrderFilter() noexcept = default
There are stored::LowPass
and stored::HighPass
aliases for the corresponding stored::FistOrderFilter
template parameters.
stored::PID
-
template<typename Container, unsigned long long flags = 0, typename T = float>
class PID PID controller, based on store variables.
To use this class, add a scope to your store, like:
{ (float) frequency (Hz) float y float setpoint bool=true enable float=1 Kp float=inf Ti (s) float=0 Td (s) float=0 Kff float int float=-inf int low float=inf int high float=-inf low float=inf high float=inf error max float=inf epsilon bool reset float=nan override float u } pid
Only
frequency
,setpoint
, andKp
are mandatory. All variables of typefloat
, except forfrequency
, can be any other type, as long as it matches the template parameterT
.It has the following objects:
frequency:
the control frequency; the application must invoke the PID controller at this frequencyy:
the process variable (output of the plant)setpoint:
the setpoint to controly
toKp:
P coefficientTi:
I time constantTd:
D time constantKff:
feed-forward coefficientint:
current integral valueint low
: lower bound forint
int high
: upper bound forint
low:
lower bound for computedu
high:
upper bound for computedu
epsilon:
minimum value of the error ( |setpoint
-y
| ), which must result in a change of the outputu
. Otherwise, numerical stability is compromised. See isHealthy().reset:
when set totrue
, recompute and apply changed control parametersoverride:
when not NaN, forceu
to this value, withoutlow
andhigh
appliedu:
control output (input for the plant)
Then, instantiate the controller like this:
// Construct a compile-time object, which resolves all fields in your store. constexpr auto pid_o = stored::PID<stored::YourStore>::objects("/pid/"); // Instantiate a PID, tailored to the available fields in the store. stored::PID<stored::YourStore, pid_o.flags()> pid{pid_o, yourStore};
The PID controller has the following properties:
The parameters specify a serial PID.
The integral windup prevention stops the integral when the output clips.
Changing Ti is implemented smoothly; changing the parameters (and setting
reset
afterwards) can be done while running.isHealthy() checks for numerical stability.
Public Types
Public Functions
-
constexpr PID() noexcept = default
Default ctor.
Use this when initialization is postponed. You can assign another instance later on.
-
inline constexpr PID(PIDObjects<Container, type> const &o, Container &container)
Initialize the pin, given a list of objects and a container.
-
inline void enable(bool value = true) noexcept
Enable (or disable) the PID.
Ignored when the
enable
object is not available.
-
inline bool enabled() const noexcept
Return the
enable
value, ortrue
when not available.
-
inline decltype(auto) enableObject() const noexcept
Return the
enable
object.
-
inline decltype(auto) enableObject() noexcept
Return the
enable
object.
-
inline decltype(auto) epsilonObject() const noexcept
Return the
epsilon
object.
-
inline decltype(auto) epsilonObject() noexcept
Return the
epsilon
object.
-
inline decltype(auto) errorMaxObject() const noexcept
Return the
error max
object.
-
inline decltype(auto) errorMaxObject() noexcept
Return the
error max
object.
-
inline float frequency() const noexcept
Return the control frequency.
-
inline decltype(auto) frequencyObject() const noexcept
Return the
frequency
object.
-
inline decltype(auto) highObject() const noexcept
Return the
high
object.
-
inline decltype(auto) highObject() noexcept
Return the
high
object.
-
inline type int_() const noexcept
Return the current integral value.
This is the integral of the
(setpoint - y) * Ki
. So, when Ti (and there fore Ki) changes, it may take a while till the new Ti is in effect, depending on the current integral value.
-
inline decltype(auto) intHighObject() const noexcept
Return the
int high
object.
-
inline decltype(auto) intHighObject() noexcept
Return the
int high
object.
-
inline decltype(auto) intLowObject() const noexcept
Return the
int low
object.
-
inline decltype(auto) intLowObject() noexcept
Return the
int low
object.
-
inline decltype(auto) intObject() const noexcept
Return the
int
object.
-
inline decltype(auto) intObject() noexcept
Return the
int
object.
-
inline bool isHealthy() const noexcept
Check numerical stability.
epsilon() is the smallest change in error ( | setpoint() - y() | ) that must have influence the output u(). If the error is smaller, the output may remain the same. This function checks if that is still the case.
The integrator is especially interesting. If it becomes too large, successive (small) errors may not be able to reduce it anymore, because of rounding. If that is the case, it is considered unhealthy.
This value can optionally be defined in the store. If omitted, this function always returns
true
.You may want to check (or assert on) this function once in a while, like once per second or after every run, to detect a stuck controller within reasonable time for your application.
-
inline decltype(auto) KffObject() const noexcept
Return the
Kff
object.
-
inline decltype(auto) KffObject() noexcept
Return the
Kff
object.
-
inline decltype(auto) KpObject() const noexcept
Return the
Kp
object.
-
inline decltype(auto) KpObject() noexcept
Return the
Kp
object.
-
inline decltype(auto) lowObject() const noexcept
Return the
low
object.
-
inline decltype(auto) lowObject() noexcept
Return the
low
object.
-
inline decltype(auto) overrideObject() const noexcept
Return the
override
object.
-
inline decltype(auto) overrideObject() noexcept
Return the
override
object.
-
inline bool reset() const noexcept
Return the
reset
value, orfalse
when not available.
-
inline decltype(auto) resetObject() const noexcept
Return the
reset
object.
-
inline decltype(auto) resetObject() noexcept
Return the
reset
object.
-
inline decltype(auto) setpointObject() const noexcept
Return the
setpoint
object.
-
inline decltype(auto) setpointObject() noexcept
Return the
setpoint
object.
-
inline decltype(auto) TdObject() const noexcept
Return the
Td
object.
-
inline decltype(auto) TdObject() noexcept
Return the
Td
object.
-
inline decltype(auto) TiObject() const noexcept
Return the
Ti
object.
-
inline decltype(auto) TiObject() noexcept
Return the
Ti
object.
-
inline decltype(auto) uObject() const noexcept
Return the
u
object.
-
inline decltype(auto) uObject() noexcept
Return the
u
object.
-
inline decltype(auto) yObject() const noexcept
Return the
y
object.
-
inline decltype(auto) yObject() noexcept
Return the
y
object.
stored::PinIn
-
template<typename Container, unsigned long long flags = 0>
class PinIn An GPIO input pin, based on store variables.
This class comes in very handy when a GPIO input should be observed and overridden while debugging. It gives some interface between the hardware pin and the input that the application sees.
To use this class, add a scope to your store, like:
{ (bool) pin int8=-1 override bool input (bool) get } pin
All fields are optional. You can implement the store’s
pin
function, override the virtualpin()
function of the PinIn class, or pass the hardware pin value as an argument to the PinIn::operator().The pin basically does:
switch(override) { case -1: input = pin; break; case 0: input = false; break; case 1: input = true; break; case 2: input = !pin; break; }
Then, instantiate the pin like this:
// Construct a compile-time object, which resolves all fields in your store. constexpr auto pin_o = stored::PinIn<stored::YourStore>::objects("/pin/"); // Instantiate an PinIn, tailored to the available fields in the store. stored::PinIn<stored::YourStore, pin_o.flags()> pin{pin_o, yourStore};
When
pin()
is called, it will invoke thepin
function to get the actual hardware pin status. Then, it will set theinput
variable.The
get
function is not used/provided by thisPinIn
. Implement this store function such that it calls and returnspin()
. When applications read theget
function, they will always get the appropriate/actual pin value.Public Functions
-
constexpr PinIn() noexcept = default
Default ctor.
Use this when initialization is postponed. You can assign another instance later on.
-
inline constexpr PinIn(PinInObjects<Container> const &o, Container &container)
Initialize the pin, given a list of objects and a container.
-
virtual ~PinIn() = default
Dtor.
-
inline bool input() const noexcept
Return the last computed
input
value, or compute the pin state when the object is not available.
-
inline decltype(auto) inputObject() const noexcept
Return the
input
object.
-
inline decltype(auto) inputObject() noexcept
Return the
input
object.
-
inline bool operator()() noexcept
Determine pin input, given the current hardware state.
-
inline bool operator()(bool pin) noexcept
Determine pin input, given the provided hardware state.
-
inline int8_t override_() const noexcept
Return the
override
value, or -1 when the object is not available.
-
inline decltype(auto) overrideObject() const noexcept
Return the
override
object.
-
inline decltype(auto) overrideObject() noexcept
Return the
override
object.
-
inline virtual bool pin() const noexcept
Return the hardware pin value.
By default, it calls the
pin
function in the store. Override in a subclass to implement other behavior.
-
inline decltype(auto) pinObject() const noexcept
Return the
pin
object.
-
constexpr PinIn() noexcept = default
stored::PinOut
-
template<typename Container, unsigned long long flags = 0>
class PinOut An GPIO output pin, based on store variables.
This class comes in very handy when a GPIO output should be observed and overridden while debugging. It gives some interface between the hardware pin and the output that the application wants.
To use this class, add a scope to your store, like:
{ (bool) set bool output (int8) override (bool) pin } pin
All fields are optional, except
output
. You can implement the store’spin
function, override the virtualpin()
function of the PinOut class, or forward the return value of PinOut::operator() to the hardware pin.The pin basically does:
switch(override) { case -1: pin = output; break; case 0: pin = false; break; case 1: pin = true; break; case 2: pin = !output; break; }
Then, instantiate the pin like this:
// Construct a compile-time object, which resolves all fields in your store. constexpr auto pin_o = stored::PinOut<stored::YourStore>::objects("/pin/"); // Instantiate an PinOut, tailored to the available fields in the store. stored::PinOut<stored::YourStore, pin_o.flags()> pin{pin_o, yourStore};
The
set
function is not used/provided by thisPinOut
. Implement this store function such that it callspin()
with the provided value. When applications write theset
function, they will immediately control the hardware pin.Similar holds for the
override
function; implement it to call the override_() of PinOut. This way, if one sets the override value, the hardware pin is updated accordingly.Public Functions
-
constexpr PinOut() noexcept = default
Default ctor.
Use this when initialization is postponed. You can assign another instance later on.
-
inline constexpr PinOut(PinOutObjects<Container> const &o, Container &container)
Initialize the pin, given a list of objects and a container.
-
virtual ~PinOut() = default
Dtor.
-
inline bool operator()() noexcept
Compute and set the hardware pin status, given the last provided application’s output value.
-
inline bool operator()(bool output) noexcept
Compute and set the hardware pin status, given the application’s output value.
-
inline bool output() const noexcept
Return the
output
value.
-
inline decltype(auto) outputObject() const noexcept
Return the
output
object.
-
inline decltype(auto) outputObject() noexcept
Return the
output
object.
-
inline int8_t override_() const noexcept
Return the override value.
-
inline void override_(int8_t x) noexcept
Set the override value.
-
inline virtual void pin(bool value) noexcept
Set the hardware pin state.
The default implementation calls the store’s
pin
function. Override in a subclass to implement custom behavior.
-
inline decltype(auto) pinObject() noexcept
Return the
pin
object.
-
constexpr PinOut() noexcept = default
stored::PulseWave
-
template<typename Container, unsigned long long flags = 0, typename T = float>
class PulseWave Pulse wave generator, based on store variables.
To use this class, add a scope to your store, like:
{ (float) sample frequency (Hz) float=1 amplitude float=1 frequency (Hz) float=0 phase (rad) float=0.5 duty cycle bool=true enable float=nan override float output } pulse
Only
sample frequency
is mandatory. All variables of typefloat
, except forsample frequency
, can be any other type, as long as it matches the template parameterT
.When either
override
oroutput
is omitted, names may become ambiguous. In that case, provide the ids of the fields that are in the store, as template parameters to objects():field
id
sample frequency
s
amplitude
A
frequency
f
phase
p
duty cycle
d
enable
e
override
F
output
O
Then, instantiate the controller like this:
// Construct a compile-time object, which resolves all fields in your store. constexpr auto pulse_o = stored::PulseWave<stored::YourStore>::objects("/pulse/"); // Instantiate the generator, tailored to the available fields in the store. stored::PulseWave<stored::YourStore, pulse_o.flags()> pulse{pulse_o, yourStore};
Public Types
Public Functions
-
constexpr PulseWave() noexcept = default
Default ctor.
Use this when initialization is postponed. You can assign another instance later on.
-
inline constexpr PulseWave(PulseWaveObjects<Container, type> const &o, Container &container)
Initialize the pulse wave, given a list of objects and a container.
-
inline decltype(auto) amplitudeObject() const noexcept
Return the
amplitude
object.
-
inline decltype(auto) amplitudeObject() noexcept
Return the
amplitude
object.
-
inline void disable() noexcept
Disable the pulse wave.
Ignored when the
enable
object is not available.
-
inline decltype(auto) dutyCycleObject() const noexcept
Return the
duty cycle
object.
-
inline decltype(auto) dutyCycleObject() noexcept
Return the
duty cycle
object.
-
inline void enable(bool value = true) noexcept
Enable (or disable) the pulse wave.
Ignored when the
enable
object is not available.
-
inline bool enabled() const noexcept
Return the
enable
value, ortrue
when not available.
-
inline decltype(auto) enableObject() const noexcept
Return the
enable
object.
-
inline decltype(auto) enableObject() noexcept
Return the
enable
object.
-
inline decltype(auto) frequencyObject() const noexcept
Return the
frequency
object.
-
inline decltype(auto) frequencyObject() noexcept
Return the
frequency
object.
-
inline bool isHealthy() const noexcept
Check numerical stability.
This function checks if for every control interval (1 / sampleFrequency()), the output is actually updated. Especially the period and phase values are checked if they are not too big.
You may want to check (or assert on) this function once in a while, like once per second or after every run, to detect a stuck controller within reasonable time for your application.
-
inline decltype(auto) outputObject() const noexcept
Return the
output
object.
-
inline decltype(auto) outputObject() noexcept
Return the
output
object.
-
inline decltype(auto) overrideObject() const noexcept
Return the
override
object.
-
inline decltype(auto) overrideObject() noexcept
Return the
override
object.
-
inline decltype(auto) phaseObject() const noexcept
Return the
phase
object.
-
inline decltype(auto) phaseObject() noexcept
Return the
phase
object.
-
inline float sampleFrequency() const noexcept
Return the sample frequency.
-
inline decltype(auto) sampleFrequencyObject() const noexcept
Return the
sample frequency
object.
-
constexpr PulseWave() noexcept = default
stored::Ramp
-
template<typename Container, unsigned long long flags = 0, typename T = float>
class Ramp Ramping setpoints, based on store variables.
This is a quadratic path planner, that creates a smooth path from the current output towards the provided input. The speed and acceleration can be limited.
To use this class, add a scope to your store, like:
{ (float) sample frequency (Hz) float input float=inf speed limit float=inf acceleration limit bool reset bool=true enable float=nan override float output } ramp
Only
sample frequency
is mandatory. All variables of typefloat
, except forsample frequency
, can be any other type, as long as it matches the template parameterT
.Then, instantiate the controller like this:
// Construct a compile-time object, which resolves all fields in your store. constexpr auto ramp_o = stored::Ramp<stored::YourStore>::objects("/ramp/"); // Instantiate the generator, tailored to the available fields in the store. stored::Ramp<stored::YourStore, ramp_o.flags()> ramp{ramp_o, yourStore};
The parameters can be changed while running (when
reset
is set totrue
). The change will be applied smoothly to the path.Public Types
-
using type_ = long
Public Functions
-
constexpr Ramp() noexcept = default
Default ctor.
Use this when initialization is postponed. You can assign another instance later on.
-
inline constexpr Ramp(RampObjects<Container, type> const &o, Container &container)
Initialize the ramp, given a list of objects and a container.
-
inline type accelerationLimit() const noexcept
Return the
acceleration limit
value, or inf when not available.
-
inline decltype(auto) accelerationLimitObject() const noexcept
Return the
acceleration limit
object.
-
inline decltype(auto) accelerationLimitObject() noexcept
Return the
acceleration limit
object.
-
inline void disable() noexcept
Disable the pulse wave.
Ignored when the
enable
object is not available.
-
inline void enable(bool value = true) noexcept
Enable (or disable) the ramp.
Ignored when the
enable
object is not available.
-
inline bool enabled() const noexcept
Return the
enable
value, ortrue
when not available.
-
inline decltype(auto) enableObject() const noexcept
Return the
enable
object.
-
inline decltype(auto) enableObject() noexcept
Return the
enable
object.
-
inline decltype(auto) inputObject() const noexcept
Return the
input
object.
-
inline decltype(auto) inputObject() noexcept
Return the
input
object.
-
inline bool isHealthy() const noexcept
Check numerical stability.
The Ramp is considered healthy when the configured acceleration and speed values are within the floating point precision.
You may want to check (or assert on) this function once in a while, like once per second or after every run, to detect a stuck ramp within reasonable time for your application.
-
inline decltype(auto) outputObject() const noexcept
Return the
output
object.
-
inline decltype(auto) outputObject() noexcept
Return the
output
object.
-
inline decltype(auto) overrideObject() const noexcept
Return the
override
object.
-
inline decltype(auto) overrideObject() noexcept
Return the
override
object.
-
inline bool reset() const noexcept
Return the
reset
value, orfalse
when not available.
-
inline decltype(auto) resetObject() const noexcept
Return the
reset
object.
-
inline decltype(auto) resetObject() noexcept
Return the
reset
object.
-
inline float sampleFrequency() const noexcept
Return the sample frequency.
-
inline decltype(auto) sampleFrequencyObject() const noexcept
Return the
sample frequency
object.
-
inline decltype(auto) speedLimitObject() const noexcept
Return the
speed limit
object.
-
inline decltype(auto) speedLimitObject() noexcept
Return the
speed limit
object.
-
using type_ = long
stored::Sine
-
template<typename Container, unsigned long long flags = 0, typename T = float>
class Sine Sine wave generator, based on store variables.
To use this class, add a scope to your store, like:
{ (float) sample frequency (Hz) float=1 amplitude float=0.159 frequency (Hz) float=0 phase (rad) float=0 offset bool=true enable float=nan override float output } sine
Only
sample frequency
is mandatory. All variables of typefloat
, except forsample frequency
, can be any other type, as long as it matches the template parameterT
.When either
override
oroutput
is omitted, names may become ambiguous. In that case, provide the ids of the fields that are in the store, as template parameters to objects():field
id
sample frequency
s
amplitude
A
frequency
f
phase
p
offset
o
enable
e
override
F
output
O
Then, instantiate the sine wave generator like this:
// Construct a compile-time object, which resolves all fields in your store. constexpr auto sine_o = stored::Sine<stored::YourStore>::objects("/sine/"); // Instantiate the generator, tailored to the available fields in the store. stored::Sine<stored::YourStore, sine_o.flags()> sine{sine_o, yourStore};
When the parameters of the sine wave are changed while running, they are applied immediately, without a smooth transition.
Public Types
Public Functions
-
constexpr Sine() noexcept = default
Default ctor.
Use this when initialization is postponed. You can assign another instance later on.
-
inline constexpr Sine(SineObjects<Container, type> const &o, Container &container)
Initialize the sine, given a list of objects and a container.
-
inline decltype(auto) amplitudeObject() const noexcept
Return the
amplitude
object.
-
inline decltype(auto) amplitudeObject() noexcept
Return the
amplitude
object.
-
inline void disable() noexcept
Disable the sine wave.
Ignored when the
enable
object is not available.
-
inline void enable(bool value = true) noexcept
Enable (or disable) the sine wave.
Ignored when the
enable
object is not available.
-
inline bool enabled() const noexcept
Return the
enable
value, ortrue
when not available.
-
inline decltype(auto) enableObject() const noexcept
Return the
enable
object.
-
inline decltype(auto) enableObject() noexcept
Return the
enable
object.
-
inline decltype(auto) frequencyObject() const noexcept
Return the
frequency
object.
-
inline decltype(auto) frequencyObject() noexcept
Return the
frequency
object.
-
inline bool isHealthy() const noexcept
Check numerical stability.
This function checks if for every control interval (1 / sampleFrequency()), the output is actually updated. Especially the period and phase values are checked if they are not too big.
You may want to check (or assert on) this function once in a while, like once per second or after every run, to detect a stuck controller within reasonable time for your application.
-
inline decltype(auto) offsetObject() const noexcept
Return the
offset
object.
-
inline decltype(auto) offsetObject() noexcept
Return the
offset
object.
-
inline decltype(auto) outputObject() const noexcept
Return the
output
object.
-
inline decltype(auto) outputObject() noexcept
Return the
output
object.
-
inline decltype(auto) overrideObject() const noexcept
Return the
override
object.
-
inline decltype(auto) overrideObject() noexcept
Return the
override
object.
-
inline decltype(auto) phaseObject() const noexcept
Return the
phase
object.
-
inline decltype(auto) phaseObject() noexcept
Return the
phase
object.
-
inline float sampleFrequency() const noexcept
Return the sample frequency.
-
inline decltype(auto) sampleFrequencyObject() const noexcept
Return the
sample frequency
object.
-
constexpr Sine() noexcept = default