00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00045 #include <serial.h>
00046 #include <param.h>
00047 #include <control.h>
00048 #include <command.h>
00049
00050
00051 #include <ypspur.h>
00052
00053
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
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 }