control_motion.c
Go to the documentation of this file.
00001 // Copyright (c) 2010-2016 The YP-Spur Authors, except where otherwise indicated.
00002 //
00003 // Permission is hereby granted, free of charge, to any person obtaining a copy
00004 // of this software and associated documentation files (the "Software"), to
00005 // deal in the Software without restriction, including without limitation the
00006 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00007 // sell copies of the Software, and to permit persons to whom the Software is
00008 // furnished to do so, subject to the following conditions:
00009 //
00010 // The above copyright notice and this permission notice shall be included in
00011 // all copies or substantial portions of the Software.
00012 //
00013 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00014 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00016 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00019 // SOFTWARE.
00020 
00021 #include <math.h>
00022 #include <stdio.h>
00023 #include <strings.h>
00024 #include <unistd.h>
00025 
00026 #include <stdint.h>
00027 #include <stdlib.h>
00028 #include <time.h>
00029 #include <unistd.h>
00030 
00031 #include <fcntl.h>
00032 #include <sys/stat.h>
00033 #include <sys/time.h>
00034 #include <sys/types.h>
00035 #include <time.h>
00036 
00037 #ifdef HAVE_CONFIG_H
00038 #include <config.h>
00039 #endif  // HAVE_CONFIG_H
00040 
00041 /* ボディパラメータ */
00042 #include <shvel-param.h>
00043 
00044 /* yp-spur用 */
00045 #include <serial.h>
00046 #include <param.h>
00047 #include <control.h>
00048 #include <command.h>
00049 
00050 /* ライブラリ用 */
00051 #include <ypspur.h>
00052 
00053 /*-PI < theta < PIに調整する*/
00054 double trans_q(double theta)
00055 {
00056   while (theta > M_PI)
00057     theta -= 2.0 * M_PI;
00058   while (theta < -M_PI)
00059     theta += 2.0 * M_PI;
00060   return theta;
00061 }
00062 
00063 /* 円弧追従 */
00064 double circle_follow(OdometryPtr odm, SpurUserParamsPtr spur)
00065 {
00066   double d, q, r, ang, rad;
00067 
00068   r = sqrt((spur->x - odm->x) * (spur->x - odm->x) + (spur->y - odm->y) * (spur->y - odm->y));
00069 
00070   ang = atan2((odm->y - spur->y), (odm->x - spur->x));
00071   ang = trans_q(ang);
00072 
00073   // レギュレータ問題に変換
00074   d = fabs(spur->radius) - r;
00075   q = trans_q(odm->theta - (ang + SIGN(spur->radius) * (M_PI / 2.0)));
00076 
00077   if (r < fabs(spur->radius))
00078   {
00079     rad = spur->radius;
00080   }
00081   else
00082   {
00083     rad = SIGN(spur->radius) * r;
00084   }
00085 
00086   return regurator(d, q, rad, spur->v, spur->w, spur);
00087 }
00088 
00089 /* 直線追従 */
00090 double line_follow(OdometryPtr odm, SpurUserParamsPtr spur)
00091 {
00092   double d, q;
00093 
00094   d = (spur->x - odm->x) * sin(spur->theta) - (spur->y - odm->y) * cos(spur->theta);
00095   q = odm->theta - spur->theta;
00096   q = trans_q(q);
00097 
00098   return regurator(d, q, 1000, spur->v, spur->w, spur);
00099   // 1000は無限大のつもり(1km)
00100 }
00101 
00102 /* 軌跡追従レギュレータ */
00103 double regurator(double d, double q, double r, double v_max, double w_max, SpurUserParamsPtr spur)
00104 {
00105   double v, w;
00106   double cd;
00107   double wref;
00108 
00109   v = v_max - SIGN(v_max) * p(YP_PARAM_L_C1, 0) * fabs(spur->wref);
00110   if (v * v_max < 0)
00111     v = 0;
00112 
00113   wref = v / r;
00114   if (wref > fabs(w_max))
00115     wref = fabs(w_max);
00116   else if (wref < -fabs(w_max))
00117     wref = -fabs(w_max);
00118 
00119   cd = d;
00120   if (cd > p(YP_PARAM_L_DIST, 0))
00121     cd = p(YP_PARAM_L_DIST, 0);
00122   if (cd < -p(YP_PARAM_L_DIST, 0))
00123     cd = -p(YP_PARAM_L_DIST, 0);
00124   w = spur->wref_smooth -
00125       spur->control_dt * (SIGN(r) * SIGN(v_max) * p(YP_PARAM_L_K1, 0) * cd +
00126                           p(YP_PARAM_L_K2, 0) * q + p(YP_PARAM_L_K3, 0) * (spur->wref_smooth - wref));
00127 
00128   spur->vref = v;
00129   spur->wref = w;
00130   return d;
00131 }
00132 
00133 /* 回転 */
00134 double spin(OdometryPtr odm, SpurUserParamsPtr spur)
00135 {
00136   double w, theta;
00137   double dt;
00138 
00139   dt = p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
00140   theta = odm->theta + spur->wref_smooth * dt;
00141   w = timeoptimal_servo(
00142       trans_q(theta - spur->theta),
00143       spur->w,
00144       0,
00145       spur->dw);
00146 
00147   spur->wref = w;
00148   spur->vref = 0;
00149   return fabs(odm->theta - spur->theta);
00150 }
00151 
00152 /* 方角 */
00153 double orient(OdometryPtr odm, SpurUserParamsPtr spur)
00154 {
00155   double w, theta;
00156   double dt;
00157 
00158   dt = p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
00159   theta = odm->theta + spur->wref_smooth * dt;
00160   w = timeoptimal_servo(
00161       trans_q(theta - spur->theta),
00162       spur->w,
00163       0,
00164       spur->dw);
00165 
00166   spur->wref = w;
00167   spur->vref = spur->v;
00168   return fabs(odm->theta - spur->theta);
00169 }
00170 
00171 /* 点までの距離 */
00172 double dist_pos(OdometryPtr odm, SpurUserParamsPtr spur)
00173 {
00174   double r;
00175   r = sqrt((spur->x - odm->x) * (spur->x - odm->x) + (spur->y - odm->y) * (spur->y - odm->y));
00176 
00177   return r;
00178 }
00179 
00180 /* 直線まで移動し止まる */
00181 int stop_line(OdometryPtr odm, SpurUserParamsPtr spur)
00182 {
00183   double a;
00184   double q;
00185   double vel;
00186   int over;
00187   double x, y;
00188   double dt;
00189 
00190   dt = p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
00191   x = odm->x + spur->vref_smooth * cos(odm->theta) * dt;
00192   y = odm->y + spur->vref_smooth * sin(odm->theta) * dt;
00193 
00194   a = (x - spur->x) * cos(spur->theta) + (y - spur->y) * sin(spur->theta);
00195   vel = timeoptimal_servo(
00196       a,
00197       spur->v,
00198       0,
00199       spur->dv);
00200   over = 0;
00201 
00202   q = odm->theta - spur->theta;
00203   q = trans_q(q);
00204   regurator(0, q, 1000, vel, spur->w, spur);
00205 
00206   if (a > 0.05)
00207   {
00208     // 越えている
00209     over = 3;
00210   }
00211   else if (a < -0.05)
00212   {
00213     // まだ
00214     over = 1;
00215   }
00216   else
00217   {
00218     // 大体乗った
00219     over = 2;
00220   }
00221   return over;
00222 }
00223 
00224 double timeoptimal_servo(double err, double vel_max, double vel, double acc)
00225 {
00226   double vel_ref_next;
00227   double v;
00228   double _err;
00229 
00230   _err = err + vel * p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
00231   if (_err * err < 0)
00232     _err = 0;
00233 
00234   // 次の目標位置で停止するために必要な現在の速度を計算
00235   v = sqrt(2 * acc * fabs(_err));
00236   if (vel_max < v)
00237   {
00238     vel_ref_next = -SIGN(_err) * fabs(vel_max);
00239   }
00240   else
00241   {
00242     vel_ref_next = -SIGN(_err) * v;
00243   }
00244 
00245   // 次の制御周期で目標値をこえてしまう場合をクリップ
00246   if ((err + vel_ref_next * p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5) * (err) < 0)
00247   {
00248     vel_ref_next = -err / p(YP_PARAM_CONTROL_CYCLE, 0);
00249   }
00250   return vel_ref_next;
00251 }
00252 
00253 double timeoptimal_servo2(double err, double vel_max, double vel, double acc, double vel_end)
00254 {
00255   double v;
00256   double _err;
00257   double _vel_max;
00258 
00259   _err = err + vel * p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
00260 
00261   v = sqrt(vel_end * vel_end + 2 * acc * fabs(_err));
00262 
00263   if (fabs(vel_max) < fabs(vel_end))
00264   {
00265     if (fabs(err) < (vel_end * vel_end - vel_max * vel_max) / (2.0 * acc))
00266       _vel_max = fabs(vel_end);
00267     else
00268       _vel_max = vel_max;
00269   }
00270   else
00271     _vel_max = vel_max;
00272 
00273   if (_vel_max < v)
00274   {
00275     v = _vel_max;
00276   }
00277   if (_err > 0)
00278   {
00279     v = -v;
00280   }
00281 
00282   return v;
00283 }


yp-spur
Author(s):
autogenerated on Fri May 10 2019 02:52:19