在webots中实现pid控制

在webots中实现pid控制

webots是一款开源机器人仿真软件,拥有强大的仿真能力,在机器人开发中也经常被使用。这篇文章向大家介绍如何在webots中实现自己的pid控制

前置知识

有关webots和PID的知识这里不再介绍,有需要者可移步以下链接:

webots:

  1. webots-超详细入门教程(2020)_哔哩哔哩_bilibili
  2. Webots: robot simulator (cyberbotics.com)

PID:

  1. 图文详解PID调参_Top嵌入式的博客-CSDN博客_pid调参

开发环境

webots:2023a

VScode

搭建仿真环境

新建project,命名为pid_controller

在这里插入图片描述

生成这样一个世界:

在这里插入图片描述

然后我们搭建用于演示pid的物体,它是由一个大方块和一个小长方体组成的:

在这里插入图片描述

大方块我们设为robot节点,尺寸为0.1,0.1,0.12(x,y,z),appearance选PBRAppearance,颜色设为红色

在这里插入图片描述

小长方体是一个solid节点,尺寸为0.025,0.025,0.1(x,y,z),在大方块的一侧并与大方块有一定空隙

在这里插入图片描述

大方块和小长方体通过一个HingeJoint连接,关节的原点设在endPoint的solid的中心,绕Y轴旋转;关节的device有motor和position sensor

在这里插入图片描述

需要注意的是为了体现一个比较好的旋转效果,并尽量贴合实际,我将大方块的physics字段中的density设为了5000,而小长方体的density为1000。这样大方块就会更重,体现出来是小长方体转动而大方块不动,小长方体旋转的惯性不会影响大方块,类似于把一个杆固定在墙上旋转。

编写控制器

控制器实现了一个简单的pid控制速度

/*
 * File:          pid_controller.c
 * Date:
 * Description:
 * Author:        RobotFreak
 * Modifications:
 */

/*
 * You may need to add include files like <webots/distance_sensor.h> or
 * <webots/motor.h>, etc.
 */
#include <webots/robot.h>
#include <webots/motor.h>
#include <webots/position_sensor.h>
#include <stdio.h>
//#include "pid.h"
/*
 * You may want to add macros here.
 */
#define TIME_STEP 64
#define SPD_KP 0.001
#define SPD_KI 0
#define SPD_KD 0
#define POS_KP 0
#define POS_KI 0
#define POS_KD 0
#define SPD_OUT_MAX 10
#define SPD_I_MAX 0

typedef struct
{   
    double kp;           //比例系数
    double ki;           //积分系数
    double kd;           //微分系数
    double err_all;      //误差和
    double err_now;      //当前误差
    double err_last;     //上次误差
    double err_llast;    //上上次误差
    double p_out;        //比例输出
    double i_out;        //积分输出
    double d_out;        //微分输出
    double output;       //输出量
    double i_out_max;    //积分限幅
    double out_max;      //输出限幅
    double delta_output; //输出量增量
}PID;

void PID_Init(PID* pid_ptr, double kp, double ki, double kd, double output_max, double i_max)
{
    pid_ptr->kp = kp;
    pid_ptr->ki = ki;
    pid_ptr->kd = kd;
    pid_ptr->err_now = 0;
    pid_ptr->err_last = 0;
    pid_ptr->err_llast = 0;
    pid_ptr->err_all = 0;
    pid_ptr->p_out = 0;
    pid_ptr->i_out = 0;
    pid_ptr->d_out = 0;
    pid_ptr->delta_output = 0;
    pid_ptr->output = 0;
    pid_ptr->i_out_max = i_max;
    pid_ptr->out_max = output_max;
}

void PID_ErrUpdate(PID* pid_ptr, double target, double real)
{
    double err = target - real;  //期望值-实际值得到误差
    pid_ptr->err_llast = pid_ptr->err_last;
    pid_ptr->err_last = pid_ptr->err_now;
    pid_ptr->err_now = err;
    pid_ptr->err_all += err;
}

double PID_PositionalCalcOutput(PID* pid_ptr)
{
    pid_ptr->p_out = pid_ptr->kp * pid_ptr->err_now;
    pid_ptr->i_out = pid_ptr->ki * pid_ptr->err_all;
    // if(pid_ptr->i_out > pid_ptr->i_out_max)  //必要时可对积分限幅
    //     pid_ptr->i_out = pid_ptr->i_out_max;
    pid_ptr->d_out = pid_ptr->kd * (pid_ptr->err_now - pid_ptr->err_last);
    pid_ptr->output = pid_ptr->p_out + pid_ptr->i_out + pid_ptr->d_out;
    if(pid_ptr->output > pid_ptr->out_max)   //必要时可对输出限幅
      pid_ptr->output = pid_ptr->out_max;
    if(pid_ptr->output < -1 * pid_ptr->out_max)
      pid_ptr->output = -1 * pid_ptr->out_max;
    return pid_ptr->output;
}

double PID_IncrementalCalcOutput(PID* pid_ptr)
{
    pid_ptr->delta_output = pid_ptr->kp * (pid_ptr->err_now - pid_ptr->err_last) + pid_ptr->ki * pid_ptr->err_now + pid_ptr->kd * (pid_ptr->err_now - 2*pid_ptr->err_last + pid_ptr->err_llast);
    return pid_ptr->delta_output;
}

/*
 * This is the main program.
 * The arguments of the main function can be specified by the
 * "controllerArgs" field of the Robot node
 */
int main(int argc, char **argv) {
  /* necessary to initialize webots stuff */
  wb_robot_init();
  /*
   * You should declare here WbDeviceTag variables for storing
   * robot devices like this:
   *  WbDeviceTag my_sensor = wb_robot_get_device("my_sensor");
   *  WbDeviceTag my_actuator = wb_robot_get_device("my_actuator");
   */
    //获取deviceTag
  WbDeviceTag motor = wb_robot_get_device("motor");
  WbDeviceTag positionSensor = wb_robot_get_device("positionSensor");
  wb_position_sensor_enable(positionSensor, TIME_STEP); //位置传感器使能
  //PID结构体
  PID speedPD; //p,i,d看作三个独立的单词(缩写)
  PID_Init(&speedPD, SPD_KP, SPD_KI, SPD_KD, SPD_OUT_MAX, SPD_I_MAX);
  //位置(rad)和速度(rad/s)
  double position = 0;
  double positionLast = 0;
  double speed = 0;
  double speedTarget = 5.0;
  /* main loop
   * Perform simulation steps of TIME_STEP milliseconds
   * and leave the loop when the simulation is over
   */
  while (wb_robot_step(TIME_STEP) != -1) {
    /*
     * Read the sensors :
     * Enter here functions to read sensor data, like:
     *  double val = wb_distance_sensor_get_value(my_sensor);
     */
    positionLast = position;
    position = wb_position_sensor_get_value(positionSensor);
    speed = (position - positionLast) / TIME_STEP * 1000; //TIME_STEP是毫秒

    /* Process sensor data here */
    PID_ErrUpdate(&speedPD, speedTarget, speed);
    /*
     * Enter here functions to send actuator commands, like:
     * wb_motor_set_position(my_actuator, 10.0);
     */
    printf("position: %f speed: %f force: %f\n", position, speed, PID_PositionalCalcOutput(&speedPD));
    wb_motor_set_force(motor, PID_PositionalCalcOutput(&speedPD));
  };

  /* Enter your cleanup code here */

  /* This is necessary to cleanup webots resources */
  wb_robot_cleanup();

  return 0;
}

这里我们使用的是wb_motor_set_force(或wb_motor_set_torque),使用这两个api可以关闭webots内自带的PID控制器,从而实现自己的pid

在这里插入图片描述

最终效果

最终就可以实现速控的效果

在这里插入图片描述

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 Vivado 实现 PID 控制器需要以下步骤: 1. 创建 Vivado 项目:打开 Vivado,选择 "Create Project",指定项目名称和位置,选择 "RTL Project",继续下一步。 2. 添加源文件:在添加源文件页面上,选择 "Create File",创建一个 VHDL 或 Verilog 文件,用于实现 PID 控制器的逻辑。 3. 设计 PID 控制器:在创建的 VHDL 或 Verilog 文件,根据 PID 控制器的逻辑方程实现控制器的输入、输出以及控制器参数。 4. 创建测试文件:在同一项目创建测试文件,用于验证 PID 控制器的功能是否正确。 5. 运行综合:选择 "Run Synthesis",Vivado 将对设计进行综合,将高级语言代码转换为门级逻辑网表。 6. 实现布局:选择 "Run Implementation",Vivado 将对综合后的设计进行布局,将网表布置在物理 FPGA 设备的逻辑块(CLB)。 7. 进行静态时序分析:在实现完成后进行静态时序分析,确保设计满足时序要求。 8. 烧录到 FPGA 设备:选择 "Generate Bitstream",Vivado 将生成可烧录到 FPGA 设备的二进制位流文件。 9. 烧录位流到 FPGA 设备:通过 JTAG 线连接 FPGA 开发板和计算机,将生成的位流文件烧录到 FPGA 设备。 10. 验证 PID 控制器:使用测试文件对 PID 控制器进行验证和调试,确保其性能和功能符合要求。 需要注意的是,实现 PID 控制器还需要根据具体的需求进行参数调整和优化,以获得更好的控制效果。另外,Vivado 还提供了丰富的仿真和调试功能,可以帮助进一步验证和优化设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

RobotFreak

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

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

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

打赏作者

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

抵扣说明:

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

余额充值