多旋翼无人机仿真 rotors_simulator:基于PID控制器的位置控制---水平位置控制

news2024/11/18 21:35:45

多旋翼无人机仿真 rotors_simulator:基于PID控制器的位置控制---水平位置控制

  • 前言
  • 水平位置控制
    • 串级P控制
      • 收敛结果
      • 收敛过程
    • 串级PID控制
      • 收敛结果
      • 收敛过程
    • 结果总结

在这里插入图片描述

前言

无人机(Unmanned Aerial Vehicle),指的是一种由动力驱动的、无线遥控或自主飞行、机上无人驾驶并可重复使用的飞行器,飞机通过机载的计算机系统自动对飞行的平衡进行有效的控制,并通过预先设定或飞机自动生成的复杂航线进行飞行,并在飞行过程中自动执行相关任务和异常处理。

在前面的博客中,分析了 rotors_simulator 一个开源的无人机gazebo的仿真系统的一个控制接口(roll、pitch、yawrate、thrust),并通过键盘发布控制指令,使飞机飞了起来,但是真正实验过的人则知道,起控制会飞常难,需要一直调整键盘,稍微一不注意,无人机就飞走了。
其原因就是这个接口在无人机内部并没有位置控制的闭环。

在这篇文章中,分析了自动控制原理;并在这篇文章中分析了无人机各种模式的控制框图。

本篇博客主要就是基于无人机的控制原理与控制框图,基于PID控制器,利用rotors_simulator 的控制接口,实现无人机的位置控制。

其中在前一篇博客中已经实现了 高度 控制,本篇博客在其基础上继续实现水平位置控制。

水平位置控制

无人机的水平位置控制的控制框图如下:
在这里插入图片描述
经过前面的分析,我们需要利用的 rotors_simulator 的控制接口有 roll pitch 。

即姿态环的控制不需我们自己实现,只实现水平位置控制器和水平速度控制器即可。

与高度控制类似,我们先实现串级P控制

串级P控制

    void PidPositionControllerNode::PosXYControl()
    {
        float PID_POS_X_GAIN = 1;
        float PID_POS_Y_GAIN = 1;
        float PID_VEL_X_GAIN = 0.1;
        float PID_VEL_Y_GAIN = 0.1;   
        double pos_x_des = 1;
        double pos_y_des = 1;
        double pos_x_cur = odometry_.position.x();        
        double pos_y_cur = odometry_.position.y();
        double vel_x_des = (pos_x_des-pos_x_cur)*PID_POS_X_GAIN;
        double vel_y_des = (pos_y_des-pos_y_cur)*PID_POS_Y_GAIN;
        Eigen::Matrix3d R = odometry_.orientation.toRotationMatrix();
        double yaw = atan2(R(1, 0), R(0, 0)); 
        double b_vel_x_des = vel_x_des*cos(yaw) + vel_y_des*sin(yaw);
        double b_vel_y_des = -vel_x_des*sin(yaw) + vel_y_des*cos(yaw);
        double b_vel_x_cur = odometry_.velocity.x();
        double b_vel_y_cur = odometry_.velocity.y();
        double b_acc_x_des = (b_vel_x_des-b_vel_x_cur)*PID_VEL_X_GAIN;
        double b_acc_y_des = (b_vel_y_des-b_vel_y_cur)*PID_VEL_Y_GAIN;
        des_pitch_ = b_acc_x_des*RADIAN;
        des_roll_ = - b_acc_y_des*RADIAN; //gazebo里是反的

        std::cout<< "无人机当前位置x : "<<std::setprecision(4)<<pos_x_cur<<std::endl;
        std::cout<< "无人机当前位置y : "<<std::setprecision(4)<<pos_y_cur<<std::endl; 
    }

期望位置固定为1,1.
外环和内环的控制均为比例作用,先打通控制回环。

控制效果如下:(以x轴为例,y轴对称关系)
x轴缓慢贴近期望值, 极小值震荡,最终收敛

收敛结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
时间足够长,可无稳态误差

收敛过程

在这里插入图片描述
超调量不大
在这里插入图片描述
约0.03
但是收敛时间过长
约40s

串级PID控制

通过对上面收敛过程的分析,收敛时间长,改善控制效果,适宜加入积分、微分环节。

向其中加入速度环加入pid控制器

    float PidPositionControllerNode::x_vel_pid_controller(float pv,float sp)
    {
        float Kp = 6 , Ki = 0.01 ,Kd = 3; 
        float max_output_pid = 30 , min_output_pid = -30 ;
        float max_output_i = 5,min_output_i = -5 ;
        static float error = 0,error_last=0,error_last_last=0;
        static float output_p,output_i,output_d,output_pid; 
        error = sp - pv ;

        // 控制器 各环节 输出 计算
        output_p += ( Kp * (error - error_last) );
        output_i += ( Ki * (error) );
        output_d += ( Kd * (error - 2*error_last + error_last_last) );

        // 更新偏差量
        error_last_last = error_last ;
        error_last = error ;
        if(output_i>max_output_i)
        {
            output_i = max_output_i;
        }else if(output_i<min_output_i)
        {
            output_i = min_output_i;
        }        
        output_pid = output_p + output_i + output_d;
        if(output_pid>max_output_pid)
        {
            output_pid = max_output_pid;
        }else if(output_pid<min_output_pid)
        {
            output_pid = min_output_pid;
        }
        return output_pid; 
    }

任何闭环控制系统的首要任务是要稳(稳定)、快(快速)、准(准确)的响应命令。

想要达到良好的控制效果,需要对代码中的三个参数进行调整。其中三个参数分别是:

  • 比例环节
    成比例地反映控制系统的偏差信号e(t),偏差一旦产生,控制器立即产生控制作用,以减小偏差。当仅有比例控制时系统输出存在稳态误差

  • 积分环节
    控制器的输出与输入误差信号的积分成正比关系。主要用于消除静差,提高系统的无差度。

  • 微分环节
    反映偏差信号的变化趋势,并能在偏差信号变得太大之前,在系统中引入一个有效的早期修正信号,从而加快系统的动作速度,减少调节时间。在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。

控制参数整定的思想如下
增大比例系数P将加快系统的响应,它的作用于输出值较快,但不能很好稳定在一个理想的数值,不良的结果是虽较能有效的克服扰动的影响,但有余差出现,过大的比例系数会使系统有比较大的超调,并产生振荡,使稳定性变坏。积分能在比例的基础上消除余差,它能对稳定后有累积误差的系统进行误差修整,减小稳态误差。微分具有超前作用,对于具有容量滞后的控制通道,引入微分参与控制,在微分项设置得当的情况下,对于提高系统的动态性能指标,有着显著效果,它可以使系统超调量减小,稳定性增加,动态误差减小。

void PidPositionControllerNode::PosXYControl(double pos_x_des,double pos_y_des)
    {
        // 位置控制器增益
         float PID_POS_X_GAIN = 0.5;
         float PID_POS_Y_GAIN = 0.5;
        double pos_x_cur = odometry_.position.x();        
        double pos_y_cur = odometry_.position.y();
        double vel_x_des = (pos_x_des-pos_x_cur)*PID_POS_X_GAIN;
        double vel_y_des = (pos_y_des-pos_y_cur)*PID_POS_Y_GAIN;
        vel_x_des = Math_doubleConstrain(vel_x_des,-5,5);
        vel_y_des = Math_doubleConstrain(vel_y_des,-5,5);

        // 获取无人机航向角度
        Eigen::Matrix3d R = odometry_.orientation.toRotationMatrix();
        double yaw = atan2(R(1, 0), R(0, 0)); 
        double b_vel_x_des = vel_x_des*cos(yaw) + vel_y_des*sin(yaw);
        double b_vel_y_des = -vel_x_des*sin(yaw) + vel_y_des*cos(yaw);
        double b_vel_x_cur = odometry_.velocity.x();
        double b_vel_y_cur = odometry_.velocity.y();
        double b_acc_x_des = x_vel_pid_controller(b_vel_x_cur,b_vel_x_des);
        double b_acc_y_des = y_vel_pid_controller(b_vel_y_cur,b_vel_y_des);

        des_pitch_ = b_acc_x_des*RADIAN;
        des_roll_ = - b_acc_y_des*RADIAN; //gazebo里是反的

        std::cout<< "无人机当前位置x : "<<std::setprecision(4)<<pos_x_cur<<std::endl;
        std::cout<< "无人机当前位置y : "<<std::setprecision(4)<<pos_y_cur<<std::endl; 
    }

再次编译,查看控制结果

收敛结果

在这里插入图片描述
在这里插入图片描述

收敛过程

在这里插入图片描述
超调量:0.05m
收敛时间:7s

结果总结

将两个位置值的变化曲线放在一起,明显串级PID控制器的效果更优

在这里插入图片描述
最终达到的控制效果:
最大超调为 0.05m
到达稳态时间约 7s
稳态误差 0m

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/834.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习从零到入门 GBDT 梯度提升决策树

GBDT 梯度提升决策树详解一、 梯度的概念1、日常生活中的梯度2、函数中的梯度2.1、走进数学2.2、从数学到机器学习(1)、损失函数的理解 loss function(2)、梯度的理解 gradient(3)、损失函数的梯度下降二、GBDT1、回归树 - Regression Decision Tree&#xff0c;DT2、梯度提升 …

利用Python实现mysql数据库的基础操作

一&#xff1a;环境准备&#xff1a; 1.安装第三方库&#xff1a;pymsql 在pycharm的terminal中执行命令&#xff1a;pip3 install pymsql 2.导入第三方库到py文件中 import pymsql 二&#xff1a;创建mysql数据库的链接对象&#xff1a; 1.封装一个Python类&#xff0c;在该…

Python爬虫入狱小技巧

呀&#xff0c;来坐牢的是吧&#xff0c;坐牢是不可能坐牢的&#xff0c;骚年&#xff0c;下面就是方法&#xff0c;早上学&#xff0c;晚上进去 一、整体思路 爬虫一开始要把思路理清楚&#xff0c;即从网页源代码或者网页数据接口&#xff0c;获取需要的数据.大致思路如下 …

【Java进阶】JUC并发基础

文章目录1.概念1.1 什么是JUC1.2 线程与进程1.3 线程的几种状态1.4 守护线程1.5 死锁与活锁1.6 乐观锁与悲观锁1.7 自旋锁2.Lock2.1 使用Lock2.2 Lock与Synchronized2.3 虚假唤醒3.八锁问题3.1 创建一个Phone实例多线程调用两个方法3.2 创建一个Phone实例多线程调用两个方法&am…

基于热传导矩阵(HCM)边缘检测方法在红外图像中的应用(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑…

3道真题训练|学会链表的前世今生

&#x1f64b;很多朋友都问我学完基础知识以后怎样提高编程水平&#xff1f;当然是刷题啦&#xff01;很多小伙伴都在纠结从哪里开始&#xff0c;今天给大家推荐一个身边朋友都在使用的刷题网站&#xff1a;点击进入牛客网刷题吧&#xff01; &#x1f64b;‍♂️今天是Java …

中文文本分类,基本模型的pytoch实现

学习说明&#xff1a;最近发现了一个宝藏仓库&#xff0c;将常见的文本分类方法做了一个介绍、及封装。现在将学习这仓库的一些笔记记录如下 参照资料 649453932/Chinese-Text-Classification-Pytorch: 中文文本分类&#xff0c;TextCNN&#xff0c;TextRNN&#xff0c;FastT…

宣布 .NET MAUI 支持 .NET 7 Release Candidate 2

支持 .NET 7 Release Candidate 2的 .NET 多平台应用程序 UI (MAUI) 现在可在 Windows 和 Mac 上的 Visual Studio 17.4 Preview 4 中使用。RC2 的主要主题是质量和对带有 iOS 16 的 Xcode 14 的 .NET 支持。此版本包含在生产中使用的上线支持许可证。 在相关新闻中&#xff0…

Linux 内存node和zone

文章目录前言一、内存模型二、&#xff08;N&#xff09;UMA2.1 简介2.2 节点2.3 UMA节点与Flat Memory Model2.4 zone2.4.1 zone2.4.2 zone_type参考资料前言 一、内存模型 所谓memory model&#xff0c;其实就是从cpu的角度看&#xff0c;其物理内存的分布情况&#xff0c;…

图解操作系统-cpu cache

不同物理器件的访问速度不一&#xff1a;速度快的代价高、容量小&#xff1b;代价低且容量大&#xff0c;速度较慢。 为充分发挥各种器件优点&#xff0c;计算机存储数据的物理器件不会只选择一种&#xff0c;而是以CPU为核心&#xff0c;由内而外地组建一整套存储体系结构。它…

亿可控_第2章_指标数据采集与断连监控

亿可控_第2章_指标数据采集与断连监控 文章目录亿可控_第2章_指标数据采集与断连监控第2章 指标数据采集与断连监控学习目标1. EMQ指标主题订阅1.1 Eclipse paho简介1.2 发送与订阅消息1.2.1 发送消息1.2.2 订阅消息1.3 订阅指标主题1.3.1 需求分析1.3.2 实现思路1.3.3 代码实现…

23模式---单例模式

单例模式&#xff0c;属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例&#xff08;根据需要&#xff0c;也有可能一个线程中属于单例&#xff0c;如&#xff1a;仅线程上下文内使用同一个实例&#xff09; 这个也是23设计模型中最…

Python 图像处理OpenCV:几何变换(笔记)

包括图像缩放、图像平移、图像旋转、图像的仿射变换、图像的透射变换及图像金字塔等内容。 图像缩放&#xff1a; 缩放是对图像的大小进行调整&#xff0c;即使图像放大或缩小。cv2.resize(src,dsize,fx0,fy0,interpolationcv2.INTER_LINEAR)src : 输入图像dsize: 绝对尺寸&a…

Linux运维面试题总结—Linux基础、计算机网络基础

文章目录一、三次握手四次挥手二、如何划分vlan三、为什么划分vlanvlan三个模式&#xff1a;vxlan和vlan区别是什么&#xff1f;四、OSI七层模型及对应协议五、Linux中 查找大于10M的文件并删除六、查看cup占用情况&#xff0c;查看内存&#xff0c;查看磁盘IO使用情况&#xf…

图像处理黑科技——弯曲矫正、去摩尔纹、切边增强、PS检测

目录0 前言1 弯曲矫正2 去摩尔纹3 图像切边增强4 PS检测5 总结0 前言 合合信息是行业领先的人工智能及大数据科技企业&#xff0c;专注文字识别领域16年&#xff0c;在智能文字识别及商业大数据等核心领域处于国内领先地位&#xff0c;全球企业和个人用户提供创新的数字化、智…

代码随想录动态规划——一和零

题目 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的大小&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#xff0c;集合 x 是集合 y 的 子集 。 示例 1&#xff1a; 输入&#xff1a;strs [“10…

Oracle Unifier 系统架构简述(安装部署)

关于Oracle Primavera Unifier 的应用架构&#xff0c;其实在我之前的博客已有介绍相关内容 谈谈 Oracle P6 , Unifier 和其他应用系统间的联系https://campin.blog.csdn.net/article/details/104972949 从官方文档方面&#xff0c;其实在《unifier_performance_and_sizing_g…

【C语言】全面解析数据在内存中的存储

文章目录前言类型的基本分类整型浮点数自定义类型整型在内存中的存储原码、反码、补码大端和小端如何判断编译器是大端还是小端浮点数在内存中的存储总结前言 C语言中有char、short、int、long、long long、float和doubole这些数据类型。这些数据类型也叫内置类型。 所占存储空…

JECloud微服务低代码平台重大发布。

JECloud微服务低代码平台【1.0.0】版升级发布&#xff0c;本次发布内容如下&#xff1a; JECloud微服务低代码平台是一款基于元数据领域模型构建的低代码开发平台&#xff0c;其底层采用微服务与微应用构建底层框架&#xff0c;并基于基础框架构建各核心微服务模块来实现低代码…

手撕七大排序 (四)

归并排序归并排序递归写法一. 基本概念二. 图解归并排序递归写法 一. 基本概念 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide andConquer&#xff09;的一个非常典型的应用。将已有序的子序列合并…