[5] | 1 | /* |
---|
| 2 | * perturb_esc_nd.cpp |
---|
| 3 | * |
---|
| 4 | * Created on: Aug 1, 2012 |
---|
| 5 | * Author: Berk Calli |
---|
| 6 | * Organization: Delft Biorobotics Lab., Delft University of Technology |
---|
| 7 | * Contact info: b.calli@tudelft.nl, web: www.dbl.tudelft.nl |
---|
| 8 | * |
---|
| 9 | * Class for perturbation based extremum seeking control |
---|
| 10 | * |
---|
| 11 | * * References: |
---|
| 12 | * - K. B. Ariyur and M. Krstic, "Real-Time Optimization by Extremum-Seeking Control", Wiley, 2003. |
---|
| 13 | * - B. Calli, W. Caarls, P. Jonker, M. Wisse, "Comparison of Extremum Seeking Control Algorithms for Robotic Applications", IROS 2012. |
---|
| 14 | * |
---|
| 15 | */ |
---|
| 16 | |
---|
| 17 | #include "esc_perturb/perturb_esc_nd.h" |
---|
| 18 | |
---|
| 19 | PerturbESCND::PerturbESCND(){ |
---|
| 20 | sin_amp_ = 0; |
---|
| 21 | sin_freq_ = 0; |
---|
| 22 | corr_gain_ = 0; |
---|
| 23 | high_pass_pole_ = 0; |
---|
| 24 | low_pass_pole_ = 0; |
---|
| 25 | comp_pole_ = 0; |
---|
| 26 | comp_zero_ = 0; |
---|
| 27 | period_ = 0; |
---|
| 28 | state_initialized_ = false; |
---|
| 29 | initialized_ = false; |
---|
| 30 | old_vals_initialized_ = false; |
---|
| 31 | } |
---|
| 32 | PerturbESCND::PerturbESCND(double sin_amp, double sin_freq, double corr_gain, double high_pass_pole, double low_pass_pole, double comp_zero, double comp_pole, double period){ |
---|
| 33 | init(sin_amp, sin_freq, corr_gain, high_pass_pole, low_pass_pole, comp_zero, comp_pole, period); |
---|
| 34 | } |
---|
| 35 | void PerturbESCND::init(double sin_amp, double sin_freq, double corr_gain, double high_pass_pole, double low_pass_pole, double comp_zero, double comp_pole, double period){ |
---|
| 36 | sin_amp_ = sin_amp; |
---|
| 37 | sin_freq_ = sin_freq; |
---|
| 38 | corr_gain_ = corr_gain; |
---|
| 39 | high_pass_pole_ = high_pass_pole; |
---|
| 40 | low_pass_pole_ = low_pass_pole; |
---|
| 41 | comp_pole_ = comp_pole; |
---|
| 42 | comp_zero_ = comp_zero; |
---|
| 43 | period_ = period; |
---|
| 44 | obj_val_old_ = 0; |
---|
| 45 | cycle_count_ = 0; |
---|
| 46 | hpf_out_old_ = 0; |
---|
| 47 | opt_dim_ = 0; |
---|
| 48 | state_initialized_ = false; |
---|
[22] | 49 | old_vals_initialized_ = false; |
---|
[5] | 50 | initialized_ = true; |
---|
| 51 | } |
---|
| 52 | |
---|
| 53 | std::vector<double> PerturbESCND::step(std::vector<double> state, double obj_val){ |
---|
| 54 | |
---|
| 55 | if(!initialized_){ |
---|
| 56 | fprintf(stderr,"The perturbation based ESC (1D) is not initialized... It will not be executed. \n"); |
---|
| 57 | return std::vector<double>(); |
---|
| 58 | } |
---|
| 59 | |
---|
| 60 | if(!state_initialized_ && state.empty()){ |
---|
| 61 | fprintf(stderr,"The state value of the perturbation based ESC (1D) cannot be initialized: State vector is empty. The algorithm will not be executed. \n"); |
---|
| 62 | return std::vector<double>(); |
---|
| 63 | } |
---|
| 64 | |
---|
| 65 | else if(!state_initialized_){ |
---|
| 66 | |
---|
| 67 | opt_dim_ = (unsigned int)state.size(); |
---|
| 68 | lpf_out_old_.resize(opt_dim_); |
---|
| 69 | signal_demodulated_old_.resize(opt_dim_); |
---|
| 70 | comp_old_.resize(opt_dim_); |
---|
| 71 | corr_signal_.resize(opt_dim_); |
---|
| 72 | pos_ref_.resize(opt_dim_); |
---|
| 73 | for (size_t i = 0; i<opt_dim_; i++){ |
---|
| 74 | pos_ref_[i] = state[i]; |
---|
| 75 | lpf_out_old_[i] = 0; |
---|
| 76 | signal_demodulated_old_[i] = 0; |
---|
| 77 | comp_old_[i] = 0; |
---|
| 78 | corr_signal_[i] = 0; |
---|
| 79 | } |
---|
| 80 | |
---|
| 81 | phase_shift_.resize(opt_dim_); |
---|
| 82 | phase_shift_[0] = 0; |
---|
| 83 | for (size_t i = 1; i<opt_dim_; i++){ |
---|
| 84 | phase_shift_[i] = i*PI/((double)opt_dim_); |
---|
| 85 | } |
---|
| 86 | state_initialized_ = true; |
---|
| 87 | } |
---|
| 88 | |
---|
| 89 | double hpf_out = (-(period_*high_pass_pole_-2)*hpf_out_old_+2*obj_val-2*obj_val_old_)/(2+high_pass_pole_*period_); |
---|
| 90 | hpf_out_old_ = hpf_out; |
---|
| 91 | obj_val_old_ = obj_val; |
---|
| 92 | std::vector<double> signal_demodulated(opt_dim_); |
---|
| 93 | std::vector<double> lpf_out(opt_dim_); |
---|
| 94 | std::vector<double> comp_out(opt_dim_); |
---|
| 95 | std::vector<double> output; |
---|
| 96 | |
---|
| 97 | for (size_t i = 0; i<opt_dim_; i++){ |
---|
| 98 | signal_demodulated[i]= hpf_out*sin_amp_*std::sin(cycle_count_*period_*sin_freq_ + phase_shift_[i]); |
---|
| 99 | lpf_out[i] = ((2.0-low_pass_pole_*period_)*lpf_out_old_[i]+low_pass_pole_*period_*signal_demodulated[i]+low_pass_pole_*period_*signal_demodulated_old_[i])/(2.0+low_pass_pole_*period_); |
---|
| 100 | comp_out[i]= ((2.0+period_*comp_zero_)*lpf_out[i]+(period_*comp_zero_-2.0)*lpf_out_old_[i]-(period_*comp_pole_-2.0)*comp_old_[i])/(2.0+period_*comp_pole_); |
---|
| 101 | corr_signal_[i] = corr_signal_[i]+corr_gain_*comp_out[i]*period_; |
---|
| 102 | if(!old_vals_initialized_) |
---|
| 103 | pos_ref_[i] = sin_amp_*std::sin(cycle_count_*period_*sin_freq_ + phase_shift_[i]); //modulation |
---|
| 104 | else |
---|
| 105 | pos_ref_[i] = corr_signal_[i]+sin_amp_*std::sin(cycle_count_*period_*sin_freq_ + phase_shift_[i]); //modulation |
---|
| 106 | output.push_back(pos_ref_[i]); |
---|
| 107 | signal_demodulated_old_[i] = signal_demodulated[i]; |
---|
| 108 | lpf_out_old_[i] = lpf_out[i]; |
---|
| 109 | comp_old_[i] = comp_out[i]; |
---|
| 110 | } |
---|
| 111 | old_vals_initialized_ = true; |
---|
| 112 | cycle_count_++; |
---|
| 113 | |
---|
| 114 | return output; |
---|
| 115 | } |
---|
| 116 | |
---|
| 117 | ESC::inputType PerturbESCND::getInputType(){ |
---|
| 118 | return ESC::inputStateValue; |
---|
| 119 | } |
---|
| 120 | |
---|
| 121 | ESC::outputType PerturbESCND::getOutputType(){ |
---|
| 122 | return ESC::outputPosition; |
---|
| 123 | } |
---|
| 124 | |
---|
| 125 | std::vector<double> PerturbESCND::monitor(){ |
---|
| 126 | std::vector<double> monitor_values; |
---|
| 127 | |
---|
| 128 | for(size_t i = 0; i<opt_dim_; i++) |
---|
| 129 | monitor_values.push_back(corr_signal_[i]); |
---|
| 130 | |
---|
| 131 | return monitor_values; |
---|
| 132 | } |
---|
| 133 | std::vector<std::string> PerturbESCND::monitorNames(){ |
---|
| 134 | std::vector<std::string> monitor_names; |
---|
| 135 | std::string base = "correction signal "; |
---|
| 136 | char numstr[21]; |
---|
| 137 | for(size_t i = 0; i<opt_dim_; i++){ |
---|
| 138 | sprintf(numstr, "%zd", i+1); |
---|
| 139 | monitor_names.push_back(base + numstr); |
---|
| 140 | } |
---|
| 141 | |
---|
| 142 | return monitor_names; |
---|
| 143 | } |
---|
[22] | 144 | |
---|
| 145 | void PerturbESCND::reset(){ |
---|
| 146 | obj_val_old_ = 0; |
---|
| 147 | cycle_count_ = 0; |
---|
| 148 | hpf_out_old_ = 0; |
---|
| 149 | opt_dim_ = 0; |
---|
| 150 | state_initialized_ = false; |
---|
| 151 | old_vals_initialized_ = false; |
---|
| 152 | } |
---|