abstract_ttl_driver.hpp
Go to the documentation of this file.
1 /*
2 abstract_ttl_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 ABSTRACT_TTL_DRIVER_HPP
18 #define ABSTRACT_TTL_DRIVER_HPP
19 
20 #include <memory>
21 #include <vector>
22 #include <string>
23 #include <iostream>
24 
25 #include "dynamixel_sdk/dynamixel_sdk.h"
26 #include "common/common_defs.hpp"
27 #include "common/model/hardware_type_enum.hpp"
28 #include "common/model/single_motor_cmd.hpp"
29 #include "common/model/abstract_synchronize_motor_cmd.hpp"
30 
31 namespace ttl_driver
32 {
33 
38 {
39 public:
40  AbstractTtlDriver() = default;
41  AbstractTtlDriver(std::shared_ptr<dynamixel::PortHandler> portHandler,
42  std::shared_ptr<dynamixel::PacketHandler> packetHandler);
43  virtual ~AbstractTtlDriver() = default;
44 
45  virtual int ping(uint8_t id);
46  virtual int getModelNumber(uint8_t id, uint16_t &model_number);
47  virtual int scan(std::vector<uint8_t> &id_list);
48  virtual int reboot(uint8_t id);
49 
50  virtual int readCustom(uint16_t address, uint8_t data_len, uint8_t id, uint32_t &data);
51  virtual int writeCustom(uint16_t address, uint8_t data_len, uint8_t id, uint32_t data);
52 
53  virtual int writeSingleCmd(const std::unique_ptr<common::model::AbstractTtlSingleMotorCmd> &cmd) = 0;
54  virtual int writeSyncCmd(int type, const std::vector<uint8_t> &ids, const std::vector<uint32_t> &params) = 0;
55 
56 public:
57  virtual std::string str() const;
58 
59  // here are only common TTL commands found in both Steppers and DXl
60  virtual std::string interpretErrorState(uint32_t hw_state) const = 0;
61 
62  // eeprom write
63 
64  // eeprom read
65  virtual int checkModelNumber(uint8_t id, uint16_t &model_number) = 0;
66  virtual int readFirmwareVersion(uint8_t id, std::string &version) = 0;
67 
68  // ram read
69  virtual int readTemperature(uint8_t id, uint8_t &temperature) = 0;
70  virtual int readVoltage(uint8_t id, double &voltage) = 0;
71  virtual int readHwErrorStatus(uint8_t id, uint8_t &hardware_error_status) = 0;
72 
73  virtual int syncReadFirmwareVersion(const std::vector<uint8_t> &id_list,
74  std::vector<std::string> &firmware_version) = 0;
75  virtual int syncReadTemperature(const std::vector<uint8_t> &id_list, std::vector<uint8_t> &temperature_list) = 0;
76  virtual int syncReadVoltage(const std::vector<uint8_t> &id_list, std::vector<double> &voltage_list) = 0;
77  virtual int syncReadRawVoltage(const std::vector<uint8_t> &id_list, std::vector<double> &voltage_list) = 0;
78  virtual int syncReadHwErrorStatus(const std::vector<uint8_t> &id_list, std::vector<uint8_t> &hw_error_list) = 0;
79  virtual int syncReadHwStatus(const std::vector<uint8_t> &id_list,
80  std::vector<std::pair<double, uint8_t> > &data_array_list) = 0;
81 
82 protected:
83  // we use those commands in the children classes to actually read and write values in registers
84  template <typename T>
85  int read(uint16_t address, uint8_t id, T &data);
86 
87  template <typename T>
88  int syncRead(uint16_t address, const std::vector<uint8_t> &id_list, std::vector<T> &data_list);
89 
90  template <typename T, const size_t N>
91  int syncReadConsecutiveBytes(uint16_t address, const std::vector<uint8_t> &id_list,
92  std::vector<std::array<T, N> > &data_list);
93 
94  template <typename T>
95  int write(uint16_t address, uint8_t id, T data);
96 
97  template <typename T>
98  int syncWrite(uint16_t address, const std::vector<uint8_t> &id_list, const std::vector<T> &data_list);
99 
100  static constexpr int PING_WRONG_MODEL_NUMBER = 30;
101 
102  virtual std::string interpretFirmwareVersion(uint32_t fw_version) const = 0;
103 
104 private:
105  std::shared_ptr<dynamixel::PortHandler> _dxlPortHandler;
106  std::shared_ptr<dynamixel::PacketHandler> _dxlPacketHandler;
107 
108  static constexpr uint8_t DXL_LEN_ONE_BYTE = 1;
109  static constexpr uint8_t DXL_LEN_TWO_BYTES = 2;
110  static constexpr uint8_t DXL_LEN_FOUR_BYTES = 4;
111 
112  static constexpr int GROUP_SYNC_REDONDANT_ID = 10;
113  static constexpr int GROUP_SYNC_READ_RX_FAIL = 11;
114  static constexpr int LEN_ID_DATA_NOT_SAME = 20;
115 
116 protected:
117  // see
118  // https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c67-a-polymorphic-class-should-suppress-public-copymove
119  AbstractTtlDriver(const AbstractTtlDriver &) = default;
120  AbstractTtlDriver(AbstractTtlDriver &&) = default;
122  AbstractTtlDriver &operator=(const AbstractTtlDriver &) = default;
123 };
124 
133 template <typename T>
134 int AbstractTtlDriver::read(uint16_t address, uint8_t id, T &data)
135 {
136  // clean output data first
137  data = 0;
138  uint8_t error = 0;
139  int dxl_comm_result = COMM_TX_FAIL;
140 
141  switch (sizeof(T))
142  {
143  case DXL_LEN_ONE_BYTE: {
144  uint8_t raw_data;
145 
146  dxl_comm_result = _dxlPacketHandler->read1ByteTxRx(_dxlPortHandler.get(), id, address, &raw_data, &error);
147  data = static_cast<T>(raw_data);
148  }
149  break;
150  case DXL_LEN_TWO_BYTES: {
151  uint16_t raw_data;
152 
153  dxl_comm_result = _dxlPacketHandler->read2ByteTxRx(_dxlPortHandler.get(), id, address, &raw_data, &error);
154  data = static_cast<T>(raw_data);
155  }
156  break;
157  case DXL_LEN_FOUR_BYTES: {
158  uint32_t raw_data;
159 
160  dxl_comm_result = _dxlPacketHandler->read4ByteTxRx(_dxlPortHandler.get(), id, address, &raw_data, &error);
161  data = static_cast<T>(raw_data);
162  }
163  break;
164  default:
165  printf("AbstractTtlDriver::read ERROR: Size param must be 1, 2 or 4 bytes\n");
166  break;
167  }
168 
169  if (0 != error)
170  {
171  printf("AbstractTtlDriver::write ERROR: device return error: id=%d, addr=%d, len=%d, err=0x%02x\n", id, address,
172  static_cast<int>(sizeof(T)), error);
173  dxl_comm_result = error;
174  }
175 
176  return dxl_comm_result;
177 }
178 
187 template <typename T, const size_t N>
188 int AbstractTtlDriver::syncReadConsecutiveBytes(uint16_t address, const std::vector<uint8_t> &id_list,
189  std::vector<std::array<T, N> > &data_list)
190 {
191  data_list.clear();
192  uint16_t data_size = sizeof(T);
193  int dxl_comm_result = COMM_TX_FAIL;
194 
195  dynamixel::GroupSyncRead groupSyncRead(_dxlPortHandler.get(), _dxlPacketHandler.get(), address, data_size * N);
196 
197  for (auto const &id : id_list)
198  {
199  if (!groupSyncRead.addParam(id))
200  {
201  groupSyncRead.clearParam();
203  }
204  }
205 
206  dxl_comm_result = groupSyncRead.txRxPacket();
207 
208  if (COMM_SUCCESS == dxl_comm_result)
209  {
210  for (auto const &id : id_list)
211  {
212  if (groupSyncRead.isAvailable(id, address, data_size * N))
213  {
214  std::array<T, N> blocks{};
215 
216  for (uint8_t b = 0; b < N; ++b)
217  {
218  T data = static_cast<T>(groupSyncRead.getData(id, address + b * data_size, data_size));
219  blocks.at(b) = data;
220  }
221 
222  data_list.emplace_back(std::move(blocks));
223  }
224  else
225  {
226  dxl_comm_result = GROUP_SYNC_READ_RX_FAIL;
227  break;
228  }
229  }
230  }
231 
232  groupSyncRead.clearParam();
233 
234  return dxl_comm_result;
235 }
236 
244 template <typename T>
245 int AbstractTtlDriver::syncRead(uint16_t address, const std::vector<uint8_t> &id_list, std::vector<T> &data_list)
246 {
247  int dxl_comm_result = COMM_TX_FAIL;
248 
249  data_list.clear();
250  uint8_t data_len = sizeof(T);
251  if (data_len <= 4)
252  {
253  dynamixel::GroupSyncRead groupSyncRead(_dxlPortHandler.get(), _dxlPacketHandler.get(), address, data_len);
254 
255  for (auto const &id : id_list)
256  {
257  if (!groupSyncRead.addParam(id))
258  {
259  groupSyncRead.clearParam();
261  }
262  }
263 
264  dxl_comm_result = groupSyncRead.txRxPacket();
265 
266  if (COMM_SUCCESS == dxl_comm_result)
267  {
268  for (auto const &id : id_list)
269  {
270  if (groupSyncRead.isAvailable(id, address, data_len))
271  {
272  T data = static_cast<T>(groupSyncRead.getData(id, address, data_len));
273  data_list.emplace_back(data);
274  }
275  else
276  {
277  dxl_comm_result = GROUP_SYNC_READ_RX_FAIL;
278  break;
279  }
280  }
281  }
282 
283  groupSyncRead.clearParam();
284  }
285  else
286  {
287  printf("AbstractTtlDriver::syncRead ERROR: Size param must be 1, 2 or 4 bytes\n");
288  }
289 
290  return dxl_comm_result;
291 }
292 
293 template <typename T>
294 int AbstractTtlDriver::write(uint16_t address, uint8_t id, T data)
295 {
296  int dxl_comm_result = COMM_TX_FAIL;
297  uint8_t error = 0;
298 
299  switch (sizeof(T))
300  {
301  case DXL_LEN_ONE_BYTE:
302  dxl_comm_result = _dxlPacketHandler->write1ByteTxRx(_dxlPortHandler.get(), id, address, data, &error);
303  break;
304  case DXL_LEN_TWO_BYTES:
305  dxl_comm_result = _dxlPacketHandler->write2ByteTxRx(_dxlPortHandler.get(), id, address, data, &error);
306  break;
307  case DXL_LEN_FOUR_BYTES:
308  dxl_comm_result = _dxlPacketHandler->write4ByteTxRx(_dxlPortHandler.get(), id, address, data, &error);
309  break;
310  default:
311  printf("AbstractTtlDriver::write ERROR: Size param must be 1, 2 or 4 bytes\n");
312  break;
313  }
314 
315  if (0 != error)
316  {
317  printf("AbstractTtlDriver::write ERROR: device return error: id=%d, addr=%d, len=%d, err=0x%02x\n", id, address,
318  static_cast<int>(sizeof(T)), error);
319  dxl_comm_result = error;
320  }
321 
322  return dxl_comm_result;
323 }
324 
325 template <typename T>
326 int AbstractTtlDriver::syncWrite(uint16_t address, const std::vector<uint8_t> &id_list, const std::vector<T> &data_list)
327 {
328  int dxl_comm_result = COMM_SUCCESS;
329  uint8_t data_len = sizeof(T);
330 
331  if (!id_list.empty())
332  {
333  if (id_list.size() == data_list.size())
334  {
335  dynamixel::GroupSyncWrite groupSyncWrite(_dxlPortHandler.get(), _dxlPacketHandler.get(), address, data_len);
336 
337  bool dxl_senddata_result = false;
338 
339  for (size_t i = 0; i < id_list.size(); ++i)
340  {
341  uint8_t id = id_list.at(i);
342  T data = data_list.at(i);
343 
344  switch (data_len)
345  {
346  case DXL_LEN_ONE_BYTE: {
347  uint8_t params[1] = { static_cast<uint8_t>(data) };
348  dxl_senddata_result = groupSyncWrite.addParam(id, params);
349  }
350  break;
351  case DXL_LEN_TWO_BYTES: {
352  uint8_t params[2] = { DXL_LOBYTE(static_cast<uint16_t>(data)), DXL_HIBYTE(static_cast<uint16_t>(data)) };
353  dxl_senddata_result = groupSyncWrite.addParam(id, params);
354  }
355  break;
356  case DXL_LEN_FOUR_BYTES: {
357  uint8_t params[4] = { DXL_LOBYTE(DXL_LOWORD(data)), DXL_HIBYTE(DXL_LOWORD(data)),
358  DXL_LOBYTE(DXL_HIWORD(data)), DXL_HIBYTE(DXL_HIWORD(data)) };
359  dxl_senddata_result = groupSyncWrite.addParam(id, params);
360  }
361  break;
362  default:
363  printf("AbstractTtlDriver::syncWrite ERROR: Size param must be 1, 2 or 4 bytes\n");
364  break;
365  }
366 
367  if (!dxl_senddata_result)
368  {
369  dxl_comm_result = GROUP_SYNC_REDONDANT_ID;
370  break;
371  }
372  }
373 
374  // send group if no error
375  if (GROUP_SYNC_REDONDANT_ID != dxl_comm_result)
376  dxl_comm_result = groupSyncWrite.txPacket();
377 
378  groupSyncWrite.clearParam();
379  }
380  else
381  {
382  dxl_comm_result = LEN_ID_DATA_NOT_SAME;
383  }
384  }
385 
386  return dxl_comm_result;
387 }
388 
389 } // namespace ttl_driver
390 
391 #endif // ABSTRACT_TTL_DRIVER_HPP
ttl_driver::AbstractTtlDriver::LEN_ID_DATA_NOT_SAME
static constexpr int LEN_ID_DATA_NOT_SAME
Definition: abstract_ttl_driver.hpp:114
ttl_driver::AbstractTtlDriver::syncReadHwErrorStatus
virtual int syncReadHwErrorStatus(const std::vector< uint8_t > &id_list, std::vector< uint8_t > &hw_error_list)=0
ttl_driver::AbstractTtlDriver::readTemperature
virtual int readTemperature(uint8_t id, uint8_t &temperature)=0
ttl_driver::AbstractTtlDriver::operator=
AbstractTtlDriver & operator=(AbstractTtlDriver &&)=default
ttl_driver::AbstractTtlDriver::str
virtual std::string str() const
AbstractTtlDriver::str : build a string describing the object. For debug purpose only.
Definition: abstract_ttl_driver.cpp:102
ttl_driver::AbstractTtlDriver
The AbstractTtlDriver class.
Definition: abstract_ttl_driver.hpp:37
ttl_driver::AbstractTtlDriver::read
int read(uint16_t address, uint8_t id, T &data)
AbstractTtlDriver::read.
Definition: abstract_ttl_driver.hpp:134
ttl_driver::AbstractTtlDriver::DXL_LEN_TWO_BYTES
static constexpr uint8_t DXL_LEN_TWO_BYTES
Definition: abstract_ttl_driver.hpp:109
ttl_driver::AbstractTtlDriver::_dxlPortHandler
std::shared_ptr< dynamixel::PortHandler > _dxlPortHandler
Definition: abstract_ttl_driver.hpp:105
ttl_driver::AbstractTtlDriver::syncRead
int syncRead(uint16_t address, const std::vector< uint8_t > &id_list, std::vector< T > &data_list)
AbstractTtlDriver::syncRead.
Definition: abstract_ttl_driver.hpp:245
ttl_driver::AbstractTtlDriver::ping
virtual int ping(uint8_t id)
AbstractTtlDriver::ping.
Definition: abstract_ttl_driver.cpp:49
ttl_driver::AbstractTtlDriver::readFirmwareVersion
virtual int readFirmwareVersion(uint8_t id, std::string &version)=0
ttl_driver::AbstractTtlDriver::syncReadConsecutiveBytes
int syncReadConsecutiveBytes(uint16_t address, const std::vector< uint8_t > &id_list, std::vector< std::array< T, N > > &data_list)
AbstractTtlDriver::syncReadConsecutiveBytes.
Definition: abstract_ttl_driver.hpp:188
ttl_driver::AbstractTtlDriver::reboot
virtual int reboot(uint8_t id)
AbstractTtlDriver::reboot.
Definition: abstract_ttl_driver.cpp:88
ttl_driver::AbstractTtlDriver::interpretErrorState
virtual std::string interpretErrorState(uint32_t hw_state) const =0
ttl_driver::AbstractTtlDriver::syncReadFirmwareVersion
virtual int syncReadFirmwareVersion(const std::vector< uint8_t > &id_list, std::vector< std::string > &firmware_version)=0
ttl_driver::AbstractTtlDriver::readVoltage
virtual int readVoltage(uint8_t id, double &voltage)=0
ttl_driver::AbstractTtlDriver::AbstractTtlDriver
AbstractTtlDriver()=default
ttl_driver::AbstractTtlDriver::readCustom
virtual int readCustom(uint16_t address, uint8_t data_len, uint8_t id, uint32_t &data)
AbstractTtlDriver::readCustom.
Definition: abstract_ttl_driver.cpp:125
ttl_driver::AbstractTtlDriver::scan
virtual int scan(std::vector< uint8_t > &id_list)
AbstractTtlDriver::scan.
Definition: abstract_ttl_driver.cpp:78
ttl_driver::AbstractTtlDriver::GROUP_SYNC_REDONDANT_ID
static constexpr int GROUP_SYNC_REDONDANT_ID
Definition: abstract_ttl_driver.hpp:112
ttl_driver::AbstractTtlDriver::write
int write(uint16_t address, uint8_t id, T data)
Definition: abstract_ttl_driver.hpp:294
ttl_driver::AbstractTtlDriver::writeSyncCmd
virtual int writeSyncCmd(int type, const std::vector< uint8_t > &ids, const std::vector< uint32_t > &params)=0
ttl_driver::AbstractTtlDriver::writeSingleCmd
virtual int writeSingleCmd(const std::unique_ptr< common::model::AbstractTtlSingleMotorCmd > &cmd)=0
ttl_driver::AbstractTtlDriver::getModelNumber
virtual int getModelNumber(uint8_t id, uint16_t &model_number)
AbstractTtlDriver::getModelNumber.
Definition: abstract_ttl_driver.cpp:64
ttl_driver
Definition: abstract_dxl_driver.hpp:30
ttl_driver::AbstractTtlDriver::PING_WRONG_MODEL_NUMBER
static constexpr int PING_WRONG_MODEL_NUMBER
Definition: abstract_ttl_driver.hpp:100
ttl_driver::AbstractTtlDriver::readHwErrorStatus
virtual int readHwErrorStatus(uint8_t id, uint8_t &hardware_error_status)=0
ttl_driver::AbstractTtlDriver::syncReadTemperature
virtual int syncReadTemperature(const std::vector< uint8_t > &id_list, std::vector< uint8_t > &temperature_list)=0
ttl_driver::AbstractTtlDriver::_dxlPacketHandler
std::shared_ptr< dynamixel::PacketHandler > _dxlPacketHandler
Definition: abstract_ttl_driver.hpp:106
ttl_driver::AbstractTtlDriver::syncReadRawVoltage
virtual int syncReadRawVoltage(const std::vector< uint8_t > &id_list, std::vector< double > &voltage_list)=0
ttl_driver::AbstractTtlDriver::syncReadVoltage
virtual int syncReadVoltage(const std::vector< uint8_t > &id_list, std::vector< double > &voltage_list)=0
ttl_driver::AbstractTtlDriver::syncWrite
int syncWrite(uint16_t address, const std::vector< uint8_t > &id_list, const std::vector< T > &data_list)
Definition: abstract_ttl_driver.hpp:326
ttl_driver::AbstractTtlDriver::interpretFirmwareVersion
virtual std::string interpretFirmwareVersion(uint32_t fw_version) const =0
ttl_driver::AbstractTtlDriver::GROUP_SYNC_READ_RX_FAIL
static constexpr int GROUP_SYNC_READ_RX_FAIL
Definition: abstract_ttl_driver.hpp:113
ttl_driver::AbstractTtlDriver::~AbstractTtlDriver
virtual ~AbstractTtlDriver()=default
ttl_driver::AbstractTtlDriver::DXL_LEN_FOUR_BYTES
static constexpr uint8_t DXL_LEN_FOUR_BYTES
Definition: abstract_ttl_driver.hpp:110
ttl_driver::AbstractTtlDriver::checkModelNumber
virtual int checkModelNumber(uint8_t id, uint16_t &model_number)=0
ttl_driver::AbstractTtlDriver::syncReadHwStatus
virtual int syncReadHwStatus(const std::vector< uint8_t > &id_list, std::vector< std::pair< double, uint8_t > > &data_array_list)=0
ttl_driver::AbstractTtlDriver::DXL_LEN_ONE_BYTE
static constexpr uint8_t DXL_LEN_ONE_BYTE
Definition: abstract_ttl_driver.hpp:108
ttl_driver::AbstractTtlDriver::writeCustom
virtual int writeCustom(uint16_t address, uint8_t data_len, uint8_t id, uint32_t data)
AbstractTtlDriver::writeCustom.
Definition: abstract_ttl_driver.cpp:167


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