param.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 <string.h>
25 #include <strings.h>
26 #include <unistd.h>
27 
28 #include <fcntl.h>
29 #include <sys/stat.h>
30 #include <sys/time.h>
31 #include <sys/types.h>
32 #include <time.h>
33 
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif // HAVE_CONFIG_H
37 
38 /* ボディパラメータ */
39 #include <shvel-param.h>
40 
41 /* yp-spur用 */
42 #include <communication.h>
43 #include <serial.h>
44 #include <param.h>
45 #include <control.h>
46 #include <command.h>
47 #include <utility.h>
48 #include <yprintf.h>
49 #include <formula-calc.h>
50 
51 /* ライブラリ用 */
52 #include <ypspur.h>
53 
54 #include <pthread.h>
55 
62 int g_param_init = 1;
63 
65 {
66  return (g_state[id] == ENABLE);
67 }
68 
70 {
71  g_state[id] = ENABLE;
72 }
73 
75 {
76  g_state[id] = DISABLE;
77 }
78 
79 double p(YPSpur_param id, enum motor_id motor)
80 {
81  return g_P[id][motor];
82 }
83 
84 int isset_p(YPSpur_param id, enum motor_id motor)
85 {
86  return g_P_set[id][motor];
87 }
88 
89 int ischanged_p(YPSpur_param id, enum motor_id motor)
90 {
91  return g_P_changed[id][motor];
92 }
93 
94 double *pp(YPSpur_param id, enum motor_id motor)
95 {
96  return &g_P[id][motor];
97 }
98 
100 {
101  if (g_param.option & option)
102  return 1;
103  return 0;
104 }
105 
107 {
108  return g_param.output_lv;
109 }
110 
112 {
113  return &g_param;
114 }
115 
116 int is_character(int c);
117 int is_number(int c);
118 
119 /* 引数の説明 */
120 void arg_help(int argc, char *argv[])
121 {
122  fprintf(stderr, "USAGE: %s [OPTION]...\n\n", argv[0]);
123  fprintf(stderr, " -v, --version Display version info and exit.\n");
124  fprintf(stderr, " -d, --device <device> Specify a B-Loco device. e.g. /dev/ttyUSB0\n");
125  fprintf(stderr, " -p, --param <tile> Specify a robot parameter file.\n");
126  fprintf(stderr, " --verbose Display detail information.\n");
127  fprintf(stderr, " --quiet Display nothing.\n");
128  fprintf(stderr, " -h, --help This help\n");
129  fprintf(stderr, " --long-help Long help\n");
130  fprintf(stderr, " --param-help Comments of parameters\n\n");
131 }
132 
133 /* 隠しコマンドの説明 */
134 void arg_longhelp(int argc, char *argv[])
135 {
136  arg_help(argc, argv);
137  fprintf(stderr, " -o, --show-odometry Display estimated robot position.\n");
138  fprintf(stderr, " -t, --show-timestamp Display timestamp of serial communication \n"
139  " with the B-Loco device.\n");
140  fprintf(stderr, " --reconnect Try reconnect device when device was closed.\n");
141  fprintf(stderr, " --without-ssm Run without ssm output.\n");
142  fprintf(stderr, " -q, --msq-key <MSQKEY> Run with message que key MSQKEY (default = 28741).\n");
143  fprintf(stderr, " -s, --speed <BAUDRATE> Set baudrate.\n");
144  fprintf(stderr, " --admask <ADMASK> Get AD data of ADMASK from B-Loco device.\n");
145  fprintf(stderr, " --enable-get-digital-io Enable digital IO port.\n");
146  fprintf(stderr, " -c, --without-control Run without control.\n");
147  fprintf(stderr, " --without-device Run without B-Loco device.\n");
148  fprintf(stderr, " --no-yp-protocol Run without checking plotocol of B-Loco device.\n");
149  fprintf(stderr, " --passive Passive run mode.\n");
150  fprintf(stderr, " --update-param Automatically reload parameter file.\n");
151  fprintf(stderr, " --high-resolution[=ARG] Use high resolution velocity control mode (default = yes).\n");
152  fprintf(stderr, " --ssm-id <SSMID> Change ssm id (default = 0).\n");
153  fprintf(stderr, " --socket <port> Use socket ipc.\n");
154  fprintf(stderr, " --daemon Run in daemon mode.\n");
155 }
156 
157 /* 引数の説明 */
158 void param_help(void)
159 {
160  int i;
161  char param_names[YP_PARAM_NUM][32] = YP_PARAM_NAME;
162  char param_comments[YP_PARAM_NUM][128] = YP_PARAM_COMMENT;
163 
164  fprintf(stderr, "INFO: Comments of parameters (parameter version %.1f)\n\n", YP_PARAM_REQUIRED_VERSION);
165  for (i = 0; i < YP_PARAM_NUM; i++)
166  {
167  if (param_names[i][0] == '_')
168  continue;
169  fprintf(stderr, " %20s: %s\n", param_names[i], param_comments[i]);
170  }
171 }
172 
173 /* 引数の解析 */
174 int arg_analyze(int argc, char *argv[])
175 {
176  int i;
177 
178  g_param.option = OPTION_DEFAULT;
179  g_param.msq_key = YPSPUR_MSQ_KEY;
180  g_param.output_lv = OUTPUT_LV_INFO;
181  g_param.speed = 0;
182  g_param.ssm_id = 0;
183 
185  strcpy(g_param.device_name, DEFAULT_DEVICE_NAME);
186 
187  for (i = 1; i < argc; i++)
188  {
189  if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
190  {
191  g_param.option |= OPTION_SHOW_HELP;
192  }
193  else if (!strcmp(argv[i], "--long-help"))
194  {
195  g_param.option |= OPTION_SHOW_LONGHELP;
196  }
197  else if (!strcmp(argv[i], "--daemon"))
198  {
199  g_param.option |= OPTION_DAEMON;
200  }
201  else if (!strcmp(argv[i], "--param-help"))
202  {
203  g_param.option |= OPTION_SHOW_PARAMHELP;
204  }
205  else if (!strcmp(argv[i], "--show-odometry") || !strcmp(argv[i], "-o"))
206  {
207  g_param.option |= OPTION_SHOW_ODOMETRY;
208  }
209  else if (!strcmp(argv[i], "--show-timestamp") || !strcmp(argv[i], "-t"))
210  {
211  g_param.option |= OPTION_SHOW_TIMESTAMP;
212  }
213  else if (!strcmp(argv[i], "--param") || !strcmp(argv[i], "-p"))
214  {
215  if (i + 1 < argc)
216  {
217  i++;
218  strcpy(g_param.parameter_filename, argv[i]);
219  g_param.option |= OPTION_PARAM_FILE;
220  }
221  else
222  break;
223  }
224  else if (!strcmp(argv[i], "--socket"))
225  {
226  if (i + 1 < argc)
227  {
228  i++;
229  g_param.port = atoi(argv[i]);
230  g_param.option |= OPTION_SOCKET;
231  }
232  else
233  break;
234  }
235  else if (!strcmp(argv[i], "--admask"))
236  {
237  if (i + 1 < argc)
238  {
239  char *pos;
240 
241  i++;
242  g_param.admask = 0;
243  for (pos = argv[i]; *pos != 0; pos++)
244  {
245  g_param.admask = g_param.admask << 1;
246  if (*pos == '1')
247  g_param.admask |= 1;
248  }
249  }
250  else
251  break;
252  }
253  else if (!strcmp(argv[i], "--device") || !strcmp(argv[i], "-d"))
254  {
255  if (i + 1 < argc)
256  {
257  i++;
258  strcpy(g_param.device_name, argv[i]);
259  }
260  else
261  break;
262  }
263  else if (!strcmp(argv[i], "--without-control") || !strcmp(argv[i], "-c"))
264  {
265  g_param.option |= OPTION_PARAM_CONTROL;
270  }
271  else if (!strcmp(argv[i], "--without-device"))
272  {
273  g_param.option |= OPTION_WITHOUT_DEVICE;
274  g_param.option |= OPTION_DO_NOT_USE_YP;
275  g_param.option |= OPTION_PARAM_CONTROL;
280  }
281  else if (!strcmp(argv[i], "--high-resolution") ||
282  !strcmp(argv[i], "--high-resolution=yes"))
283  {
284  g_param.option |= OPTION_HIGH_PREC;
285  }
286  else if (!strcmp(argv[i], "--high-resolution=no"))
287  {
288  g_param.option &= ~OPTION_HIGH_PREC;
289  }
290  else if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v"))
291  {
292  g_param.option |= OPTION_VERSION;
293  }
294  else if (!strcmp(argv[i], "--verbose"))
295  {
296  g_param.output_lv = OUTPUT_LV_DEBUG;
297  }
298  else if (!strcmp(argv[i], "--quiet"))
299  {
300  g_param.output_lv = OUTPUT_LV_WARNING;
301  }
302  else if (!strcmp(argv[i], "--reconnect"))
303  {
304  g_param.option |= OPTION_RECONNECT;
305  }
306  else if (!strcmp(argv[i], "--enable-set-bs"))
307  {
308  g_param.option |= OPTION_ENABLE_SET_BS;
309  }
310  else if (!strcmp(argv[i], "--enable-get-digital-io"))
311  {
313  }
314  else if (!strcmp(argv[i], "--no-yp-protocol"))
315  {
316  g_param.option |= OPTION_DO_NOT_USE_YP;
317  }
318  else if (!strcmp(argv[i], "--without-ssm"))
319  {
320  g_param.option |= OPTION_WITHOUT_SSM;
321  }
322  else if (!strcmp(argv[i], "--msq-key") || !strcmp(argv[i], "-q"))
323  {
324  if (i + 1 < argc)
325  {
326  i++;
327  g_param.msq_key = atoi(argv[i]);
328  }
329  else
330  break;
331  }
332  else if (!strcmp(argv[i], "--speed") || !strcmp(argv[i], "-s"))
333  {
334  if (i + 1 < argc)
335  {
336  i++;
337  g_param.speed = atoi(argv[i]);
338  }
339  else
340  break;
341  }
342  else if (!strcmp(argv[i], "--passive"))
343  {
344  g_param.option |= OPTION_PASSIVE;
345  }
346  else if (!strcmp(argv[i], "--update-param"))
347  {
348  g_param.option |= OPTION_UPDATE_PARAM;
349  }
350  else if (!strcmp(argv[i], "--ssm-id"))
351  {
352  if (i + 1 < argc)
353  {
354  i++;
355  g_param.ssm_id = atoi(argv[i]);
356  }
357  else
358  {
359  break;
360  }
361  }
362  else
363  {
364  yprintf(OUTPUT_LV_ERROR, "ERROR : invalid option -- '%s'.\n", argv[i]);
365  return 0;
366  }
367  }
368 
369  if (i < argc)
370  {
371  yprintf(OUTPUT_LV_ERROR, "ERROR : option requires an argument -- '%s'.\n", argv[i]);
372  return 0;
373  }
374 
375  return 1;
376 }
377 
378 /* parameter set command */
379 int parameter_set(char param, char id, long long int value64)
380 {
381  char buf[7];
382  int value;
383 
384  if (value64 > 0x7FFFFFFF || value64 < -0x7FFFFFFE)
385  {
386  yprintf(OUTPUT_LV_ERROR, "ERROR: parameter out of range (id: %d)\n", param);
387  return -1;
388  }
389  value = value64;
390 
392  {
393  return (0);
394  }
395 
396  buf[0] = param;
397  buf[1] = id;
398  buf[2] = ((Int_4Char)value).byte[3];
399  buf[3] = ((Int_4Char)value).byte[2];
400  buf[4] = ((Int_4Char)value).byte[1];
401  buf[5] = ((Int_4Char)value).byte[0];
402  encode_write(buf, 6);
403 
404  return (0);
405 }
406 
407 int is_character(int c)
408 {
409  if (c >= 'A' && c <= 'Z')
410  return 1;
411  if (c >= 'a' && c <= 'z')
412  return 1;
413  if (c == '_')
414  return 1;
415  return 0;
416 }
417 
418 int is_number(int c)
419 {
420  if (c >= '0' && c <= '9')
421  return 1;
422  if (c == '-')
423  return 1;
424  if (c == '.')
425  return 1;
426  return 0;
427 }
428 
430 {
431  int i, j;
432  for (i = 0; i < YP_PARAM_NUM; i++)
433  {
434  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
435  {
436  if (!g_param.motor_enable[j])
437  continue;
438  if (g_Pf[i][j])
439  {
440  double d;
441  d = formula_eval(g_Pf[i][j]);
442  yprintf(OUTPUT_LV_DEBUG, "Evaluated: [%d][%d] %f\n", i, j, d);
443  }
444  }
445  }
446 }
447 
448 /* パラメータファイルからの読み込み */
449 int set_paramptr(FILE *paramfile)
450 {
451  char param_names[YP_PARAM_NUM][20] = YP_PARAM_NAME;
452  char param_names0[YP_PARAM_NUM][24] = YP_PARAM_NAME;
453  char param_names1[YP_PARAM_NUM][24] = YP_PARAM_NAME;
454  int param_necessary[YP_PARAM_NUM] = YP_PARAM_NECESSARY;
455 #define VARIABLE_NUM 37
456  char variable_names[VARIABLE_NUM][20] =
457  {
458  "X", "Y", "THETA", "V", "W",
459  "WHEEL_VEL[0]", "WHEEL_VEL[1]",
460  "WHEEL_VEL[2]", "WHEEL_VEL[3]",
461  "WHEEL_VEL[4]", "WHEEL_VEL[5]",
462  "WHEEL_VEL[6]", "WHEEL_VEL[7]",
463  "WHEEL_VEL[8]", "WHEEL_VEL[9]",
464  "WHEEL_VEL[10]", "WHEEL_VEL[11]",
465  "WHEEL_VEL[12]", "WHEEL_VEL[13]",
466  "WHEEL_VEL[14]", "WHEEL_VEL[15]",
467  "WHEEL_ANGLE[0]", "WHEEL_ANGLE[1]",
468  "WHEEL_ANGLE[2]", "WHEEL_ANGLE[3]",
469  "WHEEL_ANGLE[4]", "WHEEL_ANGLE[5]",
470  "WHEEL_ANGLE[6]", "WHEEL_ANGLE[7]",
471  "WHEEL_ANGLE[8]", "WHEEL_ANGLE[9]",
472  "WHEEL_ANGLE[10]", "WHEEL_ANGLE[11]",
473  "WHEEL_ANGLE[12]", "WHEEL_ANGLE[13]",
474  "WHEEL_ANGLE[14]", "WHEEL_ANGLE[15]",
475  };
476  struct variables_t variables[YP_PARAM_NUM * 3 + 1 + VARIABLE_NUM];
477  struct
478  {
479  YPSpur_param alias;
480  YPSpur_param param;
481  int motor;
482  } param_alias[YP_PARAM_ALIAS_NUM] = YP_PARAM_ALIAS;
483  char name[32], value_str[100];
484  int i, j, c;
485  int str_wp;
486  int read_state;
487  int param_num, motor_num;
488  OdometryPtr odm;
489  int param_error = 0;
490 
491  for (i = 0; i < YP_PARAM_NUM; i++)
492  {
493  strcat(param_names0[i], "[0]");
494  strcat(param_names1[i], "[1]");
495  variables[i * 3 + 0].name = param_names[i];
496  variables[i * 3 + 0].pointer = &g_P[i][0];
497  variables[i * 3 + 1].name = param_names0[i];
498  variables[i * 3 + 1].pointer = &g_P[i][0];
499  variables[i * 3 + 2].name = param_names1[i];
500  variables[i * 3 + 2].pointer = &g_P[i][1];
501  }
502  i = i * 3;
503  for (j = 0; j < VARIABLE_NUM; j++)
504  {
505  variables[i + j].name = variable_names[j];
506  }
507  odm = get_odometry_ptr();
508  variables[i++].pointer = &odm->x;
509  variables[i++].pointer = &odm->y;
510  variables[i++].pointer = &odm->theta;
511  variables[i++].pointer = &odm->v;
512  variables[i++].pointer = &odm->w;
513  for (j = 0; j < 16; j++)
514  variables[i++].pointer = &odm->wvel[j];
515  for (j = 0; j < 16; j++)
516  variables[i++].pointer = &odm->wang[j];
517  variables[i].name = NULL;
518  variables[i].pointer = NULL;
519 
520  for (i = 0; i < YP_PARAM_NUM; i++)
521  {
522  int j;
523  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
524  {
525  g_P_changed[i][j] = 0;
526  }
527  }
528  if (g_param_init)
529  {
530  int j;
531  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
532  {
534  g_param.motor_enable[j] = 0;
535  }
536  // パラメータの初期化
537  for (i = 0; i < YP_PARAM_NUM; i++)
538  {
539  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
540  {
541  g_P[i][j] = 0;
542  g_P_set[i][j] = 0;
543  g_Pf[i][j] = NULL;
544  }
545  }
546  }
547 
548  // パラメータファイルの読み込み
549  read_state = 0;
550  str_wp = 0;
551  motor_num = 0;
552  param_num = YP_PARAM_NUM;
553  while (1)
554  {
555  int eof = 0;
556 
557  c = getc(paramfile);
558  if (c == EOF)
559  {
560  eof = 1;
561  c = '\n';
562  }
563 
564  switch (read_state)
565  {
566  case 0:
567  /* - */
568  if (c == '#')
569  {
570  read_state = 1;
571  }
572  if (is_character(c) || c == '-')
573  {
574  name[0] = c;
575  read_state = 2;
576  str_wp = 1;
577  }
578  break;
579  case 1: /* comment */
580  if (c == '\n')
581  {
582  read_state = 0;
583  }
584  break;
585  case 2: /* name */
586  name[str_wp] = c;
587  if (!(is_character(c) || is_number(c) || c == '[' || c == ']' || c == '-'))
588  {
589  name[str_wp] = 0;
590  read_state = 3;
591  str_wp = 0;
592  }
593  else
594  {
595  str_wp++;
596  }
597  break;
598  case 3: /* value */
599  if (is_number(c))
600  {
601  str_wp = 0;
602  value_str[str_wp] = c;
603  str_wp++;
604  read_state = 4;
605  }
606  else if (c == '=')
607  {
608  strcpy(value_str, name);
609  strcat(value_str, "=");
610  str_wp = strlen(value_str);
611  read_state = 5;
612  }
613  if (read_state != 3)
614  {
615  char *num_start;
616  char *num_end = NULL;
617  int num;
618 
619  param_num = YP_PARAM_NUM;
620  num = -1;
621 
622  num_start = strchr(name, '[');
623  if (num_start)
624  {
625  num_start++;
626  num_end = strchr(name, ']');
627  if (!num_end)
628  {
629  read_state = 4;
630  yprintf(OUTPUT_LV_ERROR, "Error: Invalid parameter -- '%s'.\n", name);
631  param_error = 1;
632  continue;
633  }
634  *(num_start - 1) = 0;
635  *num_end = 0;
636  num = atoi(num_start);
637  }
638  motor_num = num;
639  for (i = 0; i < YP_PARAM_NUM; i++)
640  {
641  if (!strcmp(name, param_names[i]))
642  {
643  int j;
644  for (j = 0; j < YP_PARAM_ALIAS_NUM; j++)
645  {
646  if (i == param_alias[j].alias)
647  {
648  yprintf(OUTPUT_LV_WARNING, "Parameter alias: %s -> %s[%d]\n",
649  param_names[i], param_names[param_alias[j].param], param_alias[j].motor);
650  i = param_alias[j].param;
651  motor_num = param_alias[j].motor;
652  break;
653  }
654  }
655  param_num = i;
656  break;
657  }
658  }
659  if (num_start)
660  {
661  *(num_start - 1) = '[';
662  *num_end = ']';
663  }
664  }
665  break;
666  case 4: /* value */
667  if (!is_number(c))
668  {
669  value_str[str_wp] = 0;
670  str_wp = 0;
671  if (param_num == YP_PARAM_NUM)
672  {
673  yprintf(OUTPUT_LV_ERROR, "Error: Invalid parameter -- '%s'.\n", name);
674  param_error = 1;
675  }
676  else if (motor_num == -1)
677  {
678  int j;
679  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
680  {
681  g_P[param_num][j] = strtod(value_str, 0);
682  g_P_set[param_num][j] = 1;
683  g_P_changed[param_num][j] = 1;
684  if (g_Pf[param_num][j])
685  {
686  formula_free(g_Pf[param_num][j]);
687  g_Pf[param_num][j] = NULL;
688  }
689  }
690  yprintf(OUTPUT_LV_DEBUG, "%d %s %f\n", param_num, param_names[param_num], g_P[param_num][0]);
691  }
692  else
693  {
694  g_P[param_num][motor_num] = strtod(value_str, 0);
695  g_P_set[param_num][motor_num] = 1;
696  g_P_changed[param_num][motor_num] = 1;
697  g_param.motor_enable[motor_num] = 1;
698  if (g_Pf[param_num][motor_num])
699  {
700  formula_free(g_Pf[param_num][motor_num]);
701  g_Pf[param_num][motor_num] = NULL;
702  }
703  yprintf(OUTPUT_LV_DEBUG, "%d %s[%d] %f\n", param_num, param_names[param_num], motor_num,
704  g_P[param_num][motor_num]);
705  }
706  param_num = YP_PARAM_NUM;
707  read_state = 0;
708  str_wp = 0;
709  break;
710  }
711  else
712  {
713  value_str[str_wp] = c;
714  str_wp++;
715  }
716  break;
717  case 5: /* value */
718  if (c == '#' || c == '\n')
719  {
720  value_str[str_wp] = 0;
721  str_wp = 0;
722  if (param_num == YP_PARAM_NUM)
723  {
724  yprintf(OUTPUT_LV_ERROR, "Error: Invalid parameter -- '%s'.\n", name);
725  param_error = 1;
726  }
727  else if (motor_num == -1)
728  {
729  int j;
730  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
731  {
732  g_P[param_num][j] = 0;
733  g_P_set[param_num][j] = 1;
734  if (g_Pf[param_num][j])
735  formula_free(g_Pf[param_num][j]);
736  formula(value_str, &g_Pf[param_num][j], variables);
737  }
738  if (g_Pf[param_num][0] == NULL)
739  {
740  yprintf(OUTPUT_LV_ERROR, "Error: Invalid formula -- '%s'.\n", value_str);
741  param_error = 1;
742  }
743  else
744  {
745  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
746  {
747  g_Pf[param_num][j] = formula_optimize(g_Pf[param_num][j]);
748  }
749  yprintf(OUTPUT_LV_DEBUG, "%d %s ", param_num, param_names[param_num]);
750  if (output_lv() >= OUTPUT_LV_DEBUG)
751  formula_print(stderr, g_Pf[param_num][0]);
752  yprintf(OUTPUT_LV_DEBUG, "\n");
753  }
754  }
755  else
756  {
757  g_P[param_num][motor_num] = 0;
758  g_P_set[param_num][motor_num] = 1;
759  if (g_Pf[param_num][motor_num])
760  formula_free(g_Pf[param_num][motor_num]);
761  formula(value_str, &g_Pf[param_num][motor_num], variables);
762  if (g_Pf[param_num][motor_num] == NULL)
763  {
764  yprintf(OUTPUT_LV_ERROR, "Error: Invalid formula -- '%s'.\n", value_str);
765  param_error = 1;
766  }
767  else
768  {
769  g_Pf[param_num][motor_num] = formula_optimize(g_Pf[param_num][motor_num]);
770  yprintf(OUTPUT_LV_DEBUG, "%d %s[%d] ", param_num, param_names[param_num], motor_num);
771  if (output_lv() >= OUTPUT_LV_DEBUG)
772  formula_print(stderr, g_Pf[param_num][motor_num]);
773  yprintf(OUTPUT_LV_DEBUG, "\n");
774  }
775  }
776  param_num = YP_PARAM_NUM;
777  read_state = 0;
778  str_wp = 0;
779  break;
780  }
781  else
782  {
783  value_str[str_wp] = c;
784  str_wp++;
785  }
786  break;
787  }
788  if (eof)
789  break;
790  }
791 
792  fclose(paramfile);
794  {
795  yprintf(OUTPUT_LV_ERROR, "Error: Your parameter file format is too old!\n");
796  yprintf(OUTPUT_LV_ERROR, "Error: This program requires %3.1f.\n", YP_PARAM_REQUIRED_VERSION);
797  return 0;
798  }
800  {
801  yprintf(OUTPUT_LV_ERROR, "Error: Your parameter file format is unsupported!\n");
802  yprintf(OUTPUT_LV_ERROR, "Error: Please install newer version of YP-Spur.\n");
803  yprintf(OUTPUT_LV_ERROR, "Error: This program supports %3.1f.\n", YP_PARAM_SUPPORTED_VERSION);
804  return 0;
805  }
806 
807  for (i = 0; i < YP_PARAM_NUM; i++)
808  {
809  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
810  {
811  if (!g_param.motor_enable[j])
812  continue;
813  if (param_necessary[i] && !g_P_set[i][j])
814  {
815  yprintf(OUTPUT_LV_ERROR, "Error: %s[%d] undefined!\n", param_names[i], j);
816  param_error = 1;
817  }
818  }
819  }
820  if (param_error)
821  {
822  return 0;
823  }
824 
825  g_param.num_motor_enable = 0;
826  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
827  {
828  // Count motor number
829  if (g_param.motor_enable[j])
830  g_param.num_motor_enable++;
831  }
832  if (g_param.num_motor_enable == 0)
833  {
834  // If all parameters are common among motors, treat num_motor_enable as two
835  g_param.motor_enable[0] = g_param.motor_enable[1] = 1;
836  g_param.num_motor_enable = 2;
837  }
838 
839  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
840  {
841  if (!g_param.motor_enable[j])
842  continue;
843 
844  // Verify parameter version compatibility
847  {
848  if (g_P[YP_PARAM_VERSION][0] < 5.0)
849  {
850  yprintf(
852  "ERROR: Using ENCODER_DENOMINATOR requires parameter version >= 5.0.\n"
853  " Please make sure that all other motor parameters are based on mechanical motor revolution instead of electrical.\n");
854  return 0;
855  }
856  yprintf(
858  "Warn: ENCODER_DENOMINATOR parameter support is experimental.\n"
859  " The behavior of this parameter may be changed in the future update.\n");
860  }
861 
862  // Check and fill undefined parameters
864  {
865  yprintf(OUTPUT_LV_WARNING, "Warn: TORQUE_LIMIT[%d] undefined. TORQUE_MAX[%d] will be used.\n", j, j);
868  }
869 
871  {
872  double default_value;
873  if (j < 2)
874  default_value = 1.0;
875  else
876  default_value = 0.0;
877 
878  if (g_P[YP_PARAM_VEHICLE_CONTROL][j] != default_value)
880  g_P[YP_PARAM_VEHICLE_CONTROL][j] = default_value;
881  }
882 
884  {
885  if (g_P[YP_PARAM_ENCODER_TYPE][j] != 2.0)
887  g_P[YP_PARAM_ENCODER_TYPE][j] = 2.0;
888  }
889  if (!g_P_set[YP_PARAM_INDEX_GEAR][j])
890  {
891  if (g_P[YP_PARAM_INDEX_GEAR][j] != 1.0)
893  g_P[YP_PARAM_INDEX_GEAR][j] = 1.0;
894  }
896  {
897  if (g_P[YP_PARAM_ENCODER_DENOMINATOR][j] != 1.0)
900  }
901 
902  // Process internally calculated parameters
905  }
906 
907  // パラメータの指定によって自動的に求まるパラメータの計算
909 
910  /* パラメータを有効にする */
915 
916  yprintf(OUTPUT_LV_DEBUG, "Info: %d motors defined\n", g_param.num_motor_enable);
917 
918  return 1;
919 }
920 
921 /* パラメータファイルからの読み込み */
922 int set_param(char *filename, char *concrete_path)
923 {
924  FILE *paramfile;
925  paramfile = fopen(filename, "r");
926 
927  if (!paramfile)
928  {
929 #if HAVE_PKG_CONFIG
930  char dir_name[256];
931  char file_name[256];
932  char *pret;
933  FILE *fd;
934 #endif // HAVE_PKG_CONFIG
935 
936  yprintf(OUTPUT_LV_DEBUG, "Warn: File [%s] is not exist.\n", filename);
937 
938 #if HAVE_PKG_CONFIG
939  if (!strchr(filename, '/'))
940  {
941  /* ファイルが見つからないとき、かつパス指定でないときshareディレクトリを見に行く
942  */
943  fd = popen("pkg-config --variable=YP_PARAMS_DIR yp-robot-params", "r");
944  if ((fd == NULL))
945  {
947  "Error: Cannot open pipe 'pkg-config --variable=YP_PARAMS_DIR yp-robot-params'.\n");
948  return 0;
949  }
950  pret = fgets(dir_name, sizeof(dir_name), fd);
951 
952  if ((pclose(fd) == 0) && (pret != 0))
953  {
954  dir_name[strlen(dir_name) - 1] = '\0';
955  // printf( "dir = '%s'\n", dir_name );
956  sprintf(file_name, "%s/%s", dir_name, filename);
957 
958  paramfile = fopen(file_name, "r");
959 
960  if (!paramfile)
961  {
962  yprintf(OUTPUT_LV_WARNING, "Warn: File [%s] is not exist.\n", file_name);
963  return 0;
964  }
965  }
966  else
967  {
969  "Error: Cannot read pipe 'pkg-config --variable=YP_PARAMS_DIR yp-robot-params'.\n");
970  return 0;
971  }
972  // fprintf( stdout, "open %s\n", file_name );
973  if (concrete_path)
974  strcpy(concrete_path, file_name);
975  strcpy(file_name, filename);
976  }
977  else
978 #endif // HAVE_PKG_CONFIG
979  {
980  return 0;
981  }
982  }
983  else
984  {
985  if (concrete_path)
986  strcpy(concrete_path, filename);
987  }
988 
989  return set_paramptr(paramfile);
990 }
991 
992 void init_param_update_thread(pthread_t *thread, char *filename)
993 {
994  g_param.parameter_applying = 0;
995  if (pthread_create(thread, NULL, (void *)param_update, filename) != 0)
996  {
997  yprintf(OUTPUT_LV_ERROR, "Can't create command thread\n");
998  }
999 }
1000 
1002 {
1003  yprintf(OUTPUT_LV_INFO, "Parameter updater stopped.\n");
1004 }
1005 
1006 void param_update(void *filename)
1007 {
1008  struct stat prev_status;
1009 
1010  yprintf(OUTPUT_LV_INFO, "Parameter updater started. Watching %s\n", filename);
1011  pthread_cleanup_push(param_update_loop_cleanup, filename);
1012 
1013  stat(filename, &prev_status);
1014 
1015  while (1)
1016  {
1017  int i;
1018  struct stat status;
1019 
1020  // 0.3秒に一回パラメータファイル更新をチェック
1021  for (i = 0; i < 3; i++)
1022  {
1023  yp_usleep(100000);
1024  pthread_testcancel();
1025  }
1026  g_param.parameter_applying = 0;
1027  stat(filename, &status);
1028 
1029  if (difftime(status.st_mtime, prev_status.st_mtime) != 0.0)
1030  {
1031  yp_usleep(100000);
1032  set_param(filename, NULL);
1033  if (!(option(OPTION_PARAM_CONTROL)))
1034  {
1035  g_param.parameter_applying = 1;
1037  }
1038  }
1039 
1040  prev_status = status;
1041  }
1042  pthread_cleanup_pop(1);
1043 }
1044 
1045 /* パラメータ適用 */
1047 {
1048  yprintf(OUTPUT_LV_INFO, "Applying parameters.\n");
1049 
1050  int j;
1051  // ウォッチドックタイマの設定
1052  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
1053  {
1054  if (g_param.motor_enable[j])
1056  }
1057 
1058  if (g_param_init)
1059  {
1060  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
1061  {
1062  if (g_param.motor_enable[j])
1063  parameter_set(PARAM_w_ref, j, 0);
1064  }
1065  g_param_init = 0;
1066  }
1067 
1068  if (g_param.device_version >= 10)
1069  {
1070  int version, age;
1071  sscanf(YP_PROTOCOL_NAME, "YPP:%d:%d", &version, &age);
1072  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
1073  {
1074  if (g_param.motor_enable[j])
1076  }
1077  }
1078 
1079  /* モータのパラメータ */
1080  if (set_param_motor() < 1)
1081  return 0;
1082  yp_usleep(30000);
1083 
1084  /* 速度制御パラメータ */
1085  if (set_param_velocity() < 1)
1086  return 0;
1087  yp_usleep(100000);
1088 
1089  return 1;
1090 }
1091 
1092 // FF制御パラメータの計算
1093 // 坪内 孝司 車輪移動体の制御 を参照
1095 {
1096  int i;
1097  double A, B, C, D; // 制御パラメータ
1098  double M, J; // ロボットの質量、慣性モーメント
1099  double Gr, Gl; // ギア比
1100  double Jmr, Jml; // モータの慣性モーメント
1101  double Jtr, Jtl; // タイヤの慣性モーメント
1102  double Rr, Rl; // タイヤ半径
1103  double T; // トレッド
1104 
1105  // パラメータの代入
1106  M = g_P[YP_PARAM_MASS][0];
1107  J = g_P[YP_PARAM_MOMENT_INERTIA][0];
1108  Gr = fabs(g_P[YP_PARAM_GEAR][0]);
1109  Gl = fabs(g_P[YP_PARAM_GEAR][1]);
1110  Jmr = g_P[YP_PARAM_MOTOR_M_INERTIA][0];
1111  Jml = g_P[YP_PARAM_MOTOR_M_INERTIA][1];
1112  Jtr = g_P[YP_PARAM_TIRE_M_INERTIA][0];
1113  Jtl = g_P[YP_PARAM_TIRE_M_INERTIA][1];
1114  Rr = g_P[YP_PARAM_RADIUS][0];
1115  Rl = g_P[YP_PARAM_RADIUS][1];
1116  T = g_P[YP_PARAM_TREAD][0];
1117 
1118  // パラメータの計算
1119  A = (Gr * Gr * Jmr + Jtr + Rr * Rr / 2.0 * (M / 2.0 + J / (T * T))) / Gr;
1120  B = (Gl * Gl * Jml + Jtl + Rl * Rl / 2.0 * (M / 2.0 + J / (T * T))) / Gl;
1121  C = (Rr * Rl / 2.0 * (M / 2.0 - J / (T * T))) / Gr;
1122  D = (Rr * Rl / 2.0 * (M / 2.0 - J / (T * T))) / Gl;
1123 
1124  // パラメータの設定
1125  g_P[YP_PARAM_GAIN_A][0] = A;
1126  g_P[YP_PARAM_GAIN_B][0] = B;
1127  g_P[YP_PARAM_GAIN_C][0] = C;
1128  g_P[YP_PARAM_GAIN_D][0] = D;
1129 
1130  g_P[YP_PARAM_INERTIA_SELF][0] = A;
1131  g_P[YP_PARAM_INERTIA_SELF][1] = B;
1132  g_P[YP_PARAM_INERTIA_CROSS][0] = C;
1133  g_P[YP_PARAM_INERTIA_CROSS][1] = D;
1134 
1135  if (ischanged_p(YP_PARAM_MASS, 0) ||
1137  ischanged_p(YP_PARAM_GEAR, 0) ||
1138  ischanged_p(YP_PARAM_GEAR, 1) ||
1146  {
1147  g_P_changed[YP_PARAM_GAIN_A][0] = 1;
1148  g_P_changed[YP_PARAM_GAIN_B][0] = 1;
1149  g_P_changed[YP_PARAM_GAIN_C][0] = 1;
1150  g_P_changed[YP_PARAM_GAIN_D][0] = 1;
1155  }
1156  for (i = 0; i < YP_PARAM_MAX_MOTOR_NUM; i++)
1157  {
1158  if (!g_param.motor_enable[i])
1159  continue;
1160  if (p(YP_PARAM_VEHICLE_CONTROL, i) > 0)
1161  continue;
1162 
1164  fabs(g_P[YP_PARAM_GEAR][i]) * g_P[YP_PARAM_MOTOR_M_INERTIA][i] + g_P[YP_PARAM_TIRE_M_INERTIA][i] / fabs(g_P[YP_PARAM_GEAR][i]);
1165  g_P[YP_PARAM_INERTIA_CROSS][i] = 0;
1166 
1167  if (ischanged_p(YP_PARAM_GEAR, i) ||
1170  {
1173  }
1174  }
1175  // 出力(デバッグ)
1176  for (i = 0; i < YP_PARAM_MAX_MOTOR_NUM; i++)
1177  {
1178  if (!g_param.motor_enable[i])
1179  continue;
1180 
1181  yprintf(OUTPUT_LV_DEBUG, " LOAD_INERTIA_SELF[%d] %f\n", i, g_P[YP_PARAM_INERTIA_SELF][i]);
1182  yprintf(OUTPUT_LV_DEBUG, " LOAD_INERTIA_CROSS[%d] %f\n", i, g_P[YP_PARAM_INERTIA_CROSS][i]);
1183  }
1184 }
1185 
1186 // モータパラメータの送信
1188 {
1189  int j;
1190  // モータのパラメータ
1191  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
1192  {
1193  if (!g_param.motor_enable[j])
1194  continue;
1195  if (ischanged_p(YP_PARAM_VOLT, j))
1196  {
1197  parameter_set(PARAM_vsrc, j, g_P[YP_PARAM_VOLT][j] * 256);
1198  }
1199  if (ischanged_p(YP_PARAM_CYCLE, j))
1200  {
1202  }
1204  {
1206  }
1210  {
1211  const double enc_rev_phase = g_P[YP_PARAM_COUNT_REV][j] / g_P[YP_PARAM_ENCODER_DENOMINATOR][j];
1213  g_P[YP_PARAM_PHASE_OFFSET][j] * enc_rev_phase / (2.0 * M_PI));
1214  }
1216  {
1218  }
1220  {
1222  }
1223  if (ischanged_p(YP_PARAM_PWM_MAX, j) ||
1228  {
1229  // ki [pwmcnt/toqcnt] = (voltage unit [V/toqcnt]) * (PWM_MAX [pwmcnt]) / (VOLT [V])
1230  // voltage unit [V/toqcnt] = (current unit [A/toqcnt]) * (MOTOR_R [ohm])
1231  // current unit [A/toqcnt] = (1 [toqcnt]) / ((TORQUE_UNIT [toqcnt/Nm]) * (MOTOR_TC [Nm/A]))
1232 
1233  // ki [pwmcnt/toqcnt] = ((MOTOR_R [ohm]) * (PWM_MAX [pwmcnt])) / ((TORQUE_UNIT [toqcnt/Nm]) * (MOTOR_TC [Nm/A]) * (VOLT [V]))
1234 
1235  long long int ki;
1236  ki = (double)(65536.0 * g_P[YP_PARAM_PWM_MAX][j] * g_P[YP_PARAM_MOTOR_R][j] * g_P[YP_PARAM_ENCODER_DENOMINATOR][j] /
1238  g_P[YP_PARAM_VOLT][j]));
1239  yprintf(OUTPUT_LV_DEBUG, "Info: TORQUE_CONSTANT[%d]: %d\n", j, (int)ki);
1240  if (ki == 0)
1241  {
1242  yprintf(OUTPUT_LV_ERROR, "ERROR: TORQUE_CONSTANT[%d] fixed point value underflow\n", j);
1243  yprintf(OUTPUT_LV_ERROR, "ERROR: Increase TORQUE_FINENESS[%d]\n", j);
1244  }
1245  parameter_set(PARAM_p_ki, j, ki);
1246  }
1247 
1248  if (ischanged_p(YP_PARAM_PWM_MAX, j) ||
1253  {
1254  // kv [(pwmcnt)/(cnt/ms)] = (vc native [V/(cnt/ms)]) * (PWM_MAX [pwmcnt]) / (VOLT [V])
1255  // vc native [V/(cnt/ms)] = (((60 [sec/min]) / (MOTOR_VC [(rev/min)/V]])) / (COUNT_REV [cnt/rev])) / (CYCLE [sec/ms])
1256 
1257  // kv [(pwmcnt)/(cnt/ms)] = ((60 [sec/min]) * (PWM_MAX [pwmcnt]))
1258  // / ((MOTOR_VC [(rev/min)/V]]) * (COUNT_REV [cnt/rev]) * (CYCLE [sec/ms]) * (VOLT [V]))
1259 
1261  (double)(65536.0 * g_P[YP_PARAM_PWM_MAX][j] * 60.0 /
1263  g_P[YP_PARAM_CYCLE][j])));
1264  }
1265 
1266  // 摩擦補償
1268  {
1270  }
1271 
1273  {
1275  {
1277  }
1278  }
1279  else
1280  {
1282  {
1284  }
1285  }
1286 
1287  // cnt/ms -> rad/s = cnt/ms * ms/s * rad/cnt = cnt/ms * 2pi/COUNT_REV / CYCLE
1288  if (ischanged_p(YP_PARAM_COUNT_REV, j) ||
1290  {
1291  const double tvc = (2.0 * M_PI / g_P[YP_PARAM_COUNT_REV][j]) / g_P[YP_PARAM_CYCLE][j];
1293  {
1295  }
1297  {
1299  {
1301  }
1302  }
1303  else
1304  {
1306  {
1308  }
1309  }
1310  }
1311 
1313  {
1315  }
1316 
1318  {
1321  }
1322 
1324  {
1326  }
1327 
1328  if (ischanged_p(YP_PARAM_PWM_MAX, j))
1329  {
1332  }
1333 
1335  {
1337  }
1340  {
1341  if (g_param.device_version <= 9)
1342  {
1343  yprintf(OUTPUT_LV_ERROR, "ERROR: the device doesn't support ENCODER_DENOMINATOR\n");
1344  return 0;
1345  }
1347  }
1348 
1349  // Sleep to keep bandwidth margin
1350  yp_usleep(20000);
1351  }
1352  return 1;
1353 }
1354 
1356 {
1357  int j;
1358 
1359  if (g_param.device_version <= 6)
1360  {
1361  double ffr, ffl;
1362  int ffr_changed = 0, ffl_changed = 0;
1363 
1364  // Feed-forward dynamics compensation parameter
1365  // (torque [Nm]) = (wheel acc [rad/(s*s)]) * (wheel inertia [kgf*m*m])
1366  // (torque [toqcnt])
1367  // = (wheel acc [cnt/(s*s)) * (TORQUE_UNIT [toqcnt/Nm] * (wheel inertia [kgf*m*m]) * (2 * pi) / ((COUNT_REV [cnt]) * (GEAR))
1368  // (acc-torque factor [toqcnt/(cnt/(s*s))])
1369  // = (TORQUE_UNIT [toqcnt/Nm]) * (wheel inertia [kgf*m*m]) * (2 * pi) / ((COUNT_REV [cnt]) * (GEAR))
1370 
1374  {
1375  ffr_changed = 1;
1376  }
1377  ffr = 256.0 * 2.0 * M_PI * g_P[YP_PARAM_TORQUE_UNIT][0] / (g_P[YP_PARAM_COUNT_REV][0] * fabs(g_P[YP_PARAM_GEAR][0]));
1378  if (ischanged_p(YP_PARAM_GAIN_A, 0) || ffr_changed)
1379  {
1380  yprintf(OUTPUT_LV_DEBUG, "Info: GAIN_A: %d\n",
1381  (int)(g_P[YP_PARAM_GAIN_A][0] * ffr));
1382  if (abs(g_P[YP_PARAM_GAIN_A][0] * ffr) == 0)
1383  {
1384  yprintf(OUTPUT_LV_ERROR, "ERROR: GAIN_A fixed point value underflow\n");
1385  yprintf(OUTPUT_LV_ERROR, "ERROR: Decrease TORQUE_FINENESS[%d]\n", 0);
1386  return 0;
1387  }
1388  parameter_set(PARAM_p_A, 0, g_P[YP_PARAM_GAIN_A][0] * ffr);
1389  }
1390  if (ischanged_p(YP_PARAM_GAIN_C, 0) || ffr_changed)
1391  parameter_set(PARAM_p_C, 0, g_P[YP_PARAM_GAIN_C][0] * ffr);
1392  if (ischanged_p(YP_PARAM_GAIN_E, 0) || ffr_changed)
1393  parameter_set(PARAM_p_E, 0, g_P[YP_PARAM_GAIN_E][0] * ffr);
1394 
1397  ischanged_p(YP_PARAM_GEAR, 1))
1398  {
1399  ffl_changed = 1;
1400  }
1401  ffl = 256.0 * 2.0 * M_PI * g_P[YP_PARAM_TORQUE_UNIT][1] / (g_P[YP_PARAM_COUNT_REV][1] * fabs(g_P[YP_PARAM_GEAR][1]));
1402  if (ischanged_p(YP_PARAM_GAIN_B, 0) || ffl_changed)
1403  {
1404  yprintf(OUTPUT_LV_DEBUG, "Info: GAIN_B: %d\n",
1405  (int)(g_P[YP_PARAM_GAIN_A][0] * ffl));
1406  if (abs(g_P[YP_PARAM_GAIN_B][0] * ffl) == 0)
1407  {
1408  yprintf(OUTPUT_LV_ERROR, "ERROR: GAIN_B fixed point value underflow\n");
1409  yprintf(OUTPUT_LV_ERROR, "ERROR: Decrease TORQUE_FINENESS[%d]\n", 1);
1410  return 0;
1411  }
1412  parameter_set(PARAM_p_B, 0, g_P[YP_PARAM_GAIN_B][0] * ffl);
1413  }
1414  if (ischanged_p(YP_PARAM_GAIN_D, 0) || ffl_changed)
1415  parameter_set(PARAM_p_D, 0, g_P[YP_PARAM_GAIN_D][0] * ffl);
1416  if (ischanged_p(YP_PARAM_GAIN_F, 0) || ffl_changed)
1417  parameter_set(PARAM_p_F, 0, g_P[YP_PARAM_GAIN_F][0] * ffl);
1418  }
1419  // PI制御のパラメータ
1420  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
1421  {
1422  if (!g_param.motor_enable[j])
1423  continue;
1424 
1425  if (g_param.device_version > 6)
1426  {
1427  int ff_changed = 0;
1428  double ff = 256.0 * 2.0 * M_PI * g_P[YP_PARAM_TORQUE_UNIT][j] /
1429  (g_P[YP_PARAM_COUNT_REV][j] * fabs(g_P[YP_PARAM_GEAR][j]));
1433  {
1434  ff_changed = 1;
1435  }
1436  if (ischanged_p(YP_PARAM_INERTIA_SELF, j) || ff_changed)
1437  {
1438  yprintf(OUTPUT_LV_DEBUG, "Info: INERTIA_SELF[%d]: %d\n", j,
1439  (int)(g_P[YP_PARAM_INERTIA_SELF][j] * ff));
1440  if (abs(g_P[YP_PARAM_INERTIA_SELF][j] * ff) == 0)
1441  {
1442  yprintf(OUTPUT_LV_ERROR, "ERROR: INERTIA_SELF[%d] fixed point value underflow\n", j);
1443  yprintf(OUTPUT_LV_ERROR, "ERROR: Decrease TORQUE_FINENESS[%d]\n", j);
1444  return 0;
1445  }
1447  }
1448  if (ischanged_p(YP_PARAM_INERTIA_CROSS, j) || ff_changed)
1449  {
1451  }
1452  }
1453 
1454  // [1/s]
1455  if (ischanged_p(YP_PARAM_GAIN_KP, j))
1457  // [1/s^2]
1458  if (ischanged_p(YP_PARAM_GAIN_KI, j))
1460  // 各種制限
1464  {
1469  }
1470  }
1471 
1472  // ウォッチドックタイマの設定
1473  for (j = 0; j < YP_PARAM_MAX_MOTOR_NUM; j++)
1474  {
1475  if (!g_param.motor_enable[j])
1476  continue;
1478  }
1479  return 1;
1480 }
unsigned char admask
Definition: param.h:80
void yp_usleep(int usec)
Definition: utility.c:54
double y
Definition: odometry.h:34
int speed
Definition: param.h:77
YPSpur_state
Definition: ypparam.h:450
void param_calc()
Definition: param.c:429
char g_state[YP_STATE_NUM]
Definition: param.c:60
#define OPTION_DEFAULT
Definition: param.h:54
ParamOptions
Definition: param.h:29
#define YP_PARAM_ALIAS_NUM
Definition: ypparam.h:432
double * pp(YPSpur_param id, enum motor_id motor)
Definition: param.c:94
void init_param_update_thread(pthread_t *thread, char *filename)
Definition: param.c:992
struct rpf_t * g_Pf[YP_PARAM_NUM][YP_PARAM_MAX_MOTOR_NUM]
Definition: param.c:59
ParamOutputLv output_lv(void)
Definition: param.c:106
char device_name[132]
Definition: param.h:74
int encode_write(char *data, int len)
Definition: serial.c:520
double wang[YP_PARAM_MAX_MOTOR_NUM]
Definition: odometry.h:40
int is_character(int c)
Definition: param.c:407
ParametersPtr get_param_ptr()
Definition: param.c:111
パラメータの最大値
Definition: ypparam.h:207
int ischanged_p(YPSpur_param id, enum motor_id motor)
Definition: param.c:89
YPSpur_param
Definition: ypparam.h:109
void arg_longhelp(int argc, char *argv[])
Definition: param.c:134
int apply_robot_params()
Definition: param.c:1046
int state(YPSpur_state id)
Definition: param.c:64
int ssm_id
Definition: param.h:81
#define YP_PARAM_SUPPORTED_VERSION
Definition: ypparam.h:446
int set_paramptr(FILE *paramfile)
Definition: param.c:449
char parameter_filename[132]
Definition: param.h:73
double w
Definition: odometry.h:37
ParamOutputLv
Definition: param.h:62
void param_update_loop_cleanup(void *data)
Definition: param.c:1001
int arg_analyze(int argc, char *argv[])
Definition: param.c:174
double v
Definition: odometry.h:36
int g_P_set[YP_PARAM_NUM][YP_PARAM_MAX_MOTOR_NUM]
Definition: param.c:58
#define DEFAULT_PARAMETER_FILE
Definition: param.h:56
#define DISABLE
Definition: serial.h:25
int set_param_motor(void)
Definition: param.c:1187
#define DEFAULT_DEVICE_NAME
Definition: param.h:57
int is_number(int c)
Definition: param.c:418
void param_help(void)
Definition: param.c:158
void calc_param_inertia2ff(void)
Definition: param.c:1094
int parameter_set(char param, char id, long long int value64)
Definition: param.c:379
#define ENABLE
Definition: serial.h:24
int num_motor_enable
Definition: param.h:83
#define YP_PARAM_MAX_MOTOR_NUM
Definition: ypparam.h:430
struct rpf_t * formula_optimize(struct rpf_t *rpf)
double formula_eval(struct rpf_t *rpf)
double theta
Definition: odometry.h:35
double wvel[YP_PARAM_MAX_MOTOR_NUM]
Definition: odometry.h:39
void yprintf(ParamOutputLv level, const char *format,...)
Definition: yprintf.c:32
int motor_enable[YP_PARAM_MAX_MOTOR_NUM]
Definition: param.h:82
int port
Definition: param.h:76
void param_update(void *filename)
Definition: param.c:1006
int g_P_changed[YP_PARAM_NUM][YP_PARAM_MAX_MOTOR_NUM]
Definition: param.c:57
void disable_state(YPSpur_state id)
Definition: param.c:74
#define YPSPUR_MSQ_KEY
Definition: ypparam.h:515
ParamOutputLv output_lv
Definition: param.h:79
int formula(const char *expr, struct rpf_t **rpf, const struct variables_t *variable)
OdometryPtr get_odometry_ptr()
Definition: odometry.c:332
void enable_state(YPSpur_state id)
Definition: param.c:69
void formula_print(FILE *stream, struct rpf_t *rpf)
void * value
Definition: formula-calc.h:53
#define YP_PARAM_ALIAS
Definition: ypparam.h:434
int device_version
Definition: param.h:84
#define VARIABLE_NUM
#define YP_PARAM_NAME
Definition: ypparam.h:211
int isset_p(YPSpur_param id, enum motor_id motor)
Definition: param.c:84
double g_P[YP_PARAM_NUM][YP_PARAM_MAX_MOTOR_NUM]
Definition: param.c:56
double p(YPSpur_param id, enum motor_id motor)
Definition: param.c:79
void formula_free(struct rpf_t *rpf)
ParamOptions option
Definition: param.h:78
#define YP_PARAM_REQUIRED_VERSION
Definition: ypparam.h:445
const char * name
Definition: formula-calc.h:59
#define YP_PARAM_NECESSARY
Definition: ypparam.h:282
void arg_help(int argc, char *argv[])
Definition: param.c:120
#define YP_PARAM_COMMENT
Definition: ypparam.h:353
motor_id
Definition: ypparam.h:425
double x
Definition: odometry.h:33
int parameter_applying
Definition: param.h:86
int msq_key
Definition: param.h:75
int option(ParamOptions option)
Definition: param.c:99
int set_param_velocity(void)
Definition: param.c:1355
double * pointer
Definition: formula-calc.h:60
Parameters g_param
Definition: param.c:61
int g_param_init
Definition: param.c:62
int set_param(char *filename, char *concrete_path)
Definition: param.c:922


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