Decorators¶
Decorators add behavioral features to motors by wrapping them. Multiple decorators can be stacked to combine features.
CurveDecor – Non-linear Response¶
Converts linear input into an S-shaped curve.

Applying to Motors: Negative bend values create a softer response at low speeds (finer control) with steeper response at high speeds. Positive bend values create sharper initial response with compressed high-end.
template <class Motor, signed short kBend = 0>
class CurveDecor : public Motor
Parameters:
kBend: -10..10 (0 = linear, positive = precise low-speed control, negative = aggressive start)
Methods:
-
SetBend(value)– Set bend at runtime -
Go(value)– Apply curved transformation
Example:
// Precise low-speed control with strong high-end response
using PreciseMotor = evam::CurveDecor<evam::DirectionalMotor<evam::TA6586Driver<9, 10>>, -6>;
PreciseMotor motor;
// Gentle reaction at low-speed
motor.Go(150);
motor.Go(200);
// Strong reaction at high speeds
motor.Go(750);
motor.Go(800);
Use cases:
-
Camera gimbals requiring smooth micro-adjustments
-
Precision positioning systems
-
Vehicles needing both crawling speed control and full power
-
CNC machines with fine feed control
InertiaDecor – Flywheel Effect¶
Simulates mechanical inertia where speed decreases gradually when stopping. Acceleration and direction changes are applied immediately, but deceleration follows an exponential decay curve.
template <class Motor, unsigned short kInertiaMass = 10>
class InertiaDecor : public virtual Tickable, public Motor
Requirements:
Acording EVA principle must call eva::tac() in loop() to drive the deceleration updates.
Parameters:
kInertiaMass: 1..200 (higher = slower deceleration)
Methods:
-
SetInertiaMass(value)– Set virtual mass (1..200) -
Go(speed)– Apply speed with inertia simulation
Example:
using InertialMotor = evam::InertiaDecor<evam::DirectionalMotor<evam::TA6586Driver<9, 10>>, 20>;
InertialMotor motor;
motor.SetInertiaMass(25);
motor.Go(800); // Accelerate
motor.Go(0); // Gradual deceleration
Behavior:
-
Small mass (1-10): Quick stops, responsive
-
Medium mass (11-30): Realistic car-like behavior
-
Large mass (31-200): Heavy flywheel, slow deceleration
Use-case:
For extremely high transmission ratios (e.g., geared motors with high reduction), consider using higher inertia mass values to compensate for the mechanical advantage and gear train inertia.
KickDecor – Static Friction Overcome¶
Applies a momentary power pulse when starting from stop or changing direction to overcome static friction and inertia.
template <class Motor, unsigned short kKickDuration = 20, signed short kKickPower = 1000>
class KickDecor : public virtual Tickable, public Motor
Requirements:
Must call eva::tac() in loop() to manage kick pulse timing.
Parameters:
-
kKickDuration: Pulse duration in milliseconds (> 0) -
kKickPower: Pulse power (-1000..1000)
Methods:
-
SetupKickstart(duration, power)– Configure kick parameters -
SetKickDuration(value)– Set pulse duration -
SetKickPower(value)– Set pulse power -
Go(value)– Apply with kick-start when needed
Example:
using KickerMotor = evam::KickDecor<evam::DirectionalMotor<evam::TA6586Driver<9, 10>>, 30, 900>;
KickerMotor motor;
motor.SetupKickstart(25, 800); // 25ms pulse at 80% power
motor.Go(300); // Kick then maintain 30% power
Kick Logic:
-
From stop to forward: Applies positive kick pulse
-
From stop to reverse: Applies negative kick pulse
-
Direction change: Applies kick in new direction
-
Already moving: No kick, direct control
Combining Decorators¶
Decorators can be stacked in any order to achieve complex behaviors:
#include <evaTac.h>
#include <evamTA6586Driver.h>
#include <evamDirectionalMotor.h>
#include <evamCurveDecor.h>
#include <evamInertiaDecor.h>
#include <evamKickDecor.h>
using namespace eva;
// Stack all three decorators
using BaseMotor = evam::DirectionalMotor<evam::TA6586Driver<9, 10>>;
using PreciseMotor = evam::CurveDecor<BaseMotor, 5>;
using InertialMotor = evam::InertiaDecor<PreciseMotor, 15>;
using SmartMotor = evam::KickDecor<InertialMotor, 25, 900>;
SmartMotor motor;
void setup() {
motor.SetupRange(-1000, -200, 200, 1000);
motor.SetBend(6);
motor.SetInertiaMass(20);
motor.SetupKickstart(30, 850);
motor.Go(800); // All decorators applied
}
void loop() {
eva::tac();
}
Order Effects:
-
Curve before Inertia: Precise low-speed shaping, then inertia applied to smooth signal
-
Inertia before Curve: Inertia on raw signal, then curve shapes the result
-
Kick at any level: Always applied at appropriate layer
Performance Considerations¶
-
InertiaDecor and KickDecor require
eva::tac()calls for timing -
All decorators add minimal overhead (inline templates)
-
Multiple decorators compile to single optimized function chain
-
No runtime polymorphism overhead