完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
|
|
相关推荐
1个回答
|
|
鉴于控制算法常于嵌入式平台使用,所以博主使用C语言实现模糊PID控制算法,该项目已上传至GitHub以及码云。实现的功能包括但不限于:
隶属度函数 Membership function 高斯隶属度函数 Gaussian membership function 广义钟形隶属度函数 Generalized bell-shaped membership function S形隶属度函数 Sigmoidal membership function 梯形隶属度函数 Trapezoidal membership function 三角形隶属度函数 Triangular membership function Z形隶属度函数 Z-shaped membership function 模糊算子 Fuzzy operator 并算子 Union operator 交算子 Intersection operator 平衡算子 Equilibrium operator 中心平均解模糊器 Center average defuzzifier API使用的示例代码如下: #include "fuzzyPID.h" #define DOF 6 int main() { // Default fuzzy rule base of delta kp/ki/kd int rule_base[][qf_default] = { //delta kp rule base {PB, PB, PM, PM, PS, ZO, ZO}, {PB, PB, PM, PS, PS, ZO, NS}, {PM, PM, PM, PS, ZO, NS, NS}, {PM, PM, PS, ZO, NS, NM, NM}, {PS, PS, ZO, NS, NS, NM, NM}, {PS, ZO, NS, NM, NM, NM, NB}, {ZO, ZO, NM, NM, NM, NB, NB}, //delta ki rule base {NB, NB, NM, NM, NS, ZO, ZO}, {NB, NB, NM, NS, NS, ZO, ZO}, {NB, NM, NS, NS, ZO, PS, PS}, {NM, NM, NS, ZO, PS, PM, PM}, {NM, NS, ZO, PS, PS, PM, PB}, {ZO, ZO, PS, PS, PM, PB, PB}, {ZO, ZO, PS, PM, PM, PB, PB}, //delta kd rule base {PS, NS, NB, NB, NB, NM, PS}, {PS, NS, NB, NM, NM, NS, ZO}, {ZO, NS, NM, NM, NS, NS, ZO}, {ZO, NS, NS, NS, NS, NS, ZO}, {ZO, ZO, ZO, ZO, ZO, ZO, ZO}, {PB, PS, PS, PS, PS, PS, PB}, {PB, PM, PM, PM, PS, PS, PB}}; // Default parameters of membership function int mf_params[4 * qf_default] = {-3, -3, -2, 0, -3, -2, -1, 0, -2, -1, 0, 0, -1, 0, 1, 0, 0, 1, 2, 0, 1, 2, 3, 0, 2, 3, 3, 0}; // Default parameters of pid controller float fuzzy_pid_params[DOF][pid_params_count] = {{0.65f, 0, 0, 0, 0.5f, -2.4f, 1}, {-0.34f, 0, 0, 0, 0.5f, 0.536f, 2.3f}, {-1.1f, 0, 0, 0, 0.5f, 0.00f, 1}, {-2.4f, 0, 0, 0, 0.5f, 2.3f, 1}, {1.2f, 0, 0, 0, 0.5f, -0.7f, 2.3f}, {1.2f, 0.05f, 0.1f, 0, 0, 0, 1}}; // Obtain the PID controller vector according to the parameters struct PID **pid_vector = fuzzy_vector_pid_init(fuzzy_pid_params, 2.0f, 4, 1, 0, mf_params, rule_base, DOF); printf("output:n"); bool direct[DOF] = {true, false, false, false, true, true}; float real = 0; float idea = max_error * 0.9f; for (int j = 0; j < 500; ++j) { int out = fuzzy_pid_motor_pwd_output(real, idea, direct[5], pid_vector[5]); real += (float) (out - middle_pwm_output) / (float) middle_pwm_output * (float) max_error * 0.1f; printf("%d,%fn", out, real); } delete_pid_vector(pid_vector, DOF); return 0; } 下面进行详细讲解,一般的模糊控制流程图如下: 可以需要根据参考输入与被控对象的实际输出产生的误差 e ee 、误差变化量 Δ e Delta eΔe 以及整定得的模糊规则表获取最终的模糊控制量。本项目主要针对模糊PID控制算法,所以选择的模糊条件语句为双输入多输出,即: IF e is A ∨ Δ e is B THEN Δ k p is C 1 and Δ k i is C 2 and Δ k d is C 3 ⋯ text{IF } e text{ is } A vee Delta e text{ is } B text{ THEN } Delta k_p text{ is } C_1 text{ and } Delta k_i text{ is } C_2 text{ and } Delta k_d text{ is } C_3 cdots IF e is A∨Δe is B THEN Δk p is C 1 and Δk i is C 2 and Δk d is C 3 ⋯ 其中 ∨ vee∨ 代表并 (and) 操作,当然也可以用或 (or, ∧ wedge∧) 生成条件语句。同时由于模糊概念的存在,误差 e ee 、误差变化量 Δ e Delta eΔe 是 A AA 和 B BB 呈一定概率,该概率则使用隶属度函数计算得出。项目的源码实现如下: int j = 0; for (int i = 0; i < qf_default; ++i) { float temp = mf(e, fuzzy_struct->mf_type[0], fuzzy_struct->mf_params + 4 * i); if (temp > 1e-4) { membership[j] = temp; index[j++] = i; } } count[0] = j; for (int i = 0; i < qf_default; ++i) { float temp = mf(de, fuzzy_struct->mf_type[1], fuzzy_struct->mf_params + 4 * i); if (temp > 1e-4) { membership[j] = temp; index[j++] = i; } } count[1] = j - count[0]; 其中使用 fuzzy_struct->mf_type 存储隶属度函数类型, fuzzy_struct->mf_params 存储隶属度函数所需的参数,通过调用 mf 便可实现隶属度的计算,同时多输入的情况下需要使用交并函数(模糊算子)求出联合隶属度。项目的源码实现如下: // Joint membership float joint_membership[count[0] * count[1]]; for (int i = 0; i < count[0]; ++i) { for (int j = 0; j < count[1]; ++j) { joint_membership[i * count[1] + j] = fo(membership, membership[count[0] + j], fuzzy_struct->fo_type); } } 其中使用 fuzzy_struct->fo_type 存储交并函数类型,通过调用 fo 实现联合隶属度的求取。在得到每个语言值的联合隶属度,便可以通过模糊推理求取。项目的源码实现如下: // Mean of centers defuzzifier, only for two input multiple index void moc(const float *joint_membership, const unsigned int *index, const unsigned int *count, struct fuzzy *fuzzy_struct) { float denominator_count = 0; float numerator_count[fuzzy_struct->output_num]; for (unsigned int l = 0; l < fuzzy_struct->output_num; ++l) { numerator_count[l] = 0; } for (int i = 0; i < count[0]; ++i) { for (int j = 0; j < count[1]; ++j) { denominator_count += joint_membership[i * count[1] + j]; } } for (unsigned int k = 0; k < fuzzy_struct->output_num; ++k) { for (unsigned int i = 0; i < count[0]; ++i) { for (unsigned int j = 0; j < count[1]; ++j) { numerator_count[k] += joint_membership[i * count[1] + j] * fuzzy_struct->rule_base[k * qf_default * qf_default + index * qf_default + index[count[0] + j]]; } } } for (unsigned int l = 0; l < fuzzy_struct->output_num; ++l) { fuzzy_struct->output[l] = numerator_count[l] / denominator_count; } } 最终便可以实现模糊PID控制算法了。同时项目中提供了便捷的模糊PID控制器的数组生成器,便于生成多个控制器服务于多自由度控制需求,调用接口如下: struct PID ** fuzzy_pid_vector_init(float params[][pid_params_count], float delta_k, unsigned int mf_type, unsigned int fo_type, unsigned int df_type, int *mf_params, int rule_base[][qf_default], unsigned int count); 其中 count 用于设定控制器个数,rule_base 用于传递模糊规则库,delta_k 用于控制PID的三个参数在初始值的基础上可以调节的程度,params 用于传递基础的PID参数,mf_type、fo_type、df_type三个参数分别决定了隶属度函数类型、模糊算子类型以及解模糊器类型。 |
|
|
|
只有小组成员才能发言,加入小组>>
2386 浏览 0 评论
8910 浏览 4 评论
36486 浏览 19 评论
4981 浏览 0 评论
24307 浏览 34 评论
1375浏览 2评论
1627浏览 1评论
2017浏览 1评论
1441浏览 0评论
386浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 02:34 , Processed in 1.221913 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号