control_motion.c
Go to the documentation of this file.
1 // Copyright (c) 2010-2016 The YP-Spur Authors, except where otherwise indicated.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to
5 // deal in the Software without restriction, including without limitation the
6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 // sell copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #include <math.h>
22 #include <stdio.h>
23 #include <strings.h>
24 #include <unistd.h>
25 
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #include <unistd.h>
30 
31 #include <fcntl.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <time.h>
36 
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif // HAVE_CONFIG_H
40 
41 /* ボディパラメータ */
42 #include <shvel-param.h>
43 
44 /* yp-spur用 */
45 #include <serial.h>
46 #include <param.h>
47 #include <control.h>
48 #include <command.h>
49 
50 /* ライブラリ用 */
51 #include <ypspur.h>
52 
53 /*-PI < theta < PIに調整する*/
54 double trans_q(double theta)
55 {
56  while (theta > M_PI)
57  theta -= 2.0 * M_PI;
58  while (theta < -M_PI)
59  theta += 2.0 * M_PI;
60  return theta;
61 }
62 
63 /* 円弧追従 */
65 {
66  double d, q, r, ang, rad;
67 
68  r = sqrt((spur->x - odm->x) * (spur->x - odm->x) + (spur->y - odm->y) * (spur->y - odm->y));
69 
70  ang = atan2((odm->y - spur->y), (odm->x - spur->x));
71  ang = trans_q(ang);
72 
73  // レギュレータ問題に変換
74  d = fabs(spur->radius) - r;
75  q = trans_q(odm->theta - (ang + SIGN(spur->radius) * (M_PI / 2.0)));
76 
77  if (r < fabs(spur->radius))
78  {
79  rad = spur->radius;
80  }
81  else
82  {
83  rad = SIGN(spur->radius) * r;
84  }
85 
86  return regurator(d, q, rad, spur->v, spur->w, spur);
87 }
88 
89 /* 直線追従 */
91 {
92  double d, q;
93 
94  d = (spur->x - odm->x) * sin(spur->theta) - (spur->y - odm->y) * cos(spur->theta);
95  q = odm->theta - spur->theta;
96  q = trans_q(q);
97 
98  return regurator(d, q, 1000, spur->v, spur->w, spur);
99  // 1000は無限大のつもり(1km)
100 }
101 
102 /* 軌跡追従レギュレータ */
103 double regurator(double d, double q, double r, double v_max, double w_max, SpurUserParamsPtr spur)
104 {
105  double v, w;
106  double cd;
107  double wref;
108 
109  v = v_max - SIGN(v_max) * p(YP_PARAM_L_C1, 0) * fabs(spur->wref);
110  if (v * v_max < 0)
111  v = 0;
112 
113  wref = v / r;
114  if (wref > fabs(w_max))
115  wref = fabs(w_max);
116  else if (wref < -fabs(w_max))
117  wref = -fabs(w_max);
118 
119  cd = d;
120  if (cd > p(YP_PARAM_L_DIST, 0))
121  cd = p(YP_PARAM_L_DIST, 0);
122  if (cd < -p(YP_PARAM_L_DIST, 0))
123  cd = -p(YP_PARAM_L_DIST, 0);
124  w = spur->wref_smooth -
125  spur->control_dt * (SIGN(r) * SIGN(v_max) * p(YP_PARAM_L_K1, 0) * cd +
126  p(YP_PARAM_L_K2, 0) * q + p(YP_PARAM_L_K3, 0) * (spur->wref_smooth - wref));
127 
128  spur->vref = v;
129  spur->wref = w;
130  return d;
131 }
132 
133 /* 回転 */
135 {
136  double w, theta;
137  double dt;
138 
139  dt = p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
140  theta = odm->theta + spur->wref_smooth * dt;
141  w = timeoptimal_servo(
142  trans_q(theta - spur->theta),
143  spur->w,
144  0,
145  spur->dw);
146 
147  spur->wref = w;
148  spur->vref = 0;
149  return fabs(odm->theta - spur->theta);
150 }
151 
152 /* 方角 */
154 {
155  double w, theta;
156  double dt;
157 
158  dt = p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
159  theta = odm->theta + spur->wref_smooth * dt;
160  w = timeoptimal_servo(
161  trans_q(theta - spur->theta),
162  spur->w,
163  0,
164  spur->dw);
165 
166  spur->wref = w;
167  spur->vref = spur->v;
168  return fabs(odm->theta - spur->theta);
169 }
170 
171 /* 点までの距離 */
173 {
174  double r;
175  r = sqrt((spur->x - odm->x) * (spur->x - odm->x) + (spur->y - odm->y) * (spur->y - odm->y));
176 
177  return r;
178 }
179 
180 /* 直線まで移動し止まる */
182 {
183  double a;
184  double q;
185  double vel;
186  int over;
187  double x, y;
188  double dt;
189 
190  dt = p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
191  x = odm->x + spur->vref_smooth * cos(odm->theta) * dt;
192  y = odm->y + spur->vref_smooth * sin(odm->theta) * dt;
193 
194  a = (x - spur->x) * cos(spur->theta) + (y - spur->y) * sin(spur->theta);
195  vel = timeoptimal_servo(
196  a,
197  spur->v,
198  0,
199  spur->dv);
200  over = 0;
201 
202  q = odm->theta - spur->theta;
203  q = trans_q(q);
204  regurator(0, q, 1000, vel, spur->w, spur);
205 
206  if (a > 0.05)
207  {
208  // 越えている
209  over = 3;
210  }
211  else if (a < -0.05)
212  {
213  // まだ
214  over = 1;
215  }
216  else
217  {
218  // 大体乗った
219  over = 2;
220  }
221  return over;
222 }
223 
224 double timeoptimal_servo(double err, double vel_max, double vel, double acc)
225 {
226  double vel_ref_next;
227  double v;
228  double _err;
229 
230  _err = err + vel * p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
231  if (_err * err < 0)
232  _err = 0;
233 
234  // 次の目標位置で停止するために必要な現在の速度を計算
235  v = sqrt(2 * acc * fabs(_err));
236  if (vel_max < v)
237  {
238  vel_ref_next = -SIGN(_err) * fabs(vel_max);
239  }
240  else
241  {
242  vel_ref_next = -SIGN(_err) * v;
243  }
244 
245  // 次の制御周期で目標値をこえてしまう場合をクリップ
246  if ((err + vel_ref_next * p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5) * (err) < 0)
247  {
248  vel_ref_next = -err / p(YP_PARAM_CONTROL_CYCLE, 0);
249  }
250  return vel_ref_next;
251 }
252 
253 double timeoptimal_servo2(double err, double vel_max, double vel, double acc, double vel_end)
254 {
255  double v;
256  double _err;
257  double _vel_max;
258 
259  _err = err + vel * p(YP_PARAM_CONTROL_CYCLE, 0) * 1.5;
260 
261  v = sqrt(vel_end * vel_end + 2 * acc * fabs(_err));
262 
263  if (fabs(vel_max) < fabs(vel_end))
264  {
265  if (fabs(err) < (vel_end * vel_end - vel_max * vel_max) / (2.0 * acc))
266  _vel_max = fabs(vel_end);
267  else
268  _vel_max = vel_max;
269  }
270  else
271  _vel_max = vel_max;
272 
273  if (_vel_max < v)
274  {
275  v = _vel_max;
276  }
277  if (_err > 0)
278  {
279  v = -v;
280  }
281 
282  return v;
283 }
double trans_q(double theta)
double y
Definition: odometry.h:34
double circle_follow(OdometryPtr odm, SpurUserParamsPtr spur)
double control_dt
Definition: command.h:82
double theta
Definition: command.h:78
double p(YPSpur_param id, enum motor_id motor)
Definition: param.c:79
double radius
Definition: command.h:79
#define SIGN(x)
Definition: param.h:60
static YPSpur spur
Definition: libypspur.c:42
double dist_pos(OdometryPtr odm, SpurUserParamsPtr spur)
int stop_line(OdometryPtr odm, SpurUserParamsPtr spur)
double spin(OdometryPtr odm, SpurUserParamsPtr spur)
double timeoptimal_servo2(double err, double vel_max, double vel, double acc, double vel_end)
double line_follow(OdometryPtr odm, SpurUserParamsPtr spur)
double theta
Definition: odometry.h:35
double orient(OdometryPtr odm, SpurUserParamsPtr spur)
double regurator(double d, double q, double r, double v_max, double w_max, SpurUserParamsPtr spur)
double vref_smooth
Definition: command.h:63
double wref_smooth
Definition: command.h:64
double timeoptimal_servo(double err, double vel_max, double vel, double acc)
double x
Definition: odometry.h:33


yp-spur
Author(s):
autogenerated on Sat May 11 2019 02:08:24