//not applicable to angles
inline float minmax( float Input_i, float MIN, float MAX)
{
return Input_i> MAX? MAX : (Input_i< MIN? MIN : Input);
}
Behavior: the output is always one of the values encountered
when starting a rotation from MIN included and moving counterclockwise till MAX is reached.
If Input is outside range, the return value is the closest of MIN and MAX.
//for angles only
float minmaxAng( float Input_i, float MIN, float MAX)// all in [0,PERIOD[
{
float TmpHalfRange= 0.5f*( MAX- MIN);
float TmpCenter= 0.5f*( MAX+ MIN);
if( MIN> MAX)
{
TmpCenter+= HALFPERIOD;
if( TmpCenter> PERIOD) TmpCenter-= PERIOD;
TmpHalfRange+= HALFPERIOD;
}
float TmpDelta= wrapHalfPrd(Input_i- TmpCenter);
if( TmpDelta> TmpHalfRange) return MAX;
else if( TmpDelta< -TmpHalfRange) return MIN;
return Input_i;
}
//not applicable to angles
float threshold( float Input_i, float MIN, float MAX)
{
return ( Input_i- minmax(Input_i, MIN, MAX)) ;
}
Threshold for angles, symmetrical and centered on "PrmCenter"
// for angles only
float thresholdSymAng( float Input_i, float PrmCenter_i, float PrmHalfRange_i)//all in [0, PERIOD[
{
float D_a= wrapHalfPrd( Input_i- PrmCenter_i);
if( D_a> PrmHalfRange_i)
{
Input_i-= PrmHalfRange_i;
if( Input_i< 0) Input_i+= PERIOD;
return Input_i;
}
else if( D_a< -PrmHalfRange_i)
{
Input_i+= PrmHalfRange_i;
if( Input_i>= PERIOD) Input_i-= PERIOD;
return Input_i;
}
return PrmCenter_i;
}
Threshold for angles, general case
for angles only
float thresholdAng( float InputAng_i, float MIN, float MAX)//all in [0, PERIOD[
{
float TmpHR= 0.5f*( MAX- MIN);
float TmpC= 0.5f*( MAX+ MIN);
if( MIN> MAX)
{
TmpC+= HALFPERIOD;
if( TmpC> PERIOD) TmpC-= PERIOD;
TmpHR+= HALFPERIOD;
}
return thresholdSymAng( InputAng_i, TmpC, TmpHR);
}
timestep independent 1st order dynsyst.
Sometimes ( wrongly) referred to as hysteresis.
Behavior: it is a "floating" dead-range around the current input value ,and is actually
implemented by placing a threshold on (Input-Output).
//not applicable to angles
inline float backlash( float Output_i/*previous step value*/, float Input_i, float HALFDEADRANGE)
{
return Output_i+ threshold( Input_i- Output_i, -HALFDEADRANGE, HALFDEADRANGE);
//or: return Input_i- minmax( Input_i- Output_i, -HALFDEADRANGE, HALFDEADRANGE);
}
//for angles only
float backlashAng( float Output_i/*previous step value*/, float Input_i, float HALFDEADRANGE)
{
float TmpDelta= wrapHalfPrd( Input_i- Output_i);
Output_i+= TmpDelta;
TmpDelta= minmax( TmpDelta,-HALFDEADRANGE,+ HALFDEADRANGE);
Output_i-= TmpDelta;
Output_i= wrapPrd( Output_i);
return Output_i;
}
time step dependent 1st order dynsysts.
Behavior: the output rate of increase or "Speed"=(Xn - Xn-1)/T is bounded to the [SPEEDMIN, SPEEDMAX] range, with SPEEDMIN<0< SPEEDMAX.
float minmaxSpeed( float T/*current timestep*/, float Output_i/*previous step value*/, float Input_i, float SPEEDMIN, float SPEEDMAX)
{
float TmpDelta= (Input_i- Output_i);
TmpDelta= wrapHalfPrd( TmpDelta);
float TmpSpeed= TmpDelta/ T;
TmpSpeed= minmax( TmpSpeed, SPEEDMIN, SPEEDMAX);
Output_i= Output_i+ T* TmpSpeed;
Output_i= wrapPrd( Output_i);
return Output_i;
}