velocityCtrl.c

Go to the documentation of this file.
00001 
00010 #include "velocityCtrl.h"
00011 #include "isqrt.h"
00012 #include "iatan2.h"
00013 #include "isincos.h"
00014 
00015 
00016 void initVelocityCtrlInfo(velocityCtrlInfo_t *velCtrl) {
00017   velCtrl->ref_vel = 0;
00018   velCtrl->current_vel = 0;
00019   velCtrl->acc = 0;
00020   velCtrl->current_pos = 0;
00021   velCtrl->circle_r = 500;
00022   velCtrl->stable = CONTROL_UNSTABLE;
00023 }
00024 
00025 
00026 void getFirstHoldVelocity(velocityCtrlInfo_t *velCtrl, int vel) {
00027   velCtrl->current_vel = vel * 1000;
00028 }
00029 
00030 
00031 /* 速度制御 */
00032 int holdVelocityCtrl(velocityCtrlInfo_t *velCtrl) {
00033   int diff = (velCtrl->ref_vel * 1000) - velCtrl->current_vel;
00034 
00035   if (diff > +velCtrl->acc) {
00036     velCtrl->current_vel += velCtrl->acc;
00037   } else if (diff < -velCtrl->acc) {
00038     velCtrl->current_vel -= velCtrl->acc;
00039   } else {
00040     velCtrl->stable = CONTROL_STABLE;
00041     return velCtrl->ref_vel;
00042   }
00043 
00044   return velCtrl->current_vel / 1000;
00045 }
00046 
00047 
00048 /* 位置制御 */
00049 int holdPositionCtrl(velocityCtrlInfo_t *velCtrl, int stable_shift) {
00050   int pos_sign, pos_abs;
00051   int vel_sign, vel_abs;
00052   int ret_value;
00053   int store_ref_vel = velCtrl->ref_vel;
00054 
00055   pos_sign = (velCtrl->current_pos < 0) ? -1 : +1;
00056   pos_abs = pos_sign * velCtrl->current_pos;
00057   vel_sign = (velCtrl->current_vel < 0) ? -1 : +1;
00058   vel_abs = vel_sign * velCtrl->current_vel / 1000;
00059 
00060   if ((isqrt(velCtrl->acc << 1) * isqrt(pos_abs)) > (unsigned)(vel_abs)) {
00061     velCtrl->ref_vel = - pos_sign * velCtrl->ref_vel;
00062   } else {
00063     velCtrl->ref_vel =
00064       - pos_sign * isqrt(velCtrl->acc << 1) * isqrt(pos_abs);
00065   }
00066   ret_value = holdVelocityCtrl(velCtrl);
00067   velCtrl->ref_vel = store_ref_vel;
00068   velCtrl->stable = ((pos_abs >> stable_shift) == 0) ?
00069     CONTROL_STABLE : CONTROL_UNSTABLE;
00070 
00071   if ((isqrt(velCtrl->acc << 1) * isqrt(pos_abs)) > (unsigned)(vel_abs)) {
00072     return ret_value;
00073   } else {
00074     return (1000 * ret_value) >> 10;
00075   }
00076 }
00077 
00078 
00079 int followLineCtrl(velocityCtrlInfo_t *velCtrl, int follow_r,
00080                    velocityInfo_t *velInfo, int run_crd_div16) {
00081   int set_current_pos;
00082   int l = velCtrl->current_pos;
00083   int l_sign, l_abs;
00084   int vel_sign = (velInfo->straight_mm_sec_vel < 0) ? -1 : +1;
00085   int r = follow_r;
00086   int rl_diff;
00087   int ret_value;
00088 
00089   l_sign = (l < 0) ? -1 : +1;
00090   l_abs = (l < 0) ? -l : +l;
00091 
00092   if (l_abs >= r) {
00093     set_current_pos = l_sign * (0x10000 >> 2);
00094   } else {
00095     int vel_adjust =
00096       l_sign * iatan2(vel_sign * velInfo->straight_mm_sec_vel, r);
00097     rl_diff = (l_sign > 0) ? r - l : r + l;
00098     set_current_pos =
00099       l_sign * ((0x10000 >> 2)
00100                 - vel_sign * iatan2(rl_diff, isqrt(r*r - rl_diff*rl_diff)));
00101 
00102     // 並進速度の補正
00103     set_current_pos -= vel_sign * vel_adjust >> 1;
00104   }
00105 
00106   // 後進時
00107   if (vel_sign < 0) {
00108     set_current_pos -= l_sign * (0x10000 >> 1);
00109   }
00110 
00111   // 目標直線を越えないための補正
00112   if (l_abs < (r >> 2)) {
00113     set_current_pos >>= 1;
00114     if (l_abs < (r >> 5)) {
00115       set_current_pos >>= 1;
00116     }
00117   }
00118 
00119   velCtrl->current_pos =
00120     getSignedDiv16((set_current_pos + run_crd_div16) & 0xffff);
00121   ret_value = holdPositionCtrl(velCtrl, DIV16_STABLE_SHIFT);
00122   if (velCtrl->stable == CONTROL_STABLE) {
00123     velCtrl->stable = ((l_abs >> (MM_STABLE_SHIFT + 2)) == 0)
00124       ? CONTROL_STABLE : CONTROL_UNSTABLE;
00125   }
00126   return ret_value;
00127 }
00128 
00129 
00130 int followCircleCtrl(velocityCtrlInfo_t *velCtrl, int follow_r, int x, int y,
00131                      velocityInfo_t *velInfo, int run_crd_div16) {
00132   int r = isqrt(x*x + y*y);
00133   int sign = (velCtrl->circle_r < 0) ? -1 : +1;
00134   int offset = iatan2(y, x);
00135   int ret_value;
00136   int diff = 0;
00137 
00138   velCtrl->current_pos = (sign * r) - velCtrl->circle_r;
00139   if (velCtrl->circle_r != 0) {
00140     diff = - (int)(0x10000 / (2 * M_PI))
00141       * velInfo->straight_mm_sec_vel / velCtrl->circle_r;
00142   }
00143   ret_value = followLineCtrl(velCtrl, follow_r, velInfo,
00144                              run_crd_div16
00145                              - getSignedDiv16(offset - sign * (0x10000 >> 2)));
00146 
00147   return ret_value + diff;
00148 }
00149 

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