#ifndef DEF_FlyByWire #define DEF_FlyByWire #include typedef double Real; #define HUGE_VALUE_REAL Real(1e20) // ============================================================================= // General fly-by-wire helper functions // ============================================================================= namespace FlyByWire { /// Computes the heading error using the shortest route from hdg to tgt, both expressed in radians. Real Hdg_err(Real tgt, Real hdg); /// Computes the heading error using the shortest route from hdg to tgt, both expressed in degrees. Real Hdg_err_deg(Real tgt, Real hdg); /// Computes the median of the triplet (a, b, c). Useful to reject an invalid measurement from a triplet of sensors, or to mix 3 control laws in a continuous fashion (C0 continuity). /// Internally, it is implemented as a sorting network. The middle value is the median of the triplet. Real Vote(Real a, Real b, Real c); /// Copies the input as long as it's not within +/- a from the origin. The output is then 0. Real Deadzone(Real x, Real a); /// Saturation function. Ensures that a <= x <= b. Real Sat1(Real x, Real a, Real b); /// Limits the rate of the signal x(t) : [dx/dt](t) to the interval [dy_dt_min, dy_dt_max]. /// Use like a recursive filter. /// /// \variable x_n : Input value at step n /// \variable y_n_1 : Output value at step n-1 /// \variable dy_dt_min : Min derivative /// \variable dy_dt_max : Max derivative /// \variable dt : Time step /// \return y[n] rate-limited. Real Ratelim(Real x_n, Real y_n_1, Real dy_dt_min, Real dy_dt_max, Real dt); /// Rate limiter implemented as a self-contained recursive filter. class RateLimiter { public: /// Creates the RateLimiter object with the specified limits, and initial value. By default, y0 = 0. RateLimiter(Real dy_dt_min, Real dy_dt_max, Real dt, Real y_ = Real(0.)); /// Applies the rate limiter filter to the input x[n] (parameter x_n) and returns the result y[n]. Real Filter(Real x_n); public: Real dy_dt_min; //< Min rate. Real dy_dt_max; //< Max rate. Real dt; //< Time step. Real y_n_1; //< Previous filter value. }; /// Heaviside function. 1 when x >= 0, 0 otherwise. Real Heaviside(Real x); // ============================================================================= // IRR Filters from the continuous Laplace transfer function. // ============================================================================= /// 1st order integrator implemented using the trapezoïdal method. /// G(s) = 1/s /// The integrator can also be limited using the lower_bound and upper_bound parameters. /// By default, the integrator is not bounded. /// /// The class is to be used like so : /// flt = Integrator1(Ts) /// /// while control/filtering loop: /// y_n = flt.Filter(x_n) class Integrator1 { public: /// Creates an integrator object. By default, y0 = 0, and the limits are +/- HUGE_VALUE_REAL. Integrator1(Real Ts_, Real y_ = Real(0.), Real lower_bound_ = -HUGE_VALUE_REAL, Real upper_bound_ = HUGE_VALUE_REAL); /// Sets the state of the filter so that it can be initialized at any value. /// By default, the states are initialized to 0. void SetState(Real y_ = Real(0.), Real x_ = Real(0.)); /// Computes the next output value of the filter y[n] from the next input value x[n]. Real Filter(Real x_n); public: Real Ts;//< Time step. Real lower_bound;//< Time step. Real upper_bound;//< Time step. Real x_n_1;//< x[n-1]. Real y_n_1;//< y[n-1]. }; } #endif