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 
40 public:
41  AbstractTtlDriver() = default;
42  AbstractTtlDriver(std::shared_ptr<dynamixel::PortHandler> portHandler,
43  std::shared_ptr<dynamixel::PacketHandler> packetHandler);
44  virtual ~AbstractTtlDriver() = default;
45 
46  virtual int ping(uint8_t id);
47  virtual int getModelNumber(uint8_t id,
48  uint16_t& model_number);
49  virtual int scan(std::vector<uint8_t>& id_list);
50  virtual int reboot(uint8_t id);
51 
52  virtual int readCustom(uint16_t address, uint8_t data_len, uint8_t id, uint32_t& data);
53  virtual int writeCustom(uint16_t address, uint8_t data_len, uint8_t id, uint32_t data);
54 
55  virtual int writeSingleCmd(const std::unique_ptr<common::model::AbstractTtlSingleMotorCmd >& cmd) = 0;
56  virtual int writeSyncCmd(int type, const std::vector<uint8_t>& ids, const std::vector<uint32_t>& params) = 0;
57 
58 public:
59  virtual std::string str() const;
60 
61  // here are only common TTL commands found in both Steppers and DXl
62  virtual std::string interpretErrorState(uint32_t hw_state) const = 0;
63 
64  // eeprom write
65 
66  // eeprom read
67  virtual int checkModelNumber(uint8_t id) = 0;
68  virtual int readFirmwareVersion(uint8_t id, std::string& version) = 0;
69 
70  // ram read
71  virtual int readTemperature(uint8_t id, uint8_t& temperature) = 0;
72  virtual int readVoltage(uint8_t id, double& voltage) = 0;
73  virtual int readHwErrorStatus(uint8_t id, uint8_t& hardware_error_status) = 0;
74 
75  virtual int syncReadFirmwareVersion(const std::vector<uint8_t>& id_list, std::vector<std::string>& firmware_version) = 0;
76  virtual int syncReadTemperature(const std::vector<uint8_t>& id_list, std::vector<uint8_t>& temperature_list) = 0;
77  virtual int syncReadVoltage(const std::vector<uint8_t>& id_list, std::vector<double>& voltage_list) = 0;
78  virtual int syncReadRawVoltage(const std::vector<uint8_t>& id_list, std::vector<double>& voltage_list) = 0;
79  virtual int syncReadHwErrorStatus(const std::vector<uint8_t>& id_list, std::vector<uint8_t>& hw_error_list) = 0;
80  virtual int syncReadHwStatus(const std::vector<uint8_t> &id_list, 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,
92  const std::vector<uint8_t> &id_list,
93  std::vector<std::array<T, N> >& data_list);
94 
95  template<typename T>
96  int write(uint16_t address, uint8_t id, T data);
97 
98  template<typename T>
99  int syncWrite(uint16_t address, const std::vector<uint8_t>& id_list, const std::vector<T>& data_list);
100 
101  static constexpr int PING_WRONG_MODEL_NUMBER = 30;
102 
103  virtual std::string interpretFirmwareVersion(uint32_t fw_version) const = 0;
104 
105 private:
106  std::shared_ptr<dynamixel::PortHandler> _dxlPortHandler;
107  std::shared_ptr<dynamixel::PacketHandler> _dxlPacketHandler;
108 
109  static constexpr uint8_t DXL_LEN_ONE_BYTE = 1;
110  static constexpr uint8_t DXL_LEN_TWO_BYTES = 2;
111  static constexpr uint8_t DXL_LEN_FOUR_BYTES = 4;
112 
113  static constexpr int GROUP_SYNC_REDONDANT_ID = 10;
114  static constexpr int GROUP_SYNC_READ_RX_FAIL = 11;
115  static constexpr int LEN_ID_DATA_NOT_SAME = 20;
116 
117 protected:
118  // see 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  {
145  uint8_t raw_data;
146 
147  dxl_comm_result = _dxlPacketHandler->read1ByteTxRx(_dxlPortHandler.get(),
148  id, address, &raw_data, &error);
149  data = static_cast<T>(raw_data);
150  }
151  break;
152  case DXL_LEN_TWO_BYTES:
153  {
154  uint16_t raw_data;
155 
156  dxl_comm_result = _dxlPacketHandler->read2ByteTxRx(_dxlPortHandler.get(),
157  id, address, &raw_data, &error);
158  data = static_cast<T>(raw_data);
159  }
160  break;
161  case DXL_LEN_FOUR_BYTES:
162  {
163  uint32_t raw_data;
164 
165  dxl_comm_result = _dxlPacketHandler->read4ByteTxRx(_dxlPortHandler.get(),
166  id, address, &raw_data, &error);
167  data = static_cast<T>(raw_data);
168  }
169  break;
170  default:
171  printf("AbstractTtlDriver::read ERROR: Size param must be 1, 2 or 4 bytes\n");
172  break;
173  }
174 
175  if (0 != error)
176  {
177  printf("AbstractTtlDriver::write ERROR: device return error: id=%d, addr=%d, len=%d, err=0x%02x\n", id, address, static_cast<int>(sizeof(T)), error);
178  dxl_comm_result = error;
179  }
180 
181  return dxl_comm_result;
182 }
183 
184 
193 template<typename T, const size_t N>
195  const std::vector<uint8_t> &id_list,
196  std::vector<std::array<T, N> >& data_list)
197 {
198  data_list.clear();
199  uint16_t data_size = sizeof(T);
200  int dxl_comm_result = COMM_TX_FAIL;
201 
202  dynamixel::GroupSyncRead groupSyncRead(_dxlPortHandler.get(), _dxlPacketHandler.get(), address, data_size * N);
203 
204  for (auto const& id : id_list)
205  {
206  if (!groupSyncRead.addParam(id))
207  {
208  groupSyncRead.clearParam();
210  }
211  }
212 
213  dxl_comm_result = groupSyncRead.txRxPacket();
214 
215  if (COMM_SUCCESS == dxl_comm_result)
216  {
217  for (auto const& id : id_list)
218  {
219  if (groupSyncRead.isAvailable(id, address, data_size * N))
220  {
221  std::array<T, N> blocks{};
222 
223  for(uint8_t b = 0; b < N; ++b)
224  {
225  T data = static_cast<T>(groupSyncRead.getData(id, address + b * data_size, data_size));
226  blocks.at(b) = data;
227  }
228 
229  data_list.emplace_back(std::move(blocks));
230  }
231  else
232  {
233  dxl_comm_result = GROUP_SYNC_READ_RX_FAIL;
234  break;
235  }
236  }
237  }
238 
239  groupSyncRead.clearParam();
240 
241  return dxl_comm_result;
242 }
243 
251 template<typename T>
252 int AbstractTtlDriver::syncRead(uint16_t address,
253  const std::vector<uint8_t> &id_list,
254  std::vector<T> &data_list)
255 {
256  int dxl_comm_result = COMM_TX_FAIL;
257 
258  data_list.clear();
259  uint8_t data_len = sizeof(T);
260  if(data_len <= 4)
261  {
262  dynamixel::GroupSyncRead groupSyncRead(_dxlPortHandler.get(), _dxlPacketHandler.get(), address, data_len);
263 
264  for (auto const& id : id_list)
265  {
266  if (!groupSyncRead.addParam(id))
267  {
268  groupSyncRead.clearParam();
270  }
271  }
272 
273  dxl_comm_result = groupSyncRead.txRxPacket();
274 
275  if (COMM_SUCCESS == dxl_comm_result)
276  {
277  for (auto const& id : id_list)
278  {
279  if (groupSyncRead.isAvailable(id, address, data_len))
280  {
281  T data = static_cast<T>(groupSyncRead.getData(id, address, data_len));
282  data_list.emplace_back(data);
283  }
284  else
285  {
286  dxl_comm_result = GROUP_SYNC_READ_RX_FAIL;
287  break;
288  }
289  }
290  }
291 
292  groupSyncRead.clearParam();
293  }
294  else
295  {
296  printf("AbstractTtlDriver::syncRead ERROR: Size param must be 1, 2 or 4 bytes\n");
297  }
298 
299  return dxl_comm_result;
300 }
301 
302 template<typename T>
303 int AbstractTtlDriver::write(uint16_t address, uint8_t id, T data)
304 {
305  int dxl_comm_result = COMM_TX_FAIL;
306  uint8_t error = 0;
307 
308  switch (sizeof(T))
309  {
310  case DXL_LEN_ONE_BYTE:
311  dxl_comm_result = _dxlPacketHandler->write1ByteTxRx(_dxlPortHandler.get(),
312  id, address, data, &error);
313  break;
314  case DXL_LEN_TWO_BYTES:
315  dxl_comm_result = _dxlPacketHandler->write2ByteTxRx(_dxlPortHandler.get(),
316  id, address, data, &error);
317  break;
318  case DXL_LEN_FOUR_BYTES:
319  dxl_comm_result = _dxlPacketHandler->write4ByteTxRx(_dxlPortHandler.get(),
320  id, address, data, &error);
321  break;
322  default:
323  printf("AbstractTtlDriver::write ERROR: Size param must be 1, 2 or 4 bytes\n");
324  break;
325  }
326 
327  if (0 != error)
328  {
329  printf("AbstractTtlDriver::write ERROR: device return error: id=%d, addr=%d, len=%d, err=0x%02x\n", id, address, static_cast<int>(sizeof(T)), error);
330  dxl_comm_result = error;
331  }
332 
333  return dxl_comm_result;
334 }
335 
336 template<typename T>
337 int AbstractTtlDriver::syncWrite(uint16_t address, const std::vector<uint8_t>& id_list, const std::vector<T>& data_list)
338 {
339  int dxl_comm_result = COMM_SUCCESS;
340  uint8_t data_len = sizeof(T);
341 
342  if (!id_list.empty())
343  {
344  if (id_list.size() == data_list.size())
345  {
346  dynamixel::GroupSyncWrite groupSyncWrite(_dxlPortHandler.get(),
347  _dxlPacketHandler.get(),
348  address,
349  data_len);
350 
351  bool dxl_senddata_result = false;
352 
353  for (size_t i = 0; i < id_list.size(); ++i)
354  {
355  uint8_t id = id_list.at(i);
356  T data = data_list.at(i);
357 
358  switch (data_len)
359  {
360  case DXL_LEN_ONE_BYTE:
361  {
362  uint8_t params[1] = {static_cast<uint8_t>(data)};
363  dxl_senddata_result = groupSyncWrite.addParam(id, params);
364  }
365  break;
366  case DXL_LEN_TWO_BYTES:
367  {
368  uint8_t params[2] = {DXL_LOBYTE(static_cast<uint16_t>(data)),
369  DXL_HIBYTE(static_cast<uint16_t>(data))};
370  dxl_senddata_result = groupSyncWrite.addParam(id, params);
371  }
372  break;
373  case DXL_LEN_FOUR_BYTES:
374  {
375  uint8_t params[4] = {DXL_LOBYTE(DXL_LOWORD(data)),
376  DXL_HIBYTE(DXL_LOWORD(data)),
377  DXL_LOBYTE(DXL_HIWORD(data)),
378  DXL_HIBYTE(DXL_HIWORD(data))};
379  dxl_senddata_result = groupSyncWrite.addParam(id, params);
380  }
381  break;
382  default:
383  printf("AbstractTtlDriver::syncWrite ERROR: Size param must be 1, 2 or 4 bytes\n");
384  break;
385  }
386 
387  if (!dxl_senddata_result)
388  {
389  dxl_comm_result = GROUP_SYNC_REDONDANT_ID;
390  break;
391  }
392  }
393 
394  // send group if no error
395  if (GROUP_SYNC_REDONDANT_ID != dxl_comm_result)
396  dxl_comm_result = groupSyncWrite.txPacket();
397 
398  groupSyncWrite.clearParam();
399  }
400  else
401  {
402  dxl_comm_result = LEN_ID_DATA_NOT_SAME;
403  }
404  }
405 
406  return dxl_comm_result;
407 }
408 
409 } // ttl_driver
410 
411 #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:115
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:98
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:110
ttl_driver::AbstractTtlDriver::_dxlPortHandler
std::shared_ptr< dynamixel::PortHandler > _dxlPortHandler
Definition: abstract_ttl_driver.hpp:106
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:252
ttl_driver::AbstractTtlDriver::ping
virtual int ping(uint8_t id)
AbstractTtlDriver::ping.
Definition: abstract_ttl_driver.cpp:48
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:194
ttl_driver::AbstractTtlDriver::reboot
virtual int reboot(uint8_t id)
AbstractTtlDriver::reboot.
Definition: abstract_ttl_driver.cpp:84
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::checkModelNumber
virtual int checkModelNumber(uint8_t id)=0
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:121
ttl_driver::AbstractTtlDriver::scan
virtual int scan(std::vector< uint8_t > &id_list)
AbstractTtlDriver::scan.
Definition: abstract_ttl_driver.cpp:77
ttl_driver::AbstractTtlDriver::GROUP_SYNC_REDONDANT_ID
static constexpr int GROUP_SYNC_REDONDANT_ID
Definition: abstract_ttl_driver.hpp:113
ttl_driver::AbstractTtlDriver::write
int write(uint16_t address, uint8_t id, T data)
Definition: abstract_ttl_driver.hpp:303
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:63
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:101
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:107
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:337
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:114
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:111
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:109
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:166


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