dxl_driver.hpp
Go to the documentation of this file.
1 /*
2 dxl_driver.hpp
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 
17 #ifndef DXL_DRIVER_HPP
18 #define DXL_DRIVER_HPP
19 
20 #include <memory>
21 #include <vector>
22 #include <string>
23 #include <iostream>
24 #include <sstream>
25 #include <cassert>
26 
27 #include "abstract_dxl_driver.hpp"
28 #include "common/common_defs.hpp"
29 
30 #include "xc430_reg.hpp"
31 #include "xl430_reg.hpp"
32 #include "xm430_reg.hpp"
33 #include "xl330_reg.hpp"
34 #include "xl320_reg.hpp"
35 #include "xh430_reg.hpp"
36 
37 namespace ttl_driver
38 {
39 
43 template <typename reg_type>
45 {
46 public:
47  DxlDriver(std::shared_ptr<dynamixel::PortHandler> portHandler,
48  std::shared_ptr<dynamixel::PacketHandler> packetHandler);
49 
50  std::string str() const override;
51  std::string interpretErrorState(uint32_t hw_state) const override;
52 
53 public:
54  int checkModelNumber(uint8_t id, uint16_t &model_number) override;
55  int readFirmwareVersion(uint8_t id, std::string &version) override;
56 
57  int readTemperature(uint8_t id, uint8_t &temperature) override;
58  int readVoltage(uint8_t id, double &voltage) override;
59  int readHwErrorStatus(uint8_t id, uint8_t &hardware_error_status) override;
60 
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;
65  int syncReadHwStatus(const std::vector<uint8_t> &id_list,
66  std::vector<std::pair<double, uint8_t>> &data_list) override;
67 
68  int syncReadHwErrorStatus(const std::vector<uint8_t> &id_list, std::vector<uint8_t> &hw_error_list) override;
69 
70 protected:
71  // AbstractTtlDriver interface
72  std::string interpretFirmwareVersion(uint32_t fw_version) const override;
73 
74 public:
75  // AbstractMotorDriver interface : we cannot define them globally in AbstractMotorDriver
76  // as it is needed here for polymorphism (AbstractMotorDriver cannot be a template class and does not
77  // have access to reg_type). So it seems like a duplicate of StepperDriver
78 
79  // eeprom write
80  int changeId(uint8_t id, uint8_t new_id) override;
81 
82  // eeprom read
83  int readMinPosition(uint8_t id, uint32_t &min_pos) override;
84  int readMaxPosition(uint8_t id, uint32_t &max_pos) override;
85 
86  // ram write
87  int writeVelocityProfile(uint8_t id, const std::vector<uint32_t> &data_list) override;
88 
89  int writeTorquePercentage(uint8_t id, uint8_t torque_percentage) override;
90 
91  int writePositionGoal(uint8_t id, uint32_t position) override;
92  int writeVelocityGoal(uint8_t id, uint32_t velocity) override;
93 
94  int syncWriteTorquePercentage(const std::vector<uint8_t> &id_list,
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;
98 
99  // ram read
100  int readVelocityProfile(uint8_t id, std::vector<uint32_t> &data_list) override;
101 
102  int readPosition(uint8_t id, uint32_t &present_position) override;
103  int readVelocity(uint8_t id, uint32_t &present_velocity) override;
104 
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;
107  int syncReadJointStatus(const std::vector<uint8_t> &id_list,
108  std::vector<std::array<uint32_t, 2>> &data_array_list) override;
109 
110 public:
111  // AbstractDxlDriver interface
112 
113  // eeprom read
114 
115  // eeprom write
116  int writeStartupConfiguration(uint8_t id, uint8_t config) override;
117  int writeTemperatureLimit(uint8_t id, uint8_t temperature_limit) override;
118  int writeShutdownConfiguration(uint8_t id, uint8_t configuration) override;
119 
120  // ram read
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;
123 
124  int readPID(uint8_t id, std::vector<uint16_t> &data_list) override;
125  int readControlMode(uint8_t id, uint8_t &control_mode) override;
126 
127  int readMoving(uint8_t id, uint8_t &status) override;
128 
129  // ram write
130  int writePID(uint8_t id, const std::vector<uint16_t> &data) override;
131  int writeControlMode(uint8_t id, uint8_t control_mode) override;
132 
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;
135 
136  int writeTorqueGoal(uint8_t id, uint16_t torque) override;
137  int syncWriteTorqueGoal(const std::vector<uint8_t> &id_list, const std::vector<uint16_t> &torque_list) override;
138 };
139 
140 // definition of methods
141 
145 template <typename reg_type>
146 DxlDriver<reg_type>::DxlDriver(std::shared_ptr<dynamixel::PortHandler> portHandler,
147  std::shared_ptr<dynamixel::PacketHandler> packetHandler)
148  : AbstractDxlDriver(std::move(portHandler), std::move(packetHandler))
149 {
150 }
151 
152 //*****************************
153 // AbstractMotorDriver interface
154 //*****************************
155 
160 template <typename reg_type>
161 std::string DxlDriver<reg_type>::str() const
162 {
163  return common::model::HardwareTypeEnum(reg_type::motor_type).toString() + " : " + AbstractDxlDriver::str();
164 }
165 
170 template <typename reg_type>
171 std::string DxlDriver<reg_type>::interpretErrorState(uint32_t /*hw_state*/) const
172 {
173  return "";
174 }
175 
181 template <typename reg_type>
182 std::string DxlDriver<reg_type>::interpretFirmwareVersion(uint32_t fw_version) const
183 {
184  std::string version = std::to_string(static_cast<uint8_t>(fw_version));
185 
186  return version;
187 }
188 
195 template <typename reg_type>
196 int DxlDriver<reg_type>::changeId(uint8_t id, uint8_t new_id)
197 {
198  return write<typename reg_type::TYPE_ID>(reg_type::ADDR_ID, id, new_id);
199 }
200 
206 template <typename reg_type>
207 int DxlDriver<reg_type>::checkModelNumber(uint8_t id, uint16_t &model_number)
208 {
209  int ping_result = getModelNumber(id, model_number);
210 
211  if (ping_result == COMM_SUCCESS)
212  {
213  if (model_number && model_number != reg_type::MODEL_NUMBER)
214  {
215  return PING_WRONG_MODEL_NUMBER;
216  }
217  }
218 
219  return ping_result;
220 }
221 
228 template <typename reg_type>
229 int DxlDriver<reg_type>::readFirmwareVersion(uint8_t id, std::string &version)
230 {
231  int res = COMM_RX_FAIL;
232  uint8_t data{};
233  res = read<typename reg_type::TYPE_FIRMWARE_VERSION>(reg_type::ADDR_FIRMWARE_VERSION, id, data);
234  version = interpretFirmwareVersion(data);
235  return res;
236 }
237 
244 template <typename reg_type>
245 int DxlDriver<reg_type>::writeStartupConfiguration(uint8_t id, uint8_t config)
246 {
247  std::string version;
248  int res = readFirmwareVersion(id, version);
249 
250  // only for version above certain version (see registers)
251  if (COMM_SUCCESS == res && std::stoi(version) >= reg_type::VERSION_STARTUP_CONFIGURATION)
252  {
253  res = write<typename reg_type::TYPE_STARTUP_CONFIGURATION>(reg_type::ADDR_STARTUP_CONFIGURATION, id, config);
254  }
255  else
256  {
257  std::cout << "Startup configuration available only for version > "
258  << static_cast<int>(reg_type::VERSION_STARTUP_CONFIGURATION) << std::endl;
259  res = COMM_SUCCESS;
260  }
261 
262  return res;
263 }
264 
271 template <typename reg_type>
272 int DxlDriver<reg_type>::writeTemperatureLimit(uint8_t id, uint8_t temperature_limit)
273 {
274  std::cout << "temperature limit not available for this motor type" << std::endl;
275  return COMM_SUCCESS;
276 }
277 
284 template <typename reg_type>
285 int DxlDriver<reg_type>::writeShutdownConfiguration(uint8_t id, uint8_t configuration)
286 {
287  std::cout << "shutdown configuration not available for this motor type" << std::endl;
288  return COMM_SUCCESS;
289 }
290 
297 template <typename reg_type>
298 int DxlDriver<reg_type>::readMinPosition(uint8_t id, uint32_t &pos)
299 {
300  return read<typename reg_type::TYPE_MIN_POSITION_LIMIT>(reg_type::ADDR_MIN_POSITION_LIMIT, id, pos);
301 }
302 
309 template <typename reg_type>
310 int DxlDriver<reg_type>::readMaxPosition(uint8_t id, uint32_t &pos)
311 {
312  return read<typename reg_type::TYPE_MAX_POSITION_LIMIT>(reg_type::ADDR_MAX_POSITION_LIMIT, id, pos);
313 }
314 
315 // ram write
316 
324 template <typename reg_type>
325 int DxlDriver<reg_type>::writeVelocityProfile(uint8_t id, const std::vector<uint32_t> &data_list)
326 {
327  // in mode control Position Control Mode, velocity profile in datasheet is used to write velocity (except xl320)
328  int res = COMM_RX_FAIL;
329 
330  for (int tries = 10; tries > 0; --tries)
331  {
332  res = write<typename reg_type::TYPE_PROFILE>(reg_type::ADDR_PROFILE_VELOCITY, id, data_list.at(0));
333  if (COMM_SUCCESS == res)
334  break;
335  }
336 
337  for (int tries = 10; tries > 0; --tries)
338  {
339  res = write<typename reg_type::TYPE_PROFILE>(reg_type::ADDR_PROFILE_ACCELERATION, id, data_list.at(1));
340  if (COMM_SUCCESS == res)
341  break;
342  }
343 
344  if (COMM_SUCCESS != res)
345  return res;
346 
347  return res;
348 }
349 
356 template <typename reg_type>
357 int DxlDriver<reg_type>::writeTorquePercentage(uint8_t id, uint8_t torque_percentage)
358 {
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);
361 }
362 
369 template <typename reg_type>
370 int DxlDriver<reg_type>::writePositionGoal(uint8_t id, uint32_t position)
371 {
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));
374 }
375 
382 template <typename reg_type>
383 int DxlDriver<reg_type>::writeVelocityGoal(uint8_t id, uint32_t velocity)
384 {
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));
387 }
388 
395 template <typename reg_type>
396 int DxlDriver<reg_type>::syncWriteTorquePercentage(const std::vector<uint8_t> &id_list,
397  const std::vector<uint8_t> &torque_percentage_list)
398 {
399  std::vector<uint8_t> torque_enable_list;
400  for (const auto &torque_percentage : torque_percentage_list)
401  {
402  auto torque_enable = torque_percentage > 0 ? 1 : 0;
403  torque_enable_list.push_back(torque_enable);
404  }
405  return syncWrite<typename reg_type::TYPE_TORQUE_ENABLE>(reg_type::ADDR_TORQUE_ENABLE, id_list, torque_enable_list);
406 }
407 
414 template <typename reg_type>
415 int DxlDriver<reg_type>::syncWritePositionGoal(const std::vector<uint8_t> &id_list,
416  const std::vector<uint32_t> &position_list)
417 {
418  return syncWrite<typename reg_type::TYPE_GOAL_POSITION>(reg_type::ADDR_GOAL_POSITION, id_list, position_list);
419 }
420 
427 template <typename reg_type>
428 int DxlDriver<reg_type>::syncWriteVelocityGoal(const std::vector<uint8_t> &id_list,
429  const std::vector<uint32_t> &velocity_list)
430 {
431  return syncWrite<typename reg_type::TYPE_GOAL_VELOCITY>(reg_type::ADDR_GOAL_VELOCITY, id_list, velocity_list);
432 }
433 
434 // ram read
435 template <typename reg_type>
436 int DxlDriver<reg_type>::readVelocityProfile(uint8_t id, std::vector<uint32_t> &data_list)
437 {
438  data_list.clear();
439  typename reg_type::TYPE_PROFILE velocity_profile{};
440  typename reg_type::TYPE_PROFILE acceleration_profile{};
441 
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);
445 
446  data_list.emplace_back(velocity_profile);
447  data_list.emplace_back(acceleration_profile);
448 
449  return res;
450 }
451 
458 template <typename reg_type>
459 int DxlDriver<reg_type>::readPosition(uint8_t id, uint32_t &present_position)
460 {
461  return read<typename reg_type::TYPE_PRESENT_POSITION>(reg_type::ADDR_PRESENT_POSITION, id, present_position);
462 }
463 
470 template <typename reg_type>
471 int DxlDriver<reg_type>::readTemperature(uint8_t id, uint8_t &temperature)
472 {
473  return read<typename reg_type::TYPE_PRESENT_TEMPERATURE>(reg_type::ADDR_PRESENT_TEMPERATURE, id, temperature);
474 }
475 
482 template <typename reg_type>
483 int DxlDriver<reg_type>::readVoltage(uint8_t id, double &voltage)
484 {
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;
488  return res;
489 }
490 
497 template <typename reg_type>
498 int DxlDriver<reg_type>::readHwErrorStatus(uint8_t id, uint8_t &hardware_error_status)
499 {
500  return read<typename reg_type::TYPE_HW_ERROR_STATUS>(reg_type::ADDR_HW_ERROR_STATUS, id, hardware_error_status);
501 }
502 
509 template <typename reg_type>
510 int DxlDriver<reg_type>::syncReadPosition(const std::vector<uint8_t> &id_list, std::vector<uint32_t> &position_list)
511 {
512  return syncRead<typename reg_type::TYPE_PRESENT_POSITION>(reg_type::ADDR_PRESENT_POSITION, id_list, position_list);
513 }
514 
521 template <typename reg_type>
522 int DxlDriver<reg_type>::writePID(uint8_t id, const std::vector<uint16_t> &data)
523 {
524  int res = COMM_TX_FAIL;
525 
526  // only rewrite params which is not success
527  for (int tries = 10; tries > 0; --tries)
528  {
529  res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_POSITION_P_GAIN, id, data.at(0));
530  if (COMM_SUCCESS == res)
531  break;
532  }
533 
534  if (COMM_SUCCESS != res)
535  return res;
536 
537  for (int tries = 10; tries > 0; --tries)
538  {
539  res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_POSITION_I_GAIN, id, data.at(1));
540  if (COMM_SUCCESS == res)
541  break;
542  }
543  if (COMM_SUCCESS != res)
544  return res;
545 
546  for (int tries = 10; tries > 0; --tries)
547  {
548  res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_POSITION_D_GAIN, id, data.at(2));
549  if (COMM_SUCCESS == res)
550  break;
551  }
552  if (COMM_SUCCESS != res)
553  return res;
554 
555  for (int tries = 10; tries > 0; --tries)
556  {
557  res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_VELOCITY_P_GAIN, id, data.at(3));
558  if (COMM_SUCCESS == res)
559  break;
560  }
561  if (COMM_SUCCESS != res)
562  return res;
563 
564  for (int tries = 10; tries > 0; --tries)
565  {
566  res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_VELOCITY_I_GAIN, id, data.at(4));
567  if (COMM_SUCCESS == res)
568  break;
569  }
570  if (COMM_SUCCESS != res)
571  return res;
572 
573  for (int tries = 10; tries > 0; --tries)
574  {
575  res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_FF1_GAIN, id, data.at(5));
576  if (COMM_SUCCESS == res)
577  break;
578  }
579  if (COMM_SUCCESS != res)
580  return res;
581 
582  for (int tries = 10; tries > 0; --tries)
583  {
584  res = write<typename reg_type::TYPE_PID_GAIN>(reg_type::ADDR_FF2_GAIN, id, data.at(6));
585  if (res == COMM_SUCCESS)
586  break;
587  }
588 
589  return res;
590 }
591 
598 template <typename reg_type>
599 int DxlDriver<reg_type>::syncReadFirmwareVersion(const std::vector<uint8_t> &id_list,
600  std::vector<std::string> &firmware_list)
601 {
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));
607  return res;
608 }
609 
616 template <typename reg_type>
617 int DxlDriver<reg_type>::syncReadTemperature(const std::vector<uint8_t> &id_list,
618  std::vector<uint8_t> &temperature_list)
619 {
620  return syncRead<typename reg_type::TYPE_PRESENT_TEMPERATURE>(reg_type::ADDR_PRESENT_TEMPERATURE, id_list,
621  temperature_list);
622 }
623 
630 template <typename reg_type>
631 int DxlDriver<reg_type>::syncReadVoltage(const std::vector<uint8_t> &id_list, std::vector<double> &voltage_list)
632 {
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);
638  return res;
639 }
640 
647 template <typename reg_type>
648 int DxlDriver<reg_type>::syncReadRawVoltage(const std::vector<uint8_t> &id_list, std::vector<double> &voltage_list)
649 {
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));
655  return res;
656 }
657 
664 template <typename reg_type>
665 int DxlDriver<reg_type>::syncReadHwStatus(const std::vector<uint8_t> &id_list,
666  std::vector<std::pair<double, uint8_t>> &data_list)
667 {
668  data_list.clear();
669 
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);
672 
673  for (auto const &data : raw_data)
674  {
675  // Voltage is first reg, uint16
676  auto voltage = static_cast<double>((static_cast<uint16_t>(data.at(1)) << 8) | data.at(0));
677 
678  // Temperature is second reg, uint8
679  uint8_t temperature = data.at(2);
680 
681  data_list.emplace_back(std::make_pair(voltage, temperature));
682  }
683 
684  return res;
685 }
686 
693 template <typename reg_type>
694 int DxlDriver<reg_type>::syncReadHwErrorStatus(const std::vector<uint8_t> &id_list, std::vector<uint8_t> &hw_error_list)
695 {
696  return syncRead<typename reg_type::TYPE_HW_ERROR_STATUS>(reg_type::ADDR_HW_ERROR_STATUS, id_list, hw_error_list);
697 }
698 
699 //*****************************
700 // AbstractDxlDriver interface
701 //*****************************
702 
709 template <typename reg_type>
710 int DxlDriver<reg_type>::writeLed(uint8_t id, uint8_t led_value)
711 {
712  return write<typename reg_type::TYPE_LED>(reg_type::ADDR_LED, id, led_value);
713 }
714 
721 template <typename reg_type>
722 int DxlDriver<reg_type>::syncWriteLed(const std::vector<uint8_t> &id_list, const std::vector<uint8_t> &led_list)
723 {
724  return syncWrite<typename reg_type::TYPE_LED>(reg_type::ADDR_LED, id_list, led_list);
725 }
726 
733 template <typename reg_type>
734 int DxlDriver<reg_type>::writeTorqueGoal(uint8_t id, uint16_t torque)
735 {
736  return write<typename reg_type::TYPE_GOAL_TORQUE>(reg_type::ADDR_GOAL_TORQUE, id, torque);
737 }
738 
745 template <typename reg_type>
746 int DxlDriver<reg_type>::syncWriteTorqueGoal(const std::vector<uint8_t> &id_list,
747  const std::vector<uint16_t> &torque_list)
748 {
749  return syncWrite<typename reg_type::TYPE_GOAL_TORQUE>(reg_type::ADDR_GOAL_TORQUE, id_list, torque_list);
750 }
751 
752 // read
753 
760 template <typename reg_type>
761 int DxlDriver<reg_type>::readPID(uint8_t id, std::vector<uint16_t> &data_list)
762 {
763  int res = 0;
764  data_list.clear();
765  std::vector<std::array<typename reg_type::TYPE_PID_GAIN, 8>> raw_data;
766 
767  // only rewrite params which is not success
768  for (int tries = 10; tries > 0; --tries)
769  {
770  res =
771  syncReadConsecutiveBytes<typename reg_type::TYPE_PID_GAIN, 8>(reg_type::ADDR_VELOCITY_I_GAIN, { id }, raw_data);
772  if (COMM_SUCCESS == res)
773  break;
774  }
775 
776  // we need to reorder the data in its correct place in data_list
777  if (COMM_SUCCESS == res && raw_data.size() == 1)
778  {
779  data_list.emplace_back(raw_data.at(0).at(4)); // pos p is 5th
780  data_list.emplace_back(raw_data.at(0).at(3)); // pos i is 4th
781  data_list.emplace_back(raw_data.at(0).at(2)); // pos d is 3rd
782  data_list.emplace_back(raw_data.at(0).at(1)); // vel p is 2nd
783  data_list.emplace_back(raw_data.at(0).at(0)); // vel i is 1st
784  data_list.emplace_back(raw_data.at(0).at(7)); // ff1 is 8th
785  data_list.emplace_back(raw_data.at(0).at(6)); // ff2 is 7th
786  // nothing at 6th
787  }
788  else
789  {
790  std::cout << "Failures during read PID gains: " << res << std::endl;
791  return COMM_TX_FAIL;
792  }
793 
794  return COMM_SUCCESS;
795 }
796 
803 template <typename reg_type>
804 int DxlDriver<reg_type>::readMoving(uint8_t id, uint8_t &status)
805 {
806  return read<typename reg_type::TYPE_MOVING>(reg_type::ADDR_MOVING, id, status);
807 }
808 
815 template <typename reg_type>
816 int DxlDriver<reg_type>::writeControlMode(uint8_t id, uint8_t control_mode)
817 {
818  int res = COMM_TX_ERROR;
819  uint8_t torque{ 0 };
820  res = read<typename reg_type::TYPE_TORQUE_ENABLE>(reg_type::ADDR_TORQUE_ENABLE, id, torque);
821  if (res == COMM_SUCCESS)
822  {
823  if (torque == 0)
824  {
825  return write<typename reg_type::TYPE_OPERATING_MODE>(reg_type::ADDR_OPERATING_MODE, id, control_mode);
826  }
827  }
828  return res;
829 }
830 
837 template <typename reg_type>
838 int DxlDriver<reg_type>::readControlMode(uint8_t id, uint8_t &control_mode)
839 {
840  int res = 0;
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);
844  return res;
845 }
846 // other
847 
854 template <typename reg_type>
855 int DxlDriver<reg_type>::readLoad(uint8_t id, uint16_t &present_load)
856 {
857  return read<typename reg_type::TYPE_PRESENT_LOAD>(reg_type::ADDR_PRESENT_LOAD, id, present_load);
858 }
859 
866 template <typename reg_type>
867 int DxlDriver<reg_type>::syncReadLoad(const std::vector<uint8_t> &id_list, std::vector<uint16_t> &load_list)
868 {
869  return syncRead<typename reg_type::TYPE_PRESENT_LOAD>(reg_type::ADDR_PRESENT_LOAD, id_list, load_list);
870 }
871 
878 template <typename reg_type>
879 int DxlDriver<reg_type>::readVelocity(uint8_t id, uint32_t &present_velocity)
880 {
881  return read<typename reg_type::TYPE_PRESENT_VELOCITY>(reg_type::ADDR_PRESENT_VELOCITY, id, present_velocity);
882 }
883 
890 template <typename reg_type>
891 int DxlDriver<reg_type>::syncReadVelocity(const std::vector<uint8_t> &id_list, std::vector<uint32_t> &velocity_list)
892 {
893  return syncRead<typename reg_type::TYPE_PRESENT_VELOCITY>(reg_type::ADDR_PRESENT_VELOCITY, id_list, velocity_list);
894 }
895 
902 template <typename reg_type>
903 int DxlDriver<reg_type>::syncReadJointStatus(const std::vector<uint8_t> &id_list,
904  std::vector<std::array<uint32_t, 2>> &data_array_list)
905 {
906  int res = COMM_TX_FAIL;
907 
908  if (id_list.empty())
909  return res;
910 
911  data_array_list.clear();
912 
913  // read torque enable on first id
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;
920 
921  // if torque on, read position and velocity
922  if (torque)
923  {
924  res = syncReadConsecutiveBytes<uint32_t, 2>(reg_type::ADDR_PRESENT_VELOCITY, id_list, data_array_list);
925  }
926  else // else read position only
927  {
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 });
932  }
933 
934  return res;
935 }
936 
937 /*
938  * ----------------- specializations --------------------
939  */
940 
941 // XL320
942 
943 template <>
944 inline int DxlDriver<XL320Reg>::writeStartupConfiguration(uint8_t /*id*/, uint8_t /*config*/)
945 {
946  std::cout << "startup configuration for XL320 not available" << std::endl;
947  return COMM_SUCCESS;
948 }
949 
950 template <>
951 inline int DxlDriver<XL320Reg>::readMinPosition(uint8_t /*id*/, uint32_t &pos)
952 {
953  pos = 0;
954  std::cout << "min position hardcoded for motor XL320" << std::endl;
955  return COMM_SUCCESS;
956 }
957 
958 template <>
959 inline int DxlDriver<XL320Reg>::readMaxPosition(uint8_t /*id*/, uint32_t &pos)
960 {
961  pos = 1023;
962  std::cout << "max position hardcoded for motor XL320" << std::endl;
963  return COMM_SUCCESS;
964 }
965 
966 template <>
967 inline std::string DxlDriver<XL320Reg>::interpretErrorState(uint32_t hw_state) const
968 {
969  std::string hardware_message;
970 
971  if (hw_state & 1 << 0) // 0b00000001
972  {
973  hardware_message += "Overload";
974  }
975  if (hw_state & 1 << 1) // 0b00000010
976  {
977  if (!hardware_message.empty())
978  hardware_message += ", ";
979  hardware_message += "OverHeating";
980  }
981  if (hw_state & 1 << 2) // 0b00000100
982  {
983  if (!hardware_message.empty())
984  hardware_message += ", ";
985  hardware_message += "Input voltage out of range";
986  }
987  if (hw_state & 1 << 7) // 0b10000000 => added by us : disconnected error
988  {
989  if (!hardware_message.empty())
990  hardware_message += ", ";
991  hardware_message += "Disconnection";
992  }
993 
994  return hardware_message;
995 }
996 
997 template <>
998 inline int DxlDriver<XL320Reg>::readVelocityProfile(uint8_t /*id*/, std::vector<uint32_t> & /*data_list*/)
999 {
1000  std::cout << "readVelocityProfile not available for XL320" << std::endl;
1001  return COMM_SUCCESS;
1002 }
1003 
1004 template <>
1005 inline int DxlDriver<XL320Reg>::writeVelocityProfile(uint8_t /*id*/, const std::vector<uint32_t> & /*data_list*/)
1006 {
1007  std::cout << "writeVelocityProfile not available for XL320" << std::endl;
1008  return COMM_SUCCESS;
1009 }
1010 
1011 template <>
1012 inline int DxlDriver<XL320Reg>::readPosition(uint8_t id, uint32_t &present_position)
1013 {
1014  typename XL320Reg::TYPE_PRESENT_POSITION raw_data{};
1015  int res = read<typename XL320Reg::TYPE_PRESENT_POSITION>(XL320Reg::ADDR_PRESENT_POSITION, id, raw_data);
1016  present_position = raw_data;
1017  return res;
1018 }
1019 
1020 template <>
1021 inline int DxlDriver<XL320Reg>::syncReadPosition(const std::vector<uint8_t> &id_list,
1022  std::vector<uint32_t> &position_list)
1023 {
1024  position_list.clear();
1025  std::vector<typename XL320Reg::TYPE_PRESENT_POSITION> raw_data_list{};
1026 
1027  int res = syncRead<typename XL320Reg::TYPE_PRESENT_POSITION>(XL320Reg::ADDR_PRESENT_POSITION, id_list, raw_data_list);
1028  for (auto p : raw_data_list)
1029  position_list.emplace_back(p);
1030 
1031  return res;
1032 }
1033 
1034 template <>
1035 inline int DxlDriver<XL320Reg>::readVelocity(uint8_t id, uint32_t &present_velocity)
1036 {
1037  typename XL320Reg::TYPE_PRESENT_VELOCITY raw_data{};
1038  int res = read<typename XL320Reg::TYPE_PRESENT_VELOCITY>(XL320Reg::ADDR_PRESENT_VELOCITY, id, raw_data);
1039  present_velocity = raw_data;
1040 
1041  return res;
1042 }
1043 
1044 template <>
1045 inline int DxlDriver<XL320Reg>::syncReadVelocity(const std::vector<uint8_t> &id_list,
1046  std::vector<uint32_t> &velocity_list)
1047 {
1048  std::vector<typename XL320Reg::TYPE_PRESENT_VELOCITY> raw_data_list;
1049  int res = syncRead<typename XL320Reg::TYPE_PRESENT_VELOCITY>(XL320Reg::ADDR_PRESENT_VELOCITY, id_list, raw_data_list);
1050  for (auto v : raw_data_list)
1051  velocity_list.emplace_back(v);
1052  return res;
1053 }
1054 
1061 template <>
1062 inline int DxlDriver<XL320Reg>::syncReadJointStatus(const std::vector<uint8_t> &id_list,
1063  std::vector<std::array<uint32_t, 2>> &data_array_list)
1064 {
1065  int res = COMM_TX_FAIL;
1066 
1067  if (id_list.empty())
1068  return res;
1069 
1070  data_array_list.clear();
1071 
1072  std::vector<uint32_t> position_list;
1073  res = syncReadPosition(id_list, position_list);
1074  if (res == COMM_SUCCESS)
1075  {
1076  for (auto p : position_list)
1077  data_array_list.emplace_back(std::array<uint32_t, 2>{ 0, p });
1078  }
1079 
1080  return res;
1081 }
1082 
1089 template <>
1090 inline int DxlDriver<XL320Reg>::syncReadHwStatus(const std::vector<uint8_t> &id_list,
1091  std::vector<std::pair<double, uint8_t>> &data_list)
1092 {
1093  data_list.clear();
1094 
1095  std::vector<std::array<uint8_t, 2>> raw_data;
1096  int res = syncReadConsecutiveBytes<uint8_t, 2>(XL320Reg::ADDR_PRESENT_VOLTAGE, id_list, raw_data);
1097 
1098  for (auto const &data : raw_data)
1099  {
1100  // Voltage is first reg, uint16
1101  auto voltage = static_cast<double>(data.at(0));
1102 
1103  // Temperature is second reg, uint8
1104  uint8_t temperature = data.at(1);
1105 
1106  data_list.emplace_back(std::make_pair(voltage, temperature));
1107  }
1108 
1109  return res;
1110 }
1111 
1118 template <>
1119 inline int DxlDriver<XL320Reg>::readPID(uint8_t id, std::vector<uint16_t> &data_list)
1120 {
1121  int res = COMM_RX_FAIL;
1122  data_list.clear();
1123  std::vector<std::array<typename XL320Reg::TYPE_PID_GAIN, 3>> raw_data;
1124 
1125  // only rewrite params which is not success
1126  for (int tries = 10; tries > 0; --tries)
1127  {
1128  res =
1129  syncReadConsecutiveBytes<typename XL320Reg::TYPE_PID_GAIN, 3>(XL320Reg::ADDR_POSITION_D_GAIN, { id }, raw_data);
1130  if (COMM_SUCCESS == res)
1131  break;
1132  }
1133 
1134  // we need to reorder the data in its correct place in data_list
1135  if (COMM_SUCCESS == res && raw_data.size() == 1)
1136  {
1137  data_list.emplace_back(static_cast<uint16_t>(raw_data.at(0).at(2))); // pos p is 3rd
1138  data_list.emplace_back(static_cast<uint16_t>(raw_data.at(0).at(1))); // pos i is 2nd
1139  data_list.emplace_back(static_cast<uint16_t>(raw_data.at(0).at(0))); // pos d is 1st
1140  data_list.emplace_back(0); // no vel p
1141  data_list.emplace_back(0); // no vel i
1142  data_list.emplace_back(0); // no ff1
1143  data_list.emplace_back(0); // no ff2
1144  }
1145  else
1146  {
1147  std::cout << "Failures during read PID gains: " << res << std::endl;
1148  return COMM_TX_FAIL;
1149  }
1150 
1151  return COMM_SUCCESS;
1152 }
1153 
1161 template <>
1162 inline int DxlDriver<XL320Reg>::writePID(uint8_t id, const std::vector<uint16_t> &data_list)
1163 {
1164  int res = COMM_TX_FAIL;
1165 
1166  // only rewrite params which is not success
1167  for (int tries = 10; tries > 0; --tries)
1168  {
1169  res = write<typename XL320Reg::TYPE_PID_GAIN>(XL320Reg::ADDR_POSITION_P_GAIN, id,
1170  static_cast<typename XL320Reg::TYPE_PID_GAIN>(data_list.at(0)));
1171  if (COMM_SUCCESS == res)
1172  break;
1173  }
1174  if (COMM_SUCCESS != res)
1175  return res;
1176 
1177  for (int tries = 10; tries > 0; --tries)
1178  {
1179  res = write<typename XL320Reg::TYPE_PID_GAIN>(XL320Reg::ADDR_POSITION_I_GAIN, id,
1180  static_cast<typename XL320Reg::TYPE_PID_GAIN>(data_list.at(1)));
1181  if (COMM_SUCCESS == res)
1182  break;
1183  }
1184  if (COMM_SUCCESS != res)
1185  return res;
1186 
1187  for (int tries = 10; tries > 0; --tries)
1188  {
1189  res = write<typename XL320Reg::TYPE_PID_GAIN>(XL320Reg::ADDR_POSITION_D_GAIN, id,
1190  static_cast<typename XL320Reg::TYPE_PID_GAIN>(data_list.at(2)));
1191  if (COMM_SUCCESS == res)
1192  break;
1193  }
1194 
1195  return res;
1196 }
1197 
1204 template <>
1205 inline int DxlDriver<XL320Reg>::syncWritePositionGoal(const std::vector<uint8_t> &id_list,
1206  const std::vector<uint32_t> &position_list)
1207 {
1208  std::vector<typename XL320Reg::TYPE_GOAL_POSITION> casted_list;
1209  casted_list.reserve(position_list.size());
1210  for (auto const &p : position_list)
1211  {
1212  casted_list.emplace_back(static_cast<typename XL320Reg::TYPE_GOAL_POSITION>(p));
1213  }
1214  return syncWrite<typename XL320Reg::TYPE_GOAL_POSITION>(XL320Reg::ADDR_GOAL_POSITION, id_list, casted_list);
1215 }
1216 
1223 template <>
1224 inline int DxlDriver<XL320Reg>::syncWriteVelocityGoal(const std::vector<uint8_t> &id_list,
1225  const std::vector<uint32_t> &velocity_list)
1226 {
1227  std::vector<typename XL320Reg::TYPE_GOAL_VELOCITY> casted_list;
1228  casted_list.reserve(velocity_list.size());
1229  for (auto const &v : velocity_list)
1230  {
1231  casted_list.emplace_back(static_cast<typename XL320Reg::TYPE_GOAL_VELOCITY>(v));
1232  }
1233  return syncWrite<typename XL320Reg::TYPE_GOAL_VELOCITY>(XL320Reg::ADDR_GOAL_VELOCITY, id_list, casted_list);
1234 }
1235 
1236 template <>
1237 inline int DxlDriver<XL320Reg>::readControlMode(uint8_t /*id*/, uint8_t & /*data*/)
1238 {
1239  std::cout << "readControlMode not available for motor XL320" << std::endl;
1240  return COMM_SUCCESS;
1241 }
1242 
1243 // XL430
1244 
1245 template <>
1246 inline std::string DxlDriver<XL430Reg>::interpretErrorState(uint32_t hw_state) const
1247 {
1248  std::string hardware_message;
1249 
1250  if (hw_state & 1 << 0) // 0b00000001
1251  {
1252  hardware_message += "Input Voltage";
1253  }
1254  if (hw_state & 1 << 2) // 0b00000100
1255  {
1256  if (!hardware_message.empty())
1257  hardware_message += ", ";
1258  hardware_message += "OverHeating";
1259  }
1260  if (hw_state & 1 << 3) // 0b00001000
1261  {
1262  if (!hardware_message.empty())
1263  hardware_message += ", ";
1264  hardware_message += "Motor Encoder";
1265  }
1266  if (hw_state & 1 << 4) // 0b00010000
1267  {
1268  if (!hardware_message.empty())
1269  hardware_message += ", ";
1270  hardware_message += "Electrical Shock";
1271  }
1272  if (hw_state & 1 << 5) // 0b00100000
1273  {
1274  if (!hardware_message.empty())
1275  hardware_message += ", ";
1276  hardware_message += "Overload";
1277  }
1278  if (hw_state & 1 << 7) // 0b10000000 => added by us : disconnected error
1279  {
1280  if (!hardware_message.empty())
1281  hardware_message += ", ";
1282  hardware_message += "Disconnection";
1283  }
1284  if (!hardware_message.empty())
1285  hardware_message += " Error";
1286 
1287  return hardware_message;
1288 }
1289 
1290 template <>
1291 inline int DxlDriver<XL430Reg>::writeTorqueGoal(uint8_t /*id*/, uint16_t /*torque*/)
1292 {
1293  std::cout << "writeTorqueGoal not available for motor XL430" << std::endl;
1294  return COMM_TX_ERROR;
1295 }
1296 
1297 template <>
1298 inline int DxlDriver<XL430Reg>::syncWriteTorqueGoal(const std::vector<uint8_t> & /*id_list*/,
1299  const std::vector<uint16_t> & /*torque_list*/)
1300 {
1301  std::cout << "syncWriteTorqueGoal not available for motor XL430" << std::endl;
1302  return COMM_TX_ERROR;
1303 }
1304 
1305 // XC430
1306 
1307 template <>
1308 inline std::string DxlDriver<XC430Reg>::interpretErrorState(uint32_t hw_state) const
1309 {
1310  std::string hardware_message;
1311 
1312  if (hw_state & 1 << 0) // 0b00000001
1313  {
1314  hardware_message += "Input Voltage";
1315  }
1316  if (hw_state & 1 << 2) // 0b00000100
1317  {
1318  if (!hardware_message.empty())
1319  hardware_message += ", ";
1320  hardware_message += "OverHeating";
1321  }
1322  if (hw_state & 1 << 3) // 0b00001000
1323  {
1324  if (!hardware_message.empty())
1325  hardware_message += ", ";
1326  hardware_message += "Motor Encoder";
1327  }
1328  if (hw_state & 1 << 4) // 0b00010000
1329  {
1330  if (!hardware_message.empty())
1331  hardware_message += ", ";
1332  hardware_message += "Electrical Shock";
1333  }
1334  if (hw_state & 1 << 5) // 0b00100000
1335  {
1336  if (!hardware_message.empty())
1337  hardware_message += ", ";
1338  hardware_message += "Overload";
1339  }
1340  if (hw_state & 1 << 7) // 0b10000000 => added by us : disconnected error
1341  {
1342  if (!hardware_message.empty())
1343  hardware_message += ", ";
1344  hardware_message += "Disconnection";
1345  }
1346  if (!hardware_message.empty())
1347  hardware_message += " Error";
1348 
1349  return hardware_message;
1350 }
1351 
1352 template <>
1353 inline int DxlDriver<XC430Reg>::writeTorqueGoal(uint8_t /*id*/, uint16_t /*torque*/)
1354 {
1355  std::cout << "writeTorqueGoal not available for motor XC430" << std::endl;
1356  return COMM_TX_ERROR;
1357 }
1358 
1359 template <>
1360 inline int DxlDriver<XC430Reg>::syncWriteTorqueGoal(const std::vector<uint8_t> & /*id_list*/,
1361  const std::vector<uint16_t> & /*torque_list*/)
1362 {
1363  std::cout << "syncWriteTorqueGoal not available for motor XC430" << std::endl;
1364  return COMM_TX_ERROR;
1365 }
1366 
1367 // XM430
1368 
1369 template <>
1370 inline std::string DxlDriver<XM430Reg>::interpretErrorState(uint32_t hw_state) const
1371 {
1372  std::string hardware_message;
1373 
1374  if (hw_state & 1 << 0) // 0b00000001
1375  {
1376  hardware_message += "Input Voltage";
1377  }
1378  if (hw_state & 1 << 2) // 0b00000100
1379  {
1380  if (!hardware_message.empty())
1381  hardware_message += ", ";
1382  hardware_message += "OverHeating";
1383  }
1384  if (hw_state & 1 << 3) // 0b00001000
1385  {
1386  if (!hardware_message.empty())
1387  hardware_message += ", ";
1388  hardware_message += "Motor Encoder";
1389  }
1390  if (hw_state & 1 << 4) // 0b00010000
1391  {
1392  if (!hardware_message.empty())
1393  hardware_message += ", ";
1394  hardware_message += "Electrical Shock";
1395  }
1396  if (hw_state & 1 << 5) // 0b00100000
1397  {
1398  if (!hardware_message.empty())
1399  hardware_message += ", ";
1400  hardware_message += "Overload";
1401  }
1402  if (hw_state & 1 << 7) // 0b10000000 => added by us : disconnected error
1403  {
1404  if (!hardware_message.empty())
1405  hardware_message += ", ";
1406  hardware_message += "Disconnection";
1407  }
1408  if (!hardware_message.empty())
1409  hardware_message += " Error";
1410 
1411  return hardware_message;
1412 }
1413 
1414 // works with current instead of load
1415 
1416 template <>
1417 inline int DxlDriver<XM430Reg>::writeTorqueGoal(uint8_t id, uint16_t torque)
1418 {
1419  return write<typename XM430Reg::TYPE_GOAL_CURRENT>(XM430Reg::ADDR_GOAL_CURRENT, id, torque);
1420 }
1421 
1422 template <>
1423 inline int DxlDriver<XM430Reg>::syncWriteTorqueGoal(const std::vector<uint8_t> &id_list,
1424  const std::vector<uint16_t> &torque_list)
1425 {
1426  return syncWrite<typename XM430Reg::TYPE_GOAL_CURRENT>(XM430Reg::ADDR_GOAL_CURRENT, id_list, torque_list);
1427 }
1428 
1429 template <>
1430 inline int DxlDriver<XM430Reg>::readLoad(uint8_t id, uint16_t &present_load)
1431 {
1432  return read<typename XM430Reg::TYPE_PRESENT_CURRENT>(XM430Reg::ADDR_PRESENT_CURRENT, id, present_load);
1433 }
1434 
1435 template <>
1436 inline int DxlDriver<XM430Reg>::syncReadLoad(const std::vector<uint8_t> &id_list, std::vector<uint16_t> &load_list)
1437 {
1438  return syncRead<typename XM430Reg::TYPE_PRESENT_CURRENT>(XM430Reg::ADDR_PRESENT_CURRENT, id_list, load_list);
1439 }
1440 
1441 // XL330
1442 
1443 template <>
1444 inline std::string DxlDriver<XL330Reg>::interpretErrorState(uint32_t hw_state) const
1445 {
1446  std::string hardware_message;
1447 
1448  if (hw_state & 1 << 0) // 0b00000001
1449  {
1450  hardware_message += "Input Voltage";
1451  }
1452  if (hw_state & 1 << 2) // 0b00000100
1453  {
1454  if (!hardware_message.empty())
1455  hardware_message += ", ";
1456  hardware_message += "OverHeating";
1457  }
1458  if (hw_state & 1 << 3) // 0b00001000
1459  {
1460  if (!hardware_message.empty())
1461  hardware_message += ", ";
1462  hardware_message += "Motor Encoder";
1463  }
1464  if (hw_state & 1 << 4) // 0b00010000
1465  {
1466  if (!hardware_message.empty())
1467  hardware_message += ", ";
1468  hardware_message += "Electrical Shock";
1469  }
1470  if (hw_state & 1 << 5) // 0b00100000
1471  {
1472  if (!hardware_message.empty())
1473  hardware_message += ", ";
1474  hardware_message += "Overload";
1475  }
1476  if (hw_state & 1 << 7) // 0b10000000 => added by us : disconnected error
1477  {
1478  if (!hardware_message.empty())
1479  hardware_message += ", ";
1480  hardware_message += "Disconnection";
1481  }
1482  if (!hardware_message.empty())
1483  hardware_message += " Error";
1484 
1485  return hardware_message;
1486 }
1487 
1488 // works with current instead of load
1489 
1490 template <>
1491 inline int DxlDriver<XL330Reg>::writeTorqueGoal(uint8_t id, uint16_t torque)
1492 {
1493  return write<typename XL330Reg::TYPE_GOAL_CURRENT>(XL330Reg::ADDR_GOAL_CURRENT, id, torque);
1494 }
1495 
1496 template <>
1497 inline int DxlDriver<XL330Reg>::syncWriteTorqueGoal(const std::vector<uint8_t> &id_list,
1498  const std::vector<uint16_t> &torque_list)
1499 {
1500  return syncWrite<typename XL330Reg::TYPE_GOAL_CURRENT>(XL330Reg::ADDR_GOAL_CURRENT, id_list, torque_list);
1501 }
1502 
1503 template <>
1504 inline int DxlDriver<XL330Reg>::readLoad(uint8_t id, uint16_t &present_load)
1505 {
1506  return read<typename XL330Reg::TYPE_PRESENT_CURRENT>(XL330Reg::ADDR_PRESENT_CURRENT, id, present_load);
1507 }
1508 
1509 template <>
1510 inline int DxlDriver<XL330Reg>::syncReadLoad(const std::vector<uint8_t> &id_list, std::vector<uint16_t> &load_list)
1511 {
1512  return syncRead<typename XL330Reg::TYPE_PRESENT_CURRENT>(XL330Reg::ADDR_PRESENT_CURRENT, id_list, load_list);
1513 }
1514 
1515 template <>
1516 inline int DxlDriver<XL330Reg>::writeTemperatureLimit(uint8_t id, uint8_t temperature_limit)
1517 {
1518  return write<typename XL330Reg::TYPE_TEMPERATURE_LIMIT>(XL330Reg::ADDR_TEMPERATURE_LIMIT, id, temperature_limit);
1519 }
1520 
1521 template <>
1522 inline int DxlDriver<XL330Reg>::writeShutdownConfiguration(uint8_t id, uint8_t configuration)
1523 {
1524  return write<typename XL330Reg::TYPE_ALARM_SHUTDOWN>(XL330Reg::ADDR_ALARM_SHUTDOWN, id, configuration);
1525 }
1526 
1527 // XH430
1528 
1529 template <>
1530 inline std::string DxlDriver<XH430Reg>::interpretErrorState(uint32_t hw_state) const
1531 {
1532  std::string hardware_message;
1533 
1534  if (hw_state & 1 << 0) // 0b00000001
1535  {
1536  hardware_message += "Input Voltage";
1537  }
1538  if (hw_state & 1 << 2) // 0b00000100
1539  {
1540  if (!hardware_message.empty())
1541  hardware_message += ", ";
1542  hardware_message += "OverHeating";
1543  }
1544  if (hw_state & 1 << 3) // 0b00001000
1545  {
1546  if (!hardware_message.empty())
1547  hardware_message += ", ";
1548  hardware_message += "Motor Encoder";
1549  }
1550  if (hw_state & 1 << 4) // 0b00010000
1551  {
1552  if (!hardware_message.empty())
1553  hardware_message += ", ";
1554  hardware_message += "Electrical Shock";
1555  }
1556  if (hw_state & 1 << 5) // 0b00100000
1557  {
1558  if (!hardware_message.empty())
1559  hardware_message += ", ";
1560  hardware_message += "Overload";
1561  }
1562  if (hw_state & 1 << 7) // 0b10000000 => added by us : disconnected error
1563  {
1564  if (!hardware_message.empty())
1565  hardware_message += ", ";
1566  hardware_message += "Disconnection";
1567  }
1568  if (!hardware_message.empty())
1569  hardware_message += " Error";
1570 
1571  return hardware_message;
1572 }
1573 
1574 template <>
1575 inline int DxlDriver<XH430Reg>::writeTorqueGoal(uint8_t id, uint16_t torque)
1576 {
1577  return write<typename XL330Reg::TYPE_GOAL_CURRENT>(XL330Reg::ADDR_GOAL_CURRENT, id, torque);
1578 }
1579 
1580 template <>
1581 inline int DxlDriver<XH430Reg>::syncWriteTorqueGoal(const std::vector<uint8_t> &id_list,
1582  const std::vector<uint16_t> &torque_list)
1583 {
1584  return syncWrite<typename XL330Reg::TYPE_GOAL_CURRENT>(XL330Reg::ADDR_GOAL_CURRENT, id_list, torque_list);
1585 }
1586 
1587 } // namespace ttl_driver
1588 
1589 #endif // DxlDriver
ttl_driver::DxlDriver::writePositionGoal
int writePositionGoal(uint8_t id, uint32_t position) override
DxlDriver<reg_type>::writePositionGoal.
Definition: dxl_driver.hpp:370
ttl_driver::DxlDriver::syncReadHwErrorStatus
int syncReadHwErrorStatus(const std::vector< uint8_t > &id_list, std::vector< uint8_t > &hw_error_list) override
DxlDriver<reg_type>::syncReadHwErrorStatus.
Definition: dxl_driver.hpp:694
ttl_driver::XL320Reg::TYPE_PRESENT_VELOCITY
uint16_t TYPE_PRESENT_VELOCITY
Definition: xl320_reg.hpp:102
ttl_driver::XL320Reg::TYPE_PRESENT_POSITION
uint16_t TYPE_PRESENT_POSITION
Definition: xl320_reg.hpp:99
ttl_driver::DxlDriver::syncReadHwStatus
int syncReadHwStatus(const std::vector< uint8_t > &id_list, std::vector< std::pair< double, uint8_t >> &data_list) override
DxlDriver<reg_type>::syncReadHwStatus.
Definition: dxl_driver.hpp:665
ttl_driver::XL320Reg::ADDR_PRESENT_VELOCITY
static constexpr uint16_t ADDR_PRESENT_VELOCITY
Definition: xl320_reg.hpp:101
ttl_driver::DxlDriver::syncReadLoad
int syncReadLoad(const std::vector< uint8_t > &id_list, std::vector< uint16_t > &load_list) override
DxlDriver<reg_type>::syncReadLoad.
Definition: dxl_driver.hpp:867
ttl_driver::XL320Reg::ADDR_POSITION_P_GAIN
static constexpr uint16_t ADDR_POSITION_P_GAIN
Definition: xl320_reg.hpp:87
ttl_driver::XL320Reg::ADDR_POSITION_I_GAIN
static constexpr uint16_t ADDR_POSITION_I_GAIN
Definition: xl320_reg.hpp:86
ttl_driver::DxlDriver::readTemperature
int readTemperature(uint8_t id, uint8_t &temperature) override
DxlDriver<reg_type>::readTemperature.
Definition: dxl_driver.hpp:471
ttl_driver::XL330Reg::ADDR_TEMPERATURE_LIMIT
static constexpr uint16_t ADDR_TEMPERATURE_LIMIT
Definition: xl330_reg.hpp:62
ttl_driver::DxlDriver::readVelocityProfile
int readVelocityProfile(uint8_t id, std::vector< uint32_t > &data_list) override
Definition: dxl_driver.hpp:436
ttl_driver::DxlDriver::writeTorquePercentage
int writeTorquePercentage(uint8_t id, uint8_t torque_percentage) override
DxlDriver<reg_type>::writeTorquePercentage.
Definition: dxl_driver.hpp:357
ttl_driver::DxlDriver::syncWriteTorqueGoal
int syncWriteTorqueGoal(const std::vector< uint8_t > &id_list, const std::vector< uint16_t > &torque_list) override
DxlDriver<reg_type>::syncWriteTorqueGoal.
Definition: dxl_driver.hpp:746
ttl_driver::DxlDriver::writePID
int writePID(uint8_t id, const std::vector< uint16_t > &data) override
DxlDriver<reg_type>::writePID.
Definition: dxl_driver.hpp:522
ttl_driver::DxlDriver::writeTemperatureLimit
int writeTemperatureLimit(uint8_t id, uint8_t temperature_limit) override
DxlDriver<reg_type>::writeTemperatureLimit.
Definition: dxl_driver.hpp:272
xl320_reg.hpp
ttl_driver::AbstractDxlDriver
Definition: abstract_dxl_driver.hpp:33
ttl_driver::DxlDriver::syncWriteLed
int syncWriteLed(const std::vector< uint8_t > &id_list, const std::vector< uint8_t > &led_list) override
DxlDriver<reg_type>::syncWriteLed.
Definition: dxl_driver.hpp:722
ttl_driver::DxlDriver::writeTorqueGoal
int writeTorqueGoal(uint8_t id, uint16_t torque) override
DxlDriver<reg_type>::writeTorqueGoal.
Definition: dxl_driver.hpp:734
ttl_driver::DxlDriver::readHwErrorStatus
int readHwErrorStatus(uint8_t id, uint8_t &hardware_error_status) override
DxlDriver<reg_type>::readHwErrorStatus.
Definition: dxl_driver.hpp:498
ttl_driver::DxlDriver::str
std::string str() const override
DxlDriver<reg_type>::str.
Definition: dxl_driver.hpp:161
ttl_driver::DxlDriver::syncReadRawVoltage
int syncReadRawVoltage(const std::vector< uint8_t > &id_list, std::vector< double > &voltage_list) override
DxlDriver<reg_type>::syncReadRawVoltage.
Definition: dxl_driver.hpp:648
ttl_driver::DxlDriver::syncReadVelocity
int syncReadVelocity(const std::vector< uint8_t > &id_list, std::vector< uint32_t > &velocity_list) override
DxlDriver<reg_type>::syncReadVelocity.
Definition: dxl_driver.hpp:891
ttl_driver::XL330Reg::ADDR_GOAL_CURRENT
static constexpr uint16_t ADDR_GOAL_CURRENT
Definition: xl330_reg.hpp:124
ttl_driver::XM430Reg::ADDR_GOAL_CURRENT
static constexpr uint16_t ADDR_GOAL_CURRENT
Definition: xm430_reg.hpp:124
ttl_driver::DxlDriver::syncReadJointStatus
int syncReadJointStatus(const std::vector< uint8_t > &id_list, std::vector< std::array< uint32_t, 2 >> &data_array_list) override
DxlDriver::syncReadJointStatus.
Definition: dxl_driver.hpp:903
ttl_driver::DxlDriver::syncReadFirmwareVersion
int syncReadFirmwareVersion(const std::vector< uint8_t > &id_list, std::vector< std::string > &firmware_list) override
DxlDriver<reg_type>::syncReadFirmwareVersion.
Definition: dxl_driver.hpp:599
xc430_reg.hpp
ttl_driver::XL320Reg::ADDR_PRESENT_VOLTAGE
static constexpr uint16_t ADDR_PRESENT_VOLTAGE
Definition: xl320_reg.hpp:107
abstract_dxl_driver.hpp
ttl_driver::DxlDriver::readFirmwareVersion
int readFirmwareVersion(uint8_t id, std::string &version) override
DxlDriver<reg_type>::readFirmwareVersion.
Definition: dxl_driver.hpp:229
ttl_driver::XL320Reg::ADDR_GOAL_POSITION
static constexpr uint16_t ADDR_GOAL_POSITION
Definition: xl320_reg.hpp:89
ttl_driver::DxlDriver::writeShutdownConfiguration
int writeShutdownConfiguration(uint8_t id, uint8_t configuration) override
DxlDriver<reg_type>::writeShutdownConfiguration.
Definition: dxl_driver.hpp:285
ttl_driver::XL320Reg::TYPE_GOAL_POSITION
uint16_t TYPE_GOAL_POSITION
Definition: xl320_reg.hpp:90
xl430_reg.hpp
ttl_driver::DxlDriver
The DxlDriver class.
Definition: dxl_driver.hpp:44
ttl_driver::DxlDriver::readVoltage
int readVoltage(uint8_t id, double &voltage) override
DxlDriver<reg_type>::readVoltage.
Definition: dxl_driver.hpp:483
ttl_driver::XL320Reg::TYPE_GOAL_VELOCITY
uint16_t TYPE_GOAL_VELOCITY
Definition: xl320_reg.hpp:93
ttl_driver::DxlDriver::syncWriteTorquePercentage
int syncWriteTorquePercentage(const std::vector< uint8_t > &id_list, const std::vector< uint8_t > &torque_percentage_list) override
DxlDriver<reg_type>::syncWriteTorquePercentage.
Definition: dxl_driver.hpp:396
ttl_driver::DxlDriver::readControlMode
int readControlMode(uint8_t id, uint8_t &control_mode) override
DxlDriver<reg_type>::readControlMode.
Definition: dxl_driver.hpp:838
ttl_driver::DxlDriver::changeId
int changeId(uint8_t id, uint8_t new_id) override
DxlDriver<reg_type>::changeId.
Definition: dxl_driver.hpp:196
ttl_driver
Definition: abstract_dxl_driver.hpp:30
ttl_driver::DxlDriver::writeControlMode
int writeControlMode(uint8_t id, uint8_t control_mode) override
DxlDriver<reg_type>::writeControlMode.
Definition: dxl_driver.hpp:816
ttl_driver::XL320Reg::ADDR_GOAL_VELOCITY
static constexpr uint16_t ADDR_GOAL_VELOCITY
Definition: xl320_reg.hpp:92
ttl_driver::DxlDriver::readVelocity
int readVelocity(uint8_t id, uint32_t &present_velocity) override
DxlDriver<reg_type>::readVelocity.
Definition: dxl_driver.hpp:879
ttl_driver::XM430Reg::ADDR_PRESENT_CURRENT
static constexpr uint16_t ADDR_PRESENT_CURRENT
Definition: xm430_reg.hpp:146
ttl_driver::DxlDriver::syncReadVoltage
int syncReadVoltage(const std::vector< uint8_t > &id_list, std::vector< double > &voltage_list) override
DxlDriver<reg_type>::syncReadVoltage.
Definition: dxl_driver.hpp:631
ttl_driver::DxlDriver::DxlDriver
DxlDriver(std::shared_ptr< dynamixel::PortHandler > portHandler, std::shared_ptr< dynamixel::PacketHandler > packetHandler)
DxlDriver<reg_type>::DxlDriver.
Definition: dxl_driver.hpp:146
ttl_driver::DxlDriver::readPID
int readPID(uint8_t id, std::vector< uint16_t > &data_list) override
DxlDriver<reg_type>::readPID.
Definition: dxl_driver.hpp:761
ttl_driver::DxlDriver::syncWriteVelocityGoal
int syncWriteVelocityGoal(const std::vector< uint8_t > &id_list, const std::vector< uint32_t > &velocity_list) override
DxlDriver<reg_type>::syncWriteVelocityGoal.
Definition: dxl_driver.hpp:428
xh430_reg.hpp
ttl_driver::DxlDriver::syncWritePositionGoal
int syncWritePositionGoal(const std::vector< uint8_t > &id_list, const std::vector< uint32_t > &position_list) override
DxlDriver<reg_type>::syncWritePositionGoal.
Definition: dxl_driver.hpp:415
ttl_driver::DxlDriver::writeStartupConfiguration
int writeStartupConfiguration(uint8_t id, uint8_t config) override
DxlDriver<reg_type>::writeStartupConfiguration.
Definition: dxl_driver.hpp:245
ttl_driver::DxlDriver::readLoad
int readLoad(uint8_t id, uint16_t &present_load) override
DxlDriver<reg_type>::readLoad.
Definition: dxl_driver.hpp:855
xl330_reg.hpp
xm430_reg.hpp
ttl_driver::DxlDriver::readPosition
int readPosition(uint8_t id, uint32_t &present_position) override
DxlDriver<reg_type>::readPosition.
Definition: dxl_driver.hpp:459
ttl_driver::XL330Reg::ADDR_ALARM_SHUTDOWN
static constexpr uint16_t ADDR_ALARM_SHUTDOWN
Definition: xl330_reg.hpp:90
ttl_driver::XL320Reg::ADDR_POSITION_D_GAIN
static constexpr uint16_t ADDR_POSITION_D_GAIN
Definition: xl320_reg.hpp:85
ttl_driver::AbstractDxlDriver::str
std::string str() const override
AbstractTtlDriver::str : build a string describing the object. For debug purpose only.
Definition: abstract_dxl_driver.cpp:43
ttl_driver::DxlDriver::readMaxPosition
int readMaxPosition(uint8_t id, uint32_t &max_pos) override
DxlDriver<reg_type>::readMaxPosition.
Definition: dxl_driver.hpp:310
ttl_driver::DxlDriver::writeLed
int writeLed(uint8_t id, uint8_t led_value) override
DxlDriver<reg_type>::writeLed.
Definition: dxl_driver.hpp:710
ttl_driver::DxlDriver::syncReadTemperature
int syncReadTemperature(const std::vector< uint8_t > &id_list, std::vector< uint8_t > &temperature_list) override
DxlDriver<reg_type>::syncReadTemperature.
Definition: dxl_driver.hpp:617
ttl_driver::DxlDriver::interpretFirmwareVersion
std::string interpretFirmwareVersion(uint32_t fw_version) const override
DxlDriver<reg_type>::interpretFirmwareVersion.
Definition: dxl_driver.hpp:182
ttl_driver::DxlDriver::checkModelNumber
int checkModelNumber(uint8_t id, uint16_t &model_number) override
DxlDriver<reg_type>::checkModelNumber.
Definition: dxl_driver.hpp:207
ttl_driver::XL320Reg::TYPE_PID_GAIN
uint8_t TYPE_PID_GAIN
Definition: xl320_reg.hpp:84
ttl_driver::DxlDriver::readMinPosition
int readMinPosition(uint8_t id, uint32_t &min_pos) override
DxlDriver<reg_type>::readMinPosition.
Definition: dxl_driver.hpp:298
ttl_driver::DxlDriver::readMoving
int readMoving(uint8_t id, uint8_t &status) override
DxlDriver<reg_type>::readMoving.
Definition: dxl_driver.hpp:804
ttl_driver::DxlDriver::interpretErrorState
std::string interpretErrorState(uint32_t hw_state) const override
DxlDriver<reg_type>::interpretErrorState.
Definition: dxl_driver.hpp:171
ttl_driver::DxlDriver::writeVelocityProfile
int writeVelocityProfile(uint8_t id, const std::vector< uint32_t > &data_list) override
DxlDriver<reg_type>::writeVelocityProfile Write velocity profile for dxl.
Definition: dxl_driver.hpp:325
ttl_driver::DxlDriver::syncReadPosition
int syncReadPosition(const std::vector< uint8_t > &id_list, std::vector< uint32_t > &position_list) override
DxlDriver<reg_type>::syncReadPosition.
Definition: dxl_driver.hpp:510
ttl_driver::XL320Reg::ADDR_PRESENT_POSITION
static constexpr uint16_t ADDR_PRESENT_POSITION
Definition: xl320_reg.hpp:98
ttl_driver::DxlDriver::writeVelocityGoal
int writeVelocityGoal(uint8_t id, uint32_t velocity) override
DxlDriver<reg_type>::writeVelocityGoal.
Definition: dxl_driver.hpp:383
ttl_driver::XL330Reg::ADDR_PRESENT_CURRENT
static constexpr uint16_t ADDR_PRESENT_CURRENT
Definition: xl330_reg.hpp:146


ttl_driver
Author(s): Clement Cocquempot
autogenerated on Fri Mar 6 2026 15:24:15