ttl_manager.cpp
Go to the documentation of this file.
1 /*
2  ttl_driver.cpp
3  Copyright (C) 2020 Niryo
4  All rights reserved.
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13  You should have received a copy of the GNU General Public License
14  along with this program. If not, see <http:// www.gnu.org/licenses/>.
15 */
16 
18 
19 // cpp
20 #include <algorithm>
21 #include <cassert>
22 #include <cmath>
23 #include <cstdlib>
24 #include <memory>
25 #include <set>
26 #include <sstream>
27 #include <string>
28 #include <unordered_map>
29 #include <utility>
30 #include <vector>
31 
32 // ros
33 #include "ros/serialization.h"
34 #include "ros/time.h"
35 
36 // niryo
37 #include "common/model/dxl_command_type_enum.hpp"
38 #include "common/model/end_effector_state.hpp"
39 #include "common/model/hardware_type_enum.hpp"
40 #include "common/model/stepper_calibration_status_enum.hpp"
41 #include "common/model/stepper_motor_state.hpp"
42 #include "common/model/tool_state.hpp"
43 
44 
45 #include "dynamixel_sdk/packet_handler.h"
48 
58 #include "ttl_driver/CalibrationStatus.h"
59 
60 using ::std::ostringstream;
61 using ::std::set;
62 using ::std::shared_ptr;
63 using ::std::string;
64 using ::std::to_string;
65 using ::std::vector;
66 
67 using ::common::model::EHardwareType;
68 using ::common::model::EndEffectorState;
69 using ::common::model::EStepperCalibrationStatus;
70 using ::common::model::HardwareTypeEnum;
71 using ::common::model::JointState;
72 using ::common::model::StepperMotorState;
73 using ::common::model::ConveyorState;
74 
75 namespace ttl_driver
76 {
80 TtlManager::TtlManager(ros::NodeHandle &nh) : _nh(nh), _debug_error_message("TtlManager - No connection with TTL motors has been made yet")
81 {
82  ROS_DEBUG("TtlManager - ctor");
83 
84  init(nh);
85 
86  if (COMM_SUCCESS != setupCommunication())
87  ROS_WARN("TtlManager - TTL Communication Failed");
88 }
89 
94 {
95  if (_portHandler)
96  {
97  _portHandler->clearPort();
98  _portHandler->closePort();
99  }
100 }
101 
107 bool TtlManager::init(ros::NodeHandle &nh)
108 {
109  // get params from rosparams
110  bool use_simu_gripper{false};
111  bool use_simu_conveyor{false};
112 
113  nh.getParam("bus_params/uart_device_name", _device_name);
114  nh.getParam("bus_params/baudrate", _baudrate);
115  nh.getParam("led_motor", _led_motor_type_cfg);
116 
117  nh.getParam("simulation_mode", _simulation_mode);
118  nh.getParam("simu_gripper", use_simu_gripper);
119  nh.getParam("simu_conveyor", use_simu_conveyor);
120 
121  ROS_DEBUG("TtlManager::init - Dxl : set port name (%s), baudrate(%d)", _device_name.c_str(), _baudrate);
122  ROS_DEBUG("TtlManager::init - led motor type config : %s", _led_motor_type_cfg.c_str());
123 
124  ROS_DEBUG("TtlManager::init - Simulation mode: %s, simu_gripper: %s, simu_conveyor: %s", _simulation_mode ? "True" : "False", use_simu_gripper ? "True" : "False",
125  use_simu_conveyor ? "True" : "False");
126 
127  if (!_simulation_mode)
128  {
129  _portHandler.reset(dynamixel::PortHandler::getPortHandler(_device_name.c_str()));
130  _packetHandler.reset(dynamixel::PacketHandler::getPacketHandler(TTL_BUS_PROTOCOL_VERSION));
131 
132  // init default ttl driver for common operations between drivers
133  _default_ttl_driver = std::make_shared<StepperDriver<StepperReg>>(_portHandler, _packetHandler);
134  }
135  else
136  {
137  readFakeConfig(use_simu_gripper, use_simu_conveyor);
138  _default_ttl_driver = std::make_shared<MockStepperDriver>(_fake_data);
139  }
140 
141  _calibration_status_publisher = nh.advertise<ttl_driver::CalibrationStatus>("calibration_status", 1, true);
142 
143  return true;
144 }
145 
151 {
152  int ret = COMM_NOT_AVAILABLE;
153 
154  ROS_DEBUG("TtlManager::setupCommunication - initializing connection...");
155 
156  // fake drivers will always succeed for the communication
157  if (_simulation_mode)
158  {
159  ret = COMM_SUCCESS;
160  }
161  else
162  {
163  // Ttl bus setup
164  if (_portHandler)
165  {
166  _debug_error_message.clear();
167 
168  // Open port
169  if (_portHandler->openPort())
170  {
171  // Set baudrate
172  if (_portHandler->setBaudRate(_baudrate))
173  {
174  // wait a bit to be sure the connection is established
175  ros::Duration(0.1).sleep();
176 
177  // clear port
178  _portHandler->clearPort();
179 
180  ret = COMM_SUCCESS;
181  }
182  else
183  {
184  ROS_ERROR("TtlManager::setupCommunication - Failed to set baudrate for Dynamixel bus");
185  _debug_error_message = "TtlManager - Failed to set baudrate for Dynamixel bus";
187  }
188  }
189  else
190  {
191  ROS_ERROR("TtlManager::setupCommunication - Failed to open Uart port for Dynamixel bus");
192  _debug_error_message = "TtlManager - Failed to open Uart port for Dynamixel bus";
193  ret = TTL_FAIL_OPEN_PORT;
194  }
195  }
196  else
197  ROS_ERROR("TtlManager::setupCommunication - Invalid port handler");
198  }
199 
200  return ret;
201 }
202 
207 int TtlManager::addHardwareComponent(std::shared_ptr<common::model::AbstractHardwareState> &&state) // NOLINT
208 {
209  if (!state)
210  {
211  return niryo_robot_msgs::CommandStatus::FAILURE;
212  }
213 
214  EHardwareType hardware_type = state->getHardwareType();
215  uint8_t id = state->getId();
216 
217  ROS_DEBUG("TtlManager::addHardwareComponent : %s", state->str().c_str());
218 
219  addHardwareDriver(hardware_type);
220 
221  auto driver_it = _driver_map.find(hardware_type);
222  if (driver_it == _driver_map.end())
223  {
224  ROS_ERROR("TtlManager::addHardwareComponent - No driver found for hardware type %d", static_cast<int>(hardware_type));
225  return niryo_robot_msgs::CommandStatus::FAILURE;
226  }
227  auto driver = driver_it->second;
228 
229  // check if the driver is valid for this hardware
230  if (state->getStrictModelNumber() && driver->checkModelNumber(id) != COMM_SUCCESS)
231  {
232  ROS_WARN("TtlManager::addHardwareComponent - Model number check failed for hardware id %d", id);
233  return niryo_robot_msgs::CommandStatus::HARDWARE_NOT_SUPPORTED;
234  }
235 
236  // update firmware version
237  std::string version;
238  int res = COMM_RX_FAIL;
239  for (int tries = 10; tries > 0; tries--)
240  {
241  res = driver->readFirmwareVersion(id, version);
242  if (COMM_SUCCESS == res)
243  {
244  state->setFirmwareVersion(version);
245  break;
246  }
247  ros::Duration(0.1).sleep();
248  }
249 
250  if (COMM_SUCCESS != res)
251  {
252  ROS_WARN("TtlManager::addHardwareComponent : Unable to retrieve firmware version for "
253  "hardware id %d : result = %d",
254  id, res);
255  }
256 
257  // add state to state map
258  _state_map[id] = state;
259 
260  // add id to ids_map
261  _ids_map[hardware_type].emplace_back(id);
262 
263  // add to global lists
264  if (common::model::EComponentType::CONVEYOR == state->getComponentType())
265  {
266  if (std::find(_conveyor_list.begin(), _conveyor_list.end(), id) == _conveyor_list.end())
267  _conveyor_list.emplace_back(id);
268  }
269 
270  // Reset the calibration if we add a new joint and it is not a simulated one
271  if (common::model::EComponentType::JOINT == state->getComponentType())
272  {
273  if (!(common::model::EHardwareType::FAKE_STEPPER_MOTOR == hardware_type
274  || common::model::EHardwareType::FAKE_DXL_MOTOR == hardware_type))
275  {
276  _calibration_status = EStepperCalibrationStatus::UNINITIALIZED;
277  }
278  }
279 
281  return niryo_robot_msgs::CommandStatus::SUCCESS;
282 }
283 
289 {
290  ROS_DEBUG("TtlManager::removeMotor - Remove motor id: %d", id);
291 
292  if (_state_map.count(id) && _state_map.at(id))
293  {
294  EHardwareType type = _state_map.at(id)->getHardwareType();
295 
296  // std::remove to remove hypothetic duplicates too
297  if (_ids_map.count(type))
298  {
299  auto &ids = _ids_map.at(type);
300  ids.erase(std::remove(ids.begin(), ids.end(), id), ids.end());
301  if (ids.empty())
302  {
303  _ids_map.erase(type);
304  }
305  }
306 
307  _state_map.erase(id);
308  }
309  // remove id from conveyor list if they contains id
310  _conveyor_list.erase(std::remove(_conveyor_list.begin(), _conveyor_list.end(), id), _conveyor_list.end());
311 
313 }
314 
321 bool TtlManager::isMotorType(EHardwareType type)
322 {
323  // All motors have value under 7 (check in EHardwareType)
324  return (static_cast<int>(type) <= 7);
325 }
326 
327 // ****************
328 // commands
329 // ****************
330 
338 int TtlManager::changeId(EHardwareType motor_type, uint8_t old_id, uint8_t new_id)
339 {
340  int ret = COMM_TX_FAIL;
341 
342  if (old_id == new_id)
343  {
344  ret = COMM_SUCCESS;
345  }
346  else if (_driver_map.count(motor_type))
347  {
348  auto driver = std::dynamic_pointer_cast<AbstractMotorDriver>(_driver_map.at(motor_type));
349 
350  if (driver)
351  {
352  ret = driver->changeId(old_id, new_id);
353  if (COMM_SUCCESS == ret)
354  {
355  // update all maps
356  auto i_state = _state_map.find(old_id);
357  // update all maps
358  if (i_state != _state_map.end())
359  {
360  // insert new_id in map, move i_state->second to its new place
361  std::swap(_state_map[new_id], i_state->second);
362  // update all maps
363  _state_map.erase(i_state);
364 
365  assert(_state_map.at(new_id));
366 
367  // update conveyor list if needed
368  if (common::model::EComponentType::CONVEYOR == _state_map.at(new_id)->getComponentType())
369  {
370  // change old id into new id in vector
371  auto iter = std::find(_conveyor_list.begin(), _conveyor_list.end(), old_id);
372  if (iter != _conveyor_list.end())
373  *iter = new_id;
374  }
375  }
376  if (_ids_map.count(motor_type))
377  {
378  // update all maps
379  _ids_map.at(motor_type).erase(std::remove(_ids_map.at(motor_type).begin(), _ids_map.at(motor_type).end(), old_id), _ids_map.at(motor_type).end());
380 
381  // update all maps
382  _ids_map.at(motor_type).emplace_back(new_id);
383  }
384  }
385  }
386  }
387 
388  return ret;
389 }
390 
396 {
397  ROS_DEBUG("TtlManager::scanAndCheck");
398  int result = COMM_PORT_BUSY;
399 
400  _is_connection_ok = false;
401 
402  // 1. retrieve list of connected motors
403  _all_ids_connected.clear();
404  for (int counter = 0; counter < 50 && COMM_SUCCESS != result; ++counter)
405  {
407  ROS_DEBUG_COND(COMM_SUCCESS != result, "TtlManager::scanAndCheck status: %d (counter: %d)", result, counter);
408  ros::Duration(TIME_TO_WAIT_IF_BUSY).sleep();
409  }
410 
411  if (COMM_SUCCESS == result)
412  {
413  // 2. update list of removed ids and update corresponding states
414  _removed_motor_id_list.clear();
415  std::string error_motors_message;
416  for (auto &istate : _state_map)
417  {
418  if (istate.second)
419  {
420  uint8_t id = istate.first;
421  auto it = find(_all_ids_connected.begin(), _all_ids_connected.end(), id);
422  // not found
423  if (it == _all_ids_connected.end())
424  {
425  _removed_motor_id_list.emplace_back(id);
426  error_motors_message += " " + to_string(id);
427  istate.second->setConnectionStatus(true);
428  }
429  else
430  {
431  istate.second->setConnectionStatus(false);
432  }
433  }
434  }
435 
436  if (_removed_motor_id_list.empty())
437  {
438  _is_connection_ok = true;
439  _debug_error_message.clear();
440  result = TTL_SCAN_OK;
441  }
442  else
443  {
444  _debug_error_message = "Motor(s):" + error_motors_message + " do not seem to be connected";
445  result = TTL_SCAN_MISSING_MOTOR;
446  }
447  }
448  else
449  {
450  _debug_error_message = "TtlManager - Failed to scan motors, physical bus is too busy. Will retry...";
451  ROS_WARN_THROTTLE(1, "TtlManager::scanAndCheck - Failed to scan motors, physical bus is too busy");
452  }
453 
454  return result;
455 }
456 
464 bool TtlManager::ping(uint8_t id)
465 {
466  int result = false;
467 
469  {
470  if (COMM_SUCCESS == _default_ttl_driver->ping(id))
471  result = true;
472  }
473 
474  return result;
475 }
476 
482 int TtlManager::rebootHardware(uint8_t hw_id)
483 {
484  int return_value = COMM_TX_FAIL;
485 
486  if (_state_map.count(hw_id) != 0 && _state_map.at(hw_id))
487  {
488  EHardwareType type = _state_map.at(hw_id)->getHardwareType();
489  ROS_DEBUG("TtlManager::rebootHardware - Reboot hardware with ID: %d", hw_id);
490  if (_driver_map.count(type) && _driver_map.at(type))
491  {
492  return_value = _driver_map.at(type)->reboot(hw_id);
493  if (COMM_SUCCESS == return_value)
494  {
495  std::string version;
496  int res = COMM_RX_FAIL;
497  for (int tries = 10; tries > 0; tries--)
498  {
499  res = _driver_map.at(type)->readFirmwareVersion(hw_id, version);
500  if (COMM_SUCCESS == res)
501  {
502  _state_map.at(hw_id)->setFirmwareVersion(version);
503  break;
504  }
505  ros::Duration(0.1).sleep();
506  }
507 
508  if (COMM_SUCCESS != res)
509  {
510  ROS_WARN("TtlManager::addHardwareComponent : Unable to retrieve firmware version for "
511  "hardware id %d : result = %d",
512  hw_id, res);
513  }
514  }
515  ROS_WARN_COND(COMM_SUCCESS != return_value, "TtlManager::rebootHardware - Failed to reboot hardware: %d", return_value);
516  }
517  }
518 
519  return return_value;
520 }
521 
527 {
528  for (auto const &it : _driver_map)
529  {
530  auto hw_type = it.first;
531  auto driver = std::dynamic_pointer_cast<ttl_driver::AbstractMotorDriver>(it.second);
532 
533  if (driver && _ids_map.count(hw_type) && !_ids_map.at(hw_type).empty())
534  {
535  // we retrieve all the associated id for the type of the current driver
536  vector<uint8_t> ids_list = _ids_map.at(hw_type);
537 
538  auto jStates = getMotorsStates();
539 
540  for (size_t i = 0; i < ids_list.size(); ++i)
541  {
542  auto jState_it = std::find_if(jStates.begin(), jStates.end(), [i](const std::shared_ptr<JointState> &jState){
543  return i == jState->getId();
544  });
545  if (jState_it == jStates.end())
546  {
547  continue;
548  }
549  auto jState = *jState_it;
550  ROS_DEBUG("TtlManager::resetTorques - Torque ON on stepper ID: %d", static_cast<int>(ids_list.at(i)));
551  driver->writeTorquePercentage(ids_list.at(i), jState->getTorquePercentage());
552  } // for ids_list
553  }
554  } // for _driver_map
555 }
556 
557 // ******************
558 // Read operations
559 // ******************
560 
566 uint32_t TtlManager::getPosition(const JointState &motor_state)
567 {
568  uint32_t position = 0;
569  EHardwareType hardware_type = motor_state.getHardwareType();
570  if (_driver_map.count(hardware_type))
571  {
572  auto driver = std::dynamic_pointer_cast<AbstractMotorDriver>(_driver_map.at(hardware_type));
573  if (driver)
574  {
576  {
577  if (COMM_SUCCESS == driver->readPosition(motor_state.getId(), position))
578  {
580  break;
581  }
582  }
583  }
584 
585  if (0 < _hw_fail_counter_read)
586  {
587  ROS_ERROR_THROTTLE(1, "TtlManager::getPosition - motor connection problem - Failed to read from bus");
588  _debug_error_message = "TtlManager - Connection problem with Bus.";
590  _is_connection_ok = false;
591  }
592  }
593  else
594  {
595  ROS_ERROR_THROTTLE(1, "TtlManager::getPosition - Driver not found for requested motor id");
596  _debug_error_message = "TtlManager::getPosition - Driver not found for requested motor id";
597  }
598  return position;
599 }
600 
602 {
603  EHardwareType hw_type(EHardwareType::STEPPER);
604  auto driver = std::dynamic_pointer_cast<ttl_driver::StepperDriver<ttl_driver::StepperReg>>(_driver_map[hw_type]);
605  if (driver && _ids_map.count(hw_type) && !_ids_map.at(hw_type).empty())
606  {
607  // we retrieve all the associated id for the type of the current driver
608  vector<uint8_t> ids_list = _ids_map.at(hw_type);
609 
610  // we retrieve all the associated id for the type of the current driver
611  vector<uint32_t> homing_abs_position_list;
612 
613  // retrieve joint status
614  int res = driver->syncReadHomingAbsPosition(ids_list, homing_abs_position_list);
615  if (COMM_SUCCESS == res)
616  {
617  if (ids_list.size() == homing_abs_position_list.size())
618  {
619  // set motors states accordingly
620  for (size_t i = 0; i < ids_list.size(); ++i)
621  {
622  uint8_t id = ids_list.at(i);
623 
624  if (_state_map.count(id))
625  {
626  auto state = std::dynamic_pointer_cast<common::model::StepperMotorState>(_state_map.at(id));
627  if (state)
628  {
629  state->setHomingAbsPosition(static_cast<uint32_t>(homing_abs_position_list.at(i)));
630  }
631  else
632  {
633  ROS_ERROR("TtlManager::readHomingAbsPosition - null pointer");
634  return false;
635  }
636  }
637  else
638  {
639  ROS_ERROR("TtlManager::readHomingAbsPosition - No hardware state assossiated to ID: %d", static_cast<int>(id));
640  return false;
641  }
642  }
643  }
644  else
645  {
646  ROS_ERROR("TtlManager::readHomingAbsPosition - size of requested id %d mismatch size of retrieved homing position %d", static_cast<int>(ids_list.size()),
647  static_cast<int>(homing_abs_position_list.size()));
648  return false;
649  }
650  }
651  else
652  {
653  ROS_ERROR("TtlManager::readHomingAbsPosition - communication error: %d", static_cast<int>(res));
654  return false;
655  }
656  }
657  else
658  {
659  ROS_ERROR("TtlManager::readHomingAbsPosition - null pointer or no hardware type in map %d or empty vector of ids: %d", static_cast<int>(_ids_map.count(hw_type)),
660  static_cast<int>(_ids_map.at(hw_type).empty()));
661  return false;
662  }
663 
664  return true;
665 }
666 
672 {
673  uint8_t hw_errors_increment = 0;
674 
675  // syncread position for all motors.
676  // for ned and one -> we need at least one xl430 and one xl320 drivers as they are different
677 
678  for (auto const &it : _driver_map)
679  {
680  auto hw_type = it.first;
681  auto driver = std::dynamic_pointer_cast<ttl_driver::AbstractMotorDriver>(it.second);
682 
683  if (!driver)
684  {
685  continue;
686  }
687  auto id_list_it = _ids_map.find(hw_type);
688  if (id_list_it == _ids_map.end())
689  {
690  continue;
691  }
692  auto ids_list = id_list_it->second;
693 
694  if (ids_list.empty())
695  {
696  continue;
697  }
698 
699  // we retrieve all the associated id for the type of the current driver
700  _position_list.clear();
701 
702  // retrieve joint status
703  int res = driver->syncReadPosition(ids_list, _position_list);
704  if (COMM_SUCCESS == res)
705  {
706  if (ids_list.size() == _position_list.size())
707  {
708  // set motors states accordingly
709  for (size_t i = 0; i < ids_list.size(); ++i)
710  {
711  uint8_t id = ids_list.at(i);
712 
713  if (_state_map.count(id))
714  {
715  auto state = std::dynamic_pointer_cast<common::model::AbstractMotorState>(_state_map.at(id));
716  if (state)
717  {
718  state->setPosition(static_cast<int>((_position_list.at(i))));
719  }
720  }
721  }
722  }
723  else
724  {
725  // warn to avoid sound and light error on high level (error on ROS_ERROR)
726  ROS_WARN("TtlManager::readJointStatus : Fail to sync read joint state - "
727  "vector mismatch (id_list size %d, position_list size %d)",
728  static_cast<int>(ids_list.size()), static_cast<int>(_position_list.size()));
729  hw_errors_increment++;
730  }
731  }
732  else
733  {
734  // debug to avoid sound and light error on high level (error on ROS_ERROR)
735  // also for Ned which has much more errors on XL320 motor
736  ROS_DEBUG("TtlManager::readJointStatus : Fail to sync read joint state - "
737  "driver fail to syncReadPosition");
738  hw_errors_increment++;
739  }
740  } // for driver_map
741 
742  // check collision by END_EFFECTOR
743  if (_isRealCollision)
744  {
746  }
747  else
748  {
749  _collision_status = false;
750  // check collision by END_EFFECTOR
751  if (_isRealCollision)
752  {
753  checkCollision();
754  }
755  else
756  {
757  _collision_status = false;
758  }
759  }
760 
761  ROS_DEBUG_THROTTLE(2, "_hw_fail_counter_read, hw_errors_increment: %d, %d", _hw_fail_counter_read, hw_errors_increment);
762 
763  // we reset the global error variable only if no errors
764  if (0 == hw_errors_increment)
765  {
767  }
768  else
769  {
770  _hw_fail_counter_read += hw_errors_increment;
771  }
772 
773  return (0 == hw_errors_increment);
774 }
775 
781 {
782  bool res = false;
783 
784  // hardware_version is not available within this class to know whether there is a ned2/ned3pro eef
785  // however if hardware_type == ned2 _driver_map will contain EHardwareType::END_EFFECTOR
786  // and if hardware_type == ned3pro _driver_map will contain EHardwareType::NED3PRO_END_EFFECTOR
787  EHardwareType ee_type;
788 
789  if (_simulation_mode)
790  ee_type = EHardwareType::FAKE_END_EFFECTOR;
791  else if (_driver_map.count(EHardwareType::END_EFFECTOR))
792  ee_type = EHardwareType::END_EFFECTOR;
793  else if (_driver_map.count(EHardwareType::NED3PRO_END_EFFECTOR))
794  ee_type = EHardwareType::NED3PRO_END_EFFECTOR;
795 
796 
797  if (_driver_map.count(ee_type))
798  {
799  unsigned int hw_errors_increment = 0;
800 
801  auto driver = std::dynamic_pointer_cast<AbstractEndEffectorDriver>(_driver_map.at(ee_type));
802  if (driver)
803  {
804  if (_ids_map.count(ee_type) && !_ids_map.at(ee_type).empty())
805  {
806  uint8_t id = _ids_map.at(ee_type).front();
807 
808  if (_state_map.count(id))
809  {
810  // we retrieve the associated id for the end effector
811  auto state = std::dynamic_pointer_cast<EndEffectorState>(_state_map[id]);
812 
813  if (state)
814  {
815  vector<common::model::EActionType> action_list;
816 
817  // ********** buttons
818  // get action of free driver button, save pos button, custom button
819  if (COMM_SUCCESS == driver->syncReadButtonsStatus(id, action_list))
820  {
821  for (uint8_t i = 0; i < action_list.size(); i++)
822  {
823  state->setButtonStatus(i, action_list.at(i));
824  // In case free driver button, it we hold this button, normally, because of the small threshold of collision detection
825  // this action make EE confuse that it is a collision. That's why when we hold buttons, we need to deactivate the detection of collision.
826  if (action_list.at(i) != common::model::EActionType::NO_ACTION)
827  {
828  _isRealCollision = false;
829  }
830  else if (!_isRealCollision)
831  {
832  // when previous action is not no_action => need to wait a short period to make sure no collision detected
833  // Note, we need to read one time the status of collision just after releasing button to reset the status.
834  _isRealCollision = true;
835  _isWrongAction = true;
836  _last_collision_detection_activating = ros::Time::now().toSec();
837  }
838  }
839  }
840  else
841  {
842  hw_errors_increment++;
843  }
844 
845  // ********** digital data
846  bool digital_data{};
847  if (COMM_SUCCESS == driver->readDigitalInput(id, digital_data))
848  {
849  state->setDigitalIn(digital_data);
850  }
851  else
852  {
853  hw_errors_increment++;
854  }
855  } // if (state)
856  }
857  } // if (_ids_map.count(EHardwareType::END_EFFECTOR))
858  } // if (driver)
859 
860  // we reset the global error variable only if no errors
861  if (0 == hw_errors_increment)
862  {
864  _debug_error_message.clear();
865 
866  res = true;
867  }
868  else
869  {
870  ROS_DEBUG_COND(_end_effector_fail_counter_read > 10, "TtlManager::readEndEffectorStatus: nb error > 10 : %d", _end_effector_fail_counter_read);
871  _end_effector_fail_counter_read += hw_errors_increment;
872  }
873 
875  {
876  ROS_ERROR("TtlManager::readEndEffectorStatus - motor connection problem - Failed to read from bus (hw_fail_counter_read : %d)", _end_effector_fail_counter_read);
878  _debug_error_message = "TtlManager - Connection problem with physical Bus.";
879  }
880  }
881 
882  return res;
883 }
884 
891 {
892  bool res = false;
893 
894  // hardware_version is not available within this class to know whether there is a ned2/ned3pro eef
895  // however if hardware_type == ned2 _driver_map will contain EHardwareType::END_EFFECTOR
896  // and if hardware_type == ned3pro _driver_map will contain EHardwareType::NED3PRO_END_EFFECTOR
897  EHardwareType ee_type;
898 
899  if (_simulation_mode)
900  ee_type = EHardwareType::FAKE_END_EFFECTOR;
901  else if (_driver_map.count(EHardwareType::END_EFFECTOR))
902  ee_type = EHardwareType::END_EFFECTOR;
903  else if (_driver_map.count(EHardwareType::NED3PRO_END_EFFECTOR))
904  ee_type = EHardwareType::NED3PRO_END_EFFECTOR;
905 
906  if (_driver_map.count(ee_type))
907  {
908  unsigned int hw_errors_increment = 0;
909 
910  auto driver = std::dynamic_pointer_cast<AbstractEndEffectorDriver>(_driver_map.at(ee_type));
911  if (driver)
912  {
913  if (_ids_map.count(ee_type) && !_ids_map.at(ee_type).empty())
914  {
915  uint8_t id = _ids_map.at(ee_type).front();
916 
917  // ********** collision
918  // not accept other status of collistion in 1 second if it detected a collision
920  {
921  bool last_statut = _collision_status;
922  if (COMM_SUCCESS == driver->readCollisionStatus(id, _collision_status))
923  {
924  if (last_statut == _collision_status && _collision_status)
925  {
926  // if we have a collision, we will publish the statut collision only once
927  // This avoid that the delay in reading statut influent to next movement.
928  _collision_status = false;
929  }
930  else if (_collision_status)
931  {
932  if (_isWrongAction)
933  {
934  // if an action did a wrong detection of collision, we need to read once to reset the status
935  _isWrongAction = false;
936  _collision_status = false;
937  }
938  else
939  _last_collision_detection_activating = ros::Time::now().toSec();
940  }
941  }
942  else
943  {
944  hw_errors_increment++;
945  }
946  }
947  else if (ros::Time::now().toSec() - _last_collision_detection_activating >= 1.0)
948  {
950  }
951  } // if (_ids_map.count(EHardwareType::END_EFFECTOR))
952  } // if (driver)
953 
954  // we reset the global error variable only if no errors
955  if (0 == hw_errors_increment)
956  {
958  res = true;
959  }
960  else
961  {
962  ROS_DEBUG_COND(_end_effector_fail_counter_read > 10, "TtlManager::checkCollision: nb error > 10 : %d", _end_effector_fail_counter_read);
963  _end_effector_fail_counter_read += hw_errors_increment;
964  }
965  }
966  return res;
967 }
968 
974 {
975  bool res = false;
976 
977  // hardware_version is not available within this class to know whether there is a ned2/ned3pro eef
978  // however if hardware_type == ned2 _driver_map will contain EHardwareType::END_EFFECTOR
979  // and if hardware_type == ned3pro _driver_map will contain EHardwareType::NED3PRO_END_EFFECTOR
980  EHardwareType ee_type;
981 
982  if (_simulation_mode)
983  ee_type = EHardwareType::FAKE_END_EFFECTOR;
984  else if (_driver_map.count(EHardwareType::END_EFFECTOR))
985  ee_type = EHardwareType::END_EFFECTOR;
986  else if (_driver_map.count(EHardwareType::NED3PRO_END_EFFECTOR))
987  ee_type = EHardwareType::NED3PRO_END_EFFECTOR;
988 
989  if (_driver_map.count(ee_type))
990  {
991  auto driver = std::dynamic_pointer_cast<AbstractEndEffectorDriver>(_driver_map.at(ee_type));
992 
993  if (driver)
994  {
995  if (_ids_map.count(ee_type) && !_ids_map.at(ee_type).empty())
996  {
997  uint8_t id = _ids_map.at(ee_type).front();
998 
999  // ********** collision
1000  // don't accept other status of collistion in 1 second if it detected a collision
1002  {
1003  if (COMM_SUCCESS == driver->readCollisionStatus(id, _collision_status))
1004  {
1005  res = true;
1006 
1007  if (_collision_status)
1008  {
1009  if (_isWrongAction)
1010  {
1011  // if an action did a wrong detection of collision, we need to read once to reset the status
1012  _isWrongAction = false;
1013  _collision_status = false;
1014  }
1015  else
1016  {
1017  _last_collision_detection_activating = ros::Time::now().toSec();
1018  }
1019  }
1020  }
1021  else
1022  {
1024  }
1025  }
1026  else if (ros::Time::now().toSec() - _last_collision_detection_activating >= 1.0)
1027  {
1029  }
1030  }
1031  }
1032  }
1033 
1034  return res;
1035 }
1036 
1041 {
1042  bool res = false;
1043 
1044  unsigned int hw_errors_increment = 0;
1045 
1046  // take all hw status dedicated drivers
1047  for (auto const &it : _driver_map)
1048  {
1049  auto type = it.first;
1050  auto driver = it.second;
1051 
1052  if (driver && _ids_map.count(type) && !_ids_map.at(type).empty())
1053  {
1054  // we retrieve all the associated id for the type of the current driver
1055  vector<uint8_t> ids_list = _ids_map.at(type);
1056 
1057  // 1. syncread for all motors
1058  // ********** voltage and Temperature
1059  vector<std::pair<double, uint8_t>> hw_data_list;
1060 
1061  if (COMM_SUCCESS != driver->syncReadHwStatus(ids_list, hw_data_list))
1062  {
1063  // this operation can fail, it is normal, so no error message
1064  hw_errors_increment++;
1065  }
1066  else if (ids_list.size() != hw_data_list.size())
1067  {
1068  // however, if we have a mismatch here, it is not normal
1069  ROS_ERROR("TtlManager::readHardwareStatusOptimized : syncReadHwStatus failed - "
1070  "vector mistmatch (id_list size %d, hw_data_list size %d)",
1071  static_cast<int>(ids_list.size()), static_cast<int>(hw_data_list.size()));
1072 
1073  hw_errors_increment++;
1074  }
1075 
1076  // ********** error state
1077  vector<uint8_t> hw_error_status_list;
1078 
1079  if (COMM_SUCCESS != driver->syncReadHwErrorStatus(ids_list, hw_error_status_list))
1080  {
1081  hw_errors_increment++;
1082  }
1083  else if (ids_list.size() != hw_error_status_list.size())
1084  {
1085  ROS_ERROR("TtlManager::readHardwareStatus : syncReadTemperature failed - "
1086  "vector mistmatch (id_list size %d, hw_status_list size %d)",
1087  static_cast<int>(ids_list.size()), static_cast<int>(hw_error_status_list.size()));
1088 
1089  hw_errors_increment++;
1090  }
1091 
1092  // 2. set motors states accordingly
1093  for (size_t i = 0; i < ids_list.size(); ++i)
1094  {
1095  uint8_t id = ids_list.at(i);
1096 
1097  if (_state_map.count(id) && _state_map.at(id))
1098  {
1099  auto state = _state_map.at(id);
1100 
1101  // ************** temperature and voltage
1102  if (hw_data_list.size() > i)
1103  {
1104  double voltage = (hw_data_list.at(i)).first;
1105  uint8_t temperature = (hw_data_list.at(i)).second;
1106 
1107  state->setTemperature(temperature);
1108  state->setRawVoltage(voltage);
1109  }
1110 
1111  // ********** error state
1112  if (hw_error_status_list.size() > i)
1113  {
1114  state->setHardwareError(hw_error_status_list.at(i));
1115  }
1116 
1117  // interpret any error code into message (even if not retrieved now)
1118  string hardware_message = driver->interpretErrorState(state->getHardwareError());
1119  state->setHardwareError(hardware_message);
1120  }
1121  } // for ids_list
1122  } // if driver
1123  } // for (auto it : _hw_status_driver_map)
1124 
1125  // ********** steppers related informations (conveyor and calibration)
1126  hw_errors_increment += readSteppersStatus();
1127 
1128  // we reset the global error variable only if no errors
1129  if (0 == hw_errors_increment)
1130  {
1132  _debug_error_message.clear();
1133 
1134  res = true;
1135  }
1136  else
1137  {
1138  _hw_fail_counter_read += hw_errors_increment;
1139  }
1140 
1141  // if too much errors, disconnect
1143  {
1144  ROS_ERROR_THROTTLE(1,
1145  "TtlManager::readHardwareStatus - motor connection problem - "
1146  "Failed to read from bus (hw_fail_counter_read : %d)",
1149  res = false;
1150  _is_connection_ok = false;
1151  _debug_error_message = "TtlManager - Connection problem with physical Bus.";
1152  }
1153 
1154  return res;
1155 }
1156 
1162 {
1163  uint8_t hw_errors_increment = 0;
1164 
1165  // take all hw status dedicated drivers
1166  auto [stepper_joint_driver, hw_type] = getJointsStepperDriver();
1167  if (stepper_joint_driver)
1168  {
1169  if (hw_type == EHardwareType::STEPPER || hw_type == EHardwareType::FAKE_STEPPER_MOTOR )
1170  {
1171  // 1. read calibration status if needed
1172 
1173  // we want to check calibration (done at startup and when calibration is started)
1175  {
1176  // When calibration is running, sometimes at an unexpected position, calibration make EE thinks that there is a collision
1177  // Have to disable the feature collision detection in this period
1178  _isRealCollision = false;
1179 
1180  vector<uint8_t> id_list = _ids_map.at(hw_type);
1181  vector<uint8_t> stepper_id_list;
1182  std::copy_if(id_list.begin(), id_list.end(), std::back_inserter(stepper_id_list),
1183  [this](uint8_t id) { return _state_map[id] && _state_map.at(id)->getComponentType() != common::model::EComponentType::CONVEYOR; });
1184 
1185  /* Truth Table
1186  * still_in_progress | state | new state
1187  * 0 | IDLE = IDLE
1188  * 0 | START = START
1189  * 0 | PROG > UPDAT
1190  * 0 | UPDAT R IDLE
1191  * 1 | IDLE = IDLE
1192  * 1 | START > PROG
1193  * 1 | PROG = PROG
1194  * 1 | UPDAT = UPDAT
1195  */
1196 
1197  // *********** calibration status, only if initialized
1198  std::vector<uint8_t> homing_status_list;
1199  if (COMM_SUCCESS == stepper_joint_driver->syncReadHomingStatus(stepper_id_list, homing_status_list))
1200  {
1201  if (stepper_id_list.size() == homing_status_list.size())
1202  {
1203  // max status need to be kept not converted into EStepperCalibrationStatus because max status is "in progress" in the enum
1204  int max_status = -1;
1205 
1206  // debug only
1207  std::ostringstream ss_debug;
1208  ss_debug << "homing status : ";
1209 
1210  bool still_in_progress = false;
1211 
1212  // set states accordingly
1213  for (size_t i = 0; i < homing_status_list.size(); ++i)
1214  {
1215  uint8_t id = stepper_id_list.at(i);
1216  ss_debug << static_cast<int>(homing_status_list.at(i)) << ", ";
1217 
1218  if (_state_map.count(id))
1219  {
1220  EStepperCalibrationStatus status = stepper_joint_driver->interpretHomingData(homing_status_list.at(i));
1221 
1222  // set status in state
1223  auto stepperState = std::dynamic_pointer_cast<StepperMotorState>(_state_map.at(id));
1224  if (stepperState && !stepperState->isConveyor())
1225  {
1226  stepperState->setCalibration(status, 1);
1227 
1228  // get max status of all motors (to retrieve potential errors)
1229  // carefull to those possible cases :
1230  // 1, 1, 1
1231  // 1, 2, 1
1232  // 0, 2, 2
1233  // 2, 0, 2
1234 
1235  // if 0, uninitialized, else, take max
1236  // we need to keep the status unconverted to have the correct order
1237  if (0 != max_status && homing_status_list.at(i) > max_status)
1238  max_status = homing_status_list.at(i);
1239 
1240  // if one status is in progress or uinitialized, we are really in progress
1241  if ((0 == homing_status_list.at(i)) || EStepperCalibrationStatus::IN_PROGRESS == status)
1242  {
1243  still_in_progress = true;
1244  }
1245  }
1246  }
1247  } // for homing_status_list
1248 
1249  ss_debug << " => max_status: " << static_cast<int>(max_status);
1250 
1251  ROS_DEBUG_THROTTLE(2.0, "TtlManager::readCalibrationStatus : %s", ss_debug.str().c_str());
1252 
1253  // see truth table above
1254  // timeout is here to prevent being stuck here if retrying calibration when already at the butee (then the system has no time to switch to "in progress"
1255  // before "ok" or "error"
1256  if ((!still_in_progress && CalibrationMachineState::State::IN_PROGRESS == _calib_machine_state.status()) ||
1258  (!still_in_progress && _calib_machine_state.isTimeout()))
1259  {
1261  }
1262 
1263  // see truth table above
1265  {
1266  _calibration_status = stepper_joint_driver->interpretHomingData(static_cast<uint8_t>(max_status));
1268 
1269  // In this CalibrationMachineState, the calibration is considered as finished => can activate collision detection here
1270  // we need to wait a short period to make sure no collision detected
1271  // calibration make a wrong collision, so we have to read the collision status once time to reset it.
1272  _isWrongAction = true;
1273  _isRealCollision = true;
1274  _last_collision_detection_activating = ros::Time::now().toSec();
1275  }
1276  }
1277  else
1278  {
1279  ROS_ERROR("TtlManager::readCalibrationStatus : syncReadHomingStatus failed - "
1280  "vector mistmatch (id_list size %d, homing_status_list size %d)",
1281  static_cast<int>(stepper_id_list.size()), static_cast<int>(homing_status_list.size()));
1282 
1283  hw_errors_increment++;
1284  }
1285  }
1286  else
1287  {
1288  hw_errors_increment++;
1289  }
1290  } // if (_driver_map.count(hw_type) && _driver_map.at(hw_type))
1291  }
1292  else if (hw_type == EHardwareType::NED3PRO_STEPPER)
1293  {
1294  hw_errors_increment = readNed3ProSteppersStatus();
1295  }
1296 
1297  // 2. read conveyors states if has
1298  for (auto &conveyor_state : getConveyorsStates())
1299  {
1300  auto conveyor_id = conveyor_state->getId();
1301  auto conveyor_hw_type = conveyor_state->getHardwareType();
1302  auto conveyor_driver = std::dynamic_pointer_cast<ttl_driver::AbstractStepperDriver>(_driver_map[conveyor_hw_type]);
1303  int32_t conveyor_speed_percent = 0;
1304  int32_t direction = 0;
1305  if (COMM_SUCCESS == conveyor_driver->readConveyorVelocity(conveyor_id, conveyor_speed_percent, direction))
1306  {
1307  conveyor_state->setGoalDirection(direction);
1308  conveyor_state->setSpeed(conveyor_speed_percent);
1309  conveyor_state->setState(conveyor_speed_percent);
1310  }
1311  else
1312  {
1313  hw_errors_increment++;
1314  }
1315  }
1316  }
1317 
1318  ROS_DEBUG_THROTTLE(2.0, "TtlManager::readCalibrationStatus: _calibration_status: %s", common::model::StepperCalibrationStatusEnum(_calibration_status).toString().c_str());
1319  ROS_DEBUG_THROTTLE(2.0, "TtlManager::readCalibrationStatus: _calib_machine_state: %d", static_cast<int>(_calib_machine_state.status()));
1320 
1321  return hw_errors_increment;
1322 }
1323 
1325 {
1326  uint8_t hw_errors_increment = 0;
1327 
1328  EHardwareType hw_type = EHardwareType::NED3PRO_STEPPER;
1329 
1330  // 1. read calibration status if needed
1331 
1332  // we want to check calibration (done at startup and when calibration is started)
1334  {
1335  // When calibration is running, sometimes at an unexpected position, calibration make EE thinks that
1336  // there is a collision Have to disable the feature collision detection in this period
1337  _isRealCollision = false;
1338 
1339  vector<uint8_t> id_list = _ids_map.at(hw_type);
1340  vector<uint8_t> stepper_id_list;
1341  std::copy_if(id_list.begin(), id_list.end(), std::back_inserter(stepper_id_list), [this](uint8_t id) {
1342  return _state_map[id] &&
1343  _state_map.at(id)->getComponentType() != common::model::EComponentType::CONVEYOR;
1344  });
1345 
1346  // *********** calibration status, only if initialized
1347  auto [stepper_joint_driver, hw_type] = getJointsStepperDriver();
1348  std::vector<uint8_t> homing_status_list;
1349  if (stepper_joint_driver &&
1350  COMM_SUCCESS == stepper_joint_driver->syncReadHomingStatus(stepper_id_list, homing_status_list))
1351  {
1352  if (stepper_id_list.size() == homing_status_list.size())
1353  {
1354  // TODO(i.ambit) publish calibration message
1355  ttl_driver::CalibrationStatus calibration_status_msg;
1356 
1357  EStepperCalibrationStatus highest_priority_status = EStepperCalibrationStatus::UNINITIALIZED;
1358  // set states accordingly
1359  for (size_t i = 0; i < homing_status_list.size(); ++i)
1360  {
1361  uint8_t id = stepper_id_list.at(i);
1362 
1363  if (_state_map.count(id))
1364  {
1365  // set status in state
1366  auto stepperState = std::dynamic_pointer_cast<StepperMotorState>(_state_map.at(id));
1367  if (stepperState && !stepperState->isConveyor())
1368  {
1369  auto status = stepper_joint_driver->interpretHomingData(homing_status_list.at(i));
1370  stepperState->setCalibration(status, 1);
1371 
1372  if (status > highest_priority_status)
1373  highest_priority_status = status;
1374 
1375  calibration_status_msg.ids.push_back(id);
1376 
1377  switch (status)
1378  {
1379  case EStepperCalibrationStatus::IN_PROGRESS:
1380  calibration_status_msg.status.push_back(ttl_driver::CalibrationStatus::CALIBRATING);
1381  break;
1382  case EStepperCalibrationStatus::OK:
1383  calibration_status_msg.status.push_back(ttl_driver::CalibrationStatus::CALIBRATED);
1384  break;
1385  case EStepperCalibrationStatus::FAIL:
1386  calibration_status_msg.status.push_back(ttl_driver::CalibrationStatus::CALIBRATION_ERROR);
1387  break;
1388  default:
1389  calibration_status_msg.status.push_back(ttl_driver::CalibrationStatus::CALIBRATION_ERROR);
1390  break;
1391  }
1392 
1393  _calibration_status_publisher.publish(calibration_status_msg);
1394  }
1395  }
1396  } // for homing_status_list
1397  _calibration_status = highest_priority_status;
1398  }
1399  else
1400  {
1401  ROS_ERROR("TtlManager::readCalibrationStatus : syncReadHomingStatus failed - "
1402  "vector mistmatch (id_list size %d, homing_status_list size %d)",
1403  static_cast<int>(stepper_id_list.size()), static_cast<int>(homing_status_list.size()));
1404 
1405  hw_errors_increment++;
1406  }
1407  }
1408  else
1409  {
1410  hw_errors_increment++;
1411  }
1412  } // if (_driver_map.count(hw_type) && _driver_map.at(hw_type))
1413 
1414  return hw_errors_increment;
1415 }
1416 
1424 int TtlManager::getAllIdsOnBus(vector<uint8_t> &id_list)
1425 {
1426  int result = COMM_RX_FAIL;
1427 
1428  // 1. Get all ids from ttl bus. We can use any driver for that
1429  if (_default_ttl_driver)
1430  {
1431  vector<uint8_t> l_idList;
1432  result = _default_ttl_driver->scan(l_idList);
1433  id_list.insert(id_list.end(), l_idList.begin(), l_idList.end());
1434 
1435  string ids_str;
1436  for (auto const &id : l_idList)
1437  ids_str += to_string(id) + " ";
1438 
1439  ROS_DEBUG_THROTTLE(1, "TtlManager::getAllIdsOnTtlBus - Found ids (%s) on bus using default driver", ids_str.c_str());
1440 
1441  if (COMM_SUCCESS != result)
1442  {
1443  if (COMM_RX_TIMEOUT != result)
1444  { // -3001
1445  _debug_error_message = "TtlManager - No motor found. "
1446  "Make sure that motors are correctly connected and powered on.";
1447  }
1448  else
1449  { // -3002 or other
1450  _debug_error_message = "TtlManager - Failed to scan bus.";
1451  }
1452  ROS_WARN_THROTTLE(1,
1453  "TtlManager::getAllIdsOnTtlBus - Broadcast ping failed, "
1454  "result : %d (-3001: timeout, -3002: corrupted packet)",
1455  result);
1456  }
1457  }
1458  else
1459  {
1460  // if no driver, no motors on bus, it is not a failure of scan
1461  result = COMM_SUCCESS;
1462  }
1463 
1464  return result;
1465 }
1466 
1467 // ******************
1468 // Write operations
1469 // ******************
1470 
1477 {
1478  _led_state = led;
1479  int ret = niryo_robot_msgs::CommandStatus::TTL_WRITE_ERROR;
1480 
1481  EHardwareType mType = HardwareTypeEnum(_led_motor_type_cfg.c_str());
1482 
1483  if (mType == EHardwareType::FAKE_DXL_MOTOR)
1484  return niryo_robot_msgs::CommandStatus::SUCCESS;
1485 
1486  // get list of motors of the given type
1487  vector<uint8_t> id_list;
1488  if (_ids_map.count(mType) && _driver_map.count(mType))
1489  {
1490  id_list = _ids_map.at(mType);
1491 
1492  auto driver = std::dynamic_pointer_cast<AbstractDxlDriver>(_driver_map.at(mType));
1493  if (driver)
1494  {
1495  // sync write led state
1496  vector<uint8_t> command_led_value(id_list.size(), static_cast<uint8_t>(led));
1497  if (0 <= led && 7 >= led)
1498  {
1499  int result = COMM_TX_FAIL;
1500  for (int error_counter = 0; result != COMM_SUCCESS && error_counter < 5; ++error_counter)
1501  {
1502  ros::Duration(TIME_TO_WAIT_IF_BUSY).sleep();
1503  result = driver->syncWriteLed(id_list, command_led_value);
1504  }
1505 
1506  if (COMM_SUCCESS == result)
1507  ret = niryo_robot_msgs::CommandStatus::SUCCESS;
1508  else
1509  ROS_WARN("TtlManager::setLeds - Failed to write LED");
1510  }
1511  }
1512  else
1513  {
1514  ROS_DEBUG("Set leds failed. Driver is not compatible, check the driver's implementation ");
1515  return niryo_robot_msgs::CommandStatus::FAILURE;
1516  }
1517  }
1518  else
1519  {
1520  ROS_DEBUG("Set leds failed. It is maybe that this service is not support for this product");
1521  ret = niryo_robot_msgs::CommandStatus::SUCCESS;
1522  }
1523 
1524  return ret;
1525 }
1526 
1535 int TtlManager::sendCustomCommand(uint8_t id, int reg_address, int value, int byte_number)
1536 {
1537  int result = COMM_TX_FAIL;
1538  ROS_DEBUG("TtlManager::sendCustomCommand:\n"
1539  "\t\t ID: %d, Value: %d, Address: %d, Size: %d",
1540  static_cast<int>(id), value, reg_address, byte_number);
1541 
1542  if (_state_map.count(id) != 0 && _state_map.at(id))
1543  {
1544  EHardwareType motor_type = _state_map.at(id)->getHardwareType();
1545 
1546  if (motor_type == EHardwareType::STEPPER || motor_type == EHardwareType::FAKE_STEPPER_MOTOR) {
1547  return niryo_robot_msgs::CommandStatus::SUCCESS;
1548  }
1549 
1550  if (_driver_map.count(motor_type) && _driver_map.at(motor_type))
1551  {
1552  int32_t value_conv = value;
1553  result = _driver_map.at(motor_type)->writeCustom(static_cast<uint16_t>(reg_address), static_cast<uint8_t>(byte_number), id, static_cast<uint32_t>(value_conv));
1554  if (result != COMM_SUCCESS)
1555  {
1556  ROS_WARN("TtlManager::sendCustomCommand - Failed to write custom command: %d", result);
1557  // TODO(Thuc): change TTL_WRITE_ERROR -> WRITE_ERROR
1558  result = niryo_robot_msgs::CommandStatus::TTL_WRITE_ERROR;
1559  }
1560  }
1561  else
1562  {
1563  ROS_ERROR_THROTTLE(1, "TtlManager::sendCustomCommand - driver for motor %s not available", HardwareTypeEnum(motor_type).toString().c_str());
1564  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1565  }
1566  }
1567  else
1568  {
1569  ROS_ERROR_THROTTLE(1, "TtlManager::sendCustomCommand - driver for motor id %d unknown", static_cast<int>(id));
1570  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1571  }
1572 
1573  ros::Duration(0.005).sleep();
1574  return result;
1575 }
1576 
1585 int TtlManager::readCustomCommand(uint8_t id, int32_t reg_address, int &value, int byte_number)
1586 {
1587  int result = COMM_RX_FAIL;
1588  ROS_DEBUG("TtlManager::readCustomCommand: ID: %d, Address: %d, Size: %d", static_cast<int>(id), static_cast<int>(reg_address), byte_number);
1589 
1590  if (_state_map.count(id) != 0 && _state_map.at(id))
1591  {
1592  EHardwareType motor_type = _state_map.at(id)->getHardwareType();
1593 
1594  if (_driver_map.count(motor_type) && _driver_map.at(motor_type))
1595  {
1596  uint32_t data = 0;
1597  result = _driver_map.at(motor_type)->readCustom(static_cast<uint16_t>(reg_address), static_cast<uint8_t>(byte_number), id, data);
1598  auto data_conv = static_cast<int32_t>(data);
1599  value = data_conv;
1600 
1601  if (result != COMM_SUCCESS)
1602  {
1603  ROS_WARN("TtlManager::readCustomCommand - Failed to read custom command: %d", result);
1604  result = niryo_robot_msgs::CommandStatus::TTL_READ_ERROR;
1605  }
1606  }
1607  else
1608  {
1609  ROS_ERROR_THROTTLE(1, "TtlManager::readCustomCommand - driver for motor %s not available", HardwareTypeEnum(motor_type).toString().c_str());
1610  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1611  }
1612  }
1613  else
1614  {
1615  ROS_ERROR_THROTTLE(1, "TtlManager::readCustomCommand - driver for motor id %d unknown", static_cast<int>(id));
1616  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1617  }
1618 
1619  ros::Duration(0.005).sleep();
1620  return result;
1621 }
1622 
1635 int TtlManager::readMotorPID(uint8_t id, uint16_t &pos_p_gain, uint16_t &pos_i_gain, uint16_t &pos_d_gain, uint16_t &vel_p_gain, uint16_t &vel_i_gain, uint16_t &ff1_gain,
1636  uint16_t &ff2_gain)
1637 {
1638  int result = COMM_RX_FAIL;
1639 
1640  if (_state_map.count(id) != 0 && _state_map.at(id))
1641  {
1642  EHardwareType motor_type = _state_map.at(id)->getHardwareType();
1643 
1644  if (_driver_map.count(motor_type))
1645  {
1646  auto driver = std::dynamic_pointer_cast<AbstractDxlDriver>(_driver_map.at(motor_type));
1647  if (driver)
1648  {
1649  std::vector<uint16_t> data;
1650  result = driver->readPID(id, data);
1651 
1652  if (COMM_SUCCESS == result)
1653  {
1654  pos_p_gain = data.at(0);
1655  pos_i_gain = data.at(1);
1656  pos_d_gain = data.at(2);
1657  vel_p_gain = data.at(3);
1658  vel_i_gain = data.at(4);
1659  ff1_gain = data.at(5);
1660  ff2_gain = data.at(6);
1661  }
1662  else
1663  {
1664  ROS_WARN("TtlManager::readMotorPID - Failed to read PID: %d", result);
1665  result = niryo_robot_msgs::CommandStatus::TTL_READ_ERROR;
1666  return result;
1667  }
1668  }
1669  }
1670  else
1671  {
1672  ROS_ERROR_THROTTLE(1, "TtlManager::readMotorPID - driver for motor %s not available", HardwareTypeEnum(motor_type).toString().c_str());
1673  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1674  }
1675  }
1676  else
1677  {
1678  ROS_ERROR_THROTTLE(1, "TtlManager::readMotorPID - driver for motor id %d unknown", static_cast<int>(id));
1679  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1680  }
1681 
1682  ros::Duration(0.005).sleep();
1683  return result;
1684 }
1685 
1699 int TtlManager::readVelocityProfile(uint8_t id, uint32_t &v_start, uint32_t &a_1, uint32_t &v_1, uint32_t &a_max, uint32_t &v_max, uint32_t &d_max, uint32_t &d_1, uint32_t &v_stop)
1700 {
1701  int result = COMM_RX_FAIL;
1702 
1703  if (_state_map.count(id) != 0 && _state_map.at(id))
1704  {
1705  EHardwareType motor_type = _state_map.at(id)->getHardwareType();
1706  auto [joint_stepper_driver, hw_type] = getJointsStepperDriver();
1707  if (joint_stepper_driver)
1708  {
1709  std::vector<uint32_t> data;
1710  result = joint_stepper_driver->readVelocityProfile(id, data);
1711 
1712  if (COMM_SUCCESS == result)
1713  {
1714  v_start = data.at(0);
1715  a_1 = data.at(1);
1716  v_1 = data.at(2);
1717  a_max = data.at(3);
1718  v_max = data.at(4);
1719  d_max = data.at(5);
1720  d_1 = data.at(6);
1721  v_stop = data.at(7);
1722  }
1723  else
1724  {
1725  ROS_WARN("TtlManager::readVelocityProfile - Failed to read velocity profile: %d", result);
1726  result = niryo_robot_msgs::CommandStatus::TTL_READ_ERROR;
1727  return result;
1728  }
1729  }
1730  else
1731  {
1732  ROS_ERROR_THROTTLE(1, "TtlManager::readVelocityProfile - driver for motor %s not available", HardwareTypeEnum(motor_type).toString().c_str());
1733  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1734  }
1735  }
1736  else
1737  {
1738  ROS_ERROR_THROTTLE(1, "TtlManager::readVelocityProfile - driver for motor id %d unknown", static_cast<int>(id));
1739  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1740  }
1741 
1742  ros::Duration(0.005).sleep();
1743  return result;
1744 }
1745 
1752 int TtlManager::readMoving(uint8_t id, uint8_t &status)
1753 {
1754  int result = COMM_RX_FAIL;
1755 
1756  if (_state_map.count(id) != 0 && _state_map.at(id))
1757  {
1758  EHardwareType motor_type = _state_map.at(id)->getHardwareType();
1759 
1760  // Only used for xl330 and xl320 for now
1761  if (_driver_map.count(motor_type) && (motor_type == EHardwareType::XL330 || motor_type == EHardwareType::XL320|| motor_type == EHardwareType::FAKE_DXL_MOTOR))
1762  {
1763  auto driver = std::dynamic_pointer_cast<AbstractDxlDriver>(_driver_map.at(motor_type));
1764  if (driver)
1765  {
1766  result = driver->readMoving(id, status);
1767  }
1768  }
1769  else
1770  {
1771  ROS_ERROR_THROTTLE(1, "TtlManager::readMoving - register MOVING for motor %s not available", HardwareTypeEnum(motor_type).toString().c_str());
1772  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1773  }
1774  }
1775  else
1776  {
1777  ROS_ERROR_THROTTLE(1, "TtlManager::readMoving - driver for motor id %d unknown", static_cast<int>(id));
1778  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1779  }
1780 
1781  ros::Duration(0.005).sleep();
1782  return result;
1783 }
1784 
1791 int TtlManager::readControlMode(uint8_t id, uint8_t &control_mode)
1792 {
1793  int result = COMM_RX_FAIL;
1794 
1795  if (_state_map.count(id) != 0 && _state_map.at(id))
1796  {
1797  EHardwareType motor_type = _state_map.at(id)->getHardwareType();
1798 
1799  if (_driver_map.count(motor_type))
1800  {
1801  auto driver = std::dynamic_pointer_cast<AbstractDxlDriver>(_driver_map.at(motor_type));
1802  if (driver)
1803  {
1804  result = driver->readControlMode(id, control_mode);
1805  }
1806  }
1807  else
1808  {
1809  ROS_ERROR_THROTTLE(1, "TtlManager::readControlMode - driver for motor %s not available", HardwareTypeEnum(motor_type).toString().c_str());
1810  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1811  }
1812  }
1813  else
1814  {
1815  ROS_ERROR_THROTTLE(1, "TtlManager::readControlMode - driver for motor id %d unknown", static_cast<int>(id));
1816  result = niryo_robot_msgs::CommandStatus::WRONG_MOTOR_TYPE;
1817  }
1818 
1819  ros::Duration(0.005).sleep();
1820  return result;
1821 }
1822 
1828 int TtlManager::writeSynchronizeCommand(std::unique_ptr<common::model::AbstractTtlSynchronizeMotorCmd> &&cmd) // NOLINT
1829 {
1830  int result = COMM_TX_ERROR;
1831  ROS_DEBUG_THROTTLE(0.5, "TtlManager::writeSynchronizeCommand: %s", cmd->str().c_str());
1832 
1833  if (cmd->isValid())
1834  {
1835  std::set<EHardwareType> typesToProcess = cmd->getMotorTypes();
1836 
1837  // process all the motors using each successive drivers
1838  for (uint32_t counter = 0; counter < MAX_HW_FAILURE; ++counter)
1839  {
1840  ROS_DEBUG_THROTTLE(0.5, "TtlManager::writeSynchronizeCommand: try to sync write (counter %d)", counter);
1841 
1842  for (auto const &it : _driver_map)
1843  {
1844  if (typesToProcess.count(it.first) != 0)
1845  {
1846  result = COMM_TX_ERROR;
1847 
1848  // syncwrite for this driver. The driver is responsible for sync write only to its associated motors
1849  auto driver = std::dynamic_pointer_cast<AbstractMotorDriver>(it.second);
1850  if (driver)
1851  {
1852  result = driver->writeSyncCmd(cmd->getCmdType(), cmd->getMotorsId(it.first), cmd->getParams(it.first));
1853 
1854  ros::Duration(0.05).sleep();
1855  }
1856 
1857  // if successful, don't process this driver in the next loop
1858  if (COMM_SUCCESS == result)
1859  {
1860  typesToProcess.erase(typesToProcess.find(it.first));
1861  }
1862  else
1863  {
1864  ROS_ERROR("TtlManager::writeSynchronizeCommand : unable to sync write function : %d", result);
1865  }
1866  }
1867  }
1868 
1869  // if all drivers are processed, go out of for loop
1870  if (typesToProcess.empty())
1871  {
1872  result = COMM_SUCCESS;
1873  break;
1874  }
1875 
1876  ros::Duration(TIME_TO_WAIT_IF_BUSY).sleep();
1877  }
1878  }
1879  else
1880  {
1881  ROS_ERROR("TtlManager::writeSynchronizeCommand - Invalid command");
1882  }
1883 
1884  if (COMM_SUCCESS != result)
1885  {
1886  ROS_ERROR_THROTTLE(0.5, "TtlManager::writeSynchronizeCommand - Failed to write synchronize position");
1887  _debug_error_message = "TtlManager - Failed to write synchronize position";
1888  }
1889 
1890  return result;
1891 }
1892 
1898 int TtlManager::writeSingleCommand(std::unique_ptr<common::model::AbstractTtlSingleMotorCmd> &&cmd) // NOLINT
1899 {
1900  int result = COMM_TX_ERROR;
1901 
1902  uint8_t id = cmd->getId();
1903 
1904  if (cmd->isValid())
1905  {
1906  int counter = 0;
1907 
1908  ROS_DEBUG("TtlManager::writeSingleCommand: %s", cmd->str().c_str());
1909 
1910  if (_state_map.count(id) && _state_map.at(id))
1911  {
1912  auto state = _state_map.at(id);
1913  while ((COMM_SUCCESS != result) && (counter < 50))
1914  {
1915  EHardwareType hardware_type = state->getHardwareType();
1916  result = COMM_TX_ERROR;
1917  if (_driver_map.count(hardware_type) && _driver_map.at(hardware_type))
1918  {
1919  // writeSingleCmd is in a for loop, we cannot infer that this command will succeed. Thus we cannot move cmd in parameter
1920  result = _driver_map.at(hardware_type)->writeSingleCmd(cmd);
1921  }
1922 
1923  counter += 1;
1924 
1925  ros::Duration(TIME_TO_WAIT_IF_BUSY).sleep();
1926  }
1927  }
1928  else
1929  {
1930  ROS_DEBUG("TtlManager::writeSingleCommand: command is sent to a removed hardware component. Skipped or write to a unknow device");
1931  result = COMM_TX_ERROR;
1932  }
1933  }
1934 
1935  if (result != COMM_SUCCESS)
1936  {
1937  ROS_WARN("TtlManager::writeSingleCommand - Fail to write single command : %s", cmd->str().c_str());
1938  _debug_error_message = "TtlManager - Failed to write a single command: " + cmd->str();
1939  }
1940 
1941  return result;
1942 }
1943 
1948 void TtlManager::executeJointTrajectoryCmd(std::vector<std::pair<uint8_t, uint32_t>> cmd_vec)
1949 {
1950  for (auto const &it : _driver_map)
1951  {
1952  // build list of ids and params for this motor
1953  _position_goal_ids.clear();
1954  _position_goal_params.clear();
1955  for (auto const &cmd : cmd_vec)
1956  {
1957  if (_state_map.count(cmd.first) && it.first == _state_map.at(cmd.first)->getHardwareType())
1958  {
1959  _position_goal_ids.emplace_back(cmd.first);
1960  _position_goal_params.emplace_back(cmd.second);
1961  }
1962  }
1963 
1964  // syncwrite for this driver. The driver is responsible for sync write only to its associated motors
1965  auto driver = std::dynamic_pointer_cast<AbstractMotorDriver>(it.second);
1966 
1967  if (driver)
1968  {
1969  int err = driver->syncWritePositionGoal(_position_goal_ids, _position_goal_params);
1970  if (err != COMM_SUCCESS)
1971  {
1972  ROS_WARN("TtlManager::executeJointTrajectoryCmd - Failed to write position");
1973  _debug_error_message = "TtlManager - Failed to write position";
1974  }
1975  }
1976  }
1977 }
1978 
1979 // ******************
1980 // Calibration
1981 // ******************
1982 
1987 {
1988  ROS_DEBUG("TtlManager::startCalibration: starting...");
1989 
1990  std::vector<uint8_t> stepper_list;
1991  if (_ids_map.count(EHardwareType::STEPPER))
1992  {
1993  _calibration_status = EStepperCalibrationStatus::IN_PROGRESS;
1995  stepper_list = _ids_map.at(EHardwareType::STEPPER);
1996  }
1997  else if (_ids_map.count(EHardwareType::NED3PRO_STEPPER))
1998  {
1999  stepper_list = _ids_map.at(EHardwareType::NED3PRO_STEPPER);
2000  }
2001  else if (_ids_map.count(EHardwareType::FAKE_STEPPER_MOTOR))
2002  {
2003  _calibration_status = EStepperCalibrationStatus::IN_PROGRESS;
2005  stepper_list = _ids_map.at(EHardwareType::FAKE_STEPPER_MOTOR);
2006  }
2007 
2008  for (auto const &id : stepper_list)
2009  {
2010  if (_state_map.count(id))
2011  {
2012  auto stepperState = std::dynamic_pointer_cast<StepperMotorState>(_state_map.at(id));
2013 
2014  if (stepperState && !stepperState->isConveyor())
2015  {
2016  stepperState->setCalibration(EStepperCalibrationStatus::IN_PROGRESS, 1);
2017  }
2018  }
2019  } // for steppers_list
2020 }
2021 
2026 {
2027  ROS_INFO("TtlManager::resetCalibration: reseting...");
2028 
2029  std::vector<uint8_t> stepper_list;
2030  if (_ids_map.count(EHardwareType::STEPPER))
2031  {
2032  _calibration_status = EStepperCalibrationStatus::UNINITIALIZED;
2034  stepper_list = _ids_map.at(EHardwareType::STEPPER);
2035  }
2036  else if (_ids_map.count(EHardwareType::NED3PRO_STEPPER))
2037  stepper_list = _ids_map.at(EHardwareType::NED3PRO_STEPPER);
2038 
2039  for (auto const id : stepper_list)
2040  {
2041  if (_state_map.count(id))
2042  {
2043  auto stepperState = std::dynamic_pointer_cast<StepperMotorState>(_state_map.at(id));
2044 
2045  if (stepperState && !stepperState->isConveyor())
2046  {
2047  stepperState->setCalibration(EStepperCalibrationStatus::UNINITIALIZED, 1);
2048  }
2049  }
2050  } // for steppers_list
2051 }
2052 
2058 int32_t TtlManager::getCalibrationResult(uint8_t motor_id) const
2059 {
2060  if (!_state_map.count(motor_id) && _state_map.at(motor_id))
2061  throw std::out_of_range("TtlManager::getMotorsState: Unknown motor id");
2062 
2063  return std::dynamic_pointer_cast<StepperMotorState>(_state_map.at(motor_id))->getCalibrationValue();
2064 }
2065 
2066 // ******************
2067 // Getters
2068 // ******************
2069 
2076 void TtlManager::getBusState(bool &connection_state, std::vector<uint8_t> &motor_id, std::string &debug_msg) const
2077 {
2078  debug_msg = _debug_error_message;
2079  motor_id = _all_ids_connected;
2080  connection_state = isConnectionOk();
2081 }
2082 
2087 std::vector<std::shared_ptr<JointState>> TtlManager::getMotorsStates() const
2088 {
2089  std::vector<std::shared_ptr<JointState>> states;
2090 
2091  for (const auto &it : _state_map)
2092  {
2093  if (it.second && it.second->getComponentType() == common::model::EComponentType::JOINT)
2094  {
2095  states.emplace_back(std::dynamic_pointer_cast<JointState>(it.second));
2096  }
2097  }
2098 
2099  return states;
2100 }
2101 
2102 std::vector<std::shared_ptr<ConveyorState>> TtlManager::getConveyorsStates() const
2103 {
2104  std::vector<std::shared_ptr<ConveyorState>> conveyor_states;
2105  for (const auto &it : _state_map)
2106  {
2107  if (it.second && it.second->getComponentType() == common::model::EComponentType::CONVEYOR)
2108  {
2109  conveyor_states.emplace_back(std::dynamic_pointer_cast<ConveyorState>(it.second));
2110  }
2111  }
2112 
2113  return conveyor_states;
2114 }
2115 
2121 std::shared_ptr<common::model::AbstractHardwareState> TtlManager::getHardwareState(uint8_t motor_id) const
2122 {
2123  if (!_state_map.count(motor_id) && _state_map.at(motor_id))
2124  throw std::out_of_range("TtlManager::getMotorsState: Unknown motor id");
2125 
2126  return _state_map.at(motor_id);
2127 }
2128 
2129 // ********************
2130 // Private
2131 // ********************
2132 
2137 void TtlManager::addHardwareDriver(EHardwareType hardware_type)
2138 {
2139  // if not already instanciated
2140  if (!_driver_map.count(hardware_type))
2141  {
2142  switch (hardware_type)
2143  {
2144  case EHardwareType::STEPPER:
2145  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<StepperDriver<StepperReg>>(_portHandler, _packetHandler)));
2146  break;
2147  case EHardwareType::NED3PRO_STEPPER:
2148  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<Ned3ProStepperDriver<Ned3ProStepperReg>>(_portHandler, _packetHandler)));
2149  break;
2150  case EHardwareType::FAKE_STEPPER_MOTOR:
2151  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<MockStepperDriver>(_fake_data)));
2152  break;
2153  case EHardwareType::XL430:
2154  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<DxlDriver<XL430Reg>>(_portHandler, _packetHandler)));
2155  break;
2156  case EHardwareType::XC430:
2157  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<DxlDriver<XC430Reg>>(_portHandler, _packetHandler)));
2158  break;
2159  case EHardwareType::XM430:
2160  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<DxlDriver<XM430Reg>>(_portHandler, _packetHandler)));
2161  break;
2162  case EHardwareType::XL320:
2163  _driver_map.insert(make_pair(hardware_type, std::make_shared<DxlDriver<XL320Reg>>(_portHandler, _packetHandler)));
2164  break;
2165  case EHardwareType::XL330:
2166  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<DxlDriver<XL330Reg>>(_portHandler, _packetHandler)));
2167  break;
2168  case EHardwareType::XH430:
2169  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<DxlDriver<XH430Reg>>(_portHandler, _packetHandler)));
2170  break;
2171  case EHardwareType::FAKE_DXL_MOTOR:
2172  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<MockDxlDriver>(_fake_data)));
2173  break;
2174  case EHardwareType::END_EFFECTOR:
2175  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<EndEffectorDriver<EndEffectorReg>>(_portHandler, _packetHandler)));
2176  break;
2177  case EHardwareType::NED3PRO_END_EFFECTOR:
2178  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<Ned3ProEndEffectorDriver<Ned3ProEndEffectorReg>>(_portHandler, _packetHandler)));
2179  break;
2180  case EHardwareType::FAKE_END_EFFECTOR:
2181  _driver_map.insert(std::make_pair(hardware_type, std::make_shared<MockEndEffectorDriver>(_fake_data)));
2182  break;
2183  default:
2184  ROS_ERROR("TtlManager - Unable to instanciate driver, unknown type");
2185  break;
2186  }
2187  }
2188 }
2189 
2193 void TtlManager::readFakeConfig(bool use_simu_gripper, bool use_simu_conveyor)
2194 {
2195  _fake_data = std::make_shared<FakeTtlData>();
2196 
2197  if (_nh.hasParam("fake_params"))
2198  {
2199  std::vector<int> full_id_list;
2200  if (_nh.hasParam("fake_params/id_list"))
2201  _nh.getParam("fake_params/id_list", full_id_list);
2202  for (auto id : full_id_list)
2203  _fake_data->full_id_list.emplace_back(static_cast<uint8_t>(id));
2204 
2205  if (_nh.hasParam("fake_params/steppers"))
2206  {
2207  std::string current_ns = "fake_params/steppers/";
2208  retrieveFakeMotorData(current_ns, _fake_data->stepper_registers);
2209  }
2210 
2211  if (_nh.hasParam("fake_params/dynamixels/"))
2212  {
2213  std::string current_ns = "fake_params/dynamixels/";
2214  retrieveFakeMotorData(current_ns, _fake_data->dxl_registers);
2215  }
2216 
2217  if (_nh.hasParam("fake_params/end_effector"))
2218  {
2219  string current_ns = "fake_params/end_effector/";
2220  vector<int> id_list, temperature_list, voltage_list;
2221  vector<string> firmware_list;
2222  _nh.getParam(current_ns + "id", id_list);
2223  _nh.getParam(current_ns + "temperature", temperature_list);
2224  _nh.getParam(current_ns + "voltage", voltage_list);
2225  _nh.getParam(current_ns + "firmware", firmware_list);
2226 
2227  assert(!id_list.empty());
2228  assert(!temperature_list.empty());
2229  assert(!voltage_list.empty());
2230  assert(!firmware_list.empty());
2231 
2232  _fake_data->end_effector.id = static_cast<uint8_t>(id_list.at(0));
2233  _fake_data->end_effector.temperature = static_cast<uint8_t>(temperature_list.at(0));
2234  _fake_data->end_effector.voltage = static_cast<double>(voltage_list.at(0));
2235 
2236  _fake_data->end_effector.firmware = firmware_list.at(0);
2237  }
2238 
2239  if (use_simu_gripper && _nh.hasParam("fake_params/tool/"))
2240  {
2241  std::string current_ns = "fake_params/tool/";
2242  retrieveFakeMotorData(current_ns, _fake_data->dxl_registers);
2243  }
2244 
2245  if (use_simu_conveyor && _nh.hasParam("fake_params/conveyors/"))
2246  {
2247  std::string current_ns = "fake_params/conveyors/";
2248  retrieveFakeMotorData(current_ns, _fake_data->stepper_registers);
2249  }
2250 
2251  _fake_data->updateFullIdList();
2252  }
2253 }
2254 
2261  auto joint_states = getMotorsStates();
2262  auto some_joint_state_it = std::find_if(joint_states.begin(), joint_states.end(), [](const std::shared_ptr<JointState>& joint_state){
2263  return joint_state->isStepper();
2264  });
2265  if (some_joint_state_it == joint_states.end()){
2266  return {};
2267  }
2268  auto some_joint_state = *some_joint_state_it;
2269  auto hardware_type = some_joint_state->getHardwareType();
2270  return {
2271  .driver = std::dynamic_pointer_cast<AbstractStepperDriver>(_driver_map.at(hardware_type)),
2272  .hardware_type = hardware_type
2273  };
2274 }
2275 
2276 
2277 } // namespace ttl_driver
ttl_driver::TtlManager::retrieveFakeMotorData
void retrieveFakeMotorData(const std::string &current_ns, std::map< uint8_t, Reg > &fake_params)
TtlManager::retrieveFakeMotorData.
Definition: ttl_manager.hpp:406
end_effector_driver.hpp
ttl_driver::TtlManager::startCalibration
void startCalibration() override
TtlManager::startCalibration.
Definition: ttl_manager.cpp:1986
ttl_driver::StepperDriver
The StepperDriver class.
Definition: stepper_driver.hpp:38
ttl_driver::TtlManager::addHardwareComponent
int addHardwareComponent(std::shared_ptr< common::model::AbstractHardwareState > &&state) override
TtlManager::addHardwareComponent add hardware component like joint, ee, tool... to ttl manager.
Definition: ttl_manager.cpp:207
ttl_driver::TtlManager::CalibrationMachineState::State::IDLE
@ IDLE
ttl_driver::TtlManager::readEndEffectorStatus
bool readEndEffectorStatus()
TtlManager::readEndEffectorStatus.
Definition: ttl_manager.cpp:780
ttl_driver::TtlManager::readCustomCommand
int readCustomCommand(uint8_t id, int32_t reg_address, int &value, int byte_number)
TtlManager::readCustomCommand.
Definition: ttl_manager.cpp:1585
mock_dxl_driver.hpp
ttl_driver::TtlManager::_debug_error_message
std::string _debug_error_message
Definition: ttl_manager.hpp:229
ttl_driver::TtlManager::getJointsStepperDriver
GetJointsStepperDriverResult getJointsStepperDriver()
: Return the driver of the joints
Definition: ttl_manager.cpp:2260
ttl_driver::TtlManager::writeSingleCommand
int writeSingleCommand(std::unique_ptr< common::model::AbstractTtlSingleMotorCmd > &&cmd)
TtlManager::writeSingleCommand.
Definition: ttl_manager.cpp:1898
ttl_driver::TTL_SCAN_MISSING_MOTOR
constexpr int TTL_SCAN_MISSING_MOTOR
Definition: ttl_manager.hpp:71
ttl_driver::TtlManager::_state_map
std::map< uint8_t, std::shared_ptr< common::model::AbstractHardwareState > > _state_map
Definition: ttl_manager.hpp:214
ttl_driver::TtlManager::_calib_machine_state
CalibrationMachineState _calib_machine_state
Definition: ttl_manager.hpp:311
ttl_driver::TtlManager::readHardwareStatus
bool readHardwareStatus()
TtlManager::readHardwareStatus.
Definition: ttl_manager.cpp:1040
ttl_driver::TtlManager::getCalibrationResult
int32_t getCalibrationResult(uint8_t id) const override
TtlManager::getCalibrationResult.
Definition: ttl_manager.cpp:2058
ttl_driver::TtlManager::_calibration_status
common::model::EStepperCalibrationStatus _calibration_status
Definition: ttl_manager.hpp:241
ttl_driver::TtlManager::_nh
ros::NodeHandle _nh
Definition: ttl_manager.hpp:201
ttl_driver::TtlManager::scanAndCheck
int scanAndCheck() override
TtlManager::scanAndCheck.
Definition: ttl_manager.cpp:395
ttl_driver::TtlManager::checkCollision
bool checkCollision()
TtlManager::checkCollision.
Definition: ttl_manager.cpp:890
ttl_driver::TtlManager::CalibrationMachineState::State::IN_PROGRESS
@ IN_PROGRESS
ttl_driver::TtlManager::_hw_fail_counter_read
uint32_t _hw_fail_counter_read
Definition: ttl_manager.hpp:231
mock_end_effector_driver.hpp
ttl_driver::TtlManager::executeJointTrajectoryCmd
void executeJointTrajectoryCmd(std::vector< std::pair< uint8_t, uint32_t > > cmd_vec)
TtlManager::executeJointTrajectoryCmd.
Definition: ttl_manager.cpp:1948
ttl_driver::TtlManager::_position_goal_params
std::vector< uint32_t > _position_goal_params
Definition: ttl_manager.hpp:257
stepper_reg.hpp
ttl_driver::TTL_FAIL_OPEN_PORT
constexpr int TTL_FAIL_OPEN_PORT
Definition: ttl_manager.hpp:65
ttl_driver::TtlManager::_position_goal_ids
std::vector< uint8_t > _position_goal_ids
Definition: ttl_manager.hpp:256
ttl_driver::TtlManager::_all_ids_connected
std::vector< uint8_t > _all_ids_connected
Definition: ttl_manager.hpp:210
ttl_driver::TtlManager::_last_collision_detection_activating
double _last_collision_detection_activating
Definition: ttl_manager.hpp:249
ttl_driver::TtlManager::sendCustomCommand
int sendCustomCommand(uint8_t id, int reg_address, int value, int byte_number)
TtlManager::sendCustomCommand.
Definition: ttl_manager.cpp:1535
end_effector_reg.hpp
ttl_driver::TtlManager::readSteppersStatus
uint8_t readSteppersStatus()
TtlManager::readCalibrationStatus : reads specific steppers related information (ned2 only)
Definition: ttl_manager.cpp:1161
ttl_driver::TtlManager::TtlManager
TtlManager()=delete
ttl_driver::TtlManager::CalibrationMachineState::State::UPDATING
@ UPDATING
ttl_driver::TTL_FAIL_PORT_SET_BAUDRATE
constexpr int TTL_FAIL_PORT_SET_BAUDRATE
Definition: ttl_manager.hpp:67
ttl_driver::TtlManager::changeId
int changeId(common::model::EHardwareType motor_type, uint8_t old_id, uint8_t new_id)
TtlManager::changeId.
Definition: ttl_manager.cpp:338
ttl_driver::TtlManager::getAllIdsOnBus
int getAllIdsOnBus(std::vector< uint8_t > &id_list)
TtlManager::getAllIdsOnDxlBus.
Definition: ttl_manager.cpp:1424
ttl_driver::TtlManager::removeHardwareComponent
void removeHardwareComponent(uint8_t id) override
TtlManager::removeHardwareComponent.
Definition: ttl_manager.cpp:288
ttl_driver::Ned3ProStepperDriver
The Ned3ProStepperDriver class.
Definition: ned3pro_stepper_driver.hpp:40
ttl_driver::TtlManager::readHomingAbsPosition
bool readHomingAbsPosition()
Definition: ttl_manager.cpp:601
ttl_driver::TtlManager::_device_name
std::string _device_name
Definition: ttl_manager.hpp:207
ned3pro_stepper_driver.hpp
ttl_driver::TtlManager::getHardwareState
std::shared_ptr< common::model::AbstractHardwareState > getHardwareState(uint8_t motor_id) const
TtlManager::getHardwareState.
Definition: ttl_manager.cpp:2121
ttl_driver::TtlManager::readJointsStatus
bool readJointsStatus()
TtlManager::readJointsStatus.
Definition: ttl_manager.cpp:671
ttl_driver::TtlManager::_packetHandler
std::shared_ptr< dynamixel::PacketHandler > _packetHandler
Definition: ttl_manager.hpp:203
ttl_driver::TtlManager::init
bool init(ros::NodeHandle &nh) override
TtlManager::init.
Definition: ttl_manager.cpp:107
ttl_driver::TtlManager::getConveyorsStates
std::vector< std::shared_ptr< common::model::ConveyorState > > getConveyorsStates() const
Definition: ttl_manager.cpp:2102
ttl_driver::TtlManager::getPosition
uint32_t getPosition(const common::model::JointState &motor_state)
TtlManager::getPosition.
Definition: ttl_manager.cpp:566
ttl_driver::TtlManager::resetCalibration
void resetCalibration() override
TtlManager::resetCalibration.
Definition: ttl_manager.cpp:2025
ttl_driver::TtlManager::CalibrationMachineState::State::STARTING
@ STARTING
ttl_driver::TtlManager::CalibrationMachineState::status
State status()
Definition: ttl_manager.hpp:295
ttl_driver::TtlManager::getBusState
void getBusState(bool &connection_state, std::vector< uint8_t > &motor_id, std::string &debug_msg) const override
TtlManager::getBusState.
Definition: ttl_manager.cpp:2076
ttl_driver::DxlDriver
The DxlDriver class.
Definition: dxl_driver.hpp:44
ttl_driver::TtlManager::resetTorques
void resetTorques()
TtlManager::resetTorques.
Definition: ttl_manager.cpp:526
ttl_driver::TtlManager::isMotorType
bool isMotorType(common::model::EHardwareType type)
TtlManager::isMotorType.
Definition: ttl_manager.cpp:321
ttl_driver::TtlManager::readCollisionStatus
bool readCollisionStatus()
TtlManager::readCollisionStatus.
Definition: ttl_manager.cpp:973
stepper_driver.hpp
ttl_driver::TtlManager::MAX_READ_EE_FAILURE
static constexpr uint32_t MAX_READ_EE_FAILURE
Definition: ttl_manager.hpp:238
ttl_driver::TtlManager::setLeds
int setLeds(int led)
TtlManager::setLeds.
Definition: ttl_manager.cpp:1476
ttl_driver::TtlManager::_isWrongAction
bool _isWrongAction
Definition: ttl_manager.hpp:251
ttl_driver::TtlManager::writeSynchronizeCommand
int writeSynchronizeCommand(std::unique_ptr< common::model::AbstractTtlSynchronizeMotorCmd > &&cmd)
TtlManager::writeSynchronizeCommand.
Definition: ttl_manager.cpp:1828
ttl_driver::TtlManager::_collision_status
bool _collision_status
Definition: ttl_manager.hpp:248
mock_stepper_driver.hpp
ttl_driver::TtlManager::ping
bool ping(uint8_t id) override
TtlManager::ping.
Definition: ttl_manager.cpp:464
ttl_driver::EndEffectorDriver
The EndEffectorDriver class.
Definition: end_effector_driver.hpp:42
dxl_driver.hpp
ttl_driver
Definition: abstract_dxl_driver.hpp:30
ttl_driver::TtlManager::_default_ttl_driver
std::shared_ptr< ttl_driver::AbstractTtlDriver > _default_ttl_driver
Definition: ttl_manager.hpp:221
ttl_driver::TtlManager::rebootHardware
int rebootHardware(uint8_t id)
TtlManager::rebootHardware.
Definition: ttl_manager.cpp:482
ttl_driver::TtlManager::_fake_data
std::shared_ptr< FakeTtlData > _fake_data
Definition: ttl_manager.hpp:244
ned3pro_end_effector_driver.hpp
ttl_driver::TtlManager::readNed3ProSteppersStatus
uint8_t readNed3ProSteppersStatus()
Definition: ttl_manager.cpp:1324
ttl_driver::TtlManager::CalibrationMachineState::reset
void reset()
Definition: ttl_manager.hpp:271
ttl_driver::TtlManager::_end_effector_fail_counter_read
uint32_t _end_effector_fail_counter_read
Definition: ttl_manager.hpp:232
ttl_driver::TtlManager::_is_connection_ok
bool _is_connection_ok
Definition: ttl_manager.hpp:228
nh
static std::unique_ptr< ros::NodeHandle > nh
Definition: service_client_ned2.cpp:31
ttl_driver::TtlManager::isConnectionOk
bool isConnectionOk() const override
TtlManager::isConnectionOk.
Definition: ttl_manager.hpp:322
ttl_driver::TtlManager::_position_list
std::vector< uint32_t > _position_list
Definition: ttl_manager.hpp:255
ttl_driver::TtlManager::CalibrationMachineState::start
void start()
Definition: ttl_manager.hpp:276
ttl_driver::TtlManager::_led_state
int _led_state
Definition: ttl_manager.hpp:234
ttl_driver::TtlManager::_simulation_mode
bool _simulation_mode
Definition: ttl_manager.hpp:245
ttl_driver::TTL_SCAN_OK
constexpr int TTL_SCAN_OK
Definition: ttl_manager.hpp:70
ttl_driver::TtlManager::readMoving
int readMoving(uint8_t id, uint8_t &status)
TtlManager::readMoving.
Definition: ttl_manager.cpp:1752
ttl_driver::TtlManager::_removed_motor_id_list
std::vector< uint8_t > _removed_motor_id_list
Definition: ttl_manager.hpp:211
ttl_driver::TtlManager::_ids_map
std::map< common::model::EHardwareType, std::vector< uint8_t > > _ids_map
Definition: ttl_manager.hpp:216
ttl_driver::Ned3ProEndEffectorDriver
The Ned3ProEndEffectorDriver class.
Definition: ned3pro_end_effector_driver.hpp:42
ttl_driver::TtlManager::CalibrationMachineState::next
void next()
next : next state, stops at updating (dont circle)
Definition: ttl_manager.hpp:285
ttl_driver::TtlManager::_portHandler
std::shared_ptr< dynamixel::PortHandler > _portHandler
Definition: ttl_manager.hpp:202
ttl_driver::TtlManager::GetJointsStepperDriverResult
Definition: ttl_manager.hpp:194
ttl_driver::TtlManager::CalibrationMachineState::isTimeout
bool isTimeout()
Definition: ttl_manager.hpp:300
ttl_driver::TtlManager::_driver_map
std::map< common::model::EHardwareType, std::shared_ptr< ttl_driver::AbstractTtlDriver > > _driver_map
Definition: ttl_manager.hpp:218
ttl_driver::TtlManager::setupCommunication
int setupCommunication() override
TtlManager::setupCommunication.
Definition: ttl_manager.cpp:150
ttl_driver::TtlManager::MAX_HW_FAILURE
static constexpr uint32_t MAX_HW_FAILURE
Definition: ttl_manager.hpp:237
ttl_driver::TtlManager::getMotorsStates
std::vector< std::shared_ptr< common::model::JointState > > getMotorsStates() const
TtlManager::getMotorsStates.
Definition: ttl_manager.cpp:2087
ttl_driver::TtlManager::~TtlManager
~TtlManager() override
TtlManager::~TtlManager.
Definition: ttl_manager.cpp:93
ttl_driver::TtlManager::_conveyor_list
std::vector< uint8_t > _conveyor_list
Definition: ttl_manager.hpp:225
ttl_driver::TtlManager::addHardwareDriver
void addHardwareDriver(common::model::EHardwareType hardware_type) override
TtlManager::addHardwareDriver.
Definition: ttl_manager.cpp:2137
ttl_driver::TtlManager::_calibration_status_publisher
ros::Publisher _calibration_status_publisher
Definition: ttl_manager.hpp:253
ttl_driver::TtlManager::_led_motor_type_cfg
std::string _led_motor_type_cfg
Definition: ttl_manager.hpp:235
ttl_driver::TtlManager::readControlMode
int readControlMode(uint8_t id, uint8_t &control_mode)
TtlManager::readControlMode.
Definition: ttl_manager.cpp:1791
ttl_driver::TTL_BUS_PROTOCOL_VERSION
constexpr float TTL_BUS_PROTOCOL_VERSION
Definition: ttl_manager.hpp:64
ttl_manager.hpp
ttl_driver::TtlManager::readMotorPID
int readMotorPID(uint8_t id, uint16_t &pos_p_gain, uint16_t &pos_i_gain, uint16_t &pos_d_gain, uint16_t &vel_p_gain, uint16_t &vel_i_gain, uint16_t &ff1_gain, uint16_t &ff2_gain)
TtlManager::readMotorPID.
Definition: ttl_manager.cpp:1635
ttl_driver::TtlManager::readVelocityProfile
int readVelocityProfile(uint8_t id, uint32_t &v_start, uint32_t &a_1, uint32_t &v_1, uint32_t &a_max, uint32_t &v_max, uint32_t &d_max, uint32_t &d_1, uint32_t &v_stop)
TtlManager::readVelocityProfile.
Definition: ttl_manager.cpp:1699
ttl_driver::TtlManager::_baudrate
int _baudrate
Definition: ttl_manager.hpp:208
ttl_driver::TtlManager::readFakeConfig
void readFakeConfig(bool use_simu_gripper, bool use_simu_conveyor)
TtlManager::readFakeConfig.
Definition: ttl_manager.cpp:2193
ttl_driver::TtlManager::_isRealCollision
bool _isRealCollision
Definition: ttl_manager.hpp:250
fake_ttl_data.hpp


ttl_driver
Author(s): Clement Cocquempot
autogenerated on Wed May 21 2025 08:30:14