YARP
Yet Another Robot Platform
DynamixelAX12FtdiDriver.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-FileCopyrightText: 2010 Ze Ji
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
8 
9 #include <yarp/os/Value.h>
10 #include <yarp/os/LogComponent.h>
11 
12 #include <cstdio>
13 
14 using namespace yarp::os;
15 using namespace yarp::dev;
16 
17 #define BOOL_EXIT_FAILURE false
18 
19 YARP_LOG_COMPONENT(DYNAMIXELAX12FTDIDRIVER, "yarp.devices.DynamixelAX12FtdiDriver")
20 
21 
22 bool NOT_YET_IMPLEMENTED(const char *txt) {
23  yCError(DYNAMIXELAX12FTDIDRIVER, "%s not yet implemented for DynamixelAX12FtdiDriver", txt);
24  return false;
25 }
26 
28  deviceOpen(false),
29  jointNumbers((unsigned char *) malloc(16 * sizeof (unsigned char))),
30  numOfAxes(16),
31  positions((double *) malloc(numOfAxes * sizeof (double))),
32  speeds((double *) malloc(numOfAxes * sizeof (double))),
33  devlist(NULL),
34  torques((int *) malloc(numOfAxes * sizeof (int)))
35 {
36  // initialise
37  jointNumbers[0] = 0x65;
38  jointNumbers[1] = 0x74;
39  jointNumbers[2] = 0x84;
40  jointNumbers[3] = 0x66;
41  jointNumbers[4] = 0x75;
42  jointNumbers[5] = 0x85;
43  jointNumbers[6] = 0x67;
44  jointNumbers[7] = 0x76;
45  jointNumbers[8] = 0x86;
46  jointNumbers[9] = 0x6B;
47  jointNumbers[10] = 0x77;
48  jointNumbers[11] = 0x87;
49  jointNumbers[12] = 0x6A;
50  jointNumbers[13] = 0x68;
51  jointNumbers[14] = 0x69;
52  jointNumbers[15] = 0x6C;
53 
54  ftdi_init(&ftdic);
55 }
56 
58  ftdi_list_free(&devlist);
59  ftdi_deinit(&ftdic);
60  free(jointNumbers);
61  free(positions);
62  free(speeds);
63  free(torques);
64 }
65 
67 
68  mutex.lock();
69 
70  FtdiDeviceSettings ftdiSetting;
71  strcpy(ftdiSetting.description, config.check("FTDI_DESCRIPTION", Value("FT232R USB UART"), "Ftdi device description").asString().c_str());
72  strcpy(ftdiSetting.serial, config.check("FTDI_SERIAL", Value("A7003MhG"), "Ftdi device serial").asString().c_str());
73  strcpy(ftdiSetting.manufacturer, config.check("FTDI_MANUFACTURER", Value("FTDI"), "Ftdi device manufacturer").asString().c_str());
74  ftdiSetting.baudrate = config.check("baudrate", Value(57600), "Specifies the baudrate at which the communication port operates.").asInt32();
75  ftdiSetting.vendor = config.check("ftdivendor", Value(0x0403), "USB device vendor. 0x0403 normally. Can be found by lsusb on linux").asInt32();
76  ftdiSetting.product = config.check("ftdiproduct", Value(0x6001), "USB device product number. 0x6001 normally. Can be found by lsusb on linux").asInt32();
77  ftdiSetting.flowctrol = config.check("flowctrl", Value(SIO_DISABLE_FLOW_CTRL), "flow control to use. Should be SIO_DISABLE_FLOW_CTRL = 0x0, SIO_RTS_CTS_HS = 0x1 << 8, SIO_DTR_DSR_HS = 0x2 << 8, or SIO_XON_XOFF_HS = 0x4 << 8").asInt32();
78  ftdiSetting.write_chunksize = 3;
79  ftdiSetting.read_chunksize = 256;
80 
81  yCTrace(DYNAMIXELAX12FTDIDRIVER, "DynamixelAx12Driver::initialize");
82  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Opening DynamixelAx12 Device");
83 
84  int retCode;
85 
86  char manufacturer[128], description[128];
87  char serial[128];
88  //int n = 0; // number of devices found
89 
90  retCode = ftdi_usb_find_all(&ftdic, &devlist, ftdiSetting.vendor, ftdiSetting.product);
91  switch (retCode) {
92  case -1:
93  yCError(DYNAMIXELAX12FTDIDRIVER, "usb_find_busses() failed");
94  return BOOL_EXIT_FAILURE;
95  case -2:
96  yCError(DYNAMIXELAX12FTDIDRIVER, "usb_find_devices() failed");
97  return BOOL_EXIT_FAILURE;
98  case -3:
99  yCError(DYNAMIXELAX12FTDIDRIVER, "out of memory");
100  return BOOL_EXIT_FAILURE;
101  case 0:
102  yCError(DYNAMIXELAX12FTDIDRIVER, "No device is found. Check connection.");
103  return BOOL_EXIT_FAILURE;
104  default:
105  yCInfo(DYNAMIXELAX12FTDIDRIVER, "%d devices have been found.", retCode);
106  break;
107  }
108 
109  int ret = 0;
110  int i = 0;
111 
112  for (curdev = devlist; curdev != NULL; i++) {
113  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Checking device: %d", i);
114 
115  if ((retCode = ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, serial, 128)) < 0) {
116  yCError(DYNAMIXELAX12FTDIDRIVER, "ftdi_usb_get_strings failed: %d (%s)", ret, ftdi_get_error_string(&ftdic));
117  }
118  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Manufacturer: %s, Description: %s, Serial %s", manufacturer, description, serial);
119 
120  // check if the current device is the right one
121  if (strcmp(serial, ftdiSetting.serial) == 0) {
122  break;
123  }
124  curdev = curdev->next;
125  }
126 
127  if (curdev == NULL) {
128  yCError(DYNAMIXELAX12FTDIDRIVER, "No Dynamixel device is found. Check connection.");
129  return BOOL_EXIT_FAILURE;
130  }
131 
132  // open and reset everything in case we messed everything up with a control-c..
133  if ((retCode = ftdi_usb_open_dev(&ftdic, curdev->dev)) < 0) {
134  yCError(DYNAMIXELAX12FTDIDRIVER, "unable to open ftdi device: %d (%s)", retCode, ftdi_get_error_string(&ftdic));
135  return BOOL_EXIT_FAILURE;
136  }
137  deviceOpen = true; // Only set to be able to do close()
138 
139  this->close();
140 
141  // Now open again
142  if ((retCode = ftdi_usb_open_dev(&ftdic, curdev->dev)) < 0) {
143  yCError(DYNAMIXELAX12FTDIDRIVER, "unable to open ftdi device: %d (%s)", retCode, ftdi_get_error_string(&ftdic));
144  return BOOL_EXIT_FAILURE;
145  }
146 
147  // To test connection, read out FTDIChip-ID of R type chips
148  if (ftdic.type == TYPE_R) {
149  unsigned int chipid;
150  if (ftdi_read_chipid(&ftdic, &chipid) == 0) {
151  yCInfo(DYNAMIXELAX12FTDIDRIVER, "FTDI Device open. FTDI chipid: %X", chipid);
152  } else {
153  yCError(DYNAMIXELAX12FTDIDRIVER, "Unable to access FTDI device!");
154  return BOOL_EXIT_FAILURE;
155  }
156  }
157  deviceOpen = true;
158 
159  // We have an open device and it is accessible, so set parameters
160 
161  if ((retCode = ftdi_set_baudrate(&ftdic, ftdiSetting.baudrate)) != 0) {
162  yCError(DYNAMIXELAX12FTDIDRIVER, "Error setting baudrate, ret=%d", retCode);
163  }
164  if (ftdi_set_line_property(&ftdic, BITS_8, STOP_BIT_1, NONE) == -1) {
165  yCError(DYNAMIXELAX12FTDIDRIVER, "Error setting connection properties");
166  }
167  if (ftdi_setflowctrl(&ftdic, SIO_DISABLE_FLOW_CTRL) == -1) {
168  yCError(DYNAMIXELAX12FTDIDRIVER, "Error setting flow control");
169  }
170 
171  // Set chunk sizes for in and out
172  ftdi_write_data_set_chunksize(&ftdic, ftdiSetting.write_chunksize);
173  ftdi_read_data_set_chunksize(&ftdic, ftdiSetting.read_chunksize);
174 
175  // Everything ready to rumble
176 
177  mutex.unlock();
178 
179  return true;
180 }
181 
183 
184  // First check if we have an open device
185  if (deviceOpen) {
186  // Yes, we have, so purge the buffers, reset the device and then close it
187  ftdi_usb_purge_buffers(&ftdic);
188  //ftdi_usb_reset(ftdic.usb_dev);
189  ftdi_usb_reset(&ftdic);
190  ftdi_usb_close(&ftdic);
191  } else {
192  // We don't seem to have a device open at this time
193  yCError(DYNAMIXELAX12FTDIDRIVER, "close():No device open to be be closed!");
194  return false;
195  }
196  return true;
197 }
198 
203  yarp::os::Value indexValue = config.find("SENSORINDEX");
204  yarp::os::Bottle *indexBottle = indexValue.asList();
205  this->initMotorIndex(indexBottle);
206  return true;
207 }
208 
209 int DynamixelAX12FtdiDriver::syncSendCommand(unsigned char id, unsigned char inst[], int size, unsigned char ret[], int &retSize) {
210  int r = 0;
211  mutex.lock();
212  if (!ftdi_usb_purge_buffers(&ftdic)) {
213  r = sendCommand(id, inst, size, ret, retSize);
214  }
215 
216  mutex.unlock();
217  return r;
218 }
219 
220 int DynamixelAX12FtdiDriver::sendCommand(unsigned char id, unsigned char inst[], int size, unsigned char ret[], int &retSize) {
221 
222  int i;
223  int retCode = 0;
224  bool badAnswer = false;
225  unsigned char command[16];
226  unsigned char chksum = 0x00;
227  unsigned char header[4];
228  unsigned char body[256];
229 
230  // Build packet header
231 
232  command[0] = 0xFF; // Header bytes
233  command[1] = 0xFF;
234  command[2] = id; // Id of device
235  command[3] = size + 1; // Size of instruction plus checksum byte
236 
237  // Add instruction
238  for (i = 0; i < size; i++) {
239  command[4 + i] = inst[i];
240  chksum += inst[i];
241  }
242 
243  // Calculate checksum
244  command[size + 5 - 1] = ~(chksum + command[2] + command[3]);
245  yCDebug(DYNAMIXELAX12FTDIDRIVER, "Packet sent: ");
246  for (i = 0; i < size + 5; i++) {
247  yCDebug(DYNAMIXELAX12FTDIDRIVER, " %X", command[i]);
248  }
249  // Write data to device
250  retCode = ftdi_write_data(&ftdic, command, size + 5);
251 
252  // Now receive return packet
253  if (id != AX12_BROADCAST_ID) {
254  do {
255  //retCode stores the number of bytes read, which may not correspond to the number of bytes
256  //one wants to read (the third parameter). This is a timing issue, so to learn how to fix
257  //it, I should send a command and then continually prints the bytes that I get back. At
258  //some point, I will get back the correct number of bytes. After doing this enough times,
259  //I should work out the timing issue
260  retCode = ftdi_read_data(&ftdic, header, 4);
261  } // retCode: <0,: error code from usb_bulk_read()
262  // 0: no data was available
263  // >0: number of bytes read
265  while (retCode == 0); // not needed. as it will hang if no device is connected
266 
267  if (retCode < 0) {
268  yCError(DYNAMIXELAX12FTDIDRIVER, "Error while reading header of status packet! From usb_bulk_read() (%d)", retCode);
269  return 0;
270  } else if (retCode < 4) {
271  yCError(DYNAMIXELAX12FTDIDRIVER, "Error while reading header of status packet! (%d)", retCode);
272  return 0;
273  } else {
274  retCode = 0;
275  if (header[0] != 0xFF || header[1] != 0xFF) {
276  badAnswer = true;
277  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Received data without header bytes: ");
278  } else if (header[2] != id) {
279  badAnswer = true;
280  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Received status from wrong device (expected %d): ", id);
281  } else {
282  // Now that we know a well formed packet is arriving, read remaining bytes
283  do {
284  retCode = ftdi_read_data(&ftdic, body, header[3]);
285  } while (retCode == 0);
286 
287  if (retCode != header[3]) {
288  badAnswer = true;
289  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Received data with wrong length: ");
290  } else {
291  //check checksum
292  chksum = 0;
293  for (i = 0; i < retCode - 1; i++) {
294  chksum += body[i];
295  }
296  if (body[retCode - 1] != (unsigned char) ~(chksum + header[2] + header[3])) {
297  badAnswer = true;
298  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Received data with wrong checksum (%X != %X): ", body[retCode - 1], (unsigned char) ~(chksum + header[2] + header[3]));
299  } else {
300  // Packet ok, so return the instruction part without checksum
301  for (i = 0; i < retCode - 1; i++) {
302  ret[i] = body[i];
303  }
304  // retSize = retCode; // Sven's original code.
305  retSize = retCode - 1; // retSize should be retCode - 1, as checksum is not included
306  return 1;
307  }
308  }
309  }
310  }
311 
312  // Print packet if something was wrong
313  if (badAnswer) {
314  for (i = 0; i < 4; i++) {
315  yCInfo(DYNAMIXELAX12FTDIDRIVER, "%X ", header[i]);
316  }
317  for (i = 0; i < retCode; i++) {
318  yCInfo(DYNAMIXELAX12FTDIDRIVER, "%X ", body[i]);
319  }
320  return 0;
321  }
322  }
323 
324  return 1;
325 }
326 
327 ErrorCode DynamixelAX12FtdiDriver::checkAnswerPacket(unsigned char* packet, const char*& message) {
328  if (packet[0] & 1) {
329  message = "Voltage out of operating voltage range!";
330  return VOLTAGE_ERROR;
331  }
332  if (packet[0] & 2) {
333  message = "Goal position outside angle limits!";
334  return ANGLE_ERROR;
335  }
336  if (packet[0] & 4) {
337  message = "Current temperature outside operating temperature!";
338  return OVERHEATING_ERROR;
339  }
340  if (packet[0] & 8) {
341  message = "Instruction out of defined range!";
342  return RANGE_ERROR;
343  }
344  if (packet[0] & 16) {
345  message = "Checksum of instruction package incorrect!";
346  return CHECKSUM_ERROR;
347  }
348  if (packet[0] & 32) {
349  message = "Specified torque can't control the applied load!";
350  return OVERLOAD_ERROR;
351  }
352  if (packet[0] & 64) {
353  message = "Undefined instruction or missing Reg_Write instruction!";
354  return INSTRUCTION_ERROR;
355  }
356  message = "";
357  return OK;
358 }
359 
362 int DynamixelAX12FtdiDriver::readParameter(unsigned char id, unsigned char param) {
363  // Read instruction has 2 parameters: The starting address of the parameter and the number of bytes to read
364  // Both are encoded in param (> 100 = 2 bytes)
365  unsigned char packet[] = {INST_READ, 0, 1};
366 
367  unsigned char answerPacket[256];
368  int answerSize;
369  const char* errorMessage;
370  ErrorCode errCode;
371 
372  if (param > 99) {
373  // We have to read 2 bytes
374  packet[1] = param - 100;
375  packet[2] = 2;
376  } else {
377  // We have to read 1 bytes
378  packet[1] = param;
379  }
380 
381  // Send request
382  //sendCommand(id, packet, 3, answerPacket, answerSize);
383  syncSendCommand(id, packet, 3, answerPacket, answerSize);
384  // Check for submitted error code
385  if ((errCode = checkAnswerPacket(answerPacket, errorMessage)) != OK) {
386  // We received an error code
387  return -1;
388  } else {
389  // No error
390  return 1;
391  }
392 }
393 
395  *ax = numOfAxes;
396  return true;
397 }
398 
399 bool DynamixelAX12FtdiDriver::positionMove(int j, double ref) {
400  double speed;
401  int blankReturnSize = -1;
402  unsigned char blankReturn[] = {0, 0, 0};
403  getRefSpeed(j, &speed);
404  const int instl = 5 + 1;
405 
406  unsigned char inst[instl] = {INST_WRITE, CT_GOAL_POSITION, (unsigned char) (normalisePosition(ref)&0xFF), (unsigned char) ((normalisePosition(ref) >> 8) & 0xFF), (unsigned char) (normaliseSpeed(speed)&0xFF), (unsigned char) ((normaliseSpeed(speed) >> 8)&0xFF)};
407 
408  positions[j] = ref;
409 
410  return syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
411 }
412 
416 bool DynamixelAX12FtdiDriver::positionMove(const double *refs) {
417  bool t = true;
418  for (int k = 0; k < numOfAxes; k++) {
419  if (!this->positionMove(k, refs[k])) {
420  t = false;
421  }
422  }
423  return t;
424 }
425 
426 bool DynamixelAX12FtdiDriver::relativeMove(int j, double delta) {
427  double v = positions[j];
428  if (getEncoder(j, &v)) {
429  return this->positionMove(j, v + delta);
430  } else {
431  return false;
432  }
433 }
434 
435 bool DynamixelAX12FtdiDriver::relativeMove(const double *deltas) {
436  bool t = true;
437  for (int k = 0; k < numOfAxes; k++) {
438  if (!this->positionMove(k, positions[k] + deltas[k])) {
439  t = false;
440  }
441  }
442  return t;
443 }
444 
446  double v = 0;
447  bool t = true;
448 
449  t = getEncoder(j, &v);
450  *flag = (std::fabs(v - positions[j]) < MOTION_COMPLETION_TOLERANCE);
451  return t;
452 }
453 
455  bool t = true;
456  bool tmp_done(false), all_done(true);
457  for (int k = 0; k < numOfAxes; k++)
458  {
459  if (!this->checkMotionDone(k, &tmp_done)) {
460  t = false;
461  }
462  all_done &= tmp_done;
463  }
464  *flag = all_done;
465  return t;
466 }
467 
468 bool DynamixelAX12FtdiDriver::setRefSpeed(int j, double sp) {
469  if (sp < 1) {
470  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid speed value, should be from 1 to 114");
471  speeds[j] = 1;
472  return false;
473  } else if (sp > 114) {
474  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid speed value, should be from 1 to 114");
475  speeds[j] = 114;
476  return false;
477  } else {
478  speeds[j] = sp;
479  return true;
480  }
481 }
482 
483 bool DynamixelAX12FtdiDriver::setRefSpeeds(const double *spds) {
484  bool t = true;
485  for (int k = 0; k < numOfAxes; k++) {
486  if (!setRefSpeed(k, spds[k])) {
487  t = false;
488  }
489  }
490  return t;
491 }
492 
497  return NOT_YET_IMPLEMENTED("setRefAcceleration");
498 }
499 
504  return NOT_YET_IMPLEMENTED("setRefAccelerations");
505 }
506 
507 bool DynamixelAX12FtdiDriver::getRefSpeed(int j, double *ref) {
508  *ref = speeds[j];
509  return true;
510 }
511 
513  for (int k = 0; k < numOfAxes; k++) {
514  spds[k] = speeds[k];
515  }
516  return true;
517 }
518 
523  return NOT_YET_IMPLEMENTED("getRefAcceleration");
524 }
525 
530  return NOT_YET_IMPLEMENTED("getRefAccelerations");
531 }
532 
534  return NOT_YET_IMPLEMENTED("stop");
535 }
536 
538  for (int i = 0; i < numOfAxes; i++) {
539  if (!stop(i)) {
540  return false;
541  }
542  }
543  return true;
544 }
545 
546 int DynamixelAX12FtdiDriver::normalisePosition(double position) {
547  if (position < 0) {
548  position = 0;
549  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid position value, should be from 0 to 300");
550  } else if (position > 300) {
551  position = 300;
552  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid position value, should be from 0 to 300");
553  }
554 
555  return (int) (1024 * position / 301);
556 }
557 
558 int DynamixelAX12FtdiDriver::normaliseSpeed(double speed) {
559  // speed -> [1 114] RPM
560  // when speed is 0, it is maximum possible speed, no speed control. so it is not useful here
561  if (speed < 1) {
562  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid speed value, should be from 1 to 114");
563  speed = 1;
564  } else if (speed > 114) {
565  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid speed value, should be from 1 to 114");
566  speed = 114;
567  }
568  return (int) (1024 * speed / 114 - 1);
569 }
570 
572  for (int k = 0; k < numOfAxes; k++) {
573  t[k] = torques[k];
574  }
575  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is just the MAX tourque set for the ax12 servo.");
576  return true;
577 }
578 
580  *t = torques[j];
581  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is just the MAX tourque set for the ax12 servo.");
582  return true;
583 }
584 
586  bool tt = true;
587  for (int k = 0; k < numOfAxes; k++) {
588  if (!this->setTorque(k, t[k])) {
589  tt = false;
590  }
591  }
592  return tt;
593 }
594 
600  if (t < 0) {
601  yCError(DYNAMIXELAX12FTDIDRIVER, "torque (%d) should in range [0 1023] or [0 0x3FF]. t is set to 0 here", (int)t);
602  t = 0;
603  } else if (t > 1023) {
604  yCError(DYNAMIXELAX12FTDIDRIVER, "torque (%d) should in range [0 1023] or [0 0x3FF]. t is set to 1023 here", (int)t);
605  t = 1023;
606  }
607 
608  int blankReturnSize = -1;
609  unsigned char blankReturn[] = {0, 0, 0};
610  const int instl = 3 + 1;
611 
612  unsigned char inst[instl] = {INST_WRITE, CT_MAX_TORQUE, (unsigned char) ((int) t & 0xFF), (unsigned char) (((int) t << 8) & 0x03)};
613  //return sendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
614  return syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
615 }
616 
618  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
619  return NOT_YET_IMPLEMENTED("setTorquePid");
620 }
621 
622 bool DynamixelAX12FtdiDriver::getTorque(int j, double *t) {
623  bool ret;
624 
625  int blankReturnSize = -1;
626  unsigned char blankReturn[] = {0, 0, 0};
627 
628  const int instl = 3;
629  unsigned char inst[instl] = {INST_READ, (unsigned char) CT_PRESENT_LOAD, (unsigned char) 2};
630  //ret = sendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
631  ret = syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
632 
633  const char* message = "";
634  if (checkAnswerPacket(blankReturn, message) == OK) {
635  //int load = (blankReturn[2]&0b00000011)*256 + blankReturn[1];
636  int load = (blankReturn[2]&0X03)*256 + blankReturn[1];
637  //load *= (((blankReturn[2] >> 2)&0b000001) ? -1 : 1);
638  load *= (((blankReturn[2] >> 2)&0X01) ? -1 : 1);
639  *t = load;
640  } else {
641  yCError(DYNAMIXELAX12FTDIDRIVER, "%s", message);
642  return false;
643  }
644  return ret;
645 }
646 
648  int k = 0;
649  bool tt = true;
650  for (k = 0; k < numOfAxes; k++) {
651  if (!getTorque(k, &t[k])) {
652  tt = false;
653  }
654  }
655  return tt;
656 }
657 
659  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
660  return NOT_YET_IMPLEMENTED("setTorquePids");
661 }
662 
664  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
665  return NOT_YET_IMPLEMENTED("setTorqueErrorLimit");
666 }
667 
669  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
670  return NOT_YET_IMPLEMENTED("setTorqueErrorLimits");
671 }
672 
673 bool DynamixelAX12FtdiDriver::getTorqueError(int j, double *err) {
674  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
675  return NOT_YET_IMPLEMENTED("getTorqueError");
676 }
677 
679  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
680  return NOT_YET_IMPLEMENTED("getTorqueErrors");
681 }
682 
684  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
685  return NOT_YET_IMPLEMENTED("getTorquePidOutput");
686 }
687 
689  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
690  return NOT_YET_IMPLEMENTED("getTorquePidOutputs");
691 }
692 
694  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
695  return NOT_YET_IMPLEMENTED("getTorquePid");
696 }
697 
699  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
700  return NOT_YET_IMPLEMENTED("getTorquePids");
701 }
702 
704  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
705  return NOT_YET_IMPLEMENTED("getTorqueErrorLimit");
706 }
707 
709  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
710  return NOT_YET_IMPLEMENTED("getTorqueErrorLimits");
711 }
712 
714  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
715  return NOT_YET_IMPLEMENTED("resetTorquePid");
716 }
717 
719  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
720  return NOT_YET_IMPLEMENTED("disableTorquePid");
721 }
722 
724  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
725  return NOT_YET_IMPLEMENTED("enableTorquePid");
726 }
727 
729  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
730  return NOT_YET_IMPLEMENTED("setTorqueOffset");
731 }
732 
733 bool DynamixelAX12FtdiDriver::getBemfParam(int j, double *bemf) {
734  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
735  return NOT_YET_IMPLEMENTED("getBemfParam");
736 }
737 
738 bool DynamixelAX12FtdiDriver::setBemfParam(int j, double bemf) {
739  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
740  return NOT_YET_IMPLEMENTED("setBemfParam");
741 }
742 
744  return NOT_YET_IMPLEMENTED("resetEncoder");
745 }
746 
748  return NOT_YET_IMPLEMENTED("resetEncoders");
749 }
750 
751 bool DynamixelAX12FtdiDriver::setEncoder(int j, double val) {
752  return NOT_YET_IMPLEMENTED("setEncoder");
753 }
754 
755 bool DynamixelAX12FtdiDriver::setEncoders(const double *vals) {
756  return NOT_YET_IMPLEMENTED("setEncoders");
757 }
758 
760  return NOT_YET_IMPLEMENTED("setRefTorques");
761 }
762 
764  return NOT_YET_IMPLEMENTED("setRefTorque");
765 }
766 
767 bool DynamixelAX12FtdiDriver::getTorqueRange(int j, double* min, double* max) {
768  return NOT_YET_IMPLEMENTED("getTorqueRange");
769 }
770 
771 bool DynamixelAX12FtdiDriver::getTorqueRanges(double* min, double* max) {
772  return NOT_YET_IMPLEMENTED("getTorqueRanges");
773 }
774 
775 bool DynamixelAX12FtdiDriver::getEncoder(int j, double *v) {
776  *v = -1; // invalid value for encoder of AX12 motor
777  int ret = 1;
778 
779  int blankReturnSize = -1;
780  unsigned char blankReturn[] = {0, 0, 0};
781 
782  const int instl = 3;
783  unsigned char inst[instl] = {INST_READ, (unsigned char) CT_PRESENT_POSITION, (unsigned char) 2};
784  //ret = sendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
785  ret = syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
786 
787  int pos = 0;
788  if (ret == 1) {
789  const char* message = "";
790  if (checkAnswerPacket(blankReturn, message) == OK) {
791  pos = ((int) blankReturn[2])*256 + blankReturn[1];
792  *v = ((double) pos)*300.0 / 1024.0;
793  return true;
794  } else {
795  yCError(DYNAMIXELAX12FTDIDRIVER, "%s", message);
796  return false;
797  }
798 
799  } // pos = (blankReturn[1]&0b00000011)*0x100 + blankReturn[0];
800  else {
801  return false;
802  }
803 }
804 
806  int k = 0;
807  bool tt = true;
808 
809  for (k = 0; k < numOfAxes; k++) {
810  if (!getEncoder(k, &encs[k])) {
811  tt = false;
812  }
813  }
814  return tt;
815 }
816 
818  bool ret;
819 
820  int blankReturnSize = -1;
821  unsigned char blankReturn[] = {0, 0, 0};
822  const int instl = 3;
823  unsigned char inst[instl] = {INST_READ, (unsigned char) CT_PRESENT_SPEED, (unsigned char) 2};
824  //ret = sendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
825  ret = syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
826 
827  double speed = 0;
828  const char* message = "";
829  if (checkAnswerPacket(blankReturn, message) == OK) {
830  //speed = (blankReturn[2]&0b00000011)*0xFF + blankReturn[1];
831  speed = (blankReturn[2]&0X03)*0xFF + blankReturn[1];
832 
833  //speed *= (((blankReturn[1] >> 2)&0b000001) ? -1 : 1);
834  speed *= (((blankReturn[1] >> 2)&0X01) ? -1 : 1);
835 
836  *sp = speed * 113 / 1024 + 1;
837  } else {
838  yCError(DYNAMIXELAX12FTDIDRIVER, "%s", message);
839  return false;
840  }
841  return ret;
842 }
843 
845  int k = 0;
846  bool tt = true;
847  for (k = 0; k < numOfAxes; k++) {
848  if (!getEncoderSpeed(k, &spds[k])) {
849  tt = false;
850  }
851  }
852  return tt;
853 }
854 
856  return NOT_YET_IMPLEMENTED("getEncoderAcceleration");
857 }
858 
860  return NOT_YET_IMPLEMENTED("getEncoderAccelerations");
861 }
862 
863 bool DynamixelAX12FtdiDriver::initMotorIndex(yarp::os::Bottle *sensorIndex) {
864  int s = sensorIndex->size() - 1;
865  if (s != sensorIndex->get(0).asInt32()) {
866  yCError(DYNAMIXELAX12FTDIDRIVER, "sensor number does not match the real number in configuration file");
867  return false;
868  }
869  numOfAxes = s;
870  unsigned char *tmp = NULL;
871  tmp = (unsigned char *) realloc(jointNumbers, numOfAxes * sizeof (unsigned char));
872  if (tmp != NULL) {
873  // jointNumbers = {0x65, 0x74, 0x84, 0x66, 0x75, 0x85, 0x67, 0x76, 0x86, 0x6B, 0x77, 0x87, 0x6A, 0x68, 0x69, 0x6C};
874  jointNumbers = tmp;
875  } else {
876  return false;
877  }
878  double *tmpp = NULL;
879  tmpp = (double *) realloc(positions, numOfAxes * sizeof (double));
880  if (tmpp != NULL) {
881  positions = tmpp;
882  } else {
883  return false;
884  }
885 
886  double *tmps = NULL;
887  tmps = (double *) realloc(speeds, numOfAxes * sizeof (double));
888  if (tmps != NULL) {
889  speeds = tmps;
890  } else {
891  return false;
892  }
893 
894  int *tmpt = NULL;
895  tmpt = (int *) realloc(torques, numOfAxes * sizeof (int));
896  if (tmpt != NULL) {
897  torques = tmpt;
898  } else {
899  return false;
900  }
901 
902  for (int i = 0; i < numOfAxes; i++) {
903  jointNumbers[i] = (unsigned char) (sensorIndex->get(i + 1).asInt32());
904  }
905  return true;
906 }
907 
908 bool DynamixelAX12FtdiDriver::positionMove(const int n_joint, const int *joints, const double *refs)
909 {
910  bool ret = true;
911  for(int j=0; j<n_joint; j++)
912  {
913  ret &= positionMove(joints[j], refs[j]);
914  }
915  return ret;
916 }
917 
918 bool DynamixelAX12FtdiDriver::relativeMove(const int n_joint, const int *joints, const double *deltas)
919 {
920  bool ret = true;
921  for(int j=0; j<n_joint; j++)
922  {
923  ret &= relativeMove(joints[j], deltas[j]);
924  }
925  return ret;
926 }
927 
928 bool DynamixelAX12FtdiDriver::checkMotionDone(const int n_joint, const int *joints, bool *flag)
929 {
930  bool ret = true;
931  bool tmp_joint(false), tmp_device(true);
932  for(int j=0; j<n_joint; j++)
933  {
934  ret &= checkMotionDone(joints[j], &tmp_joint);
935  tmp_device &= tmp_joint;
936  }
937  *flag = tmp_device;
938  return ret;
939 }
940 
941 bool DynamixelAX12FtdiDriver::setRefSpeeds(const int n_joint, const int *joints, const double *spds)
942 {
943  bool ret = true;
944  for(int j=0; j<n_joint; j++)
945  {
946  ret &= setRefSpeed(joints[j], spds[j]);
947  }
948  return ret;
949 }
950 
951 bool DynamixelAX12FtdiDriver::setRefAccelerations(const int n_joint, const int *joints, const double *accs)
952 {
953  bool ret = true;
954  for(int j=0; j<n_joint; j++)
955  {
956  ret &= setRefAcceleration(joints[j], accs[j]);
957  }
958  return ret;
959 }
960 
961 bool DynamixelAX12FtdiDriver::getRefSpeeds(const int n_joint, const int *joints, double *spds)
962 {
963  bool ret = true;
964  for(int j=0; j<n_joint; j++)
965  {
966  ret &= getRefSpeed(joints[j], &spds[j]);
967  }
968  return ret;
969 }
970 
971 bool DynamixelAX12FtdiDriver::getRefAccelerations(const int n_joint, const int *joints, double *accs)
972 {
973  bool ret = true;
974  for(int j=0; j<n_joint; j++)
975  {
976  ret &= getRefSpeed(joints[j], &accs[j]);
977  }
978  return ret;
979 }
980 
981 bool DynamixelAX12FtdiDriver::stop(const int n_joint, const int *joints)
982 {
983  bool ret = true;
984  for(int j=0; j<n_joint; j++)
985  {
986  ret &= stop(joints[j]);
987  }
988  return ret;
989 }
bool NOT_YET_IMPLEMENTED(const char *txt)
#define BOOL_EXIT_FAILURE
const yarp::os::LogComponent & DYNAMIXELAX12FTDIDRIVER()
#define CT_GOAL_POSITION
#define INST_WRITE
#define CT_PRESENT_SPEED
#define CT_PRESENT_LOAD
#define AX12_BROADCAST_ID
defines for AX12 general ids
@ OVERHEATING_ERROR
@ INSTRUCTION_ERROR
#define INST_READ
#define MOTION_COMPLETION_TOLERANCE
#define CT_MAX_TORQUE
#define CT_PRESENT_POSITION
float t
bool ret
bool setRefAccelerations(const double *accs) override
not implemented
bool getEncoderSpeed(int j, double *sp) override
Read the istantaneous speed of an axis.
bool setTorquePid(int j, const Pid &pid)
bool getTorquePid(int j, Pid *pid)
bool setTorqueOffset(int j, double v)
bool close() override
Close device Closes the device and shuts down connection.
bool getTorque(int j, double *t) override
Get the value of the torque on a given joint (this is the feedback if you have a torque sensor).
bool setTorqueErrorLimits(const double *limits)
virtual int sendCommand(unsigned char id, unsigned char inst[], int size, unsigned char ret[], int &retSize)
Send instruction to device Send an instruction to a device of given ID.
bool setTorquePids(const Pid *pids)
bool getBemfParam(int j, double *bemf)
virtual int readParameter(unsigned char id, unsigned char param)
Read parameter from motor Requests the value of a parameter from motor.
bool resetEncoder(int j) override
Reset encoder, single joint.
bool getTorquePidOutputs(double *outs)
bool setTorques(const double *t)
bool getRefTorque(int j, double *t) override
Get the reference value of the torque for a given joint.
bool setRefAcceleration(int j, double acc) override
not implemented
bool setEncoders(const double *vals) override
Set the value of all encoders.
bool getEncoder(int j, double *v) override
Get the angle of servo.
bool configure(yarp::os::Searchable &config) override
Configure device online Configures parts of the device that can be configures online.
bool getTorqueError(int j, double *err)
bool setRefTorque(int j, double t) override
Set the reference value of the torque for a given joint.
bool getRefSpeeds(double *spds) override
Get reference speed of all joints.
bool getEncoderAccelerations(double *accs) override
Read the instantaneous acceleration of all axes.
bool setEncoder(int j, double val) override
Set the value of the encoder for a given joint.
bool getTorqueErrorLimits(double *limits)
bool setRefTorques(const double *t) override
Set the reference value of the torque for all joints.
bool getEncoders(double *encs) override
Read the position of all axes.
bool getRefSpeed(int j, double *ref) override
Get reference speed for a joint.
bool checkMotionDone(int j, bool *flag) override
Check if the current trajectory is terminated.
bool getEncoderSpeeds(double *spds) override
Read the instantaneous speed of all axes.
bool open(yarp::os::Searchable &config) override
Open device Opens and configures the device.
DynamixelAX12FtdiDriver()
Constructor Initializes handle but doesn't open channel yet.
virtual ~DynamixelAX12FtdiDriver()
Destructor Closes connection and destroys device object.
bool getTorqueRange(int j, double *min, double *max) override
Get the full scale of the torque sensor of a given joint.
bool getAxes(int *ax) override
Get the number of controlled axes.
bool getRefAccelerations(double *accs) override
not implemented
bool resetEncoders() override
Reset encoders.
bool setTorqueErrorLimit(int j, double limit)
bool setBemfParam(int j, double bemf)
bool getEncoderAcceleration(int j, double *spds) override
Read the instantaneous acceleration of an axis.
bool setRefSpeeds(const double *spds) override
Set reference speed on all joints.
bool getTorques(double *t) override
Get the value of the torque for all joints (this is the feedback if you have torque sensors).
bool stop() override
Stop motion, multiple joints.
bool positionMove(int j, double ref) override
bool getRefTorques(double *t) override
Get the reference value of the torque for all joints.
bool getTorqueErrorLimit(int j, double *limit)
bool getRefAcceleration(int j, double *acc) override
not implemented
bool getTorqueRanges(double *min, double *max) override
Get the full scale of the torque sensors of all joints.
bool getTorquePidOutput(int j, double *out)
bool relativeMove(int j, double delta) override
Set relative position.
bool setRefSpeed(int j, double sp) override
Set reference speed for a joint, this is the speed used during the interpolation of the trajectory.
FtdiDeviceSettings contains information to identify specific device Such a device can contain informa...
Contains the parameters for a PID.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:251
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
A base class for nested structures that can be searched.
Definition: Searchable.h:66
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
A single value (typically within a Bottle).
Definition: Value.h:45
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:240
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCTrace(component,...)
Definition: LogComponent.h:85
#define yCDebug(component,...)
Definition: LogComponent.h:109
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
An interface for the device drivers.
An interface to the operating system, including Port based communication.