希望每個人都做得很好。我現在正在做一個 Quadcopter 專案,并且我設計了一個基于增益調度的控制器。
我正在使用四軸飛行器的滾動、俯仰和偏航角來確定操作間隔。讓我解釋一下基本思想:
我將滾動、俯仰和偏航分為四個操作間隔。它們是 0-30 度、30-50 度、50-70 度和 70-90 度。因此,對于側傾控制,我有 4 個 PID 控制器增益組,用于俯仰控制,4 個 PID 控制器增益組,以及用于偏航控制的 4 個 PID 控制器增益組。每個增益集包含 3 個元素。該方法有一個簡單的查找表(每個增益集是一個 3 陣列,包括比例增益、積分增益和微分增益):
該查找表是分別針對橫滾、俯仰和偏航角構建的。正如我提到的,增益集是 3 個元素的陣列。
要為滾動、俯仰和偏航角找到合適的增益集,我不知道在 C 中使用哪種方法最快,因為我將在微控制器上實作這種增益調度方法,并且這種增益調度方法正在運行在中斷函式中操作。
我擔心 if-else 結構對我的需求來說太慢了,因此想聽聽你的意見。非常感謝你。
這是我撰寫的代碼片段(它只涵蓋了 Roll/Phi Control 部分):
...
float Phi_Gain_Set_0_30[3] = {5.1838, 0.3882, 0};
float Phi_Gain_Set_30_50[3] = {5.1838, 0.3882, 0};
float Phi_Gain_Set_50_70[3] = {5.1838, 0.3882, 0};
float Phi_Gain_Set_70_90[3] = {5.1838, 0.3882, 0};
...
void scheduleGains(float *rollGainSet, float *pitchGainSet, float *yawGainSet, float phi_deg, float theta_deg, float psi_deg)
{
if (phi_deg >= 0 && phi_deg < 30)
{
float Kp_phi = Phi_Gain_Set_0_30[0];
float Kd_phi = Phi_Gain_Set_0_30[1];
float Ki_phi = Phi_Gain_Set_0_30[2];
}
else if (phi_deg >= 30 && phi_deg < 50)
{
float Kp_phi = Phi_Gain_Set_30_50[0];
float Kd_phi = Phi_Gain_Set_30_50[1];
float Ki_phi = Phi_Gain_Set_30_50[2];
}
else if (phi_deg >= 50 && phi_deg < 70)
{
float Kp_phi = Phi_Gain_Set_50_70[0];
float Kd_phi = Phi_Gain_Set_50_70[1];
float Ki_phi = Phi_Gain_Set_50_70[2];
}
else if (phi_deg >= 70 && phi_deg < 90)
{
float Kp_phi = Phi_Gain_Set_70_90[0];
float Kd_phi = Phi_Gain_Set_70_90[1];
float Ki_phi = Phi_Gain_Set_70_90[2];
}
else
{
float Kp_phi = Phi_Gain_Set_0_30[0];
float Kd_phi = Phi_Gain_Set_0_30[1];
float Ki_phi = Phi_Gain_Set_0_30[2];
}
rollGainSet[0] = Kp_phi;
rollGainSet[1] = Kd_phi;
rollGainSet[2] = Ki_phi;
}
uj5u.com熱心網友回復:
正如其他人評論的那樣,它可能已經足夠快了。那么為什么要打擾呢?
無論如何,在一般情況下,正如尼克 ODell 指出的那樣,您的比較是無用的復雜。每個只使用一個柵欄if
就足夠了。此外,您可以使用memcpy
使代碼更短更清晰。
#include <stdio.h>
#include <string.h>
float Phi_Gain_Set_0_30[3] = {5.1838, 0.3882, 0};
float Phi_Gain_Set_30_50[3] = {1, 2, 3};
float Phi_Gain_Set_50_70[3] = {4, 5, 6};
float Phi_Gain_Set_70_90[3] = {7, 8, 9};
void scheduleGains(float *rollGainSet, float *pitchGainSet, float *yawGainSet, float phi_deg, float theta_deg, float psi_deg)
{
if (phi_deg < 30) {
memcpy(rollGainSet, Phi_Gain_Set_0_30, sizeof(float[3]));
}
else if (phi_deg < 50) {
memcpy(rollGainSet, Phi_Gain_Set_30_50, sizeof(float[3]));
}
else if (phi_deg < 70) {
memcpy(rollGainSet, Phi_Gain_Set_50_70, sizeof(float[3]));
}
else if (phi_deg < 90) {
memcpy(rollGainSet, Phi_Gain_Set_70_90, sizeof(float[3]));
}
else {
memcpy(rollGainSet, Phi_Gain_Set_0_30, sizeof(float[3]));
}
}
int main(void)
{
float test_angles[] = { 17.3, 22.99, 81.398, 65.2 };
size_t ntests = sizeof test_angles / sizeof *test_angles;
for (size_t i = 0; i < ntests; i) {
float rgs[3];
scheduleGains(rgs, NULL, NULL, test_angles[i], 0, 0);
printf("phi_deg=%g --> {%g, %g, %g}\n", test_angles[i], rgs[0], rgs[1], rgs[2]);
}
return 0;
}
下次幫助我們提供一個最小的、可重現的示例,還有一個main()
.
平均而言,通過在該范圍內使用二進制搜索,您可以做得更好(如果需要):
void scheduleGains(float *rollGainSet, float *pitchGainSet, float *yawGainSet, float phi_deg, float theta_deg, float psi_deg)
{
if (phi_deg < 50) {
if (phi_deg < 30) {
memcpy(rollGainSet, Phi_Gain_Set_0_30, sizeof(float[3]));
}
else {
memcpy(rollGainSet, Phi_Gain_Set_30_50, sizeof(float[3]));
}
}
else {
if (phi_deg < 70) {
memcpy(rollGainSet, Phi_Gain_Set_50_70, sizeof(float[3]));
}
else {
if (phi_deg < 90) {
memcpy(rollGainSet, Phi_Gain_Set_70_90, sizeof(float[3]));
}
else {
memcpy(rollGainSet, Phi_Gain_Set_0_30, sizeof(float[3]));
}
}
}
}
這為您提供了 0-30、30-50、50-70 的 2 次比較,以及 70-90 或更多的 3 次比較。但我不相信這會產生任何影響。此外,如果具有低值的概率phi_deg
很高,則第一個版本更好。一如既往:
It is a capital mistake to theorize before one has data. Sherlock Holmes
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/427022.html