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


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