An observer for estimating the friction-force ratio

Revision:
0:a936477fcd4a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Observer_ftRatio.cpp	Thu Feb 23 11:12:06 2017 +0000
@@ -0,0 +1,442 @@
+#include "Observer_ftRatio.h"
+
+//
+float Dimension_ftOb[] = {
+    #include "Dimensions_ftOb.txt" // Load the parameter Dimensions_ftOb
+};
+//
+
+Observer_ftRatio::Observer_ftRatio(float samplingTime):
+        Ts(samplingTime),
+        OB(Dimension_ftOb[3], Dimension_ftOb[4], Dimension_ftOb[5], 0, samplingTime),
+        KFID_ratio_ft_right(samplingTime, 1.0, 0.0, 1.0, 1.0, 1.0, false), // For identifing the ratio_ft of the right wheel
+        KFID_ratio_ft_left(samplingTime, 1.0, 0.0, 1.0, 1.0, 1.0, false), // For identifing the ratio_ft of the left wheel
+        SAT_ratio_ft(Dimension_ftOb[1], 1.0, 0.0),
+        LPF_ratio_ft(Dimension_ftOb[1], samplingTime, 10.0, 1) // fc = 10 Hz
+{
+    // To enble, run *.start() function
+    enable = false;
+    // Dimensions of the original system
+    n = Dimension_ftOb[0];
+    p = Dimension_ftOb[1];
+    q = Dimension_ftOb[2];
+    // Dimensions of the observer
+    n_OB = Dimension_ftOb[3];
+    p_OB = Dimension_ftOb[4];
+    q_OB = Dimension_ftOb[5];
+    n_ME_OB = Dimension_ftOb[6]; // Number of the measurement errors in the PI observer
+    //
+    zeros_n.assign(n, 0.0);
+    zeros_p.assign(p, 0.0);
+    zeros_q.assign(q, 0.0);
+    zeros_n_ME_OB.assign(n_ME_OB, 0.0);
+    //
+    ones_p.assign(p, 1.0);
+
+    // Assign parameters
+    // init();
+
+    // Indexes
+    // idx_x_real = 0; // Index for x_real_est
+    idx_x_ns = n;
+    idx_ft_error_est = 2*n; // Index for ft_error_est
+
+    // Input signals
+    yc = zeros_p;
+    // States
+    ft_est = zeros_p;
+    ft_error_est = zeros_p;
+    ft_ideal_est = zeros_p;
+    //
+    x_real_est = zeros_n; // Estimation of the real states
+    // x_ns_est = zeros_n; // Estimation of the states of the no-slip system
+
+    // The estimation of measurement errors in PI observer
+    Measurement_error_est = zeros_n_ME_OB;
+
+    // The degree of no-slip
+    // ratio_ft = zeros_p;
+    ratio_ft = ones_p; // No slip
+    ratio_ft_filtered = ones_p; // No slip
+
+}
+void Observer_ftRatio::start(){
+    enable = true;
+    //
+    OB.start();
+}
+void Observer_ftRatio::pause(){
+    enable = false;
+    //
+    OB.enable = false;
+}
+void Observer_ftRatio::stop(){
+    if (!enable){
+        return;
+    }
+    enable = false;
+    // Reset
+    reset();
+
+    //
+    OB.stop();
+}
+void Observer_ftRatio::reset(){
+    //
+    // Input signals
+    yc = zeros_p;
+    // States
+    ft_est = zeros_p;
+    ft_error_est = zeros_p;
+    ft_ideal_est = zeros_p;
+    //
+    x_real_est = zeros_n; // Estimation of the real states
+    // x_ns_est = zeros_n; // Estimation of the states of the no-slip system
+
+    // The estimation of measurement errors in PI observer
+    Measurement_error_est.assign(2, 0.0);
+
+    // Reset the identifier for ratio_ft(s)
+    KFID_ratio_ft_right.reset(1.0); // 1.0 for no-slip (full friction-force)
+    KFID_ratio_ft_left.reset(1.0); // 1.0 for no-slip (full friction-force)
+
+    // The degree of no-slip
+    // ratio_ft = zeros_p;
+    ratio_ft = ones_p; // No slip
+    ratio_ft_filtered = ones_p;// No slip
+
+    // Reset the low-pass filter for ratio_ft
+    LPF_ratio_ft.reset(ratio_ft);
+
+    //
+    OB.reset();
+}
+//
+void Observer_ftRatio::init(void){
+    //
+    float _A_ftOb[] = {
+        #include "A_ftOb.txt" // Load the parameter A_ftOb
+    };
+    float _By_ftOb[] = {
+        #include "By_ftOb.txt" // Load the parameter By_ftOb
+    };
+    /*
+    float _Bv1_ftOb[] = {
+        #include "Bv1_ftOb.txt" // Load the parameter Bv1_ftOb
+    };
+    */
+    float _C_ftOb[] = {
+        #include "C_ftOb.txt" // Load the parameter C_ftOb
+    };
+    //
+    float _F1_ftOb[] = {
+        #include "F1_ftOb.txt" // Load the parameter F1_ftOb
+    };
+    float _F2_ftOb[] = {
+        #include "F2_ftOb.txt" // Load the parameter F2_ftOb
+    };
+    //
+    float _L_ftOb[] = {
+        #include "L_ftOb.txt" // Load the parameter L_ftOb
+    };
+    //
+    OB.assign_At(_A_ftOb, n_OB);
+    OB.assign_Bt(_By_ftOb, n_OB, p_OB);
+    OB.assign_Cd(_C_ftOb, q_OB, n_OB);
+    //
+    OB.assign_Lt(_L_ftOb, n_OB, 0, q_OB);
+
+    //-------------------------//
+    // assign_Matrix(Bv1_ftOb, _Bv1_ftOb, n_OB, p_OB);
+    //
+    assign_Matrix(F1_ftOb, _F1_ftOb, p, n);
+    assign_Matrix(F2_ftOb, _F2_ftOb, p, p);
+
+}
+
+//
+void Observer_ftRatio::iterateOnce(const vector<float> &yc_in, const vector<float> &x_real_in){
+    if(!enable){
+        return;
+    }
+    // Insert values
+    insertSignals(yc_in, x_real_in);
+
+    // Progress one time slot
+    OB.iterateOnce();
+
+
+    // Clean up the estimation of w_ideal_avg and w_ideal_delta
+
+
+    /*
+    // for test
+    return;
+    //
+    */
+
+
+    // Get the results
+    //--------------------------//
+    size_t idx = 0;
+    // x_real_est
+    for (size_t i = 0; i < n; ++i){
+        x_real_est[i] = OB.state_est[idx];
+        //
+        idx++;
+    }
+
+    // ft_est
+    for (size_t i = 0; i < p; ++i){
+        ft_est[i] = OB.state_est[idx];
+        //
+        idx++;
+    }
+
+    // Measurement_error_est
+    for (size_t i = 0; i < n_ME_OB; ++i){
+        Measurement_error_est[i] = OB.state_est[idx];
+        //
+        idx++;
+    }
+    //--------------------------//
+
+
+
+    // ft_ideal_est
+    // ft_ideal_est = F1_ftOb*x_real_est + F2_ftOb*yc
+    ft_ideal_est = Mat_multiply_Vec(F1_ftOb, x_real_est);
+    Get_VectorIncrement(ft_ideal_est, Mat_multiply_Vec(F2_ftOb, yc), false); // +=
+
+    // ft_error_est = ft_est - ft_ideal_est;
+    ft_error_est = Get_VectorPlus(ft_est, ft_ideal_est, true); // minus
+
+    /*
+    // The ratio_ft
+    for (size_t i = 0; i < p; ++i){
+        //
+        if (ft_ideal_est[i] < NUM_THRESHOLD && (-ft_ideal_est[i]) < NUM_THRESHOLD){
+            ratio_ft[i] = 1.0; // no-slip
+        }else{
+            ratio_ft[i] = ft_est[i]/ft_ideal_est[i];
+        }
+        // Saturation
+        if (ratio_ft[i] > 1.0){
+            ratio_ft[i] = 1.0;
+        }else if (ratio_ft[i] < 0.0){
+            ratio_ft[i] = 0.0;
+        }
+        //
+    }
+    */
+
+    // Identify the ratio_ft
+    //----------------------------------------------------//
+    /*
+    // Transform from (rifht, left) to (average, delta)
+    T_ft_est.assign_R_L(ft_est);
+    T_ft_ideal_est.assign_R_L(ft_ideal_est);
+
+    // ratio_ft_avg
+    KFID_ratio_ft_avg.C = T_ft_ideal_est.get_avg();
+    ratio_ft[0] = KFID_ratio_ft_avg.filter(0.0, T_ft_est.get_avg());
+    // ratio_ft_delta
+    KFID_ratio_ft_delta.C = T_ft_ideal_est.get_delta();
+    ratio_ft[1] = KFID_ratio_ft_delta.filter(0.0, T_ft_est.get_delta());
+    */
+
+    // Right-side ratio
+    KFID_ratio_ft_right.C = ft_ideal_est[0];
+    ratio_ft[0] = KFID_ratio_ft_right.filter(0.0, ft_est[0] );
+    // Left-side ratio
+    KFID_ratio_ft_left.C = ft_ideal_est[1];
+    ratio_ft[1] = KFID_ratio_ft_left.filter(0.0, ft_est[1] );
+
+    // Saturation
+    ratio_ft = SAT_ratio_ft.filter(ratio_ft);
+    //----------------------------------------------------//
+
+    // Filtering
+    ratio_ft_filtered = LPF_ratio_ft.filter(ratio_ft);
+
+}
+
+// Private methods
+//
+void Observer_ftRatio::insertSignals(const vector<float> &yc_in, const vector<float> &x_real_in){
+    //
+    yc = yc_in;
+    // Insert values
+    OB.sys_inputs = yc_in;
+    OB.sys_outputs = x_real_in;
+    //
+    // OB.sys_extraDisturbance = Mat_multiply_Vec(Bv1_ftOb, v1_in);
+}
+
+
+
+// Utilities
+void Observer_ftRatio::Mat_multiply_Vec(vector<float> &v_out, const vector<vector<float> > &m_left, const vector<float> &v_right){ // v_out = m_left*v_right
+
+    // Size check
+    if (v_out.size() != m_left.size()){
+        v_out.resize(m_left.size());
+    }
+
+    /*
+    // Iterators
+    static vector<float>::iterator it_out;
+    static vector<float>::iterator it_m_row;
+    static vector<float>::iterator it_v;
+
+    //
+    it_out = v_out.begin();
+    for (size_t i = 0; i < m_left.size(); ++i){
+        *it_out = 0.0;
+        it_m_row = vector<vector<float> >(m_left)[i].begin();
+        it_v = vector<float>(v_right).begin();
+        for (size_t j = 0; j < m_left[i].size(); ++j){
+            // *it_out += m_left[i][j] * v_right[j];
+            if (*it_m_row != 0.0 && *it_v != 0.0){
+                (*it_out) += (*it_m_row) * (*it_v);
+            }else{
+                // (*it_out) += 0.0
+            }
+            // (*it_out) += (*it_m_row) * (*it_v);
+            //
+            it_m_row++;
+            it_v++;
+        }
+        it_out++;
+    }
+    */
+
+    // Indexing
+    for (size_t i = 0; i < m_left.size(); ++i){
+        //
+        v_out[i] = 0.0;
+        //
+        for (size_t j = 0; j < v_right.size(); ++j){
+            if (m_left[i][j] != 0.0 && v_right[j] != 0.0)
+                v_out[i] += m_left[i][j]*v_right[j];
+        }
+    }
+
+}
+vector<float> Observer_ftRatio::Mat_multiply_Vec(const vector<vector<float> > &m_left, const vector<float> &v_right){ // v_out = m_left*v_right
+    static vector<float> v_out;
+    // Size check
+    if (v_out.size() != m_left.size()){
+        v_out.resize(m_left.size());
+    }
+
+    /*
+    // Iterators
+    static vector<float>::iterator it_out;
+    static vector<float>::iterator it_m_row;
+    static vector<float>::iterator it_v;
+    //
+    it_out = v_out.begin();
+    for (size_t i = 0; i < m_left.size(); ++i){
+        *it_out = 0.0;
+        it_m_row = vector<vector<float> >(m_left)[i].begin();
+        it_v = vector<float>(v_right).begin();
+        for (size_t j = 0; j < m_left[i].size(); ++j){
+            // *it_out += m_left[i][j] * v_right[j];
+            if (*it_m_row != 0.0 && *it_v != 0.0){
+                (*it_out) += (*it_m_row) * (*it_v);
+            }else{
+                // (*it_out) += 0.0
+            }
+            // (*it_out) += (*it_m_row) * (*it_v);
+            //
+            it_m_row++;
+            it_v++;
+        }
+        it_out++;
+    }
+    */
+
+    // Indexing
+    for (size_t i = 0; i < m_left.size(); ++i){
+        //
+        v_out[i] = 0.0;
+        //
+        for (size_t j = 0; j < v_right.size(); ++j){
+            if (m_left[i][j] != 0.0 && v_right[j] != 0.0)
+                v_out[i] += m_left[i][j]*v_right[j];
+        }
+    }
+
+    return v_out;
+}
+vector<float> Observer_ftRatio::Get_VectorPlus(const vector<float> &v_a, const vector<float> &v_b, bool is_minus) // v_a + (or -) v_b
+{
+    static vector<float> v_c;
+    // Size check
+    if (v_c.size() != v_a.size()){
+        v_c.resize(v_a.size());
+    }
+    //
+    for (size_t i = 0; i < v_a.size(); ++i){
+        if (is_minus){
+            v_c[i] = v_a[i] - v_b[i];
+        }else{
+            v_c[i] = v_a[i] + v_b[i];
+        }
+    }
+    return v_c;
+}
+vector<float> Observer_ftRatio::Get_VectorScalarMultiply(const vector<float> &v_a, float scale) // scale*v_a
+{
+    static vector<float> v_c;
+    // Size check
+    if (v_c.size() != v_a.size()){
+        v_c.resize(v_a.size());
+    }
+    // for pure negative
+    if (scale == -1.0){
+        for (size_t i = 0; i < v_a.size(); ++i){
+            v_c[i] = -v_a[i];
+        }
+        return v_c;
+    }
+    // else
+    for (size_t i = 0; i < v_a.size(); ++i){
+        v_c[i] = scale*v_a[i];
+
+    }
+    return v_c;
+}
+// Increment
+void Observer_ftRatio::Get_VectorIncrement(vector<float> &v_a, const vector<float> &v_b, bool is_minus){ // v_a += (or -=) v_b
+    // Size check
+    if (v_a.size() != v_b.size()){
+        v_a.resize(v_b.size());
+    }
+    //
+    if (is_minus){ // -=
+        for (size_t i = 0; i < v_b.size(); ++i){
+            v_a[i] -= v_b[i];
+        }
+    }else{ // +=
+        for (size_t i = 0; i < v_b.size(); ++i){
+            v_a[i] += v_b[i];
+        }
+    }
+
+}
+
+//
+void Observer_ftRatio::assign_Matrix(vector<vector<float> > &M, float* M_in, size_t m_in, size_t n_in){ // M_in is a m_in by n_in array
+    // M_in is the pointer of a mutidimentional array with size m_in by n_in
+    M.resize(m_in, vector<float>(n_in, 0.0));
+    //
+    for (size_t i = 0; i < m_in; ++i){
+        for (size_t j = 0; j < n_in; ++j){
+            // M[i][j] = M_in[i][j];
+            M[i][j] = *M_in;
+            M_in++;
+        }
+    }
+}