tmc_coe_interpreter.cpp
Go to the documentation of this file.
1 
6 #include "tmc_coe_interpreter.h"
7 #include "ethercat.h"
8 
10 
11 /* Constructor */
12 TmcCoeInterpreter::TmcCoeInterpreter(uint8_t SDO_PDO_retries, double interface_timeout) :
13 SDO_PDO_retries_(SDO_PDO_retries),
14 interface_timeout_(interface_timeout),
15 input_pdo_(1),
16 output_pdo_(1),
17 all_obj_name_(1),
18 all_index_(1),
19 all_sub_index_(1),
20 all_datatype_(1)
21 {
22  b_exit_threads_ = false;
23  b_cycle_finished_ = false;
24  b_start_cycle_count_ = false;
26 
27  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
28 }
29 
30 /* Destructor */
32 {
33  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
34 
35  input_pdo_.clear();
36  output_pdo_.clear();
37 }
38 
40 
44 void TmcCoeInterpreter::paramTransfer(std::vector<std::vector<std::string>> all_obj_name,
45  std::vector<std::vector<std::string>> all_index,
46  std::vector<std::vector<std::string>> all_sub_index,
47  std::vector<std::vector<std::string>> all_datatype)
48 {
49  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
50 
51  all_obj_name_ = all_obj_name;
52  all_index_ = all_index;
53  all_sub_index_ = all_sub_index;
54  all_datatype_ = all_datatype;
55 }
56 
62 {
63  ROS_INFO_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
64 
65  if(ec_init(ifname.c_str()))
66  {
67  ROS_INFO_STREAM("[" << __func__ << "] Init on " << ifname << " succeeded");
68 
69  if(ec_config_init(FALSE) > 0)
70  {
71  ROS_INFO_STREAM("[" << __func__ << "] " << ec_slavecount << " slaves found and configured");
72  }
73  else
74  {
75  ROS_ERROR_STREAM("[" << __func__ << "] No slaves found! Exiting");
76  }
77  }
78  else
79  {
80  ROS_ERROR_STREAM("[" << __func__ << "] No socket connection on " << ifname);
81  }
82 
83  return ec_slavecount;
84 }
85 
90 bool TmcCoeInterpreter::safeOPstate(std::vector<int> en_slave)
91 {
92  uint8_t slave_index = 1;
93  bool b_result = true;
94  slave_ = en_slave;
95 
96  ROS_INFO_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
97 
98  input_pdo_.resize(ec_slavecount + 1, nullptr);
99  output_pdo_.resize(ec_slavecount + 1, nullptr);
100 
102  ec_configdc();
103 
104  while(b_result && (slave_index <= ec_slavecount))
105  {
106  if(slave_[slave_index])
107  {
108  output_pdo_[slave_index] = (output_pdo_t*)ec_slave[slave_index].outputs;
109  input_pdo_[slave_index] = (input_pdo_t*)ec_slave[slave_index].inputs;
110  ROS_DEBUG_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) <<
111  " mapped. Set slave to SAFE_OP");
112 
113  if(this->deviceStateChange(slave_index, SAFE_OP) == EC_STATE_SAFE_OP)
114  {
115  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) << " is on SAFE_OP state");
116  }
117  else
118  {
119  ROS_ERROR_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) <<
120  " does not reached SAFE_OP state");
121  b_result = false;
122  }
123  }
124  slave_index++;
125  }
126 
127  if(b_result)
128  {
129  /* Create and run thread for processdata */
130  ROS_INFO_STREAM("[" << __func__ << "] Creating Process Data thread...");
131  processdata_thread_ = boost::thread(&TmcCoeInterpreter::processData, this);
132  }
133  else
134  {
135  ROS_ERROR_STREAM("[" << __func__ << "] Will not create Process Data thread.");
136  }
137 
138  return b_result;
139 }
140 
146 {
147  uint8_t slave_index = 1;
148  bool b_result = true;
149 
150  ROS_INFO_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
151 
152  while(b_result && (slave_index <= ec_slavecount))
153  {
154  if(slave_[slave_index])
155  {
156  ROS_DEBUG_STREAM("[" << __func__ << "] Set slave" << static_cast<int>(slave_index) << " state to OP");
157 
158  if(this->deviceStateChange(slave_index, OPERATIONAL) == EC_STATE_OPERATIONAL)
159  {
160  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) << " is on OP state");
161 
162  // set statusword to Operational too
163  if(!commandCodingTransition(slave_index))
164  {
165  b_result = false;
166  }
167  }
168  else
169  {
170  ROS_ERROR_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) << " does not reach OP state");
171  ec_readstate();
172  ROS_ERROR_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) << " State=" <<
173  ec_slave[slave_index].state << " - " << ec_ALstatuscode2string(ec_slave[slave_index].ALstatuscode));
174  b_result = false;
175  }
176  }
177  slave_index++;
178  }
179 
180  if(b_result)
181  {
182  /* Create and run thread for errorCheck */
183  ROS_INFO_STREAM("[" << __func__ << "] Creating Error Check thread...");
184  error_check_thread_ = boost::thread(&TmcCoeInterpreter::errorCheck, this);
185  }
186  else
187  {
188  ROS_ERROR_STREAM("[" << __func__ << "] Will not create Error Check thread.");
189  }
190 
191  return b_result;
192 }
193 
199 {
200  bool b_result = false;
201  bool b_timeout = false;
202  uint8_t index = 0;
203  uint8_t sequence_retries = SDO_PDO_retries_;
204  std::vector<fsa_state_t> status_word_state = {READY_TO_SWITCH_ON, SWITCHED_ON, OPERATION_ENABLED};
205  std::vector<control_word_state_t> control_word_state = {SHUTDOWN, SWITCH_ON, ENABLE_OPERATION};
206  int8_t CW_return_val = 0;
207 
208  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
209 
210  while(!b_timeout && (0 < sequence_retries))
211  {
212  while(index < control_word_state.size())
213  {
214  CW_return_val = setControlWord(slave_number, status_word_state[index], control_word_state[index]);
215  if(CW_return_val <= CONTROL_WORD_FAIL)
216  {
217  break;
218  }
219  index++;
220  }
221 
222  if(CW_return_val == CONTROL_WORD_SUCCESS)
223  {
224  b_result = true;
225  break;
226  }
227  else if (CW_return_val == CONTROL_WORD_FAIL)
228  {
229  sequence_retries--;
230  }
231  else
232  {
233  b_timeout = true;
234  }
235  }
236 
237  if(!b_result && !b_timeout)
238  {
239  ROS_ERROR_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) <<
240  " StatusWord did not recover from FAULT state.");
241  }
242  else if(b_result)
243  {
244  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) <<
245  " StatusWord state is on Operation Enabled");
246  }
247 
248  return b_result;
249 }
250 
251 
254 {
255  ROS_INFO_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
256 
257  /* Set b_exit_thread even with no thread created. To make sure that no threads are stucked in while loop */
258  b_exit_threads_ = true;
259 
260  /* Closes the thread after it finish cleanly */
261  if(processdata_thread_.joinable())
262  {
263  processdata_thread_.join();
264  ROS_DEBUG_STREAM("[" << __func__ << "] Process Data Thread closed");
265  }
266  if(error_check_thread_.joinable())
267  {
268  error_check_thread_.join();
269  ROS_DEBUG_STREAM("[" << __func__ << "] Error Check Thread closed");
270  }
271 
273  {
274  ROS_INFO_STREAM("[" << __func__ << "] Set all slave state to INIT");
275  (void) this->deviceStateChange(0, INIT);
276  }
277 
278  /* stop SOEM, close socket */
279  ROS_INFO_STREAM("[" << __func__ << "] Closing socket");
280  ec_close();
281 }
282 
290  control_word_state_t requested_CW)
291 {
292  int8_t result = 0;
293  double start_time = ros::Time::now().toSec();
294  double end_time = start_time;
295 
296  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
297 
299  while((this->getCycleCounter() <= SDO_PDO_retries_) && statusWordState(slave_number, FAULT))
300  {
301  if(isCycleFinished())
302  {
303  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[" << __func__ << "] Slave" << static_cast<int>(slave_number)
304  << " is on FAULT, resetting...");
305  output_pdo_[slave_number]->control_word = FAULT_RESET;
306  }
307  if(interface_timeout_ < (end_time - start_time))
308  {
309  ROS_ERROR_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) <<
310  " did not respond while changing Control Word. Timeout!");
311  result = CONTROL_WORD_TIMEOUT;
312  break;
313  }
314  end_time = ros::Time::now().toSec();
315  }
316  start_time = ros::Time::now().toSec();
318 
320  while((result >= CONTROL_WORD_FAIL) && (this->getCycleCounter() <= SDO_PDO_retries_) &&
321  !statusWordState(slave_number, response_SW))
322  {
323  if(isCycleFinished())
324  {
325  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[" << __func__ << "] Setting Slave" << static_cast<int>(slave_number)
326  << " Controlword to " << requested_CW);
327  output_pdo_[slave_number]->control_word = requested_CW;
328  }
329  if(interface_timeout_ < (end_time - start_time))
330  {
331  ROS_ERROR_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) <<
332  " did not respond while changing CW. Timeout!");
333  result = CONTROL_WORD_TIMEOUT;
334  break;
335  }
336  end_time = ros::Time::now().toSec();
337  }
339 
340  if(statusWordState(slave_number, response_SW))
341  {
342  ROS_DEBUG_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) <<
343  " ControlWord succesfully set to " << requested_CW);
344  result = CONTROL_WORD_SUCCESS;
345  }
346 
347  return result;
348 }
349 
356 {
357  bool b_result = true;
358  uint16_t statusword = 0;
359  uint16_t bitmasked_statusword = 0;
360 
361  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[TmcCoeInterpreter::" << __func__ << "] called");
362 
363  statusword = input_pdo_[slave_number]->status_word;
364  bitmasked_statusword = statusword & status_state_mask_[state];
365 
366  if(bitmasked_statusword != state_coding_val_[state])
367  {
368  b_result = false;
369  }
370 
371  return b_result;
372 }
373 
380 {
381  uint8_t return_state = 0;
382 
383  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
384 
385  if(slave_number <= ec_slavecount)
386  {
387  switch (state)
388  {
389  case INIT:
390  ec_slave[slave_number].state = EC_STATE_INIT;
391  ec_writestate(slave_number);
393  {
394  ROS_INFO_STREAM("[" << __func__ << "] State Change for Slave" << static_cast<int>(slave_number) <<
395  " is successful");
396  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) << " is on INIT");
397  }
398  else
399  {
400  ROS_ERROR_STREAM("[" << __func__ << "] State Change for Slave" << static_cast<int>(slave_number) <<
401  " failed");
402  }
403  break;
404 
405  case PRE_OP:
406  ec_slave[slave_number].state = EC_STATE_PRE_OP;
407  ec_writestate(slave_number);
409  {
410  ROS_INFO_STREAM("[" << __func__ << "] State Change for Slave" << static_cast<int>(slave_number) <<
411  " is successful");
412  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) << " is on PRE_OP");
413  }
414  else
415  {
416  ROS_ERROR_STREAM("[" << __func__ << "] State Change for Slave" << static_cast<int>(slave_number) <<
417  " failed");
418  }
419  break;
420 
421  case SAFE_OP:
422  ec_slave[slave_number].state = EC_STATE_SAFE_OP;
423  ec_writestate(slave_number);
425  {
426  ROS_INFO_STREAM("[" << __func__ << "] State Change for Slave" << static_cast<int>(slave_number) <<
427  " is successful");
428  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) << " is on SAFE_OP");
429  }
430  else
431  {
432  ROS_ERROR_STREAM("[" << __func__ << "] State Change for Slave" << static_cast<int>(slave_number) <<
433  " failed");
434  }
435  break;
436 
437  case OPERATIONAL:
438  ec_slave[slave_number].state = EC_STATE_OPERATIONAL;
439  ec_writestate(slave_number);
441  {
442  ROS_INFO_STREAM("[" << __func__ << "] State Change for Slave" << static_cast<int>(slave_number) <<
443  " is successful");
444  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) << " is on OPERATIONAL");
445  }
446  else
447  {
448  ROS_ERROR_STREAM("[" << __func__ << "] State Change for Slave" << static_cast<int>(slave_number) <<
449  " failed");
450  }
451  break;
452 
453  case SAFE_OP_ERROR_ACK:
454  ec_slave[slave_number].state = EC_STATE_SAFE_OP + EC_STATE_ACK;
455  ec_writestate(slave_number);
456  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) << " Error is Acknowledged");
457  break;
458 
459  default:
460  ROS_ERROR_STREAM("[" << __func__ << "] Wrong State request");
461  break;
462  }
463  }
464  else
465  {
466  ROS_ERROR_STREAM("[" << __func__ << "] Slave number not recognized");
467  }
468 
469  ec_readstate();
470 
471  return_state = ec_slave[slave_number].state;
472  return return_state;
473 }
474 
481 bool TmcCoeInterpreter::readSDO(uint8_t slave_number, std::string object_name, std::string *value)
482 {
483  std::string index_str = "";
484  uint16_t index_int = 0;
485  std::string sub_index_str = "";
486  uint16_t sub_index_int = 0;
487  std::string datatype = "";
488  uint16_t column = 0;
489  uint16_t index = 0;
490  const int val_int = 0;
491  const uint32_t val_uint_max = 0; // Used for special case, only if datatype of an object is UINT32
492  bool b_result = false;
493 
494  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "][High-Level] called");
495 
496  if(slave_number <= ec_slavecount)
497  {
498  while(!b_result && (column <= all_obj_name_[slave_number].size()))
499  {
500  if(all_obj_name_[slave_number][column] == object_name)
501  {
502  ROS_DEBUG_STREAM("[" << __func__ << "] Object Name: " << all_obj_name_[slave_number][column] << " found");
503  index = column;
504  b_result = true;
505  }
506  column++;
507  }
508 
509  if(b_result)
510  {
511  index_str = all_index_[slave_number][index];
512  index_int = std::stoi(index_str, nullptr, 16);
513  sub_index_str = all_sub_index_[slave_number][index];
514  sub_index_int = std::stoi(sub_index_str, nullptr, 16);
515  datatype = all_datatype_[slave_number][index];
516 
517  if(datatype == "UINT32")
518  {
519  *value = readSDO<uint32_t>(slave_number, index_int, sub_index_int, val_uint_max);
520  }
521  else
522  {
523  if(datatype == "UINT8")
524  {
525  *value = readSDO<uint8_t>(slave_number, index_int, sub_index_int, static_cast<uint8_t>(val_int));
526  }
527  else if(datatype == "UINT16")
528  {
529  *value = readSDO<uint16_t>(slave_number, index_int, sub_index_int, static_cast<uint16_t>(val_int));
530  }
531  else if(datatype == "INT8")
532  {
533  *value = readSDO<int8_t>(slave_number, index_int, sub_index_int, static_cast<int8_t>(val_int));
534  }
535  else if(datatype == "INT16")
536  {
537  *value = readSDO<int16_t>(slave_number, index_int, sub_index_int, static_cast<int16_t>(val_int));
538  }
539  else
540  {
541  *value = readSDO<int32_t>(slave_number, index_int, sub_index_int, val_int);
542  }
543  }
544  }
545  else
546  {
547  ROS_ERROR_STREAM("[" << __func__ << "] Object Name: " << object_name << " not found");
548  }
549  }
550  else
551  {
552  ROS_ERROR_STREAM("[" << __func__ << "] Slave Number: " << static_cast<int>(slave_number) << " not found");
553  }
554 
555  if(*value == "")
556  {
557  b_result = false;
558  }
559 
560  return b_result;
561 }
562 
569 bool TmcCoeInterpreter::writeSDO(uint8_t slave_number, std::string object_name, std::string *value)
570 {
571  std::string index_str = "";
572  uint16_t index_int = 0;
573  std::string sub_index_str = "";
574  uint16_t sub_index_int = 0;
575  std::string datatype = "";
576  uint16_t column = 0;
577  uint16_t index = 0;
578  int val_int = 0;
579  uint32_t val_uint_max = 0; // Used for special case, only if datatype of an object is UINT32
580  bool b_result = false;
581 
582  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "][High-Level] called");
583 
584  if(slave_number <= ec_slavecount)
585  {
586  while(!b_result && (column <= all_obj_name_[slave_number].size()))
587  {
588  if(all_obj_name_[slave_number][column] == object_name)
589  {
590  ROS_DEBUG_STREAM("[" << __func__ << "] Object Name: " << all_obj_name_[slave_number][column] << " found");
591  index = column;
592  b_result = true;
593  }
594  column++;
595  }
596 
597  if(b_result)
598  {
599  index_str = all_index_[slave_number][index];
600  index_int = std::stoi(index_str, nullptr, 16);
601  sub_index_str = all_sub_index_[slave_number][index];
602  sub_index_int = std::stoi(sub_index_str, nullptr, 16);
603  datatype = all_datatype_[slave_number][index];
604 
605  if(datatype == "UINT32")
606  {
607  val_uint_max = std::stoull(*value);
608  *value = writeSDO<uint32_t>(slave_number, index_int, sub_index_int, val_uint_max);
609  }
610  else
611  {
612  val_int = std::stoi(*value);
613 
614  if(datatype == "UINT8")
615  {
616  *value = writeSDO<uint8_t>(slave_number, index_int, sub_index_int, static_cast<uint8_t>(val_int));
617  }
618  else if(datatype == "UINT16")
619  {
620  *value = writeSDO<uint16_t>(slave_number, index_int, sub_index_int, static_cast<uint16_t>(val_int));
621  }
622  else if(datatype == "INT8")
623  {
624  *value = writeSDO<int8_t>(slave_number, index_int, sub_index_int, static_cast<int8_t>(val_int));
625  }
626  else if(datatype == "INT16")
627  {
628  *value = writeSDO<int16_t>(slave_number, index_int, sub_index_int, static_cast<int16_t>(val_int));
629  }
630  else
631  {
632  *value = writeSDO<int32_t>(slave_number, index_int, sub_index_int, val_int);
633  }
634  }
635  }
636  else
637  {
638  ROS_ERROR_STREAM("[" << __func__ << "] Object Name: " << object_name << " not found");
639  }
640  }
641  else
642  {
643  ROS_ERROR_STREAM("[" << __func__ << "] Slave Number: " << static_cast<int>(slave_number) << " not found");
644  }
645 
646  if(*value == "")
647  {
648  b_result = false;
649  }
650 
651  return b_result;
652 }
653 
658 std::string TmcCoeInterpreter::getSlaveName(uint8_t slave_number)
659 {
660  std::string slave_name = "";
661 
662  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "] called");
663 
664  if(slave_[slave_number])
665  {
666  slave_name = ec_slave[slave_number].name;
667  }
668  else
669  {
670  ROS_ERROR_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_number) << " is not enabled");
671  }
672 
673  return slave_name;
674 }
675 
680 {
681  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[TmcCoeInterpreter::" << __func__ << "] called");
682 
683  return b_cycle_finished_;
684 }
685 
690 {
691  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[TmcCoeInterpreter::" << __func__ << "] called");
692 
693  return cycle_counter_;
694 }
695 
699 {
700  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[TmcCoeInterpreter::" << __func__ << "] called");
701 
702  b_start_cycle_count_ = true;
703 }
704 
708 {
709  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[TmcCoeInterpreter::" << __func__ << "] called");
710 
711  b_start_cycle_count_ = false;
712  cycle_counter_ = 0;
713 }
714 
719 {
720  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[TmcCoeInterpreter::" << __func__ << "] called");
721 
723 }
724 
728 {
729  ROS_INFO_STREAM("[TmcCoeInterpreter::" << __func__ << "] Process Data Thread running");
730 
731  while(!b_exit_threads_)
732  {
733  b_cycle_finished_ = false;
736 
737  b_cycle_finished_ = true;
738 
740  {
741  cycle_counter_++;
742  }
743  else
744  {
745  cycle_counter_ = 0;
746  }
747 
748  boost::this_thread::sleep_for(boost::chrono::microseconds(PROCESS_DATA_DELAY));
749  }
750 }
751 
755 {
756  bool b_error_cleared = false;
757  uint8_t slave_index = 0;
758  uint16_t expected_work_count = ec_slavecount * TOTAL_WORK_COUNTER_PER_SLAVE;
759  double start_time = 0;
760  double end_time = 0;
761 
762  ROS_INFO_STREAM("[TmcCoeInterpreter::" << __func__ << "] Error Check Thread running");
763 
765  {
766  start_time = ros::Time::now().toSec();
767  end_time = start_time;
768  slave_index = 1; //resets slave_index
769 
770  while((work_count_ < expected_work_count) && (slave_index <= ec_slavecount))
771  {
772 /* NOTE: PRE OP state is excluded in error correction as it is assumed that the user is accountable in changing the
773  state of the slave. This package allows user to stay in PRE OP state to make any modifications on the configuration
774  of the slaves (Please only do this if you have enough knowledge on the slave and ofcourse CoE protocol as it may
775  destroy the firmware of the slave) */
776  if(ec_slave[slave_index].state == PRE_OP)
777  {
778  b_error_cleared = true;
779  }
780  else
781  {
782  b_error_cleared = false;
783  }
784 
785  while(!b_error_cleared && (interface_timeout_ > (end_time - start_time)))
786  {
787  ec_readstate();
788  if((ec_slave[slave_index].state == OPERATIONAL) && statusWordState(slave_index, OPERATION_ENABLED))
789  {
790  start_time = ros::Time::now().toSec(); //resets timeout count
791  b_error_cleared = true;
792  }
793  else if((ec_slave[slave_index].state == OPERATIONAL) && !statusWordState(slave_index, OPERATION_ENABLED))
794  {
795  if(!this->commandCodingTransition(slave_index))
796  {
797  ROS_WARN_STREAM("[" << __func__ << "] Command Coding Transition fail, changing state back to SAFE OP");
798  (void)this->deviceStateChange(slave_index, SAFE_OP);
799  }
800  else
801  {
802  ROS_DEBUG_STREAM("[" << __func__ << "] Command Coding Transition success!");
803  }
804  }
805  else
806  {
807  if(ec_slave[slave_index].state == EC_STATE_NONE)
808  {
809  ROS_ERROR_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) <<
810  " is lost, trying to recover...");
811  if(ec_recover_slave(slave_index, EC_TIMEOUTRET3))
812  {
813  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) << " recovered");
814  }
815  }
816  else if(ec_slave[slave_index].state == SAFE_OP_ERROR)
817  {
818  ROS_ERROR_STREAM("[" << __func__ << "]Slave" << static_cast<int>(slave_index) <<
819  " is on SAFE_OP state with ERROR : " <<
820  ec_ALstatuscode2string(ec_slave[slave_index].ALstatuscode));
821  (void)this->deviceStateChange(slave_index, SAFE_OP_ERROR_ACK);
822  }
823  else if(ec_slave[slave_index].state == SAFE_OP)
824  {
825  ROS_DEBUG_STREAM("[" << __func__ << "] Setting state to OPERATIONAL!");
826  (void)this->deviceStateChange(slave_index, OPERATIONAL);
827  }
828  else
829  {
830  if(ec_reconfig_slave(slave_index, EC_TIMEOUTRET3))
831  {
832  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) << " reconfigured!");
833  }
834  }
835  }
836  boost::this_thread::sleep_for(boost::chrono::microseconds(ERROR_CHECK_DELAY));
837  end_time = ros::Time::now().toSec();
838  }
839  if(interface_timeout_ <= (end_time - start_time))
840  {
842  break;
843  }
844  else
845  {
846  slave_index ++;
847  }
848  }
849  }
850 }
851 
859 template <typename T>
860 std::string TmcCoeInterpreter::readSDO(uint8_t slave_number, uint16_t index_number, uint16_t subindex_number, T value)
861 {
862  int val_size = sizeof(value);
863  std::string result_value = "";
864  bool b_result = false;
865  uint8_t n_retries_ = SDO_PDO_retries_;
866 
867  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "][Low-Level] called");
868 
869  while(0 < n_retries_)
870  {
871  if(ec_SDOread(slave_number, index_number, subindex_number, FALSE, &val_size, &value, EC_TIMEOUTSAFE) > 0)
872  {
873  ROS_DEBUG_STREAM("[" << __func__ << "] SDO Read Success");
874  result_value = std::to_string(value);
875  break;
876  }
877 
878  ROS_WARN_STREAM("[" << __func__ << "] SDO Read [" << static_cast<int>(n_retries_) << "] Retry");
879  n_retries_--;
880  ros::Duration(0.01).sleep(); //Safe tested delay time
881  }
882 
883  if(0 == n_retries_)
884  {
885  ROS_ERROR_STREAM("[" << __func__ << "] Fail to Read SDO");
886  }
887 
888  return result_value;
889 }
890 
898 template <typename T>
899 std::string TmcCoeInterpreter::writeSDO(uint8_t slave_number, uint16_t index_number, uint16_t subindex_number, T value)
900 {
901  std::string result_value = "";
902  bool b_result = false;
903  uint8_t n_retries_ = SDO_PDO_retries_;
904 
905  ROS_DEBUG_STREAM("[TmcCoeInterpreter::" << __func__ << "][Low-Level] called");
906 
907  while(0 < n_retries_)
908  {
909  if(ec_SDOwrite(slave_number, index_number, subindex_number, FALSE, sizeof(value), &value, EC_TIMEOUTSAFE) > 0)
910  {
911  ROS_DEBUG_STREAM("[" << __func__ << "] SDO Write Success");
912  result_value = std::to_string(value);
913  break;
914  }
915 
916  ROS_WARN_STREAM("[" << __func__ << "] SDO Write [" << static_cast<int>(n_retries_) << "] Retry");
917  n_retries_--;
918  ros::Duration(0.01).sleep(); //Safe tested delay time
919  }
920 
921  if(0 == n_retries_)
922  {
923  ROS_ERROR_STREAM("[" << __func__ << "] Fail to Write SDO");
924  }
925 
926  return result_value;
927 }
928 
929 /* Explicit Instantiation of the template */
930 template std::string TmcCoeInterpreter::readSDO<uint8_t>(uint8_t slave_number, uint16_t index_number,
931  uint16_t subindex_number, uint8_t value);
932 template std::string TmcCoeInterpreter::readSDO<uint16_t>(uint8_t slave_number, uint16_t index_number,
933  uint16_t subindex_number, uint16_t value);
934 template std::string TmcCoeInterpreter::readSDO<uint32_t>(uint8_t slave_number, uint16_t index_number,
935  uint16_t subindex_number, uint32_t value);
936 template std::string TmcCoeInterpreter::readSDO<int8_t>(uint8_t slave_number, uint16_t index_number,
937  uint16_t subindex_number, int8_t value);
938 template std::string TmcCoeInterpreter::readSDO<int16_t>(uint8_t slave_number, uint16_t index_number,
939  uint16_t subindex_number, int16_t value);
940 template std::string TmcCoeInterpreter::readSDO<int32_t>(uint8_t slave_number, uint16_t index_number,
941  uint16_t subindex_number, int32_t value);
942 
943 template std::string TmcCoeInterpreter::writeSDO<uint8_t>(uint8_t slave_number, uint16_t index_number,
944  uint16_t subindex_number, uint8_t value);
945 template std::string TmcCoeInterpreter::writeSDO<uint16_t>(uint8_t slave_number, uint16_t index_number,
946  uint16_t subindex_number, uint16_t value);
947 template std::string TmcCoeInterpreter::writeSDO<uint32_t>(uint8_t slave_number, uint16_t index_number,
948  uint16_t subindex_number, uint32_t value);
949 template std::string TmcCoeInterpreter::writeSDO<int8_t>(uint8_t slave_number, uint16_t index_number,
950  uint16_t subindex_number, int8_t value);
951 template std::string TmcCoeInterpreter::writeSDO<int16_t>(uint8_t slave_number, uint16_t index_number,
952  uint16_t subindex_number, int16_t value);
953 template std::string TmcCoeInterpreter::writeSDO<int32_t>(uint8_t slave_number, uint16_t index_number,
954  uint16_t subindex_number, int32_t value);
ec_configdc
boolean ec_configdc(void)
uint8_t
unsigned char uint8_t
EC_TIMEOUTSAFE
#define EC_TIMEOUTSAFE
int8_t
signed char int8_t
TmcCoeInterpreter::b_cycle_finished_
bool b_cycle_finished_
Definition: tmc_coe_interpreter.h:172
EC_TIMEOUTRET3
#define EC_TIMEOUTRET3
TmcCoeInterpreter::input_pdo_
std::vector< input_pdo_t * > input_pdo_
Definition: tmc_coe_interpreter.h:200
TmcCoeInterpreter::initInterface
uint8_t initInterface(std::string ifname)
Definition: tmc_coe_interpreter.cpp:61
TmcCoeInterpreter::b_interface_unresponsive_
bool b_interface_unresponsive_
Definition: tmc_coe_interpreter.h:175
ec_readstate
int ec_readstate(void)
TmcCoeInterpreter::error_check_thread_
boost::thread error_check_thread_
Definition: tmc_coe_interpreter.h:154
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
ec_close
void ec_close(void)
uint16_t
unsigned short uint16_t
ec_send_processdata
int ec_send_processdata(void)
SAFE_OP_ERROR
@ SAFE_OP_ERROR
Definition: tmc_coe_interpreter.h:23
TOTAL_WORK_COUNTER_PER_SLAVE
const uint8_t TOTAL_WORK_COUNTER_PER_SLAVE
Definition: tmc_coe_interpreter.h:145
FAULT_RESET
@ FAULT_RESET
Definition: tmc_coe_interpreter.h:33
TmcCoeInterpreter::all_obj_name_
std::vector< std::vector< std::string > > all_obj_name_
Definition: tmc_coe_interpreter.h:163
TmcCoeInterpreter::readSDO
std::string readSDO(uint8_t slave_number, uint16_t index_number, uint16_t subindex_number, T value)
Definition: tmc_coe_interpreter.cpp:860
ec_init
int ec_init(const char *ifname)
TmcCoeInterpreter::SDO_PDO_retries_
uint8_t SDO_PDO_retries_
Definition: tmc_coe_interpreter.h:168
ENABLE_OPERATION
@ ENABLE_OPERATION
Definition: tmc_coe_interpreter.h:32
TimeBase< Time, Duration >::toSec
double toSec() const
nmt_state_t
nmt_state_t
Definition: tmc_coe_interpreter.h:17
PROCESS_DATA_DELAY
const uint16_t PROCESS_DATA_DELAY
Definition: tmc_coe_interpreter.h:143
status_state_mask_
std::vector< int > status_state_mask_
Definition: tmc_coe_interpreter.h:101
TmcCoeInterpreter::statusWordState
bool statusWordState(uint8_t slave_number, fsa_state_t state)
Definition: tmc_coe_interpreter.cpp:355
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
EC_STATE_SAFE_OP
EC_STATE_SAFE_OP
TmcCoeInterpreter::errorCheck
void errorCheck()
Definition: tmc_coe_interpreter.cpp:754
int16_t
signed short int16_t
TmcCoeInterpreter::all_datatype_
std::vector< std::vector< std::string > > all_datatype_
Definition: tmc_coe_interpreter.h:166
CONTROL_WORD_FAIL
const int8_t CONTROL_WORD_FAIL
Definition: tmc_coe_interpreter.h:140
DEBUG_PERIOD
const uint8_t DEBUG_PERIOD
Definition: tmc_coe_interpreter.h:146
ec_slave::state
uint16 state
OPERATION_ENABLED
@ OPERATION_ENABLED
Definition: tmc_coe_interpreter.h:56
ethercat.h
TmcCoeInterpreter::processData
void processData()
Definition: tmc_coe_interpreter.cpp:727
ec_config_init
int ec_config_init(uint8 usetable)
EC_TIMEOUTRET
#define EC_TIMEOUTRET
PACKED
Definition: tmc_coe_interpreter.h:116
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
ec_recover_slave
int ec_recover_slave(uint16 slave, int timeout)
EC_STATE_PRE_OP
EC_STATE_PRE_OP
uint32_t
unsigned int uint32_t
TmcCoeInterpreter::slave_
std::vector< int > slave_
Definition: tmc_coe_interpreter.h:162
SAFE_OP_ERROR_ACK
@ SAFE_OP_ERROR_ACK
Definition: tmc_coe_interpreter.h:24
CONTROL_WORD_TIMEOUT
const int8_t CONTROL_WORD_TIMEOUT
Definition: tmc_coe_interpreter.h:142
OPERATIONAL
@ OPERATIONAL
Definition: tmc_coe_interpreter.h:22
ec_reconfig_slave
int ec_reconfig_slave(uint16 slave, int timeout)
TmcCoeInterpreter::getSlaveName
std::string getSlaveName(uint8_t slave_number)
Definition: tmc_coe_interpreter.cpp:658
FAULT
@ FAULT
Definition: tmc_coe_interpreter.h:59
TmcCoeInterpreter::isCycleFinished
bool isCycleFinished()
Definition: tmc_coe_interpreter.cpp:679
EC_STATE_INIT
EC_STATE_INIT
SWITCH_ON
@ SWITCH_ON
Definition: tmc_coe_interpreter.h:31
TmcCoeInterpreter::stopCycleCounter
void stopCycleCounter()
Definition: tmc_coe_interpreter.cpp:707
ROS_DEBUG_STREAM_THROTTLE
#define ROS_DEBUG_STREAM_THROTTLE(period, args)
ec_slave::name
char name[EC_MAXNAME+1]
ec_SDOwrite
int ec_SDOwrite(uint16 Slave, uint16 Index, uint8 SubIndex, boolean CA, int psize, void *p, int Timeout)
state_coding_val_
std::vector< int > state_coding_val_
Definition: tmc_coe_interpreter.h:77
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
TmcCoeInterpreter::~TmcCoeInterpreter
~TmcCoeInterpreter()
Definition: tmc_coe_interpreter.cpp:31
TmcCoeInterpreter::OPstate
bool OPstate()
Definition: tmc_coe_interpreter.cpp:145
SWITCHED_ON
@ SWITCHED_ON
Definition: tmc_coe_interpreter.h:55
SAFE_OP
@ SAFE_OP
Definition: tmc_coe_interpreter.h:21
TmcCoeInterpreter::work_count_
int work_count_
Definition: tmc_coe_interpreter.h:170
ERROR_CHECK_DELAY
const uint16_t ERROR_CHECK_DELAY
Definition: tmc_coe_interpreter.h:144
TmcCoeInterpreter::interface_timeout_
double interface_timeout_
Definition: tmc_coe_interpreter.h:169
ec_writestate
int ec_writestate(uint16 slave)
ec_slave
FALSE
#define FALSE
control_word_state_t
control_word_state_t
Definition: tmc_coe_interpreter.h:28
TmcCoeInterpreter::getCycleCounter
uint8_t getCycleCounter()
Definition: tmc_coe_interpreter.cpp:689
TmcCoeInterpreter::b_start_cycle_count_
bool b_start_cycle_count_
Definition: tmc_coe_interpreter.h:173
TmcCoeInterpreter::cycle_counter_
uint8_t cycle_counter_
Definition: tmc_coe_interpreter.h:174
TmcCoeInterpreter::commandCodingTransition
bool commandCodingTransition(uint8_t slave_number)
Definition: tmc_coe_interpreter.cpp:198
TmcCoeInterpreter::b_exit_threads_
bool b_exit_threads_
Definition: tmc_coe_interpreter.h:171
EC_TIMEOUTSTATE
#define EC_TIMEOUTSTATE
int32_t
signed int int32_t
TmcCoeInterpreter::paramTransfer
void paramTransfer(std::vector< std::vector< std::string >> all_obj_name, std::vector< std::vector< std::string >> all_index, std::vector< std::vector< std::string >> all_sub_index, std::vector< std::vector< std::string >> all_datatype)
Definition: tmc_coe_interpreter.cpp:44
TmcCoeInterpreter::all_index_
std::vector< std::vector< std::string > > all_index_
Definition: tmc_coe_interpreter.h:164
TmcCoeInterpreter::startCycleCounter
void startCycleCounter()
Definition: tmc_coe_interpreter.cpp:698
TmcCoeInterpreter::output_pdo_
std::vector< output_pdo_t * > output_pdo_
Definition: tmc_coe_interpreter.h:201
SHUTDOWN
@ SHUTDOWN
Definition: tmc_coe_interpreter.h:30
ec_slavecount
int ec_slavecount
TmcCoeInterpreter::TmcCoeInterpreter
TmcCoeInterpreter(uint8_t SDO_PDO_retries, double interface_timeout)
Definition: tmc_coe_interpreter.cpp:12
datatype
const char * datatype()
TmcCoeInterpreter::isInterfaceUnresponsive
bool isInterfaceUnresponsive()
Definition: tmc_coe_interpreter.cpp:718
INIT
@ INIT
Definition: tmc_coe_interpreter.h:19
TmcCoeInterpreter::IOmap
char IOmap[IOMAP_SIZE]
Definition: tmc_coe_interpreter.h:161
TmcCoeInterpreter::stopInterface
void stopInterface()
Definition: tmc_coe_interpreter.cpp:253
READY_TO_SWITCH_ON
@ READY_TO_SWITCH_ON
Definition: tmc_coe_interpreter.h:54
ec_SDOread
int ec_SDOread(uint16 slave, uint16 index, uint8 subindex, boolean CA, int *psize, void *p, int timeout)
ros::Duration::sleep
bool sleep() const
ec_statecheck
uint16 ec_statecheck(uint16 slave, uint16 reqstate, int timeout)
CONTROL_WORD_SUCCESS
const int8_t CONTROL_WORD_SUCCESS
Definition: tmc_coe_interpreter.h:141
TmcCoeInterpreter::setControlWord
int8_t setControlWord(uint8_t slave_number, fsa_state_t response_SW, control_word_state_t requested_CW)
Definition: tmc_coe_interpreter.cpp:289
ec_receive_processdata
int ec_receive_processdata(int timeout)
fsa_state_t
fsa_state_t
Definition: tmc_coe_interpreter.h:50
ec_ALstatuscode2string
char * ec_ALstatuscode2string(uint16 ALstatuscode)
TmcCoeInterpreter::safeOPstate
bool safeOPstate(std::vector< int > en_slave)
Definition: tmc_coe_interpreter.cpp:90
ec_config_map
int ec_config_map(void *pIOmap)
tmc_coe_interpreter.h
TmcCoeInterpreter::all_sub_index_
std::vector< std::vector< std::string > > all_sub_index_
Definition: tmc_coe_interpreter.h:165
ros::Duration
TmcCoeInterpreter::writeSDO
std::string writeSDO(uint8_t slave_number, uint16_t index_number, uint16_t subindex_number, T value)
Definition: tmc_coe_interpreter.cpp:899
TmcCoeInterpreter::processdata_thread_
boost::thread processdata_thread_
Definition: tmc_coe_interpreter.h:152
TmcCoeInterpreter::deviceStateChange
uint8_t deviceStateChange(uint8_t slave_number, nmt_state_t state)
Definition: tmc_coe_interpreter.cpp:379
PRE_OP
@ PRE_OP
Definition: tmc_coe_interpreter.h:20
EC_STATE_NONE
EC_STATE_NONE
EC_STATE_OPERATIONAL
EC_STATE_OPERATIONAL
ros::Time::now
static Time now()
EC_STATE_ACK
EC_STATE_ACK


adi_tmc_coe
Author(s):
autogenerated on Sun Feb 2 2025 03:07:24