A controller that is immune to measurement errors and keep the true states at the desired value, also known as "Zero-Torque Control"
Diff: MEASUREMENT_ERROR_ADAPTATION_CONTROL.cpp
- Revision:
- 0:533d5685b66c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MEASUREMENT_ERROR_ADAPTATION_CONTROL.cpp Wed Jan 11 09:32:26 2017 +0000 @@ -0,0 +1,287 @@ +#include "MEASUREMENT_ERROR_ADAPTATION_CONTROL.h" +// The controller is for the plant with (p, n, q) system +// Dimensions: +// +// Inputs, u | States, x +// p ----> n +// q -- ^ +// Measurement errors, phi + +MEASUREMENT_ERROR_ADAPTATION_CONTROL::MEASUREMENT_ERROR_ADAPTATION_CONTROL(size_t num_state, size_t num_in, size_t num_MeasurementError, float samplingTime): + n(num_state), p(num_in), q(num_MeasurementError), Ts(samplingTime), + C_error(num_state, vector<float>(num_MeasurementError,0.0)), + K_full(num_in, vector<float>(num_state,0.0)), + K_phi(num_MeasurementError, vector<float>(num_state,0.0)), + N_xd(num_state, vector<float>(num_in, 0.0)), + N_ud(num_in, vector<float>(num_in, 0.0)) +{ + // + zeros_n.assign(n, 0.0); + zeros_p.assign(p, 0.0); + zeros_q.assign(q, 0.0); + + // States + states_est = zeros_n; // states_est, "x_est" + sys_inputs = zeros_p; // The inputs of the plant, "u" + sys_output = zeros_n; // The output of the plant, "y" + MeasurementErrors = zeros_q; // The measurement error of the sensors, "phi" + + // Command (equalibrium state) + states_d = zeros_n; // x_d + inputs_d = zeros_p; // u_d + command = zeros_p; // r + + +} +// Assign Parameters +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::assign_C_error(float* C_error_in, size_t n_in, size_t q_in){ + // C_error_in is the pointer of a mutidimentional array with size n_in by q_in + if (n != n_in || q != q_in){ + n = n_in; + q = q_in; + zeros_n.resize(n, 0.0); + zeros_q.resize(q, 0.0); + C_error.assign(n, zeros_q); + } + // + for (size_t i = 0; i < n; ++i){ + for (size_t j = 0; j < q; ++j){ + // C_error[i][j] = C_error_in[i][j]; + C_error[i][j] = *C_error_in; + C_error_in++; + } + } +} +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::assign_K_full(float* K_full_in, size_t p_in, size_t n_in){ + // K_full_in is the pointer of a mutidimentional array with size p_in by n_in + if (n != n_in || p != p_in){ + p = p_in; + n = n_in; + zeros_n.resize(n, 0.0); + zeros_p.resize(p, 0.0); + K_full.assign(p, zeros_n); + } + // + for (size_t i = 0; i < p; ++i){ + for (size_t j = 0; j < n; ++j){ + // K_full[i][j] = K_full_in[i][j]; + K_full[i][j] = *K_full_in; + K_full_in++; + } + } +} +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::assign_K_phi(float* K_phi_in, size_t q_in, size_t n_in){ + // K_phi_in is the pointer of a mutidimentional array with size q_in by n_in + if (q != q_in || n != n_in){ + q = q_in; + n = n_in; + zeros_q.resize(q, 0.0); + zeros_n.resize(n, 0.0); + K_phi.assign(q, zeros_n); + } + // + for (size_t i = 0; i < q; ++i){ + for (size_t j = 0; j < n; ++j){ + // K_phi[i][j] = K_phi_in[i][j]; + K_phi[i][j] = *K_phi_in; + K_phi_in++; + } + } +} +// +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::assign_N_xd(float* N_xd_in, size_t n_in, size_t p_in){ + // N_xd_in is the pointer of a mutidimentional array with size n_in by p_in + if (n != n_in || p != p_in){ + n = n_in; + p = p_in; + zeros_n.resize(n, 0.0); + zeros_p.resize(p, 0.0); + N_xd.assign(n, zeros_p); + } + // + for (size_t i = 0; i < n; ++i){ + for (size_t j = 0; j < p; ++j){ + // N_xd[i][j] = N_xd_in[i][j]; + N_xd[i][j] = *N_xd_in; + N_xd_in++; + } + } +} +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::assign_N_ud(float* N_ud_in, size_t p_in){ + // N_ud_in is the pointer of a mutidimentional array with size p_in by p_in + if (p != p_in){ + p = p_in; + zeros_p.resize(p, 0.0); + N_ud.assign(p, zeros_p); + } + // + for (size_t i = 0; i < p; ++i){ + for (size_t j = 0; j < p; ++j){ + // N_ud[i][j] = N_ud_in[i][j]; + N_ud[i][j] = *N_ud_in; + N_ud_in++; + } + } +} +// +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::iterateOnce(bool enable){ + //----------------------------// + // Input: sys_output ("y"), command ("r") + // Get: sys_inputs ("u") + //----------------------------// + + // Control law + if (enable){ + // + get_inputs_compensate(); // Get states_d, inputs_d from command + + // states_est = (sys_output - C_error*MeasurementErrors) - states_d + get_states_est(); + + // sys_inputs = inputs_d - K_full*states_est + sys_inputs = Get_VectorPlus(inputs_d, Mat_multiply_Vec(K_full, states_est),true); // minus + }else{ + sys_inputs = zeros_p; + } + + // Integral action + get_MeasurementErrors_est(enable); +} + +// Private functions +// Command (equalibrium state) related calculation +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::get_inputs_compensate(void){ // Calculate the compensation variable, states_d and sys_inputs_compensate + // + Mat_multiply_Vec(states_d, N_xd, command); + Mat_multiply_Vec(inputs_d, N_ud, command); +} +// Calculate the states_est +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::get_states_est(void){ // Calculate the sys_outputs from states_est, by mutiplying C_error + // states_est = (sys_output - C_error*MeasurementErrors) - states_d + states_est = Get_VectorPlus(Get_VectorPlus(sys_output, Mat_multiply_Vec(C_error, MeasurementErrors), true), states_d, true); // minus +} +// Calculate the estimation of MeasurementErrors +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::get_MeasurementErrors_est(bool enable){ // Calculate the MeasurementErrors + // + // Integral action + // MeasurementErrors -= Ts*(K_phi*states_est) + if (enable){ + Get_VectorIncrement(MeasurementErrors, Get_VectorScalarMultiply(Mat_multiply_Vec(K_phi,states_est), Ts) , true); // -= + }else{ + MeasurementErrors = zeros_q; + } +} +// Utilities +void MEASUREMENT_ERROR_ADAPTATION_CONTROL::Mat_multiply_Vec(vector<float> &v_out, const vector<vector<float> > &m_left, const vector<float> &v_right){ // v_out = m_left*v_right + static vector<float>::iterator it_out; + static vector<const float>::iterator it_m_row; + static vector<const 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 = m_left[i].begin(); + it_v = 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++; + } +} +vector<float> MEASUREMENT_ERROR_ADAPTATION_CONTROL::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<const float>::iterator it_m_row; + static vector<const 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 = m_left[i].begin(); + it_v = 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++; + } + return v_out; +} +vector<float> MEASUREMENT_ERROR_ADAPTATION_CONTROL::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> MEASUREMENT_ERROR_ADAPTATION_CONTROL::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 MEASUREMENT_ERROR_ADAPTATION_CONTROL::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]; + } + } + +}