无人机系统PX4视频教程:飞行PID参数调试

PID参数调试一直是比较头疼的问题,在此给大家带来如下的教程!

完整文章(建议PC下观看,手机的排版有问题)视频教程下载地址:

链接:http://pan.baidu.com/s/1bptl6BP 密码:2zbe


获取更多免费资料技术咨询请搜索微信公众号:阿木实验室   

官网:www.amovauto.com


PIXHAWk无人机PID参数调试实例


PID调参在控制领域一直是个工程的活,理论相对简单,但是参数的标定确实比较困难。


    这节的课程就是来指导大家来调试PIXHAWK的PID参数的。有软件仿真和实时视频效果,理论和实践相结合。


   PID一句话就是说,经过PID算法计算出的控制量,给执行机构,来达到维持某一个状态的目的。这个控制量的多少,直接影响到系统能不能快速稳定的维持这个状态。比如我们向一个杯子倒一杯水,要求到的刚好满。一开始杯子是空的,我们倒水倾斜力度大,水很快倒入杯中,但是随着水越来越满,我们的倒水倾斜力度会越来越小。如果这个倾斜的力度把握不好那么,水就会溢出。这个PID算法就是在计算这个倒水的倾斜力度,随着时间和水越来越满,动态调整这个倒水的倾斜力度。在杯子是空的时候要加快到水,增加倒水力度,杯子快要满了,减小倒水力度,防止水的溢出。


我们先看PID算法的代码:



PID 的流程简单到了不能再简单的程度,通过误差信号控制被控量,而控制器本身就是比例、积分、微分三个环节的加和。这里我们规定(在 t 时刻): 

1.输入量为 rin(t);

2.输出量为 rout(t);

3.偏差量为 err(t)=rin(t)-rout(t);


1.说明一下反馈控制的原理,通过上一节的框图不难看出,PID 控制其实是对偏差的控制过程;


2.如果偏差为 0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。


3.积分环节主要是用来消除静差,所谓静差,就是系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原有系统上以抵消系统造成的静差。


4.而微分信号则反应了偏差信号的变化规律,或者说是变化趋势,根据偏差信号的变化趋势来进行超前调节,从而增加了系统的快速性。

 


第一步:定义 PID 变量结构体,代码如下:

struct _pid{

float SetSpeed;//定义设定值

float ActualSpeed;//定义实际值

float err;//定义偏差值

float err_last;//定义上一个偏差值

float Kp,Ki,Kd;//定义比例、积分、微分系数

float voltage;//定义电压值(控制执行器的变量)

float integral;//定义积分值

}pid;

 

控制算法中所需要用到的参数在一个结构体中统一定义,方便后面的使用。

 

第二步:初始化变量,代码如下(以速度控制为例):

 

void PID_init(){

    printf("PID_init begin \n");

pid.SetSpeed=0.0;//设定的速度

pid.ActualSpeed=0.0;//传感器检测的实际速度

pid.err=0.0;        //误差初始化

pid.err_last=0.0;   //前一刻的误差量

pid.voltage=0.0;    //PID输出量

pid.integral=0.0;   //PID误差积分项

pid.Kp=0.2;          //PID比例系数

pid.Ki=0.015;        //PID微分系数

pid.Kd=0.2; printf("PID_init end \n"); //PID积分系数

}

 

统一初始化变量,尤其是 Kp,Ki,Kd 三个参数,调试过程当中,对于要求的控制效果,可以通过调节这三个量直接进行调节。

  

第三步:编写控制算法,代码如下:

 

Float PID_realize()

{

  pid.SetSpeed = speed;

  Pid.err = pid.SetSpeed - pid.ActualSpeed;//计算误差项

  Pid.integral+=pid.err;//计算误差积分项

Pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pi

d.err_last);

  pid.err_last=pid.err;

  pid.ActualSpeed=pid.voltage*1.0;

return pid.ActualSpeed;

}

PID的控制规律为:       



1.说明一下反馈控制的原理,通过上一节的框图不难看出,PID 控制其实是对偏差的控制过程;


2.如果偏差为 0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。


3.积分环节主要是用来消除静差,所谓静差,就是系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原有系统上以抵消系统造成的静差。


4.而微分信号则反应了偏差信号的变化规律,或者说是变化趋势,根据偏差信号的变化趋势来进行超前调节,从而增加了系统的快速性。

 

对于PID讲我们用以下原则:

a.在输出不振荡时,增大比例增益P。(增大P可以快速到稳定)  
b.在输出不振荡时,减小积分时间常数Ti。(积分过大容易超调)  
c.在输出不振荡时,增大微分时间常数Td。(微分项是预测误差变化率,越接近设定目标,越要减少PID输出,来增加系统的快速性)

 

PIXHAWK的PID参数调试: 

 

PIXHAWK采用串级PID的方式,外环是控制角度,内环是控制角速度。因为内环更直接作用于电机,所以我们调试PIXHAWK的PID,一般只用调试内环的PID即可(角速度)。

 


图上我们可以看出内环PID更接近于电机输出,我们在调试PIXHAWK飞控的时候也是先调节内环角速度PID


                     

1:微分调节的现象

我在采用默认PID参数的时候,发现四轴无人机恢复稳定比较慢,有震荡现象。以下是微分作用的PID系统图表:


微分过小系统响应速度快,但是产生有衰减振荡。微分过大系统响应速度变慢。

微分D过小在接近设定目标值的时候会产生较大的过充和少量的振荡,但是会衰减。我们采用默认参数出现了衰减的振荡,就是微分D太小,我们增大微分D就可以解决。

  

2:比例调节的现象



我们发现比例系数过大会导致系统系统响应很快,更有可能导致系统振荡失调,如果发现飞机振荡很厉害,没有衰减,一定是比例系数过大的原因。


3:积分调节的现象

 

积分过大也会产生振荡失调,因为积分是误差的累积。


总结:系统有衰减振荡,有可能是D(微分过小)或者的I(积分过大)。

      系统有振荡越来越大,直到系统不受控制,有可能是P值过大。

      在系统默认的PID参数上做调节,逐步修改参数,看试飞效果。

      可以适当让微分过冲,增加响应的快速性。


注意!!! 一切PID参数的调试都是基于电调行程校准通过,桨和电机,电调匹配的基础之上。如果飞机飞起来就侧翻(没校准好传感器和电调,或者已解锁就起飞(桨和电机不匹配)。这类飞机都飞不起来的问题,调试PID参数是没有意义的,切记! 调试PID参数是基于飞机飞行的有点不稳,但是基本可以飞行的基础之上!


这部分的参考网站

http://www.stmcu.org/module/forum/thread-601133-1-1.html

  • 20
    点赞
  • 156
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是基于PX4无人机定点飞行C++代码示例: ```cpp #include <px4_posix.h> #include <px4_tasks.h> #include <uORB/topics/vehicle_local_position.h> #include <uORB/topics/vehicle_attitude.h> // 定义无人机起飞高度 #define TAKEOFF_ALTITUDE 5.0f // 定义目标位置 #define TARGET_LATITUDE 47.398039f #define TARGET_LONGITUDE 8.545572f #define TARGET_ALTITUDE 10.0f // 定义位置误差阈值 #define POSITION_TOLERANCE 0.5f // 定义姿态误差阈值 #define ATTITUDE_TOLERANCE 0.1f // 定义控制循环间隔时间 #define CONTROL_INTERVAL_US 20000 // 定义无人机状态枚举类型 enum class DroneState { INITIALIZING, TAKEOFF, FLYING, LANDING, LANDED, DISARMED }; // 定义无人机状态变量 static DroneState drone_state = DroneState::INITIALIZING; // 定义无人机位置变量 static struct vehicle_local_position_s local_position; // 定义无人机姿态变量 static struct vehicle_attitude_s attitude; // 定义无人机任务句柄 static px4_task_t control_task_handle = -1; // 定义定点飞行控制函数 void control_task_main(int argc, char *argv[]) { // 初始化本地位置和姿态订阅器 int local_position_sub_fd = orb_subscribe(ORB_ID(vehicle_local_position)); int attitude_sub_fd = orb_subscribe(ORB_ID(vehicle_attitude)); // 开始控制循环 while (true) { // 等待新数据 px4_pollfd_struct_t fds[] = { { .fd = local_position_sub_fd, .events = POLLIN }, { .fd = attitude_sub_fd, .events = POLLIN } }; int poll_ret = px4_poll(fds, 2, CONTROL_INTERVAL_US); // 处理新数据 if (poll_ret == 0) { // 超时 continue; } else if (poll_ret < 0) { // 错误 PX4_ERR("poll error: %d", poll_ret); continue; } // 获取最新的本地位置和姿态数据 orb_copy(ORB_ID(vehicle_local_position), local_position_sub_fd, &local_position); orb_copy(ORB_ID(vehicle_attitude), attitude_sub_fd, &attitude); // 根据当前状态执行相应的控制逻辑 switch (drone_state) { case DroneState::INITIALIZING: { // 等待初始化完成 if (local_position.z > TAKEOFF_ALTITUDE) { drone_state = DroneState::TAKEOFF; } break; } case DroneState::TAKEOFF: { // 起飞 if (local_position.z > TARGET_ALTITUDE - POSITION_TOLERANCE) { drone_state = DroneState::FLYING; } break; } case DroneState::FLYING: { // 到达目标位置 float position_error = sqrtf(powf(local_position.x - TARGET_LATITUDE, 2) + powf(local_position.y - TARGET_LONGITUDE, 2)); if (position_error < POSITION_TOLERANCE && fabsf(attitude.roll) < ATTITUDE_TOLERANCE && fabsf(attitude.pitch) < ATTITUDE_TOLERANCE) { drone_state = DroneState::LANDING; } break; } case DroneState::LANDING: { // 降落 if (local_position.z < POSITION_TOLERANCE) { drone_state = DroneState::LANDED; } break; } case DroneState::LANDED: { // 停止控制循环 return; } default: { // 错误状态 PX4_ERR("invalid drone state: %d", (int)drone_state); drone_state = DroneState::DISARMED; break; } } } } // 定义主函数 int main(int argc, char *argv[]) { // 初始化PX4 px4_main(argc, argv, "px4_posix_app"); // 创建控制任务 control_task_handle = px4_task_spawn_cmd("control_task", SCHED_DEFAULT, SCHED_PRIORITY_MAX - 5, 2000, (px4_main_t)&control_task_main, (char *const *)nullptr); // 等待控制任务结束 px4_task_waitpid(control_task_handle, nullptr, 0); // 退出程序 return 0; } ``` 上述代码实现了基于PX4无人机定点飞行控制逻辑,其中使用了本地位置和姿态订阅器获取无人机状态信息,使用控制循环实现了状态机控制逻辑。需要注意的是,该代码仅为示例代码,实际应用中需要根据具体情况进行修改和优化。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值