广告
淘宝内部优惠券
当前位置: 开发异常方案库» 硬件/嵌入开发 » 关于ROSArduinobridge 中的PID算法问题

关于ROSArduinobridge 中的PID算法问题

开发异常方案库  收集整理于:2020-05-27 17:58:00  浏览:66次
最近在学习ROSArduinobridge 中的PID程序, 程序中设定了一个参数值TargetTicksPerFrame,其注释意思为设定的速度目标值(以每个循环周期的编码器脉冲数来表达)。 double TargetTicksPerFrame;    // target speed in ticks per frame 我的疑问是这个循环周期到底是什么周期? 程序里的Error的计算是: p->TargetTicksPerFrame - input; 其中input 是前后两次循环周期的编码器变化值(这个周期应该是PID的计算周期),那么TargetTicksPerFrame的值也应该是同周期的目标值才有意义吧?所以,按照我的理解来讲,TargetTicksPerFrame的值应该是把设定速度转化为PID的计算周期1/30秒内的编码器脉冲数(PID_RATE=30 //HZ)。 然而,当我用"m 20 20 "命令,让电机设置速度为20脉冲/秒的时候,这个值被直接赋予了20的值,也就是周期是1秒。 请大神解答疑惑。  相关的代码:  PID计算部分:  double TargetTicksPerFrame;    // target speed in ticks per frame 每个Frame目标速度对应的TICKS值   long Encoder;                  // encoder count 编码器计数   long PrevEnc;                  // last encoder count 上个编码器计数   int PrevInput;                // last input  上一个输入   int PrevErr;                   // last error  测试用   int ITerm;                    //integrated term     long output;                    // last motor setting 输出 input = p->Encoder - p->PrevEnc; Perror = p->TargetTicksPerFrame - input;  output = (Kp * Perror - Kd * (input - p->PrevInput) + p->ITerm) / Ko;  p->PrevEnc = p->Encoder;  output += p->output; void updatePID() { //更新PDD函数,包括编码器采集、PID执行以及设定电机PWM。实际我们调这个函数即可。   leftPID.Encoder = readEncoder(LEFT);   rightPID.Encoder = readEncoder(RIGHT);   if (!moving){      if (leftPID.PrevInput != 0 || rightPID.PrevInput != 0) resetPID();     return;   }   /* Compute PID update for each motor */   doPID(&rightPID);   doPID(&leftPID);   /* Set the motor speeds accordingly */   setMotorSpeeds(leftPID.output, rightPID.output);  速度设置部分的代码:   case MOTOR_SPEEDS://这里设置速度,对应命令格式是m arg1 arg2     /* Reset the auto stop timer */     lastMotorCommand = millis();     if (arg1 == 0 && arg2 == 0) {       setMotorSpeeds(0, 0);       resetPID();       moving = 0;     }     else moving = 1;     leftPID.TargetTicksPerFrame = arg1;     rightPID.TargetTicksPerFrame = arg2;     Serial.println("OK");      break;

------网友观点--------------------
控制器一般都是循环驱动 while(true){ dowork();} 一个循环从红色开始,到蓝色位置,里面包含的代码执行完毕就是一个循环周期 单片机、PLC等基本都是这样的逻辑

------网友观点--------------------
引用 1 楼 worldy 的回复:
控制器一般都是循环驱动 while(true){ dowork();} 一个循环从红色开始,到蓝色位置,里面包含的代码执行完毕就是一个循环周期 单片机、PLC等基本都是这样的逻辑
void loop() {   while (Serial.available() > 0) {          // Read the next character     chr = Serial.read();         // Terminate a command with a CR     if (chr == 13) {       if (arg == 1) argv1[index] = NULL;       else if (arg == 2) argv2[index] = NULL;       runCommand();       resetCommand();     }     // Use spaces to delimit parts of the command     else if (chr == ' ') {       // Step through the arguments       if (arg == 0) arg = 1;       else if (arg == 1)  {         argv1[index] = NULL;         arg = 2;         index = 0;       }       continue;     }     else {       if (arg == 0) {         // The first arg is the single-letter command         cmd = chr;       }       else if (arg == 1) {         // Subsequent arguments can be more than one character         argv1[index] = chr;         index++;       }       else if (arg == 2) {         argv2[index] = chr;         index++;       }     }      }    // If we are using base control, run a PID calculation at the appropriate intervals#ifdef USE_BASE   if (millis() > nextPID) {     updatePID();     nextPID += PID_INTERVAL;   }     // Check to see if we have exceeded the auto-stop interval   if ((millis() - lastMotorCommand) > AUTO_STOP_INTERVAL) {;     setMotorSpeeds(0, 0);     moving = 0;   } #endif 代码上看,这个循环周期是PID_INTERVAL。 那么在PID算法的程序里边,计算Error,用1秒的目标值减去1/30秒的实际值,这么算也可以的?

------网友观点--------------------
当然不可以, 计算速度你必须计算编码器器差值除于计时时刻差值,这才是速度值
发布此文章仅为传递网友分享,不代表本站观点,若侵权请联系我们删除,本站将不对此承担任何责任。
软件开发 程序错误 异常 ybaby.netCopyright © 2020-2026  ybaby 版权所有  桂ICP备17004385号-2 网站地图