ros之pid

53 篇文章 0 订阅
43 篇文章 1 订阅

PID口诀

参数整定找最佳,从小到[大顺序查 先是比例后积分,最后再把微分加 曲线振荡很频繁,比例度盘要放大 曲线漂浮绕大湾,比例度盘往小扳 曲线偏离回复慢,积分时间往下降 曲线波动周期长,积分时间再加长 曲线振荡频率快,先把微分降下来 动差大来波动慢。微分时间应加长 理想曲线两个波,前高后低4比1 一看二调多分析,调节质量不会低

MainWindow.h

//
// Created by wt on 2020/7/2.
//

#ifndef DEMO_SWEEPING_ROBOT_MAINWINDOW_H
#define DEMO_SWEEPING_ROBOT_MAINWINDOW_H
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QFormLayout>
#include <ros/ros.h>
#include <QLabel>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Pose.h>
#include <std_msgs/Float64.h>
#include <thread>

class MainWindow: public QWidget {
private:
    QFormLayout layout;
    QLineEdit xEdit;
    QLineEdit yEdit;
    QLabel xLabel;
    QLabel yLabel;
    QLabel thetaLabel;
    QPushButton btn;
    QPushButton sweepBtn;
    QLineEdit kpEdit;
    QLineEdit kdEdit;
    QLineEdit kiEdit;
    //发布者
    ros::Publisher publisher;
    //plot发布者
    ros::Publisher plotPublisher;
    //订阅者
    ros::Subscriber subscriber;
    //保存的当前x和y
    float curx;
    float cury;
    //小乌龟的角度
    float curTheta;
public:
    MainWindow(ros::NodeHandle node,QWidget* parent = Q_NULLPTR);

    ~MainWindow();
    //点击
    void click();
    //扫地
    void sweep();
    //纵向扫地
    void vSweep();
    //求距离
    float distance(float curx,float cury,float dstx,float dsty);
    //回调
    void callBack(const turtlesim::Pose::ConstPtr & pose);
    //控制小乌龟
    void controlTurtle(float dstx,float dsty);
    //计算需要转的角度
    float caclAngle(float dstx,float dsty,float curx,float cury,float theta);
};


#endif //DEMO_SWEEPING_ROBOT_MAINWINDOW_H

MainWindow.cpp

//
// Created by wt on 2020/7/2.
//

#include "MainWindow.h"

MainWindow::MainWindow(ros::NodeHandle node, QWidget *parent) : QWidget(parent),
btn("执行"),sweepBtn("扫地") {
    //发布者
    publisher = node.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 5);
    //订阅者
    subscriber = node.subscribe("/turtle1/pose", 5, &MainWindow::callBack, this);
    //plot发布者
    plotPublisher = node.advertise<std_msgs::Float64>("/tutle/speed", 5);

    setLayout(&layout);
    //默认值
    xEdit.setText("5.544444561");
    yEdit.setText("5.544444561");
    layout.addRow("目标x:", &xEdit);
    layout.addRow("目标y:", &yEdit);
    layout.addRow("当前x:", &xLabel);
    layout.addRow("当前y:", &yLabel);
    layout.addRow("当前theta:", &thetaLabel);
    kpEdit.setText("0.1");
    kdEdit.setText("0.1");
    kiEdit.setText("0.1");
    layout.addRow("kp:",&kpEdit);
    layout.addRow("kd:",&kdEdit);
    layout.addRow("ki:",&kiEdit);
    layout.addRow("", &btn);
    layout.addRow("", &sweepBtn);

    //信号和槽绑定
    connect(&btn, &QPushButton::clicked, this, &MainWindow::click);
    connect(&sweepBtn, &QPushButton::clicked, this, &MainWindow::sweep);
}

MainWindow::~MainWindow() {

}

//真实的速度
void MainWindow::click() {
    //当前的x和y
    //目标的x和y
    float dstx = xEdit.text().toFloat();
    float dsty = yEdit.text().toFloat();
    //开启线程执行耗时操作
    new std::thread(&MainWindow::controlTurtle, this, dstx, dsty);
}

//转向
void MainWindow::controlTurtle(float dstx, float dsty) {
    //走的距离
    float dst = distance(curx, cury, dstx, dsty);
    //走的时间
    float time = 5.0;
    //调头时间
    float turnTime = time/12;
    //频率
    float hz = 10;
    //频率
    ros::Rate rate(hz);
    //当前速度
    float curSpeed = 0;
    //记录上一次误差
    float lastError = 0;
    //总误差
    float totalError = 0;
    //kp系数
    float kp = kpEdit.text().toFloat();
    //kd系数
    float kd = kdEdit.text().toFloat();
    //ki系数
    float ki = kiEdit.text().toFloat();

    geometry_msgs::Twist data;
    while (distance(curx, cury, dstx, dsty) > 0.1) {
        //目标速度
        float tarSpeed = distance(curx, cury, dstx, dsty) / time;
        /*-------------------------- p --------------------------*/
        //误差= 目标速度 - 当前速度
        float pError = tarSpeed - curSpeed;
        //调节速度  当前速度=当前速度 + 误差*kp系数(比例系数)
        curSpeed += pError * kp;
        /*-------------------------- d --------------------------*/
        // dError =  当前误差-记录的上一次误差
        float dError = pError - lastError;
        //   
        curSpeed += dError * kd;
        //记录当前误差
        lastError = pError;
        /*-------------------------- i --------------------------*/
        // 总误差 = 当前误差累加
        totalError += pError;
        curSpeed+=totalError*ki;

        //数据
        data.linear.x = curSpeed;
        //角速度
        data.angular.z = caclAngle(dstx,dsty,curx,cury,curTheta)/turnTime;
        //移动 (只会按照当前这个速度走1秒钟)
        publisher.publish(data);

        //数据
        std_msgs::Float64 sp;
        sp.data = curSpeed;
        //发送速度给plot展示
        plotPublisher.publish(sp);
        //剩下的时间
        time -= 1 / hz;
        //睡眠
        rate.sleep();
    }
    //把速度设置为0
    //数据
    data.linear.x = 0;
    data.angular.z = 0;
    //移动 (只会按照当前这个速度走1秒钟)
    publisher.publish(data);
}

//D算法
//void MainWindow::controlTurtle(float dstx, float dsty) {
//    //走的距离
//    float dst = distance(curx, cury, dstx, dsty);
//    //走的时间
//    float time = 5.0;
//    //频率
//    float hz = 10;
//    //频率
//    ros::Rate rate(hz);
//    //当前速度
//    float curSpeed = 0;
//    //记录上一次误差
//    float lastError = 0;
//    //总误差
//    float totalError = 0;
//    //kp系数
//    float kp = kpEdit.text().toFloat();
//    //kd系数
//    float kd = kdEdit.text().toFloat();
//    //ki系数
//    float ki = kiEdit.text().toFloat();
//
//    geometry_msgs::Twist data;
//    while (distance(curx, cury, dstx, dsty) > 0.1) {
//        //目标速度
//        float tarSpeed = distance(curx, cury, dstx, dsty) / time;
//        /*-------------------------- p --------------------------*/
//        //误差
//        float pError = tarSpeed - curSpeed;
//        //调节速度
//        curSpeed += pError * kp;
//        /*-------------------------- d --------------------------*/
//        float dError = pError - lastError;
//        curSpeed += dError * kd;
//        lastError = pError;
//        /*-------------------------- i --------------------------*/
//        totalError += pError;
//        curSpeed+=totalError*ki;
//
//        //数据
//        data.linear.x = curSpeed;
//        data.angular.z = 0;
//        //移动 (只会按照当前这个速度走1秒钟)
//        publisher.publish(data);
//
//        //数据
//        std_msgs::Float64 sp;
//        sp.data = curSpeed;
//        //发送速度给plot展示
//        plotPublisher.publish(sp);
//        //剩下的时间
//        time -= 1 / hz;
//        //睡眠
//        rate.sleep();
//    }
//    //把速度设置为0
//    //数据
//    data.linear.x = 0;
//    data.angular.z = 0;
//    //移动 (只会按照当前这个速度走1秒钟)
//    publisher.publish(data);
//}


//P算法
//void MainWindow::controlTurtle(float dstx, float dsty) {
//    //走的距离
//    float dst = distance(curx,cury,dstx,dsty);
//    //走的时间
//    float time = 5.0;
//    //频率
//    float hz = 10;
//    //频率
//    ros::Rate rate(hz);
//    //当前速度
//    float curSpeed = 0;
//    //kp系数
//    float kp = 0.1;
//
//    geometry_msgs::Twist data;
//    while (distance(curx,cury,dstx,dsty)>0.1){
//        //目标速度
//        float tarSpeed = distance(curx,cury,dstx,dsty)/time;
//        //误差
//        float pError = tarSpeed-curSpeed;
//        //调节速度
//        curSpeed += pError*kp;
//
//        //数据
//        data.linear.x = curSpeed;
//        data.angular.z = 0;
//        //移动 (只会按照当前这个速度走1秒钟)
//        publisher.publish(data);
//
//        //数据
//        std_msgs::Float64 sp;
//        sp.data = curSpeed;
//        //发送速度给plot展示
//        plotPublisher.publish(sp);
//        //剩下的时间
//        time -= 1/hz;
//        //睡眠
//        rate.sleep();
//    }
//    //把速度设置为0
//    //数据
//    data.linear.x = 0;
//    data.angular.z = 0;
//    //移动 (只会按照当前这个速度走1秒钟)
//    publisher.publish(data);
//}

//计算速度
//void MainWindow::controlTurtle(float dstx, float dsty) {
//    //走的距离
//    float dst = distance(curx,cury,dstx,dsty);
//    //走的时间
//    float time = 5.0;
//    //频率
//    float hz = 10;
//    //频率
//    ros::Rate rate(hz);
//    //速度
//    float speed = dst/time;
//    geometry_msgs::Twist data;
//    while (distance(curx,cury,dstx,dsty)>0.1){
//        speed = distance(curx,cury,dstx,dsty)/time;
//        //数据
//        data.linear.x = speed;
//        data.angular.z = 0;
//        //移动 (只会按照当前这个速度走1秒钟)
//        publisher.publish(data);
//
//        //数据
//        std_msgs::Float64 sp;
//        sp.data = speed;
//        //发送速度给plot展示
//        plotPublisher.publish(sp);
//        //剩下的时间
//        time -= 1/hz;
//        //睡眠
//        rate.sleep();
//    }
//    //把速度设置为0
//    //数据
//    data.linear.x = 0;
//    data.angular.z = 0;
//    //移动 (只会按照当前这个速度走1秒钟)
//    publisher.publish(data);
//}

//指定时间走完
//void MainWindow::click() {
//    //当前的x和y
//    //目标的x和y
//    float dstx = xEdit.text().toFloat();
//    float dsty = yEdit.text().toFloat();
//    //走的距离
//    float dst = distance(curx,cury,dstx,dsty);
//    //走的时间
//    float time = 5.0;
//    //频率
//    float hz = 10;
//    //频率
//    ros::Rate rate(hz);
//    //速度
//    float speed = dst/time;
//    geometry_msgs::Twist data;
//    while (distance(curx,cury,dstx,dsty)>0.1){
//        //数据
//        data.linear.x = speed;
//        data.angular.z = 0;
//        //移动 (只会按照当前这个速度走1秒钟)
//        publisher.publish(data);
//
//        //数据
//        std_msgs::Float64 sp;
//        sp.data = speed;
//        //发送速度给plot展示
//        plotPublisher.publish(sp);
//        //睡眠
//        rate.sleep();
//    }
//    //把速度设置为0
//    //数据
//    data.linear.x = 0;
//    data.angular.z = 0;
//    //移动 (只会按照当前这个速度走1秒钟)
//    publisher.publish(data);
//}

//指定时间走完
//void MainWindow::click() {
//    //当前的x和y
//    //目标的x和y
//    float dstx = xEdit.text().toFloat();
//    float dsty = yEdit.text().toFloat();
//    //走的距离
//    float dst = distance(curx,cury,dstx,dsty);
//    //走的时间
//    float time = 5.0;
//    //频率
//    float hz = 10;
//    //频率
//    ros::Rate rate(hz);
//    //速度
//    float speed = dst/time;
//    //走的距离
//    float runDst = 0;
//    geometry_msgs::Twist data;
//    while (runDst<dst){
//        //数据
//        data.linear.x = speed;
//        data.angular.z = 0;
//        //移动 (只会按照当前这个速度走1秒钟)
//        publisher.publish(data);
//        //增加走的距离
//        runDst += speed/hz;
//        //睡眠
//        rate.sleep();
//    }
//    //把速度设置为0
//    //数据
//    data.linear.x = 0;
//    data.angular.z = 0;
//    //移动 (只会按照当前这个速度走1秒钟)
//    publisher.publish(data);
//}

//指定时间走完
//void MainWindow::click() {
//    //当前的x和y
//    //目标的x和y
//    float dstx = xEdit.text().toFloat();
//    float dsty = yEdit.text().toFloat();
//    //走的距离
//    float dst = distance(curx,cury,dstx,dsty);
//    //走的时间
//    float time = 5.0;
//    //频率
//    float hz = 10;
//    //频率
//    ros::Rate rate(hz);
//    //速度
//    float speed = dst/time;
//    geometry_msgs::Twist data;
//    for (int i = 0; i < (int)(time*hz); ++i) {
//        //数据
//        data.linear.x = speed;
//        data.angular.z = 0;
//        //移动 (只会按照当前这个速度走1秒钟)
//        publisher.publish(data);
//        //睡眠
//        rate.sleep();
//    }
//    //把速度设置为0
//    //数据
//    data.linear.x = 0;
//    data.angular.z = 0;
//    //移动 (只会按照当前这个速度走1秒钟)
//    publisher.publish(data);
//}

//5秒钟走完(问题)
//void MainWindow::click() {
//    //当前的x和y
//    //目标的x和y
//    float dstx = xEdit.text().toFloat();
//    float dsty = yEdit.text().toFloat();
//    //走的距离
//    float dst = distance(curx,cury,dstx,dsty);
//    //走的时间
//    float time = 5;
//    //频率
//    ros::Rate rate(1);
//    //速度
//    float speed = dst/time;
//    for (int i = 0; i < (int)time; ++i) {
//        //数据
//        geometry_msgs::Twist data;
//        data.linear.x = speed;
//        data.angular.z = 0;
//        //移动 (只会按照当前这个速度走1秒钟)
//        publisher.publish(data);
//        //睡眠
//        rate.sleep();
//    }
//}

//1秒钟走完
//void MainWindow::click() {
//    //当前的x和y
//    //目标的x和y
//    float dstx = xEdit.text().toFloat();
//    float dsty = yEdit.text().toFloat();
//    //走的距离
//    float dst = distance(curx,cury,dstx,dsty);
//    //走的时间
//    float time = 1;
//    //速度
//    float speed = dst/time;
//    //数据
//    geometry_msgs::Twist data;
//    data.linear.x = speed;
//    data.angular.z = 0;
//    //移动
//    publisher.publish(data);
//}

float MainWindow::distance(float curx, float cury, float dstx, float dsty) {
    return sqrt(pow(curx - dstx, 2) + pow(cury - dsty, 2));
}

void MainWindow::callBack(const turtlesim::Pose_<std::allocator<void>>::ConstPtr &pose) {
    curx = pose->x;
    cury = pose->y;
    curTheta = pose->theta;
    xLabel.setText(QString::number(curx));
    yLabel.setText(QString::number(cury));
    thetaLabel.setText(QString::number(pose->theta));
}
/**
 * 计算需要转的角度
 * @param dstx
 * @param dsty
 * @param curx
 * @param cury
 * @param theta 小乌龟当前角度
 * @return
 */
float MainWindow::caclAngle(float dstx,float dsty,float curx,float cury,float theta){
    float angle = atan2(dsty-cury,dstx-curx)-theta;
    //角度范围在0-180 -180-0
    if(angle>M_PI){
        angle -= 2*M_PI;
    } else if (angle<-M_PI){
        angle += 2*M_PI;
    }
    return angle;
}

void MainWindow::sweep() {
    new std::thread(&MainWindow::vSweep,this);
}

void MainWindow::vSweep() {
    for (int i = 1; i < 11; ++i) {
        controlTurtle((float)i,1);
        controlTurtle((float)i,10);
    }
}





main.cpp

//
// Created by wt on 2020/7/2.
//
#include <iostream>
#include <ros/ros.h>
#include <QApplication>
#include "MainWindow.h"
using namespace std;

int main(int argc,char *argv[]){
    //节点名
    string nodeName = "sweeping_node";
    //初始化节点
    ros::init(argc,argv,nodeName);
    //创建节点
    ros::NodeHandle node;
    /*-------------------------- 异步spiner --------------------------*/
    ros::AsyncSpinner spinner(1);
    spinner.start();
    /*-------------------------- qt --------------------------*/
    QApplication app(argc,argv);
    MainWindow w(node);
    w.show();
    return QApplication::exec();
}

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_无往而不胜_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值