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