tmc_coe_ros.cpp
Go to the documentation of this file.
1 
6 #include "tmc_coe_ros.h"
7 
9 
10 /* Constructor */
12 p_nh_ (p_nh),
13 p_motor_(1),
14 p_tmc_coe_interpreter_(nullptr)
15 {
16  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
17 }
18 
19 /* Destructor */
21 {
22  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
23  uint8_t slave_index = 0;
24  uint8_t motor_index = 0;
25  for(slave_index = 0; slave_index < p_motor_.size(); slave_index++)
26  {
27  for(motor_index = 0; motor_index < p_motor_[slave_index].size(); motor_index++)
28  {
29  delete p_motor_[slave_index][motor_index];
30  p_motor_[slave_index][motor_index] = nullptr;
31  ROS_DEBUG_STREAM("[" << __func__ << "] Deleting Slave" << static_cast<int>(slave_index) << " motor" <<
32  static_cast<int>(motor_index));
33  }
34  }
35 
36  if(p_tmc_coe_interpreter_ != nullptr)
37  {
38  ROS_DEBUG_STREAM("[" << __func__ << "] Deleting Interpreter and NodeHandle");
40  p_tmc_coe_interpreter_ = nullptr;
41  p_nh_ = nullptr;
42  }
43 }
44 
46 
48 {
49  bool b_result = true;
50  uint8_t index = 0;
51  uint16_t total_motor_ = 0;
52 
53  ROS_INFO_STREAM("[TmcCoeROS::" << __func__ << "] called");
54 
57  ROS_INFO_STREAM("[" << __func__ << "] Namespace: " << s_namespace_);
58  ROS_INFO_STREAM("[" << __func__ << "] Node name: " << s_node_name_);
59 
61  {
64  if(total_slaves_ > 0)
65  {
67  {
68  // Shift elements of param_en_slave - to imitate CoE protocol where slave 1 is device 1
69  param_en_slave_.insert(begin(param_en_slave_), 0);
70  slave_name_str_.push_back("");
71  total_motor_vector_.push_back(0);
73  {
74  for(index = 1; index <= total_slaves_; index++)
75  {
76  if(param_en_slave_[index])
77  {
79  total_motor_ = std::stoi(slave_name_str_[index].substr(5));
80  total_motor_ /= 1000;
81  total_motor_vector_.push_back(total_motor_);
82  }
83  else
84  {
85  slave_name_str_.push_back("");
86  total_motor_vector_.push_back(0);
87  }
88  }
89 
91  {
92  this->createMotor();
93  this->initService();
94  }
95  else
96  {
97  ROS_ERROR_STREAM("[" << __func__ << "] validateAutogenParams() failed");
98  b_result = false;
99  }
100 
102  {
103  ROS_ERROR_STREAM("[" << __func__ << "] OPstate() failed");
104  b_result = false;
105  }
106  }
107  else
108  {
109  ROS_ERROR_STREAM("[" << __func__ << "] safeOPstate() failed");
110  b_result = false;
111  }
112  }
113  else
114  {
115  ROS_WARN_STREAM("[" << __func__ << "] No Slaves are enabled");
116  }
117  }
118  else
119  {
120  ROS_ERROR_STREAM("[" << __func__ << "] initInterface() failed");
121  b_result = false;
122  }
123  }
124  else
125  {
126  ROS_ERROR_STREAM("[" << __func__ << "] validateInterfaceParams() failed");
127  b_result = false;
128  }
129 
130  return b_result;
131 }
132 
134 {
135  bool b_result = true;
136 
137  ROS_INFO_STREAM("[TmcCoeROS::" << __func__ << "] called");
138 
139  /* Interface Name is essential to run the node, expected to exit node once parameter is missing */
140  const std::string s_interface_name = s_node_name_ + "/interface_name";
141  if(!p_nh_->getParam(s_interface_name, param_interface_name_))
142  {
143  ROS_ERROR_STREAM("[" << __func__ << "] Failed to get interface_name. Exiting!");
144  b_result = false;
145  }
146 
147  /* SDO PDO retries has limits. Will set default value if limit exceeded */
148  const std::string s_SDO_PDO_retries = s_node_name_ + "/SDO_PDO_retries";
149  if(!p_nh_->getParam(s_SDO_PDO_retries, param_SDO_PDO_retries_))
150  {
152  p_nh_->setParam(s_SDO_PDO_retries, param_SDO_PDO_retries_);
153  ROS_WARN_STREAM("[" << __func__ << "] Failed to get SDO_PDO_retries, Setting to default value: " <<
155  }
156  else
157  {
158  if(param_SDO_PDO_retries_ < SDO_PDO_RETRIES_MIN || param_SDO_PDO_retries_ > SDO_PDO_RETRIES_MAX)
159  {
161  p_nh_->setParam(s_SDO_PDO_retries, param_SDO_PDO_retries_);
162  ROS_WARN_STREAM("[" << __func__ << "] Set value to SDO_PDO_retries is out of range, "
163  "Setting SDO_PDO_retries to default value: " << param_SDO_PDO_retries_);
164  }
165  }
166 
167  /* interface_timeout has limits. Will set default value if limit exceeded */
168  const std::string s_interface_timeout = s_node_name_ + "/interface_timeout";
169  if(!p_nh_->getParam(s_interface_timeout, param_interface_timeout_))
170  {
172  p_nh_->setParam(s_interface_timeout, param_interface_timeout_);
173  ROS_WARN_STREAM("[" << __func__ << "] Failed to get interface_timeout, Setting to default value: " <<
175  }
176  else
177  {
178  if(param_interface_timeout_ < TIMEOUT_MIN || param_interface_timeout_ > TIMEOUT_MAX)
179  {
181  p_nh_->setParam(s_interface_timeout, param_interface_timeout_);
182  ROS_WARN_STREAM("[" << __func__ << "] Set value to interface_timeout is out of range, "
183  "Setting interface_timeout to default value: " << param_interface_timeout_);
184  }
185  }
186  return b_result;
187 }
188 
190 {
191  std::vector<std::string> param_obj_name;
192  std::vector<std::string> param_index;
193  std::vector<std::string> param_sub_index;
194  std::vector<std::string> param_datatype;
195  std::vector<std::vector<std::string>> all_obj_name;
196  std::vector<std::vector<std::string>> all_index;
197  std::vector<std::vector<std::string>> all_sub_index;
198  std::vector<std::vector<std::string>> all_datatype;
199  uint8_t index = 0;
200  bool b_result = true;
201 
202  ROS_INFO_STREAM("[TmcCoeROS::" << __func__ << "] called");
203 
204  // Shift elements of param_en_slave - to imitate CoE protocol where slave 1 is device 1
205  all_obj_name.push_back(std::vector<std::string>());
206  all_index.push_back(std::vector<std::string>());
207  all_sub_index.push_back(std::vector<std::string>());
208  all_datatype.push_back(std::vector<std::string>());
209 
210  for(index = 0; index <= total_slaves_; index++)
211  {
212  // Will not check disabled slaves
213  if(slave_name_str_[index] != "")
214  {
215  const std::string s_obj_name = s_node_name_ + "/tmcm_" + slave_name_str_[index].substr(5) + "/obj_name";
216  if(!p_nh_->getParam(s_obj_name, param_obj_name))
217  {
218  ROS_ERROR_STREAM("[" << __func__ << "] Failed to get obj_name. "
219  "Check autogenerated YAML if broken or missing. Exiting!");
220  b_result = false;
221  }
222  const std::string s_index = s_node_name_ + "/tmcm_" + slave_name_str_[index].substr(5) + "/index";
223  if(b_result && !p_nh_->getParam(s_index, param_index))
224  {
225  ROS_ERROR_STREAM("[" << __func__ << "] Failed to get index. "
226  "Check autogenerated YAML if broken or missing. Exiting!");
227  b_result = false;
228  }
229  const std::string s_sub_index = s_node_name_ + "/tmcm_" + slave_name_str_[index].substr(5) + "/sub_index";
230  if(b_result && !p_nh_->getParam(s_sub_index, param_sub_index))
231  {
232  ROS_ERROR_STREAM("[" << __func__ << "] Failed to get sub_index. "
233  "Check autogenerated YAML if broken or missing. Exiting!");
234  b_result = false;
235  }
236  const std::string s_datatype = s_node_name_ + "/tmcm_" + slave_name_str_[index].substr(5) + "/datatype";
237  if(b_result && !p_nh_->getParam(s_datatype, param_datatype))
238  {
239  ROS_ERROR_STREAM("[" << __func__ << "] Failed to get datatype. "
240  "Check autogenerated YAML if broken or missing. Exiting!");
241  b_result = false;
242  }
243 
244  /* Check if obj_name, index, sub_index and datatype vectors have the same length/size */
245  if(b_result && (param_obj_name.size() != param_index.size()) &&
246  (param_index.size() != param_sub_index.size()) && (param_sub_index.size() != param_datatype.size()))
247  {
248  ROS_ERROR_STREAM("[" << __func__ << "] Vector size mismatch between obj_name, index, sub_index and datatype."
249  "Check autogenerated YAML. Exiting!");
250  b_result = false;
251  }
252  else
253  {
254  all_obj_name.push_back(param_obj_name);
255  all_index.push_back(param_index);
256  all_sub_index.push_back(param_sub_index);
257  all_datatype.push_back(param_datatype);
258  }
259  }
260  }
261 
262  if(b_result)
263  {
264  p_tmc_coe_interpreter_->paramTransfer(all_obj_name, all_index, all_sub_index, all_datatype);
265  }
266 
267  return b_result;
268 }
269 
271 {
272  uint8_t slave_index = 0;
273  uint8_t motor_index = 0;
274  uint16_t motor_type = 0;
275 
276  ROS_INFO_STREAM("[TmcCoeROS::" << __func__ << "] called");
277 
278  p_motor_.resize(total_slaves_ + 1);
280 
281  for(slave_index = 1; slave_index <= total_slaves_; slave_index ++)
282  {
283  p_motor_[slave_index].resize(total_motor_vector_[slave_index]);
284 
285  if(enFlagsVectorParamCheck("/slv" + std::to_string(slave_index) + "/en_motor", param_en_motor_,
286  total_motor_vector_[slave_index]) > 0)
287  {
288  std::cout << "\n";
289  ROS_INFO_STREAM("[" << __func__ << "] Slave" << static_cast<int>(slave_index) << " name: " <<
290  slave_name_str_[slave_index]);
291  motor_type = std::stoi(slave_name_str_[slave_index].substr(5));
292  motor_type = (motor_type - (total_motor_vector_[slave_index] * 1000)) / 100;
293  ROS_INFO_STREAM("[" << __func__ << "] Total motors: " << static_cast<int>(total_motor_vector_[slave_index]));
294 
295  /* Check for motor type */
296  if(param_adhoc_mode_[slave_index - 1])
297  {
298  ROS_INFO_STREAM("[" << __func__ << "] Adhoc Mode is enabled");
299  for(motor_index = 0; motor_index < total_motor_vector_[slave_index]; motor_index++)
300  {
301  p_motor_[slave_index][motor_index] = new TmcCoeMotor(p_nh_, p_tmc_coe_interpreter_,
302  slave_index, motor_index);
303  p_motor_[slave_index][motor_index]->init();
304  }
305  }
306  else
307  {
308  if(motor_type == MOTOR_TYPE_BLDC)
309  {
310  ROS_INFO_STREAM("[" << __func__ << "] Motor Type : BLDC Motor");
311  for(motor_index = 0; motor_index < total_motor_vector_[slave_index]; motor_index++)
312  {
313  p_motor_[slave_index][motor_index] = new TmcCoeBLDCMotor(p_nh_, p_tmc_coe_interpreter_,
314  slave_index, motor_index);
315  p_motor_[slave_index][motor_index]->init();
316  }
317  }
318  else if((motor_type >= MOTOR_TYPE_STEPPER_MIN || motor_type <= MOTOR_TYPE_STEPPER_MAX))
319  {
320  ROS_INFO_STREAM("[" << __func__ << "] Motor Type : STEPPER Motor");
321  for(motor_index = 0; motor_index < total_motor_vector_[slave_index]; motor_index++)
322  {
323  p_motor_[slave_index][motor_index] = new TmcCoeStepperMotor(p_nh_, p_tmc_coe_interpreter_,
324  slave_index, motor_index);
325  p_motor_[slave_index][motor_index]->init();
326  }
327  }
328  else
329  {
330  ROS_ERROR_STREAM("[" << __func__ << "] Invalid Motor Type. Will not create Motor Class on slave"
331  << static_cast<int>(slave_index));
332  }
333  }
334  }
335  else
336  {
337  ROS_INFO_STREAM("[" << __func__ << "] No enabled motor in Slave" << static_cast<int>(slave_index) << "\n");
338  }
339  }
340 }
341 
342 uint8_t TmcCoeROS::enFlagsVectorParamCheck(std::string param_name, std::vector<int> &param_var, uint32_t max_val)
343 {
344  std::vector<int> local_vector;
345  uint8_t total_en_param_ = 0;
346  uint8_t index = 0;
347 
348  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
349 
350  /* Special handling for en_slave*/
351  const std::string s_param_name = s_node_name_ + param_name;
352  if(!p_nh_->getParam(s_param_name, local_vector))
353  {
354  for(index = 0; index < max_val; index++)
355  {
356  local_vector.push_back(0);
357  }
358  p_nh_->setParam(s_param_name, local_vector);
359  ROS_WARN_STREAM("[" << __func__ << "] Failed to get " << param_name << ", setting to default value: 0");
360  }
361  else
362  {
363  /* Check if param size is equal to max_val */
364  if((local_vector.size()) < max_val)
365  {
366  for(index = local_vector.size(); index < max_val; index++)
367  {
368  local_vector.push_back(0);
369  }
370  ROS_WARN_STREAM("[" << __func__ << "] Missing indeces for " << param_name <<
371  ", setting missing value to default: 0");
372  }
373  else if((local_vector.size()) > max_val)
374  {
375  local_vector.erase(local_vector.begin() + max_val, local_vector.end());
376  ROS_WARN_STREAM("[" << __func__ << "] Indeces exceeded total " << param_name <<
377  " available, deleting unused indeces");
378  }
379  /* Check each indeces of param if valid */
380  for(index = 0; index < local_vector.size(); index++)
381  {
382  if(local_vector[index] != 0 && local_vector[index] != 1)
383  {
384  local_vector[index] = 0;
385  ROS_WARN_STREAM("[" << __func__ << "] Set value for " << param_name << static_cast<int>(index) <<
386  " is out of range, setting value to default:" << local_vector[index]);
387  }
388  if(local_vector[index] == 1)
389  {
390  total_en_param_++;
391  }
392  }
393  param_var = std::move(local_vector);
394  p_nh_->setParam(s_param_name, param_var);
395  }
396 
397  return total_en_param_;
398 }
399 
401 {
402  ROS_INFO_STREAM("[TmcCoeROS::" << __func__ << "] called");
404  ROS_INFO_STREAM("[" << __func__ << "] Successfully de-initialized TMC-CoE.");
405 }
406 
408 {
410 
411  ROS_DEBUG_STREAM_THROTTLE(DEBUG_PERIOD, "[TmcCoeROS::" << __func__ << "] called");
412 
413  if(b_result)
414  {
415  ROS_ERROR_STREAM("[" << __func__ << "] Interface is Unresponsive! Exiting...");
416  }
417 
418  return b_result;
419 }
420 
421 /* Initialize ROS Service */
423 {
424  ROS_INFO_STREAM("[TmcCoeROS::" << __func__ << "] called");
425  /* Make s_namespace_ empty if namespace is empty */
426  if(s_namespace_.compare("/") == 0)
427  {
428  s_namespace_ = "";
429  }
430 
431  std::string s_read_sdo_srvname = s_namespace_ + "/read_SDO";
432  std::string s_write_sdo_srvname = s_namespace_ + "/write_SDO";
433  std::string s_read_pdo_srvname = s_namespace_ + "/read_PDO";
434  std::string s_write_pdo_srvname = s_namespace_ + "/write_PDO";
435  std::string s_state_change_srvname = s_namespace_ + "/state_change";
436  std::string s_cyclic_sync_srvname = s_namespace_ + "/cyclic_sync_mode";
437 
438  read_sdo_server_ = p_nh_->advertiseService(s_read_sdo_srvname, &TmcCoeROS::readSDOCallBack, this);
439  if(ros::service::exists(s_read_sdo_srvname, true))
440  {
441  ROS_INFO_STREAM("[" << __func__ << "] read_sdo server advertised. Service name: " << s_read_sdo_srvname);
442  }
443  else
444  {
445  ROS_WARN_STREAM("[" << __func__ << "] read_sdo server failed to advertise.");
446  }
447 
449  if(ros::service::exists(s_write_sdo_srvname, true))
450  {
451  ROS_INFO_STREAM("[" << __func__ << "] write_sdo server advertised. Service name: " << s_write_sdo_srvname);
452  }
453  else
454  {
455  ROS_WARN_STREAM("[" << __func__ << "] write_sdo server failed to advertise.");
456  }
457 
458  read_pdo_server_ = p_nh_->advertiseService(s_read_pdo_srvname, &TmcCoeROS::readPDOCallBack, this);
459  if(ros::service::exists(s_read_pdo_srvname, true))
460  {
461  ROS_INFO_STREAM("[" << __func__ << "] read_pdo server advertised. Service name: " << s_read_pdo_srvname);
462  }
463  else
464  {
465  ROS_WARN_STREAM("[" << __func__ << "] read_pdo server failed to advertise.");
466  }
467 
469  if(ros::service::exists(s_write_pdo_srvname, true))
470  {
471  ROS_INFO_STREAM("[" << __func__ << "] write_pdo server advertised. Service name: " << s_write_pdo_srvname);
472  }
473  else
474  {
475  ROS_WARN_STREAM("[" << __func__ << "] write_pdo server failed to advertise.");
476  }
477 
479  if(ros::service::exists(s_state_change_srvname, true))
480  {
481  ROS_INFO_STREAM("[" << __func__ << "] state_change server advertised. Service name: " << s_state_change_srvname);
482  }
483  else
484  {
485  ROS_WARN_STREAM("[" << __func__ << "] state_change server failed to advertise.");
486  }
487 
489  if(ros::service::exists(s_cyclic_sync_srvname, true))
490  {
491  ROS_INFO_STREAM("[" << __func__ << "] cyclic_sync server advertised. Service name: " <<
492  s_cyclic_sync_srvname << "\n");
493  }
494  else
495  {
496  ROS_WARN_STREAM("[" << __func__ << "] cyclic_sync server failed to advertise.\n");
497  }
498 }
499 
500 /* ROS Service Callbacks */
501 
502 /* Make sure that the input for index number / sub index number is in hex */
503 bool TmcCoeROS::readSDOCallBack(adi_tmc_coe::read_write_SDO::Request& req,
504  adi_tmc_coe::read_write_SDO::Response& res)
505 {
506  bool b_result = true;
507  std::string local_value = "";
508 
509  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
510 
511  if(req.slave_number <= total_slaves_ && req.slave_number > 0)
512  {
513  if(!p_tmc_coe_interpreter_->readSDO(req.slave_number, req.object_name, &local_value))
514  {
515  ROS_ERROR_STREAM("[" << __func__ << "] Service SDO Read Fail");
516  b_result = false;
517  }
518  }
519  else
520  {
521  ROS_ERROR_STREAM("[" << __func__ << "] Slave number not recognized");
522  b_result = false;
523  }
524 
525  res.output = local_value;
526  res.result = b_result;
527 
528  return true;
529 }
530 
531 /* Make sure that the input for index number / sub index number is in hex */
532 bool TmcCoeROS::writeSDOCallBack(adi_tmc_coe::read_write_SDO::Request& req,
533  adi_tmc_coe::read_write_SDO::Response& res)
534 {
535  bool b_result = true;
536  std::string local_value = req.value;
537 
538  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
539 
540  if(req.slave_number <= total_slaves_ && req.slave_number > 0)
541  {
542  if(!p_tmc_coe_interpreter_->writeSDO(req.slave_number, req.object_name, &local_value))
543  {
544  ROS_ERROR_STREAM("[" << __func__ << "] Service SDO Write Fail");
545  b_result = false;
546  }
547  }
548  else
549  {
550  ROS_ERROR_STREAM("[" << __func__ << "] Slave number not recognized");
551  b_result = false;
552  }
553 
554  res.output = local_value;
555  res.result = b_result;
556 
557  return true;
558 }
559 
560 bool TmcCoeROS::writePDOCallBack(adi_tmc_coe::read_write_PDO::Request& req, adi_tmc_coe::read_write_PDO::Response& res)
561 {
562  bool b_result = true;
563  int32_t actual_value = 0;
564 
565  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
566 
567  /* Make inputs uppercase */
568  std::transform(req.cmd.begin(), req.cmd.end(), req.cmd.begin(), ::toupper);
569 
570  if(req.slave_number <= total_slaves_ && req.slave_number > 0)
571  {
573 
574  if(req.cmd == "MODES OF OPERATION")
575  {
577  {
579  {
580  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->modes_of_operation = req.value;
581  if(p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display == req.value)
582  {
584  break;
585  }
586  }
587  }
588 
589  if(p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display != req.value)
590  {
591  ROS_ERROR_STREAM("[" << __func__ << "]Modes of Operation not set properly");
592  b_result = false;
593  }
594 
595  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display;
596  }
597  else if(req.cmd == "CONTROLWORD")
598  {
600  {
602  {
603  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->control_word = req.value;
604  }
605  }
607  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->status_word;
608  }
609  else if(req.cmd == "TARGET POSITION")
610  {
612  {
614  {
615  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->target_position = req.value;
616  }
617  }
619  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->position_actual_value;
620  }
621  else if(req.cmd == "TARGET VELOCITY")
622  {
624  {
626  {
627  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->target_velocity = req.value;
628  }
629  }
631  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->velocity_actual_value;
632  }
633  else if(req.cmd == "TARGET TORQUE")
634  {
636  {
638  {
639  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->target_torque = req.value;
640  }
641  }
643  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->torque_actual_value;
644  }
645  else
646  {
648  ROS_ERROR_STREAM("[" << __func__ << "] Wrong CMD input");
649  b_result = false;
650  }
651  }
652  else
653  {
654  ROS_ERROR_STREAM("[" << __func__ << "] Slave number not recognized");
655  b_result = false;
656  }
657 
658  res.actual_value = actual_value;
659  res.result = b_result;
660 
661  return true;
662 }
663 
664 bool TmcCoeROS::readPDOCallBack(adi_tmc_coe::read_write_PDO::Request& req, adi_tmc_coe::read_write_PDO::Response& res)
665 {
666  bool b_result = true;
667  int32_t actual_value = 0;
668 
669  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
670 
671  /* Make inputs uppercase */
672  std::transform(req.cmd.begin(), req.cmd.end(), req.cmd.begin(), ::toupper);
673 
674  if(req.slave_number <= total_slaves_ && req.slave_number > 0)
675  {
676  if(req.cmd == "MODES OF OPERATION DISPLAY")
677  {
678  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display;
679  }
680  else if(req.cmd == "STATUSWORD")
681  {
682  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->status_word;
683  }
684  else if(req.cmd == "ACTUAL POSITION")
685  {
686  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->position_actual_value;
687  }
688  else if(req.cmd == "DEMAND POSITION")
689  {
690  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->position_demand_value;
691  }
692  else if(req.cmd == "ACTUAL VELOCITY")
693  {
694  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->velocity_actual_value;
695  }
696  else if(req.cmd == "DEMAND VELOCITY")
697  {
698  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->velocity_demand_value;
699  }
700  else if(req.cmd == "ACTUAL TORQUE")
701  {
702  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->torque_actual_value;
703  }
704  else if(req.cmd == "DEMAND TORQUE")
705  {
706  actual_value = p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->torque_demand_value;
707  }
708  else
709  {
710  ROS_ERROR_STREAM("[" << __func__ << "] Wrong CMD input");
711  b_result = false;
712  }
713  }
714  else
715  {
716  ROS_ERROR_STREAM("[" << __func__ << "] Slave number not recognized");
717  b_result = false;
718  }
719 
720  res.actual_value = actual_value;
721  res.result = b_result;
722 
723  return true;
724 }
725 
726 bool TmcCoeROS::stateChangeCallback(adi_tmc_coe::state_change::Request& req, adi_tmc_coe::state_change::Response& res)
727 {
728  bool b_result = true;
729  uint8_t state = 0;
730  uint8_t current_state = 0;
731  std::string current_state_str = "";
732 
733  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
734 
735  std::transform(req.request_state.begin(), req.request_state.end(), req.request_state.begin(), ::toupper);
736 
737  if(req.slave_number <= total_slaves_ && req.slave_number > 0)
738  {
739  if(req.request_state == "INIT")
740  {
742  }
743  else if(req.request_state == "PREOP")
744  {
746  }
747  else if(req.request_state == "SAFEOP")
748  {
750  }
751  else if(req.request_state == "OPERATIONAL")
752  {
754  }
755  else
756  {
757  ROS_ERROR_STREAM("[" << __func__ << "] Wrong request_state input");
758  b_result = false;
759  }
760  }
761  else
762  {
763  ROS_ERROR_STREAM("[" << __func__ << "] Slave number not recognized");
764  b_result = false;
765  }
766 
767  if(b_result)
768  {
769  current_state = (nmt_state_t) p_tmc_coe_interpreter_->deviceStateChange(req.slave_number,
771 
772  if(current_state != p_tmc_coe_interpreter_->nmt_state_)
773  {
774  ROS_ERROR_STREAM("[" << __func__ << "] State Change Failed. Current device state: " <<
775  static_cast<int>(current_state));
776  b_result = false;
777  }
778 
779  switch (current_state)
780  {
781  case INIT:
782  current_state_str = "INIT";
783  break;
784  case PRE_OP:
785  current_state_str = "PREOP";
786  break;
787  case SAFE_OP:
788  current_state_str = "SAFEOP";
789  break;
790  case OPERATIONAL:
791  current_state_str = "OPERATIONAL";
792  if(b_result)
793  {
794  b_result = p_tmc_coe_interpreter_->commandCodingTransition(req.slave_number);
795  }
796  break;
797  }
798  res.current_state = current_state_str;
799  }
800 
801  res.result = b_result;
802 
803  return true;
804 }
805 
806 bool TmcCoeROS::cyclicSyncModeCallback(adi_tmc_coe::CSx_mode::Request& req, adi_tmc_coe::CSx_mode::Response& res)
807 {
808  bool b_result = true;
809  uint32_t index = 0;
810  uint16_t motor_type = 0;
811  double interpolation_time = req.interpolation_time_period * pow(10, req.interpolation_time_index);
812  std::string interpolation_time_period = std::to_string(req.interpolation_time_period);
813  std::string interpolation_time_index = std::to_string(req.interpolation_time_index);
814 
815  ROS_DEBUG_STREAM("[TmcCoeROS::" << __func__ << "] called");
816 
817  std::transform(req.CS_cmd.begin(), req.CS_cmd.end(), req.CS_cmd.begin(), ::toupper);
818 
819  /* Remove first 5 letters in slaves name (TMCM-) */
820  motor_type = std::stoi(slave_name_str_[req.slave_number].substr(5));
821 
822  /* Parse slave model number to get 3rd digit (motor type) */
823  motor_type = (motor_type - (total_motor_vector_[req.slave_number] * 1000)) / 100;
824 
825  if(req.slave_number <= total_slaves_ && req.slave_number > 0)
826  {
827  if(req.interpolation_time_period >= 0 && req.interpolation_time_period <= UINT8_MAX &&
828  req.interpolation_time_index >= INTERPOLATION_TIME_INDEX_MIN &&
829  req.interpolation_time_index <= INTERPOLATION_TIME_INDEX_MAX)
830  {
831  if(motor_type == MOTOR_TYPE_BLDC)
832  {
833  if(p_tmc_coe_interpreter_->writeSDO(req.slave_number, "Interpolation time period - Time units",
834  &interpolation_time_period))
835  {
836  ROS_DEBUG_STREAM("[" << __func__ << "] Interpolation Time period set");
837  }
838  else
839  {
840  b_result = false;
841  }
842 
843  if(p_tmc_coe_interpreter_->writeSDO(req.slave_number, "Interpolation time period - Time index",
844  &interpolation_time_index))
845  {
846  ROS_DEBUG_STREAM("[" << __func__ << "] Interpolation Time index set");
847  }
848  else
849  {
850  b_result = false;
851  }
852  }
853  else
854  {
855  if(p_tmc_coe_interpreter_->writeSDO(req.slave_number,
856  "Interpolation Time Period - Interpolation time period value", &interpolation_time_period))
857  {
858  ROS_DEBUG_STREAM("[" << __func__ << "] Interpolation Time period set");
859  }
860  else
861  {
862  b_result = false;
863  }
864 
865  if(p_tmc_coe_interpreter_->writeSDO(req.slave_number,
866  "Interpolation Time Period - Interpolation time index", &interpolation_time_index))
867  {
868  ROS_DEBUG_STREAM("[" << __func__ << "] Interpolation Time index set");
869  }
870  else
871  {
872  b_result = false;
873  }
874  }
875  }
876  else
877  {
878  ROS_ERROR_STREAM("[" << __func__ << "] Wrong interpolation_time input");
879  b_result = false;
880  }
881 
883 
884  if(req.CS_cmd == "CSP")
885  {
887  {
889  {
890  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->modes_of_operation = CYCLIC_SYNC_POS;
891  if(p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display == CYCLIC_SYNC_POS)
892  {
893  break;
894  }
895  }
896  }
898 
899  if(p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display != CYCLIC_SYNC_POS)
900  {
901  ROS_ERROR_STREAM("[" << __func__ << "]Modes of Operation not set properly");
902  b_result = false;
903  }
904 
905  if(b_result)
906  {
907  for(index = 0; index < req.value.size(); index++)
908  {
909  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->target_position = req.value[index];
910  ROS_DEBUG_STREAM("[" << __func__ << "] Data Sent");
911  ros::Duration(interpolation_time).sleep();
912  }
913  }
914  else
915  {
916  ROS_ERROR_STREAM("[" << __func__ << "] Cyclic Synchronous Position Failed");
917  }
918  }
919  else if(req.CS_cmd == "CSV")
920  {
922  {
924  {
925  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->modes_of_operation = CYCLIC_SYNC_VEL;
926  if(p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display == CYCLIC_SYNC_VEL)
927  {
928  break;
929  }
930  }
931  }
933 
934  if(p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display != CYCLIC_SYNC_VEL)
935  {
936  ROS_ERROR_STREAM("[" << __func__ << "]Modes of Operation not set properly");
937  b_result = false;
938  }
939 
940  if(b_result)
941  {
942  for(index = 0; index < req.value.size(); index++)
943  {
944  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->target_velocity = req.value[index];
945  ROS_DEBUG_STREAM("[" << __func__ << "] Data Sent");
946  ros::Duration(interpolation_time).sleep();
947  }
948  }
949  else
950  {
951  ROS_ERROR_STREAM("[" << __func__ << "] Cyclic Synchronous Velocity Failed");
952  }
953  }
954  else if(req.CS_cmd == "CST")
955  {
957  {
959  {
960  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->modes_of_operation = CYCLIC_SYNC_TRQ;
961  if(p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display == CYCLIC_SYNC_TRQ)
962  {
963  break;
964  }
965  }
966  }
968 
969  if(p_tmc_coe_interpreter_->input_pdo_[req.slave_number]->modes_of_operation_display != CYCLIC_SYNC_TRQ)
970  {
971  ROS_ERROR_STREAM("[" << __func__ << "]Modes of Operation not set properly");
972  b_result = false;
973  }
974 
975  if(b_result)
976  {
977  for(index = 0; index < req.value.size(); index++)
978  {
979  p_tmc_coe_interpreter_->output_pdo_[req.slave_number]->target_torque = req.value[index];
980  ROS_DEBUG_STREAM("[" << __func__ << "] Data Sent");
981  ros::Duration(interpolation_time).sleep();
982  }
983  }
984  else
985  {
986  ROS_ERROR_STREAM("[" << __func__ << "] Cyclic Synchronous Torque Failed");
987  }
988  }
989  else
990  {
992  ROS_ERROR_STREAM("[" << __func__ << "] Wrong CS_cmd input");
993  b_result = false;
994  }
995  }
996  else
997  {
998  ROS_ERROR_STREAM("[" << __func__ << "] Slave number not recognized");
999  b_result = false;
1000  }
1001 
1002  res.result = b_result;
1003 
1004  return true;
1005 }
uint8_t
unsigned char uint8_t
TIMEOUT_MAX
const uint8_t TIMEOUT_MAX
Definition: tmc_coe_ros.h:24
ros::NodeHandle::setParam
void setParam(const std::string &key, bool b) const
ros::this_node::getNamespace
const ROSCPP_DECL std::string & getNamespace()
ros::service::exists
ROSCPP_DECL bool exists(const std::string &service_name, bool print_failure_reason)
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
UINT8_MAX
#define UINT8_MAX
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
TmcCoeROS::read_pdo_server_
ros::ServiceServer read_pdo_server_
Definition: tmc_coe_ros.h:43
uint16_t
unsigned short uint16_t
TmcCoeROS::p_motor_
std::vector< std::vector< TmcCoeMotor * > > p_motor_
Definition: tmc_coe_ros.h:65
ros::NodeHandle::getParam
bool getParam(const std::string &key, bool &b) const
TmcCoeROS::s_namespace_
std::string s_namespace_
Definition: tmc_coe_ros.h:53
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
TmcCoeROS::readSDOCallBack
bool readSDOCallBack(adi_tmc_coe::read_write_SDO::Request &req, adi_tmc_coe::read_write_SDO::Response &res)
Definition: tmc_coe_ros.cpp:503
TmcCoeROS::param_interface_timeout_
double param_interface_timeout_
Definition: tmc_coe_ros.h:56
TmcCoeROS::stateChangeCallback
bool stateChangeCallback(adi_tmc_coe::state_change::Request &req, adi_tmc_coe::state_change::Response &res)
Definition: tmc_coe_ros.cpp:726
ros::NodeHandle::advertiseService
ServiceServer advertiseService(AdvertiseServiceOptions &ops)
nmt_state_t
nmt_state_t
Definition: tmc_coe_interpreter.h:17
TmcCoeROS::param_en_motor_
std::vector< int > param_en_motor_
Definition: tmc_coe_ros.h:59
TmcCoeROS::TmcCoeROS
TmcCoeROS(ros::NodeHandle *p_nh)
Definition: tmc_coe_ros.cpp:11
TmcCoeROS::cyclicSyncModeCallback
bool cyclicSyncModeCallback(adi_tmc_coe::CSx_mode::Request &req, adi_tmc_coe::CSx_mode::Response &res)
Definition: tmc_coe_ros.cpp:806
TmcCoeROS::param_interface_name_
std::string param_interface_name_
Definition: tmc_coe_ros.h:54
TmcCoeROS::validateInterfaceParams
bool validateInterfaceParams()
Definition: tmc_coe_ros.cpp:133
MOTOR_TYPE_STEPPER_MIN
const uint8_t MOTOR_TYPE_STEPPER_MIN
Definition: tmc_coe_ros.h:17
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
TmcCoeROS::p_tmc_coe_interpreter_
TmcCoeInterpreter * p_tmc_coe_interpreter_
Definition: tmc_coe_ros.h:64
CYCLIC_SYNC_VEL
@ CYCLIC_SYNC_VEL
Definition: tmc_coe_motor.h:23
MOTOR_TYPE_STEPPER_MAX
const uint8_t MOTOR_TYPE_STEPPER_MAX
Definition: tmc_coe_ros.h:18
MOTOR_TYPE_BLDC
const uint8_t MOTOR_TYPE_BLDC
Definition: tmc_coe_ros.h:16
TmcCoeROS::s_node_name_
std::string s_node_name_
Definition: tmc_coe_ros.h:52
DEBUG_PERIOD
const uint8_t DEBUG_PERIOD
Definition: tmc_coe_interpreter.h:146
TmcCoeROS::initService
void initService()
Definition: tmc_coe_ros.cpp:422
TmcCoeROS::initialize
bool initialize()
Definition: tmc_coe_ros.cpp:47
TmcCoeROS::isInterfaceUnresponsive
bool isInterfaceUnresponsive()
Definition: tmc_coe_ros.cpp:407
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
TmcCoeROS::readPDOCallBack
bool readPDOCallBack(adi_tmc_coe::read_write_PDO::Request &req, adi_tmc_coe::read_write_PDO::Response &res)
Definition: tmc_coe_ros.cpp:664
TmcCoeROS::state_change_server_
ros::ServiceServer state_change_server_
Definition: tmc_coe_ros.h:47
uint32_t
unsigned int uint32_t
TmcCoeROS::write_pdo_server_
ros::ServiceServer write_pdo_server_
Definition: tmc_coe_ros.h:45
SDO_PDO_RETRIES_DEFAULT
const uint8_t SDO_PDO_RETRIES_DEFAULT
Definition: tmc_coe_ros.h:19
TmcCoeROS::~TmcCoeROS
~TmcCoeROS()
Definition: tmc_coe_ros.cpp:20
OPERATIONAL
@ OPERATIONAL
Definition: tmc_coe_interpreter.h:22
TmcCoeROS::slave_name_str_
std::vector< std::string > slave_name_str_
Definition: tmc_coe_ros.h:61
TmcCoeInterpreter::getSlaveName
std::string getSlaveName(uint8_t slave_number)
Definition: tmc_coe_interpreter.cpp:658
TmcCoeROS::writePDOCallBack
bool writePDOCallBack(adi_tmc_coe::read_write_PDO::Request &req, adi_tmc_coe::read_write_PDO::Response &res)
Definition: tmc_coe_ros.cpp:560
TIMEOUT_DEFAULT
const uint8_t TIMEOUT_DEFAULT
Definition: tmc_coe_ros.h:22
TmcCoeROS::createMotor
void createMotor()
Definition: tmc_coe_ros.cpp:270
TmcCoeROS::total_slaves_
uint8_t total_slaves_
Definition: tmc_coe_ros.h:51
TmcCoeInterpreter::isCycleFinished
bool isCycleFinished()
Definition: tmc_coe_interpreter.cpp:679
TmcCoeROS::write_sdo_server_
ros::ServiceServer write_sdo_server_
Definition: tmc_coe_ros.h:41
TmcCoeInterpreter::stopCycleCounter
void stopCycleCounter()
Definition: tmc_coe_interpreter.cpp:707
ROS_DEBUG_STREAM_THROTTLE
#define ROS_DEBUG_STREAM_THROTTLE(period, args)
TmcCoeROS::total_motor_vector_
std::vector< uint8_t > total_motor_vector_
Definition: tmc_coe_ros.h:60
tmc_coe_ros.h
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
TmcCoeInterpreter::OPstate
bool OPstate()
Definition: tmc_coe_interpreter.cpp:145
TmcCoeInterpreter::nmt_state_
nmt_state_t nmt_state_
Definition: tmc_coe_interpreter.h:202
CYCLIC_SYNC_POS
@ CYCLIC_SYNC_POS
Definition: tmc_coe_motor.h:22
SAFE_OP
@ SAFE_OP
Definition: tmc_coe_interpreter.h:21
TmcCoeBLDCMotor
Definition: tmc_coe_bldc_motor.h:19
TmcCoeROS::validateAutogenParams
bool validateAutogenParams()
Definition: tmc_coe_ros.cpp:189
TmcCoeMotor
Definition: tmc_coe_motor.h:47
INTERPOLATION_TIME_INDEX_MAX
const uint8_t INTERPOLATION_TIME_INDEX_MAX
Definition: tmc_coe_ros.h:26
ros::this_node::getName
const ROSCPP_DECL std::string & getName()
SDO_PDO_RETRIES_MAX
const uint8_t SDO_PDO_RETRIES_MAX
Definition: tmc_coe_ros.h:21
TmcCoeInterpreter::getCycleCounter
uint8_t getCycleCounter()
Definition: tmc_coe_interpreter.cpp:689
TmcCoeROS::p_nh_
ros::NodeHandle * p_nh_
Definition: tmc_coe_ros.h:63
TmcCoeInterpreter::commandCodingTransition
bool commandCodingTransition(uint8_t slave_number)
Definition: tmc_coe_interpreter.cpp:198
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
Definition: tmc_coe_interpreter.h:148
TmcCoeInterpreter::output_pdo_
std::vector< output_pdo_t * > output_pdo_
Definition: tmc_coe_interpreter.h:201
TmcCoeInterpreter::startCycleCounter
void startCycleCounter()
Definition: tmc_coe_interpreter.cpp:698
TmcCoeROS::deInit
void deInit()
Definition: tmc_coe_ros.cpp:400
TmcCoeROS::param_adhoc_mode_
std::vector< int > param_adhoc_mode_
Definition: tmc_coe_ros.h:58
TmcCoeInterpreter::isInterfaceUnresponsive
bool isInterfaceUnresponsive()
Definition: tmc_coe_interpreter.cpp:718
INIT
@ INIT
Definition: tmc_coe_interpreter.h:19
TmcCoeInterpreter::stopInterface
void stopInterface()
Definition: tmc_coe_interpreter.cpp:253
INTERPOLATION_TIME_INDEX_MIN
const int8_t INTERPOLATION_TIME_INDEX_MIN
Definition: tmc_coe_ros.h:25
ros::Duration::sleep
bool sleep() const
CYCLIC_SYNC_TRQ
@ CYCLIC_SYNC_TRQ
Definition: tmc_coe_motor.h:24
TmcCoeROS::read_sdo_server_
ros::ServiceServer read_sdo_server_
Definition: tmc_coe_ros.h:39
TmcCoeROS::param_en_slave_
std::vector< int > param_en_slave_
Definition: tmc_coe_ros.h:57
TmcCoeStepperMotor
Definition: tmc_coe_stepper_motor.h:19
TmcCoeInterpreter::safeOPstate
bool safeOPstate(std::vector< int > en_slave)
Definition: tmc_coe_interpreter.cpp:90
ros::Duration
TmcCoeROS::writeSDOCallBack
bool writeSDOCallBack(adi_tmc_coe::read_write_SDO::Request &req, adi_tmc_coe::read_write_SDO::Response &res)
Definition: tmc_coe_ros.cpp:532
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
TmcCoeROS::cyclic_sync_server_
ros::ServiceServer cyclic_sync_server_
Definition: tmc_coe_ros.h:49
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
ros::NodeHandle
TmcCoeROS::enFlagsVectorParamCheck
uint8_t enFlagsVectorParamCheck(std::string param_name, std::vector< int > &param_var, uint32_t max_val)
Definition: tmc_coe_ros.cpp:342
TmcCoeROS::param_SDO_PDO_retries_
int param_SDO_PDO_retries_
Definition: tmc_coe_ros.h:55


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