17 #ifndef DXL_DRIVER_HPP
18 #define DXL_DRIVER_HPP
28 #include "common/common_defs.hpp"
43 template <
typename reg_type>
47 DxlDriver(std::shared_ptr<dynamixel::PortHandler> portHandler,
48 std::shared_ptr<dynamixel::PacketHandler> packetHandler);
50 std::string
str()
const override;
58 int readVoltage(uint8_t
id,
double &voltage)
override;
61 int syncReadFirmwareVersion(
const std::vector<uint8_t> &id_list, std::vector<std::string> &firmware_list)
override;
62 int syncReadTemperature(
const std::vector<uint8_t> &id_list, std::vector<uint8_t> &temperature_list)
override;
63 int syncReadVoltage(
const std::vector<uint8_t> &id_list, std::vector<double> &voltage_list)
override;
64 int syncReadRawVoltage(
const std::vector<uint8_t> &id_list, std::vector<double> &voltage_list)
override;
66 std::vector<std::pair<double, uint8_t>> &data_list)
override;
68 int syncReadHwErrorStatus(
const std::vector<uint8_t> &id_list, std::vector<uint8_t> &hw_error_list)
override;
80 int changeId(uint8_t
id, uint8_t new_id)
override;
95 const std::vector<uint8_t> &torque_percentage_list)
override;
96 int syncWritePositionGoal(
const std::vector<uint8_t> &id_list,
const std::vector<uint32_t> &position_list)
override;
97 int syncWriteVelocityGoal(
const std::vector<uint8_t> &id_list,
const std::vector<uint32_t> &velocity_list)
override;
102 int readPosition(uint8_t
id, uint32_t &present_position)
override;
103 int readVelocity(uint8_t
id, uint32_t &present_velocity)
override;
105 int syncReadPosition(
const std::vector<uint8_t> &id_list, std::vector<uint32_t> &position_list)
override;
106 int syncReadVelocity(
const std::vector<uint8_t> &id_list, std::vector<uint32_t> &velocity_list)
override;
108 std::vector<std::array<uint32_t, 2>> &data_array_list)
override;
121 int readLoad(uint8_t
id, uint16_t &present_load)
override;
122 int syncReadLoad(
const std::vector<uint8_t> &id_list, std::vector<uint16_t> &load_list)
override;
124 int readPID(uint8_t
id, std::vector<uint16_t> &data_list)
override;
127 int readMoving(uint8_t
id, uint8_t &status)
override;
130 int writePID(uint8_t
id,
const std::vector<uint16_t> &data)
override;
133 int writeLed(uint8_t
id, uint8_t led_value)
override;
134 int syncWriteLed(
const std::vector<uint8_t> &id_list,
const std::vector<uint8_t> &led_list)
override;
137 int syncWriteTorqueGoal(
const std::vector<uint8_t> &id_list,
const std::vector<uint16_t> &torque_list)
override;
145 template <
typename reg_type>
147 std::shared_ptr<dynamixel::PacketHandler> packetHandler)
160 template <
typename reg_type>
163 return common::model::HardwareTypeEnum(reg_type::motor_type).toString() +
" : " +
AbstractDxlDriver::str();
170 template <
typename reg_type>
181 template <
typename reg_type>
184 std::string version = std::to_string(
static_cast<uint8_t
>(fw_version));
195 template <
typename reg_type>
198 return write<typename reg_type::TYPE_ID>(reg_type::ADDR_ID,
id, new_id);
206 template <
typename reg_type>
209 int ping_result = getModelNumber(
id, model_number);
211 if (ping_result == COMM_SUCCESS)
213 if (model_number && model_number != reg_type::MODEL_NUMBER)
215 return PING_WRONG_MODEL_NUMBER;
228 template <
typename reg_type>
231 int res = COMM_RX_FAIL;
233 res = read<typename reg_type::TYPE_FIRMWARE_VERSION>(reg_type::ADDR_FIRMWARE_VERSION,
id, data);
234 version = interpretFirmwareVersion(data);
244 template <
typename reg_type>
248 int res = readFirmwareVersion(
id, version);
251 if (COMM_SUCCESS == res && std::stoi(version) >= reg_type::VERSION_STARTUP_CONFIGURATION)
253 res = write<typename reg_type::TYPE_STARTUP_CONFIGURATION>(reg_type::ADDR_STARTUP_CONFIGURATION,
id, config);
257 std::cout <<
"Startup configuration available only for version > "
258 <<
static_cast<int>(reg_type::VERSION_STARTUP_CONFIGURATION) << std::endl;
271 template <
typename reg_type>
274 std::cout <<
"temperature limit not available for this motor type" << std::endl;
284 template <
typename reg_type>
287 std::cout <<
"shutdown configuration not available for this motor type" << std::endl;
297 template <
typename reg_type>
300 return read<typename reg_type::TYPE_MIN_POSITION_LIMIT>(reg_type::ADDR_MIN_POSITION_LIMIT,
id, pos);
309 template <
typename reg_type>
312 return read<typename reg_type::TYPE_MAX_POSITION_LIMIT>(reg_type::ADDR_MAX_POSITION_LIMIT,
id, pos);
324 template <
typename reg_type>
328 int res = COMM_RX_FAIL;
330 for (
int tries = 10; tries > 0; --tries)
332 res = write<typename reg_type::TYPE_PROFILE>(reg_type::ADDR_PROFILE_VELOCITY,
id, data_list.at(0));
333 if (COMM_SUCCESS == res)
337 for (
int tries = 10; tries > 0; --tries)
339 res = write<typename reg_type::TYPE_PROFILE>(reg_type::ADDR_PROFILE_ACCELERATION,
id, data_list.at(1));
340 if (COMM_SUCCESS == res)
344 if (COMM_SUCCESS != res)
356 template <
typename reg_type>
359 auto torque_enable = torque_percentage > 0 ? 1 : 0;
360 return write<typename reg_type::TYPE_TORQUE_ENABLE>(reg_type::ADDR_TORQUE_ENABLE,
id, torque_enable);
369 template <
typename reg_type>
372 return write<typename reg_type::TYPE_GOAL_POSITION>(reg_type::ADDR_GOAL_POSITION,
id,
373 static_cast<typename reg_type::TYPE_GOAL_POSITION
>(position));
382 template <
typename reg_type>
385 return write<typename reg_type::TYPE_GOAL_VELOCITY>(reg_type::ADDR_GOAL_VELOCITY,
id,
386 static_cast<typename reg_type::TYPE_GOAL_VELOCITY
>(velocity));
395 template <
typename reg_type>
397 const std::vector<uint8_t> &torque_percentage_list)
399 std::vector<uint8_t> torque_enable_list;
400 for (
const auto &torque_percentage : torque_percentage_list)
402 auto torque_enable = torque_percentage > 0 ? 1 : 0;
403 torque_enable_list.push_back(torque_enable);
405 return syncWrite<typename reg_type::TYPE_TORQUE_ENABLE>(reg_type::ADDR_TORQUE_ENABLE, id_list, torque_enable_list);
414 template <
typename reg_type>
416 const std::vector<uint32_t> &position_list)
418 return syncWrite<typename reg_type::TYPE_GOAL_POSITION>(reg_type::ADDR_GOAL_POSITION, id_list, position_list);
427 template <
typename reg_type>
429 const std::vector<uint32_t> &velocity_list)
431 return syncWrite<typename reg_type::TYPE_GOAL_VELOCITY>(reg_type::ADDR_GOAL_VELOCITY, id_list, velocity_list);
435 template <
typename reg_type>
439 typename reg_type::TYPE_PROFILE velocity_profile{};
440 typename reg_type::TYPE_PROFILE acceleration_profile{};
442 int res = read<typename reg_type::TYPE_PROFILE>(reg_type::ADDR_PROFILE_VELOCITY,
id, velocity_profile);
443 if (COMM_SUCCESS == res)
444 res = read<typename reg_type::TYPE_PROFILE>(reg_type::ADDR_PROFILE_ACCELERATION,
id, acceleration_profile);
446 data_list.emplace_back(velocity_profile);
447 data_list.emplace_back(acceleration_profile);
458 template <
typename reg_type>
461 return read<typename reg_type::TYPE_PRESENT_POSITION>(reg_type::ADDR_PRESENT_POSITION,
id, present_position);
470 template <
typename reg_type>
473 return read<typename reg_type::TYPE_PRESENT_TEMPERATURE>(reg_type::ADDR_PRESENT_TEMPERATURE,
id, temperature);
482 template <
typename reg_type>
485 typename reg_type::TYPE_PRESENT_VOLTAGE voltage_mV{};
486 int res = read<typename reg_type::TYPE_PRESENT_VOLTAGE>(reg_type::ADDR_PRESENT_VOLTAGE,
id, voltage_mV);
487 voltage =
static_cast<double>(voltage_mV) / reg_type::VOLTAGE_CONVERSION;
497 template <
typename reg_type>
500 return read<typename reg_type::TYPE_HW_ERROR_STATUS>(reg_type::ADDR_HW_ERROR_STATUS,
id, hardware_error_status);
509 template <
typename reg_type>
512 return syncRead<typename reg_type::TYPE_PRESENT_POSITION>(reg_type::ADDR_PRESENT_POSITION, id_list, position_list);
521 template <
typename reg_type>
524 int res = COMM_TX_FAIL;
527 for (
int tries = 10; tries > 0; --tries)
529 res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_POSITION_P_GAIN,
id, data.at(0));
530 if (COMM_SUCCESS == res)
534 if (COMM_SUCCESS != res)
537 for (
int tries = 10; tries > 0; --tries)
539 res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_POSITION_I_GAIN,
id, data.at(1));
540 if (COMM_SUCCESS == res)
543 if (COMM_SUCCESS != res)
546 for (
int tries = 10; tries > 0; --tries)
548 res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_POSITION_D_GAIN,
id, data.at(2));
549 if (COMM_SUCCESS == res)
552 if (COMM_SUCCESS != res)
555 for (
int tries = 10; tries > 0; --tries)
557 res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_VELOCITY_P_GAIN,
id, data.at(3));
558 if (COMM_SUCCESS == res)
561 if (COMM_SUCCESS != res)
564 for (
int tries = 10; tries > 0; --tries)
566 res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_VELOCITY_I_GAIN,
id, data.at(4));
567 if (COMM_SUCCESS == res)
570 if (COMM_SUCCESS != res)
573 for (
int tries = 10; tries > 0; --tries)
575 res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_FF1_GAIN,
id, data.at(5));
576 if (COMM_SUCCESS == res)
579 if (COMM_SUCCESS != res)
582 for (
int tries = 10; tries > 0; --tries)
584 res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_FF2_GAIN,
id, data.at(6));
585 if (res == COMM_SUCCESS)
598 template <
typename reg_type>
600 std::vector<std::string> &firmware_list)
602 int res = COMM_RX_FAIL;
603 std::vector<uint8_t> data_list;
604 res = syncRead<typename reg_type::TYPE_FIRMWARE_VERSION>(reg_type::ADDR_FIRMWARE_VERSION, id_list, data_list);
605 for (
auto const &data : data_list)
606 firmware_list.emplace_back(interpretFirmwareVersion(data));
616 template <
typename reg_type>
618 std::vector<uint8_t> &temperature_list)
620 return syncRead<typename reg_type::TYPE_PRESENT_TEMPERATURE>(reg_type::ADDR_PRESENT_TEMPERATURE, id_list,
630 template <
typename reg_type>
633 voltage_list.clear();
634 std::vector<typename reg_type::TYPE_PRESENT_VOLTAGE> v_read;
635 int res = syncRead<typename reg_type::TYPE_PRESENT_VOLTAGE>(reg_type::ADDR_PRESENT_VOLTAGE, id_list, v_read);
636 for (
auto const &v : v_read)
637 voltage_list.emplace_back(
static_cast<double>(v) / reg_type::VOLTAGE_CONVERSION);
647 template <
typename reg_type>
650 voltage_list.clear();
651 std::vector<typename reg_type::TYPE_PRESENT_VOLTAGE> v_read;
652 int res = syncRead<typename reg_type::TYPE_PRESENT_VOLTAGE>(reg_type::ADDR_PRESENT_VOLTAGE, id_list, v_read);
653 for (
auto const &v : v_read)
654 voltage_list.emplace_back(
static_cast<double>(v));
664 template <
typename reg_type>
666 std::vector<std::pair<double, uint8_t>> &data_list)
670 std::vector<std::array<uint8_t, 3>> raw_data;
671 int res = syncReadConsecutiveBytes<uint8_t, 3>(reg_type::ADDR_PRESENT_VOLTAGE, id_list, raw_data);
673 for (
auto const &data : raw_data)
676 auto voltage =
static_cast<double>((
static_cast<uint16_t
>(data.at(1)) << 8) | data.at(0));
679 uint8_t temperature = data.at(2);
681 data_list.emplace_back(std::make_pair(voltage, temperature));
693 template <
typename reg_type>
696 return syncRead<typename reg_type::TYPE_HW_ERROR_STATUS>(reg_type::ADDR_HW_ERROR_STATUS, id_list, hw_error_list);
709 template <
typename reg_type>
712 return write<typename reg_type::TYPE_LED>(reg_type::ADDR_LED,
id, led_value);
721 template <
typename reg_type>
724 return syncWrite<typename reg_type::TYPE_LED>(reg_type::ADDR_LED, id_list, led_list);
733 template <
typename reg_type>
736 return write<typename reg_type::TYPE_GOAL_TORQUE>(reg_type::ADDR_GOAL_TORQUE,
id, torque);
745 template <
typename reg_type>
747 const std::vector<uint16_t> &torque_list)
749 return syncWrite<typename reg_type::TYPE_GOAL_TORQUE>(reg_type::ADDR_GOAL_TORQUE, id_list, torque_list);
760 template <
typename reg_type>
765 std::vector<std::array<typename reg_type::TYPE_PID_GAIN, 8>> raw_data;
768 for (
int tries = 10; tries > 0; --tries)
771 syncReadConsecutiveBytes<typename reg_type::TYPE_PID_GAIN, 8>(reg_type::ADDR_VELOCITY_I_GAIN, {
id }, raw_data);
772 if (COMM_SUCCESS == res)
777 if (COMM_SUCCESS == res && raw_data.size() == 1)
779 data_list.emplace_back(raw_data.at(0).at(4));
780 data_list.emplace_back(raw_data.at(0).at(3));
781 data_list.emplace_back(raw_data.at(0).at(2));
782 data_list.emplace_back(raw_data.at(0).at(1));
783 data_list.emplace_back(raw_data.at(0).at(0));
784 data_list.emplace_back(raw_data.at(0).at(7));
785 data_list.emplace_back(raw_data.at(0).at(6));
790 std::cout <<
"Failures during read PID gains: " << res << std::endl;
803 template <
typename reg_type>
806 return read<typename reg_type::TYPE_MOVING>(reg_type::ADDR_MOVING,
id, status);
815 template <
typename reg_type>
818 int res = COMM_TX_ERROR;
820 res = read<typename reg_type::TYPE_TORQUE_ENABLE>(reg_type::ADDR_TORQUE_ENABLE,
id, torque);
821 if (res == COMM_SUCCESS)
825 return write<typename reg_type::TYPE_OPERATING_MODE>(reg_type::ADDR_OPERATING_MODE,
id, control_mode);
837 template <
typename reg_type>
841 typename reg_type::TYPE_OPERATING_MODE raw{};
842 res = read<typename reg_type::TYPE_OPERATING_MODE>(reg_type::ADDR_OPERATING_MODE,
id, raw);
843 control_mode =
static_cast<uint8_t
>(raw);
854 template <
typename reg_type>
857 return read<typename reg_type::TYPE_PRESENT_LOAD>(reg_type::ADDR_PRESENT_LOAD,
id, present_load);
866 template <
typename reg_type>
869 return syncRead<typename reg_type::TYPE_PRESENT_LOAD>(reg_type::ADDR_PRESENT_LOAD, id_list, load_list);
878 template <
typename reg_type>
881 return read<typename reg_type::TYPE_PRESENT_VELOCITY>(reg_type::ADDR_PRESENT_VELOCITY,
id, present_velocity);
890 template <
typename reg_type>
893 return syncRead<typename reg_type::TYPE_PRESENT_VELOCITY>(reg_type::ADDR_PRESENT_VELOCITY, id_list, velocity_list);
902 template <
typename reg_type>
904 std::vector<std::array<uint32_t, 2>> &data_array_list)
906 int res = COMM_TX_FAIL;
911 data_array_list.clear();
914 typename reg_type::TYPE_TORQUE_ENABLE torque{ 1 };
915 res = read<typename reg_type::TYPE_TORQUE_ENABLE>(reg_type::ADDR_TORQUE_ENABLE, id_list.at(0), torque);
916 if (COMM_SUCCESS != res)
917 std::cout <<
"#############"
918 " ERROR reading dxl torque in syncReadJointStatus (error "
919 << res <<
")" << std::endl;
924 res = syncReadConsecutiveBytes<uint32_t, 2>(reg_type::ADDR_PRESENT_VELOCITY, id_list, data_array_list);
928 std::vector<uint32_t> position_list;
929 res = syncReadPosition(id_list, position_list);
930 for (
auto p : position_list)
931 data_array_list.emplace_back(std::array<uint32_t, 2>{ 0, p });
946 std::cout <<
"startup configuration for XL320 not available" << std::endl;
954 std::cout <<
"min position hardcoded for motor XL320" << std::endl;
962 std::cout <<
"max position hardcoded for motor XL320" << std::endl;
969 std::string hardware_message;
971 if (hw_state & 1 << 0)
973 hardware_message +=
"Overload";
975 if (hw_state & 1 << 1)
977 if (!hardware_message.empty())
978 hardware_message +=
", ";
979 hardware_message +=
"OverHeating";
981 if (hw_state & 1 << 2)
983 if (!hardware_message.empty())
984 hardware_message +=
", ";
985 hardware_message +=
"Input voltage out of range";
987 if (hw_state & 1 << 7)
989 if (!hardware_message.empty())
990 hardware_message +=
", ";
991 hardware_message +=
"Disconnection";
994 return hardware_message;
1000 std::cout <<
"readVelocityProfile not available for XL320" << std::endl;
1001 return COMM_SUCCESS;
1007 std::cout <<
"writeVelocityProfile not available for XL320" << std::endl;
1008 return COMM_SUCCESS;
1016 present_position = raw_data;
1022 std::vector<uint32_t> &position_list)
1024 position_list.clear();
1025 std::vector<typename XL320Reg::TYPE_PRESENT_POSITION> raw_data_list{};
1028 for (
auto p : raw_data_list)
1029 position_list.emplace_back(p);
1039 present_velocity = raw_data;
1046 std::vector<uint32_t> &velocity_list)
1048 std::vector<typename XL320Reg::TYPE_PRESENT_VELOCITY> raw_data_list;
1050 for (
auto v : raw_data_list)
1051 velocity_list.emplace_back(v);
1063 std::vector<std::array<uint32_t, 2>> &data_array_list)
1065 int res = COMM_TX_FAIL;
1067 if (id_list.empty())
1070 data_array_list.clear();
1072 std::vector<uint32_t> position_list;
1073 res = syncReadPosition(id_list, position_list);
1074 if (res == COMM_SUCCESS)
1076 for (
auto p : position_list)
1077 data_array_list.emplace_back(std::array<uint32_t, 2>{ 0, p });
1091 std::vector<std::pair<double, uint8_t>> &data_list)
1095 std::vector<std::array<uint8_t, 2>> raw_data;
1098 for (
auto const &data : raw_data)
1101 auto voltage =
static_cast<double>(data.at(0));
1104 uint8_t temperature = data.at(1);
1106 data_list.emplace_back(std::make_pair(voltage, temperature));
1121 int res = COMM_RX_FAIL;
1123 std::vector<std::array<typename XL320Reg::TYPE_PID_GAIN, 3>> raw_data;
1126 for (
int tries = 10; tries > 0; --tries)
1130 if (COMM_SUCCESS == res)
1135 if (COMM_SUCCESS == res && raw_data.size() == 1)
1137 data_list.emplace_back(
static_cast<uint16_t
>(raw_data.at(0).at(2)));
1138 data_list.emplace_back(
static_cast<uint16_t
>(raw_data.at(0).at(1)));
1139 data_list.emplace_back(
static_cast<uint16_t
>(raw_data.at(0).at(0)));
1140 data_list.emplace_back(0);
1141 data_list.emplace_back(0);
1142 data_list.emplace_back(0);
1143 data_list.emplace_back(0);
1147 std::cout <<
"Failures during read PID gains: " << res << std::endl;
1148 return COMM_TX_FAIL;
1151 return COMM_SUCCESS;
1164 int res = COMM_TX_FAIL;
1167 for (
int tries = 10; tries > 0; --tries)
1171 if (COMM_SUCCESS == res)
1174 if (COMM_SUCCESS != res)
1177 for (
int tries = 10; tries > 0; --tries)
1181 if (COMM_SUCCESS == res)
1184 if (COMM_SUCCESS != res)
1187 for (
int tries = 10; tries > 0; --tries)
1191 if (COMM_SUCCESS == res)
1206 const std::vector<uint32_t> &position_list)
1208 std::vector<typename XL320Reg::TYPE_GOAL_POSITION> casted_list;
1209 casted_list.reserve(position_list.size());
1210 for (
auto const &p : position_list)
1225 const std::vector<uint32_t> &velocity_list)
1227 std::vector<typename XL320Reg::TYPE_GOAL_VELOCITY> casted_list;
1228 casted_list.reserve(velocity_list.size());
1229 for (
auto const &v : velocity_list)
1239 std::cout <<
"readControlMode not available for motor XL320" << std::endl;
1240 return COMM_SUCCESS;
1248 std::string hardware_message;
1250 if (hw_state & 1 << 0)
1252 hardware_message +=
"Input Voltage";
1254 if (hw_state & 1 << 2)
1256 if (!hardware_message.empty())
1257 hardware_message +=
", ";
1258 hardware_message +=
"OverHeating";
1260 if (hw_state & 1 << 3)
1262 if (!hardware_message.empty())
1263 hardware_message +=
", ";
1264 hardware_message +=
"Motor Encoder";
1266 if (hw_state & 1 << 4)
1268 if (!hardware_message.empty())
1269 hardware_message +=
", ";
1270 hardware_message +=
"Electrical Shock";
1272 if (hw_state & 1 << 5)
1274 if (!hardware_message.empty())
1275 hardware_message +=
", ";
1276 hardware_message +=
"Overload";
1278 if (hw_state & 1 << 7)
1280 if (!hardware_message.empty())
1281 hardware_message +=
", ";
1282 hardware_message +=
"Disconnection";
1284 if (!hardware_message.empty())
1285 hardware_message +=
" Error";
1287 return hardware_message;
1293 std::cout <<
"writeTorqueGoal not available for motor XL430" << std::endl;
1294 return COMM_TX_ERROR;
1299 const std::vector<uint16_t> & )
1301 std::cout <<
"syncWriteTorqueGoal not available for motor XL430" << std::endl;
1302 return COMM_TX_ERROR;
1310 std::string hardware_message;
1312 if (hw_state & 1 << 0)
1314 hardware_message +=
"Input Voltage";
1316 if (hw_state & 1 << 2)
1318 if (!hardware_message.empty())
1319 hardware_message +=
", ";
1320 hardware_message +=
"OverHeating";
1322 if (hw_state & 1 << 3)
1324 if (!hardware_message.empty())
1325 hardware_message +=
", ";
1326 hardware_message +=
"Motor Encoder";
1328 if (hw_state & 1 << 4)
1330 if (!hardware_message.empty())
1331 hardware_message +=
", ";
1332 hardware_message +=
"Electrical Shock";
1334 if (hw_state & 1 << 5)
1336 if (!hardware_message.empty())
1337 hardware_message +=
", ";
1338 hardware_message +=
"Overload";
1340 if (hw_state & 1 << 7)
1342 if (!hardware_message.empty())
1343 hardware_message +=
", ";
1344 hardware_message +=
"Disconnection";
1346 if (!hardware_message.empty())
1347 hardware_message +=
" Error";
1349 return hardware_message;
1355 std::cout <<
"writeTorqueGoal not available for motor XC430" << std::endl;
1356 return COMM_TX_ERROR;
1361 const std::vector<uint16_t> & )
1363 std::cout <<
"syncWriteTorqueGoal not available for motor XC430" << std::endl;
1364 return COMM_TX_ERROR;
1372 std::string hardware_message;
1374 if (hw_state & 1 << 0)
1376 hardware_message +=
"Input Voltage";
1378 if (hw_state & 1 << 2)
1380 if (!hardware_message.empty())
1381 hardware_message +=
", ";
1382 hardware_message +=
"OverHeating";
1384 if (hw_state & 1 << 3)
1386 if (!hardware_message.empty())
1387 hardware_message +=
", ";
1388 hardware_message +=
"Motor Encoder";
1390 if (hw_state & 1 << 4)
1392 if (!hardware_message.empty())
1393 hardware_message +=
", ";
1394 hardware_message +=
"Electrical Shock";
1396 if (hw_state & 1 << 5)
1398 if (!hardware_message.empty())
1399 hardware_message +=
", ";
1400 hardware_message +=
"Overload";
1402 if (hw_state & 1 << 7)
1404 if (!hardware_message.empty())
1405 hardware_message +=
", ";
1406 hardware_message +=
"Disconnection";
1408 if (!hardware_message.empty())
1409 hardware_message +=
" Error";
1411 return hardware_message;
1424 const std::vector<uint16_t> &torque_list)
1446 std::string hardware_message;
1448 if (hw_state & 1 << 0)
1450 hardware_message +=
"Input Voltage";
1452 if (hw_state & 1 << 2)
1454 if (!hardware_message.empty())
1455 hardware_message +=
", ";
1456 hardware_message +=
"OverHeating";
1458 if (hw_state & 1 << 3)
1460 if (!hardware_message.empty())
1461 hardware_message +=
", ";
1462 hardware_message +=
"Motor Encoder";
1464 if (hw_state & 1 << 4)
1466 if (!hardware_message.empty())
1467 hardware_message +=
", ";
1468 hardware_message +=
"Electrical Shock";
1470 if (hw_state & 1 << 5)
1472 if (!hardware_message.empty())
1473 hardware_message +=
", ";
1474 hardware_message +=
"Overload";
1476 if (hw_state & 1 << 7)
1478 if (!hardware_message.empty())
1479 hardware_message +=
", ";
1480 hardware_message +=
"Disconnection";
1482 if (!hardware_message.empty())
1483 hardware_message +=
" Error";
1485 return hardware_message;
1498 const std::vector<uint16_t> &torque_list)
1532 std::string hardware_message;
1534 if (hw_state & 1 << 0)
1536 hardware_message +=
"Input Voltage";
1538 if (hw_state & 1 << 2)
1540 if (!hardware_message.empty())
1541 hardware_message +=
", ";
1542 hardware_message +=
"OverHeating";
1544 if (hw_state & 1 << 3)
1546 if (!hardware_message.empty())
1547 hardware_message +=
", ";
1548 hardware_message +=
"Motor Encoder";
1550 if (hw_state & 1 << 4)
1552 if (!hardware_message.empty())
1553 hardware_message +=
", ";
1554 hardware_message +=
"Electrical Shock";
1556 if (hw_state & 1 << 5)
1558 if (!hardware_message.empty())
1559 hardware_message +=
", ";
1560 hardware_message +=
"Overload";
1562 if (hw_state & 1 << 7)
1564 if (!hardware_message.empty())
1565 hardware_message +=
", ";
1566 hardware_message +=
"Disconnection";
1568 if (!hardware_message.empty())
1569 hardware_message +=
" Error";
1571 return hardware_message;
1582 const std::vector<uint16_t> &torque_list)