velocity.cpp

00001 /*
00002   車輪の直接制御により速度制御を行うプログラム
00003   Satofumi KAMIMURA
00004   $Id$
00005 
00006   C言語っぽい実装
00007 */
00008 
00009 #include "runCtrl.h"
00010 #include <unistd.h>
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <sys/time.h>
00014 #include <signal.h>
00015 
00016 enum {
00017   Right = 0, Left = 1,
00018   DefaultAcc = 100,             // 標準加速度 [mm/sec]
00019 };
00020 
00021 typedef void (callback_t)(int);
00022 
00023 static RunCtrl Run;
00024 static int EncRefVel = 0;       // エンコーダ単位の目標速度[cnt/msec^2]
00025 static int EncRefAcc = DefaultAcc; // エンコーダ単位の目標加速度 [cnt/sec^2]
00026 static int TotalTicks = 0;      // 制御開始からの時刻 [msec]
00027 static int PreTicks = 0;        // 前回の時刻 [msec]
00028 
00029 
00030 static void setIntervalTimer(callback_t *func, int interval_msec) {
00031   struct itimerval itimer;
00032   struct sigaction act;
00033   
00034   // initilaize interval tiemr
00035   itimer.it_value.tv_sec = 0;
00036   itimer.it_value.tv_usec = interval_msec * 1000;
00037   itimer.it_interval.tv_sec = 0;
00038   itimer.it_interval.tv_usec = interval_msec * 1000;
00039   setitimer(ITIMER_REAL, &itimer, NULL);
00040 
00041   // set signal handler
00042   act.sa_handler = func;
00043   sigemptyset(&act.sa_mask);
00044   act.sa_flags = 0;
00045 
00046   sigaction(SIGALRM, &act, 0);
00047 }
00048 
00049 
00050 static void stopIntervalTimer(void) {
00051   struct itimerval itimer;
00052   itimer.it_value.tv_sec = 0;
00053   itimer.it_value.tv_usec = 0;
00054   setitimer(ITIMER_REAL, &itimer, NULL);
00055 }
00056 
00057 
00058 static int getTicks(void) {
00059   struct timeval time;
00060   gettimeofday(&time, NULL);
00061   return (time.tv_sec * 1000) + (time.tv_usec / 1000);
00062 }
00063 
00064 
00065 static void setRefVelocity(int mm_sec_vel, int mm_sec_acc = DefaultAcc) {
00066   // 目標速度をエンコーダ単位系での目標速度[cnt/msec]に変換
00067 
00068   EncRefVel = static_cast<int>(mm_sec_vel * WHL_CNT_PER_MM_RIGHT / 1000);
00069   EncRefAcc = static_cast<int>(mm_sec_acc * WHL_CNT_PER_MM_RIGHT / 1000);
00070 
00071   printf("EncRefVel: %d, EncRefAcc: %d\n", EncRefVel, EncRefAcc);
00072 }
00073 
00074 
00075 static void initVelocityCtrl(void) {
00076   PreTicks = getTicks();
00077 }
00078 
00079 
00080 static int calcPwmValue(int EncRefVel, int* enc_vel, int* diff_total) {
00081   double Gain_P = 0.000004;
00082   double Gain_I = 0.00001;
00083 
00084   int diff = EncRefVel - *enc_vel;
00085   *diff_total += diff;
00086 
00087   double output = (Gain_P * diff) + (Gain_I * *diff_total);
00088   double duty = output * 255.0;
00089 
00090   int pwm = (fabs(duty) > 1.0) ?
00091     static_cast<int>(255 * duty/fabs(duty)) : static_cast<int>(255 * duty);
00092 
00093   return static_cast<int>(pwm);
00094 }
00095 
00096 
00097 static void velocityCtrl(int sig) {
00098   static bool initialized = false;
00099   if (!initialized) {
00100     initialized = true;
00101     initVelocityCtrl();
00102     return;
00103   }
00104   static int pwm[2];
00105   static int diff_total[2] = { 0, 0 };
00106 
00107   // 前回からの経過時間を取得
00108   int now = getTicks();
00109   int interval_msec = now - PreTicks;
00110   TotalTicks += interval_msec;
00111   PreTicks = now;
00112   printf("ticks: %d (%d) [msec]\n", TotalTicks, interval_msec);
00113 
00114   // エンコーダ値の読みだし
00115   int enc_vel[2];
00116   for (int i = 0; i < 2; ++i) {
00117     //Run.getEncoderVel(i, &enc_vel[i]);
00118     enc_vel[i] *= -1;
00119   }
00120 
00121   // PWM の演算
00122   int ref_enc_vel = TotalTicks * EncRefAcc;
00123   ref_enc_vel = (ref_enc_vel > EncRefVel) ? EncRefVel : ref_enc_vel;
00124   for (int i = 0; i < 2; ++i) {
00125     pwm[i] = calcPwmValue(ref_enc_vel, &enc_vel[i], &diff_total[i]);
00126   }
00127 
00128   // モータへの回転指示
00129   for (int i = 0; i < 2; ++i) {
00130     //int mode = (pwm[i] >= 0) ? DIRECT_MODE_CCW : DIRECT_MODE_CW;
00131     //Run.setMotorMode(i, mode);
00132     //Run.setMotorPwm(i, abs(pwm[i]));
00133   }
00134 
00135   printf("ref_enc_vel: %d\n", ref_enc_vel);
00136   printf("enc_vel: %d, %d\n", enc_vel[Right], enc_vel[Left]);
00137   printf("pwm: %d, %d\n", pwm[Right], pwm[Left]);
00138   printf("\n");
00139 }
00140 
00141 
00142 int main(int argc, char *argv[]) {
00143   try {
00144     enum { IntervalMsec = 130 };
00145 
00146     // ライブラリの初期化
00147     if (Run.connect(argc, argv) < 0) {
00148       printf("RunCtrl::connect: %s\n", Run.what());
00149       exit(1);
00150     }
00151 
00152     // 初期化
00153     setRefVelocity(100);
00154     setIntervalTimer(velocityCtrl, IntervalMsec);
00155 
00156     // 改行で停止
00157     while (getchar() == EOF) {
00158       sleep(1);
00159     }
00160 
00161     stopIntervalTimer();
00162     Run.stop();
00163   } catch (std::exception& e) {
00164     printf("exception: %s\n", e.what());
00165   }
00166   return 0;
00167 }
00168 

Generated on Mon Apr 13 22:52:02 2009 by  doxygen 1.5.7.1