位置环写的正确吗? for (i = 0; i < 4; i++) { PID_Calc(&chassis_move_control_loop->motor_speed_pid[i], chassis_move_control_loop->motor_chassis[i].speed, chassis_move_control_loop->motor_chassis[i].speed_set); speed_output = chassis_move_control_loop->motor_speed_pid[i].output; chassis_move_control_loop->motor_position_pid[i].set_point = speed_output; PID_Calc(&chassis_move_control_loop->motor_position_pid[i],chassis_move_control_loop->motor_chassis[i].position, chassis_move_control_loop->motor_chassis[i].position_set); position_output = chassis_move_control_loop->motor_position_pid[i].output; chassis_move_control_loop->motor_chassis[i].output = position_output; }
时间: 2023-05-26 11:07:11 浏览: 62
PID控制器的位置环,应该是在循环中不断更新输出的位置值,而不是不断计算PID值。
例如,以下代码可能更符合位置环的实现方式:
float Setpoint = 50.0; // 目标位置
float Position = 0.0; // 当前位置
float Output = 0.0; // 输出控制值
PID pid(1.0, 0.0, 0.1); // PID控制器对象
// 循环计算输出控制值
while (true) {
Position = read_position_sensor(); // 读取当前位置
Output = pid.Compute(Setpoint - Position); // 计算输出控制值
write_motor(Output); // 输出控制值到电机
delay(10); // 等待一段时间再进行下一次循环
}
以上代码中,使用了一个PID控制器对象pid,其Compute()方法可接受位置偏差作为输入(即目标位置与当前位置的差值),计算对应的输出控制值。在循环中,不断读取当前位置并计算输出控制值,然后输出到电机中进行调节。其中可以加入一些延时操作,确保每次循环的时间间隔相同。
需要注意的是,实际应用中还需要进行一些限幅、积分清零等操作,以确保PID控制器的稳定性和安全性。以上代码仅作为参考,需根据具体场景进行相应的调整和优化。
相关问题
解释这段代码static void chassis_control_loop(chassis_move_t *chassis_move_control_loop) { fp32 max_vector = 0.0f, vector_rate = 0.0f; fp32 temp = 0.0f; fp32 wheel_speed[4] = {0.0f, 0.0f, 0.0f, 0.0f}; uint8_t i = 0; float position_error, speed_error; float position_output, speed_output; float current_position, current_speed; float target_position, target_speed; chassis_move_control_loop->vx_set=vx_set; chassis_move_control_loop->vy_set=vy_set; chassis_move_control_loop->wz_set=angle_set; chassis_vector_to_mecanum_wheel_speed(chassis_move_control_loop->vx_set, chassis_move_control_loop->vy_set, chassis_move_control_loop->wz_set, wheel_speed); if (chassis_move_control_loop->chassis_mode == CHASSIS_VECTOR_RAW) { for (i = 0; i < 4; i++) { chassis_move_control_loop->motor_chassis[i].give_current = (int16_t)(wheel_speed[i]); } } for (i = 0; i < 4; i++) { chassis_move_control_loop->motor_chassis[i].speed_set = wheel_speed[i]; temp = fabs(chassis_move_control_loop->motor_chassis[i].speed_set); if (max_vector < temp) { max_vector = temp; } } if (max_vector > MAX_WHEEL_SPEED) { vector_rate = MAX_WHEEL_SPEED / max_vector; for (i = 0; i < 4; i++) { chassis_move_control_loop->motor_chassis[i].speed_set *= vector_rate; } } for (i = 0; i < 4; i++) { PID_Calc(&chassis_move_control_loop->motor_speed_pid[i], chassis_move_control_loop->motor_chassis[i].speed, chassis_move_control_loop->motor_chassis[i].speed_set); } for (i = 0; i < 4; i++) { chassis_move_control_loop->motor_chassis[i].give_current = (int16_t)(chassis_move_control_loop->motor_speed_pid[i].out); } }
chassis_move_control_loop->motor_chassis[i].position_pid, chassis_move_control_loop->motor_chassis[i].speed_pid, chassis_move_control_loop->motor_chassis[i].position_get, chassis_move_control_loop->motor_chassis[i].speed_get, chassis_move_control_loop->motor_chassis[i].speed_set, &position_error, &speed_error, &position_output, &speed_output); current_position = chassis_move_control_loop->motor_chassis[i].position_get; current_speed = chassis_move_control_loop->motor_chassis[i].speed_get; target_position = chassis_move_control_loop->motor_chassis[i].position_set; target_speed = speed_output; if(chassis_move_control_loop->motor_chassis[i].position_pid.enable == 1) //PID启动 { chassis_move_control_loop->motor_chassis[i].give_current = PID_Calc(&chassis_move_control_loop->motor_chassis[i].position_pid, current_position, target_position); } else { chassis_move_control_loop->motor_chassis[i].give_current = PID_Calc(&chassis_move_control_loop->motor_chassis[i].speed_pid, current_speed, target_speed); } } }
该函数为底盘控制代码,主要实现底盘的位置和速度控制。
具体实现方法为:
1.根据控制指令,将底盘的速度向量转换为各个驱动电机的速度。
2.根据底盘模式选择不同的控制方式:
如果模式为 CHASSIS_VECTOR_RAW,直接将每个驱动电机的输出电流设置为对应速度。
3.根据电机的最大速度设置,对转换后的速度进行限制。
4.对每个驱动电机进行PID控制,计算出目标位置和目标速度,并根据位置控制或速度控制模式下达电机电流控制指令。
5.将目标速度和目标位置在PID计算中使用,并将计算出的电流控制指令转换为电机的输出电流。
使用模块化(用户自定义函数)改写程序 4. 课本93页:自定义函数,求每个同学平均分,每门课总分及每门课程最高分,最高分是谁; #include<stdio.h> int main() { double s[8][6]={{78,82,93,74,65},{91,82,72,76,67},{100,90,85,72,98},{67,89,90,65,78},{77,88,99,45,89}}; int i,j; printf("学号\t语文\t数学\t物理\t化学\t音乐\t平均分\n"); //求平均分 for(i=0;i<5;i++) { for(j=0;j<5;j++){ s[i][5]+=s[i][j]; } s[i][5]=s[i][5]/5; } //求每门课程总分 for(i=0;i<5;i++) { for(j=0;j<5;j++){ s[5][j]+=s[i][j]; } } //求每门课最高分,以及改分数是哪个学生取得的成绩,并打印该学生学号 for(i=0;i<5;i++) { for(j=0;j<5;j++){ if(s[6][j]<s[i][j]){ s[6][j]=s[i][j]; s[7][j]=i+1;}}} //输出 for(i=0;i<8;i++) { if(i<5) printf("NO:%d\t",i+1); else if(i==5) { printf("总分:\t"); }else if(i==6){ printf("最高分:\t"); }else if(i==7){ printf("学号:\t"); } for(j=0;j<6;j++){ if(!((j==5)&&(i==5||i==6||i==7))){ printf("%.2lf\t",s[i][j]); } } printf("\n"); } }
以下是使用模块化改写后的程序:
```c
#include <stdio.h>
// 计算每个同学的平均分
void calc_avg(double s[][6], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 5; j++)
{
s[i][5] += s[i][j];
}
s[i][5] /= 5;
}
}
// 计算每门课程的总分
void calc_total(double s[][6])
{
for (int j = 0; j < 5; j++)
{
for (int i = 0; i < 5; i++)
{
s[5][j] += s[i][j];
}
}
}
// 计算每门课程的最高分及学生学号
void calc_max(double s[][6])
{
for (int j = 0; j < 5; j++)
{
double max_score = 0;
int max_student = -1;
for (int i = 0; i < 5; i++)
{
if (s[i][j] > max_score)
{
max_score = s[i][j];
max_student = i;
}
}
s[6][j] = max_score;
s[7][j] = max_student + 1;
}
}
// 输出结果
void print_result(double s[][6])
{
printf("学号\t语文\t数学\t物理\t化学\t音乐\t平均分\n");
for (int i = 0; i < 8; i++)
{
if (i < 5)
printf("NO:%d\t", i + 1);
else if (i == 5)
printf("总分:\t");
else if (i == 6)
printf("最高分:\t");
else if (i == 7)
printf("学号:\t");
for (int j = 0; j < 6; j++)
{
if (!((j == 5) && (i == 5 || i == 6 || i == 7)))
{
printf("%.2lf\t", s[i][j]);
}
}
printf("\n");
}
}
int main()
{
double s[8][6] = {{78, 82, 93, 74, 65},
{91, 82, 72, 76, 67},
{100, 90, 85, 72, 98},
{67, 89, 90, 65, 78},
{77, 88, 99, 45, 89}};
calc_avg(s, 5);
calc_total(s);
calc_max(s);
print_result(s);
return 0;
}
```
主要的改动是将原先的代码拆分成了三个函数:`calc_avg`、`calc_total` 和 `calc_max`,分别用于计算每个同学的平均分、每门课程的总分以及每门课程的最高分及学生学号。这样做有利于提高代码的可读性和可维护性。同时,`print_result` 函数用于输出结果。