ypspur-coordinator.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 <stdlib.h>
24 #include <strings.h>
25 #include <unistd.h>
26 
27 #include <fcntl.h>
28 #include <setjmp.h>
29 #include <signal.h>
30 #include <sys/stat.h>
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <time.h>
34 
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif // HAVE_CONFIG_H
38 
39 /* ボディパラメータ */
40 #include <shvel-param.h>
41 
42 /* yp-spur 用 */
43 #include <ypspur-coordinator.h>
44 #include <serial.h>
45 #include <param.h>
46 #include <control.h>
47 #include <command.h>
48 #include <odometry.h>
49 #include <ypprotocol.h>
50 #include <adinput.h>
51 #include <ssm_spur_handler.h>
52 #include <utility.h>
53 #include <yprintf.h>
54 #include <ping.h>
55 
56 /* ライブラリ用 */
57 #include <ypspur.h>
58 #include <cartesian2d.h>
59 
60 #include <pthread.h>
61 
62 #if HAVE_SIGLONGJMP
63 sigjmp_buf ctrlc_capture;
64 #elif HAVE_LONGJMP
65 jmp_buf ctrlc_capture;
66 #endif // HAVE_SIGLONGJMP
67 
68 #if defined(__MINGW32__)
69 BOOL WINAPI win32_ctrlc_handler(DWORD type)
70 {
71  fprintf(stderr, "\n");
72 #ifdef HAVE_SSM
73  /* SSM終了処理 */
75  end_ypspurSSM();
76 #endif // HAVE_SSM
78  {
79  serial_close();
80  }
81 
82  return TRUE;
83 }
84 #else
85 void emergency(int sig)
86 {
87  fprintf(stderr, "\n");
88 #if HAVE_SIGLONGJMP
89  siglongjmp(ctrlc_capture, 1);
90 #elif HAVE_LONGJMP
91  longjmp(ctrlc_capture, 1);
92 #else
93 #ifdef HAVE_SSM
94  /* SSM終了処理 */
96  end_ypspurSSM();
97 #endif // HAVE_SSM
99  {
100  serial_close();
101  }
102 
103  exit(0);
104 #endif // HAVE_SIGLONGJMP
105 }
106 #endif // defined(__MINGW32__)
107 
108 void escape_road(const int enable)
109 {
110 #if defined(__MINGW32__)
111  if (enable)
112  {
113  if (!SetConsoleCtrlHandler(win32_ctrlc_handler, TRUE))
114  {
115  yprintf(OUTPUT_LV_ERROR, "Error: Win32 Ctrl+C handler registration failed.\n");
116  }
117  }
118  else
119  {
120  if (!SetConsoleCtrlHandler(NULL, FALSE))
121  {
122  yprintf(OUTPUT_LV_ERROR, "Error: Win32 Ctrl+C handler restoration failed.\n");
123  }
124  }
125 #else
126  if (enable)
127  {
128  signal(SIGINT, emergency);
129  }
130  else
131  {
132  signal(SIGINT, SIG_DFL);
133  }
134 #endif // defined(__MINGW32__)
135 }
136 
137 /* main */
138 int main(int argc, char *argv[])
139 {
140  pthread_t command_thread;
141  pthread_t control_thread;
142  pthread_t update_thread;
143  int command_thread_en;
144  int control_thread_en;
145  int update_thread_en;
146  Ver_t version;
147  Param_t driver_param;
148  int i, ret;
149  ParametersPtr param;
150  char paramfile[512];
151  int quit;
152 
153  hook_pre_global();
154 
155  ret = arg_analyze(argc, argv);
156  if (option(OPTION_DAEMON))
157  {
158 #if HAVE_FORK
159  pid_t pid;
160 
161  pid = fork();
162  if (pid < 0)
163  {
164  return -1;
165  }
166  else if (pid != 0)
167  {
168  return 0;
169  }
170  setsid();
171  if (chdir("/") < 0)
172  {
173  yprintf(OUTPUT_LV_ERROR, "Failed to chdir.\n");
174  return EXIT_FAILURE;
175  }
176  close(STDIN_FILENO);
177  close(STDOUT_FILENO);
178  close(STDERR_FILENO);
179 #else
180  yprintf(OUTPUT_LV_ERROR, "Daemon mode is not supported in your system.\n");
181  return EXIT_FAILURE;
182 #endif // HAVE_FORK
183  }
185  {
186  arg_help(argc, argv);
187  return EXIT_SUCCESS;
188  }
190  {
191  arg_longhelp(argc, argv);
192  return EXIT_SUCCESS;
193  }
195  {
196  param_help();
197  return EXIT_SUCCESS;
198  }
199  if (option(OPTION_VERSION))
200  {
201  fprintf(stderr, "YamabicoProject-Spur\n");
202  fprintf(stderr, " Ver. %s\n", PROJECT_VERSION);
203  return EXIT_SUCCESS;
204  }
205  if (!ret) /* オプション解析に失敗したとき */
206  return EXIT_FAILURE;
207 
208  yprintf(OUTPUT_LV_INFO, "++++++++++++++++++++++++++++++++++++++++++++++++++\n");
209  yprintf(OUTPUT_LV_INFO, "YamabicoProject-Spur\n");
210  yprintf(OUTPUT_LV_INFO, " Ver. %s\n", PROJECT_VERSION);
211  yprintf(OUTPUT_LV_INFO, "++++++++++++++++++++++++++++++++++++++++++++++++++\n");
212 
213  /* パラメータを読み込み、セットする */
214  param = get_param_ptr();
215 
216 #ifdef HAVE_SSM
217  /* SSM初期化 */
219  init_ypspurSSM(param->ssm_id);
220 #endif // HAVE_SSM
221 
222  /* 座標系の初期化、コマンド処理系の初期化 */
224  init_odometry();
226 
227  fflush(stderr);
228 
229  command_thread_en = 0;
230  command_thread_en = 0;
231  do
232  {
233  FILE *temp_paramfile = NULL;
234  quit = 0;
235 
236  yprintf(OUTPUT_LV_INFO, "Device Information\n");
237 
239  {
240  yprintf(OUTPUT_LV_INFO, " Port : %s \n", param->device_name);
241  if (!serial_connect(param->device_name))
242  {
243  // quit=0;でbreakしたら異常終了と判断される
244  break;
245  }
247  {
248  int current, age;
249  int device_current, device_age;
250  sscanf(YP_PROTOCOL_NAME, "YPP:%d:%d", &current, &age);
251 
252  yprintf(OUTPUT_LV_INFO, " Checking device information");
253  for (i = 0; i < 3; i++)
254  {
255  yprintf(OUTPUT_LV_INFO, ".");
256  // Check protocol version
257  if (get_version(&version) == -1)
258  {
259  continue;
260  }
261  if (strstr(version.protocol, "YPP:") != version.protocol)
262  {
263  continue;
264  }
265  sscanf(version.protocol, "YPP:%d:%d", &device_current, &device_age);
266  param->device_version = device_current;
267  param->device_version_age = device_age;
268  if (device_current - device_age > current ||
269  device_current < current - age)
270  {
271  continue;
272  }
273  break;
274  }
276  yprintf(OUTPUT_LV_INFO, " Vender : %s\n", version.vender);
277  yprintf(OUTPUT_LV_INFO, " Product : %s\n", version.product);
278  yprintf(OUTPUT_LV_INFO, " Firmware: %s\n", version.firmware);
279  yprintf(OUTPUT_LV_INFO, " Protcol : %s\n", version.protocol);
280  yprintf(OUTPUT_LV_INFO, " Serialno: %s\n", version.serialno);
281  yprintf(OUTPUT_LV_INFO, "++++++++++++++++++++++++++++++++++++++++++++++++++\n");
282  if (i == 3)
283  {
284  yprintf(OUTPUT_LV_ERROR, "Error: Device doesn't have available YP protocol version.\n(Device: %s, coordinator: %s)\n",
285  version.protocol, YP_PROTOCOL_NAME);
287  {
288  yp_usleep(500000);
289  continue;
290  }
291  break; // quit=0でbreakしたら異常終了と判断
292  }
293  if (device_current != current)
294  {
295  if (device_current < current)
296  {
297  yprintf(OUTPUT_LV_WARNING, "Recommendation: Device protocol version is not latest.\n");
298  yprintf(OUTPUT_LV_WARNING, "Recommendation: Firmware update is recommended.\n");
299  }
300  else
301  {
302  yprintf(OUTPUT_LV_WARNING, "Recommendation: ypspur-coordinator protocol version is not latest.\n");
303  yprintf(OUTPUT_LV_WARNING, "Recommendation: Software update is recommended.\n");
304  }
305  yprintf(OUTPUT_LV_WARNING, "++++++++++++++++++++++++++++++++++++++++++++++++++\n");
306  }
307  if (get_parameter(&driver_param) == -1)
308  {
309  continue;
310  }
311  yprintf(OUTPUT_LV_DEBUG, "Driver depending parameters\n");
312  yprintf(OUTPUT_LV_DEBUG, " Name : %s\n", driver_param.robot_name);
313  yprintf(OUTPUT_LV_DEBUG, " PWM resolution: %s\n", driver_param.pwm_resolution);
314  yprintf(OUTPUT_LV_DEBUG, " Motor number : %s\n", driver_param.motor_num);
315  yprintf(OUTPUT_LV_DEBUG, "++++++++++++++++++++++++++++++++++++++++++++++++++\n");
316 
317  if (strlen(driver_param.pwm_resolution) <= 0 ||
318  strlen(driver_param.motor_num) <= 0)
319  {
320  yprintf(OUTPUT_LV_ERROR, "Error: Failed to load driver parameters.\n");
322  {
323  yp_usleep(500000);
324  continue;
325  }
326  break;
327  }
328  }
329  else
330  {
331  driver_param.robot_name[0] = 0;
332  driver_param.pwm_resolution[0] = 0;
333  strcpy(driver_param.motor_num, "2");
334  }
335  fflush(stderr);
336  }
337  else
338  {
339  yprintf(OUTPUT_LV_INFO, " Port : n/a (--without-device mode)\n");
340  }
341 
342  if (option(OPTION_PING))
343  {
344  return ping();
345  }
346 
347  if (!(option(OPTION_PARAM_FILE)))
348  {
349  // パラメータファイルが指定されておらず、ドライバにパラメータが内蔵されている場合
350  if (strcmp(driver_param.robot_name, "embedded") == 0)
351  {
352  char param[2048];
353 
354  yprintf(OUTPUT_LV_INFO, "Reading device embedded parameter.\n");
355  temp_paramfile = tmpfile();
356  if (!temp_paramfile)
357  {
358  yprintf(OUTPUT_LV_ERROR, "Error: Failed to create temporary file.\n");
359  break;
360  }
361  if (!get_embedded_param(param))
362  {
363  yprintf(OUTPUT_LV_ERROR, "Error: Failed to read embedded parameters.\n");
365  {
366  yp_usleep(500000);
367  continue;
368  }
369  break;
370  }
371  fprintf(temp_paramfile, "%s", param);
372  fseek(temp_paramfile, 0L, SEEK_SET);
373  }
374  // パラメータファイルが指定されておらず、ドライバにロボット名が登録されている場合
375  else if (strlen(driver_param.robot_name) > 0 && strcmp(driver_param.robot_name, "unknown") != 0)
376  {
377  strcpy(param->parameter_filename, driver_param.robot_name);
378  strcat(param->parameter_filename, ".param");
379  }
380  }
381  if (temp_paramfile)
382  {
383  yprintf(OUTPUT_LV_DEBUG, "Embedded parameter file\n");
384  if (!set_paramptr(temp_paramfile))
385  {
386  yprintf(OUTPUT_LV_ERROR, "Error: Cannot use embedded parameter.\n");
387  break;
388  }
389  }
390  else
391  {
392  yprintf(OUTPUT_LV_DEBUG, "Parameter file: %s\n", param->parameter_filename);
393  if (!set_param(param->parameter_filename, paramfile))
394  {
395  yprintf(OUTPUT_LV_ERROR, "Error: Cannot load parameter file.\n");
396  break;
397  }
398  }
399  {
400  if (strlen(driver_param.pwm_resolution) > 0)
401  {
402  int i;
403  for (i = 0; i < YP_PARAM_MAX_MOTOR_NUM; i++)
404  {
405  *pp(YP_PARAM_PWM_MAX, i) = atoi(driver_param.pwm_resolution);
406  }
407  }
408  else if (p(YP_PARAM_PWM_MAX, 0) == 0)
409  {
411  {
412  *pp(YP_PARAM_PWM_MAX, i) = 1000; // dummy value for simulation
413  }
414  else
415  {
416  yprintf(OUTPUT_LV_ERROR, "Error: _PWM_RESOLUTION parameter must be given on --no-yp-protocol mode.\n");
417  break;
418  }
419  }
420  }
421  yprintf(OUTPUT_LV_DEBUG, "++++++++++++++++++++++++++++++++++++++++++++++++++\n\n");
422 
424  {
426  {
427  // ボーレートの設定
428  if (param->speed)
429  {
430  yprintf(OUTPUT_LV_INFO, "Setting baudrate to %d baud.\n", param->speed);
431  }
432  else
433  {
434  // 指定されてない場合デフォルトの値
435  param->speed = DEFAULT_BAUDRATE;
436  }
437 
438  ret = set_baudrate(param->speed);
439  if (ret == 0)
440  {
441  // 設定失敗
442  yprintf(OUTPUT_LV_WARNING, "Error: Failed to change baudrate.\n");
443  break; // quit=0でbreakしたら異常終了と判断
444  }
445  if (ret == 4)
446  {
447  // ボーレートの設定未対応
448  yprintf(OUTPUT_LV_INFO, "Info: Baudrate setting is not supported on this device.\n");
449  }
450  else
451  {
452  // 設定成功
453  // 正常ならば何もしない
454  }
455 
456  if (param->admask)
457  {
458  yprintf(OUTPUT_LV_INFO, "Setting admask to %x.\n", param->admask);
459  set_admask(param->admask);
460  }
461 
463  {
464  yprintf(OUTPUT_LV_INFO, "Enabling digital io input.\n");
465  set_diomask(1);
466  }
467  }
468 
470  if (apply_robot_params() < 1)
471  break;
472 
473  /* サーボをかける */
475  spur = get_spur_user_param_ptr();
476  for (i = 0; i < YP_PARAM_MAX_MOTOR_NUM; i++)
477  {
478  spur->wheel_mode[i] = MOTOR_CONTROL_VEL;
479  spur->wheel_mode_prev[i] = -1;
480  }
481  }
482 
483  yprintf(OUTPUT_LV_INFO, "YP-Spur coordinator started.\n");
484 
485  /* スレッド初期化 */
486  init_command_thread(&command_thread);
487  command_thread_en = 1;
488 
490  {
491  init_control_thread(&control_thread);
492  control_thread_en = 1;
493  }
494  else
495  {
496  control_thread_en = 0;
497  }
499  {
500  yprintf(OUTPUT_LV_WARNING, "==================== Warning! ====================\n");
501  yprintf(OUTPUT_LV_WARNING, "Running in automatic parameter update mode.\n");
502  yprintf(OUTPUT_LV_WARNING, "Keep in mind that the coordinator doesn't stop\n");
503  yprintf(OUTPUT_LV_WARNING, "even if the parameter file gets invalid.\n");
504  yprintf(OUTPUT_LV_WARNING, "==================================================\n");
505  init_param_update_thread(&update_thread, paramfile);
506  update_thread_en = 1;
507  }
508  else
509  {
510  update_thread_en = 0;
511  }
512 
513 // オドメトリ受信ループ
514 #if HAVE_SIGLONGJMP
515  if (sigsetjmp(ctrlc_capture, 1) != 0)
516  {
517  quit = 1;
518  }
519  else
520 #elif HAVE_LONGJMP
521  if (setjmp(ctrlc_capture) != 0)
522  {
523  quit = 1;
524  }
525  else
526 #endif // HAVE_SIGLONGJMP
527  {
528  escape_road(1);
530  {
532  }
533  else
534  {
535  while (1)
536  yp_usleep(1000000);
537  }
538  yprintf(OUTPUT_LV_INFO, "Connection to %s was closed.\n", param->device_name);
539  }
540  escape_road(0);
541 
542  /* 終了処理 */
543  if (update_thread_en)
544  {
545  pthread_cancel(update_thread);
546  pthread_join(update_thread, NULL);
547  update_thread_en = 0;
548  }
549  if (control_thread_en)
550  {
551  pthread_cancel(control_thread);
552  pthread_join(control_thread, NULL);
553  control_thread_en = 0;
554  }
555  if (command_thread_en)
556  {
557  pthread_cancel(command_thread);
558  pthread_join(command_thread, NULL);
559  command_thread_en = 0;
560  }
561 
562  if (option(OPTION_RECONNECT) && quit == 0)
563  {
565  yp_usleep(500000);
567  {
568  serial_close();
569  while (!serial_tryconnect(param->device_name))
570  {
571  yp_usleep(200000);
572  }
573  }
574  yprintf(OUTPUT_LV_INFO, "++++++++++++++++++++++++++++++++++++++++++++++++++\n");
575  yp_usleep(500000);
576  continue;
577  }
578  break;
579  } while (1);
580 
582  serial_close();
583 
584 #ifdef HAVE_SSM
585  /* SSM終了処理 */
587  end_ypspurSSM();
588 #endif // HAVE_SSM
589 
590  yp_usleep(200000);
591  fflush(stderr);
592 
593  return (quit ? EXIT_SUCCESS : EXIT_FAILURE);
594 }
unsigned char admask
Definition: param.h:83
int set_baudrate(int baud)
Definition: ypprotocol.c:57
MotorControlMode wheel_mode_prev[YP_PARAM_MAX_MOTOR_NUM]
Definition: command.h:77
char serialno[128]
Definition: ypprotocol.h:38
int serial_tryconnect(char *device_name)
Definition: serial.c:178
void yp_usleep(int usec)
Definition: utility.c:54
char product[128]
Definition: ypprotocol.h:35
double * pp(YPSpur_param id, enum motor_id motor)
Definition: param.c:94
int speed
Definition: param.h:80
#define DEFAULT_BAUDRATE
Definition: serial.h:27
char device_name[132]
Definition: param.h:77
void init_command_thread(pthread_t *thread)
Definition: command.c:467
char pwm_resolution[128]
Definition: ypprotocol.h:44
char protocol[128]
Definition: ypprotocol.h:37
void init_odometry(void)
Definition: odometry.c:80
int main(int argc, char *argv[])
double p(YPSpur_param id, enum motor_id motor)
Definition: param.c:79
void arg_longhelp(int argc, char *argv[])
Definition: param.c:134
int odometry_receive_loop(void)
Definition: odometry.c:649
MotorControlMode wheel_mode[YP_PARAM_MAX_MOTOR_NUM]
Definition: command.h:76
void init_control_thread(pthread_t *thread)
int apply_robot_params(void)
Definition: param.c:1057
int ssm_id
Definition: param.h:84
void init_spur_command(void)
Definition: command.c:68
void hook_pre_global(void)
Definition: utility.c:73
static YPSpur spur
Definition: libypspur.c:42
char vender[128]
Definition: ypprotocol.h:34
int get_embedded_param(char *param)
Definition: ypprotocol.c:248
void emergency(int sig)
char parameter_filename[132]
Definition: param.h:76
void param_help(void)
Definition: param.c:159
int serial_close(void)
Definition: serial.c:363
void escape_road(const int enable)
int ping()
Definition: ping.c:27
void end_ypspurSSM(void)
char motor_num[128]
Definition: ypprotocol.h:45
SpurUserParamsPtr get_spur_user_param_ptr()
Definition: command.c:53
int set_paramptr(FILE *paramfile)
Definition: param.c:454
#define YP_PARAM_MAX_MOTOR_NUM
Definition: ypparam.h:456
int set_admask(unsigned char mask)
Definition: adinput.c:106
void yprintf(ParamOutputLv level, const char *format,...)
Definition: yprintf.c:32
int get_version(Ver_t *apVer)
Get version info.
Definition: ypprotocol.c:111
int device_version_age
Definition: param.h:88
int get_parameter(Param_t *apParam)
Get version info.
Definition: ypprotocol.c:186
char firmware[128]
Definition: ypprotocol.h:36
void ansi_clear_line(ParamOutputLv level)
Definition: yprintf.c:68
void init_coordinate_systems(void)
Definition: odometry.c:69
int option(ParamOptions option)
Definition: param.c:99
int device_version
Definition: param.h:87
int set_param(char *filename, char *concrete_path)
Definition: param.c:933
int serial_connect(char *device_name)
Definition: serial.c:320
void init_ypspurSSM(int ssm_id)
char robot_name[128]
Definition: ypprotocol.h:46
int arg_analyze(int argc, char *argv[])
Definition: param.c:175
ParametersPtr get_param_ptr()
Definition: param.c:111
void init_param_update_thread(pthread_t *thread, char *filename)
Definition: param.c:1003
void arg_help(int argc, char *argv[])
Definition: param.c:120
int set_diomask(unsigned char enable)
Definition: adinput.c:140


yp-spur
Author(s):
autogenerated on Fri May 7 2021 02:12:17