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; |
---|
49 | old_vals_initialized_ = false; |
---|
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 | } |
---|
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 | } |
---|