YARP
Yet Another Robot Platform
DynamixelAX12FtdiDriver.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  * Copyright (C) 2010 Ze Ji
4  * All rights reserved.
5  *
6  * This software may be modified and distributed under the terms of the
7  * BSD-3-Clause license. See the accompanying LICENSE file for details.
8  */
9 
11 
12 #include <yarp/os/Value.h>
13 #include <yarp/os/LogComponent.h>
14 
15 #include <cstdio>
16 
17 using namespace yarp::os;
18 using namespace yarp::dev;
19 
20 #define BOOL_EXIT_FAILURE false
21 
22 YARP_LOG_COMPONENT(DYNAMIXELAX12FTDIDRIVER, "yarp.devices.DynamixelAX12FtdiDriver")
23 
24 
25 bool NOT_YET_IMPLEMENTED(const char *txt) {
26  yCError(DYNAMIXELAX12FTDIDRIVER, "%s not yet implemented for DynamixelAX12FtdiDriver", txt);
27  return false;
28 }
29 
31  deviceOpen(false),
32  jointNumbers((unsigned char *) malloc(16 * sizeof (unsigned char))),
33  numOfAxes(16),
34  positions((double *) malloc(numOfAxes * sizeof (double))),
35  speeds((double *) malloc(numOfAxes * sizeof (double))),
36  devlist(NULL),
37  torques((int *) malloc(numOfAxes * sizeof (int)))
38 {
39  // initialise
40  jointNumbers[0] = 0x65;
41  jointNumbers[1] = 0x74;
42  jointNumbers[2] = 0x84;
43  jointNumbers[3] = 0x66;
44  jointNumbers[4] = 0x75;
45  jointNumbers[5] = 0x85;
46  jointNumbers[6] = 0x67;
47  jointNumbers[7] = 0x76;
48  jointNumbers[8] = 0x86;
49  jointNumbers[9] = 0x6B;
50  jointNumbers[10] = 0x77;
51  jointNumbers[11] = 0x87;
52  jointNumbers[12] = 0x6A;
53  jointNumbers[13] = 0x68;
54  jointNumbers[14] = 0x69;
55  jointNumbers[15] = 0x6C;
56 
57  ftdi_init(&ftdic);
58 }
59 
61  ftdi_list_free(&devlist);
62  ftdi_deinit(&ftdic);
63  free(jointNumbers);
64  free(positions);
65  free(speeds);
66  free(torques);
67 }
68 
70 
71  mutex.lock();
72 
73  FtdiDeviceSettings ftdiSetting;
74  strcpy(ftdiSetting.description, config.check("FTDI_DESCRIPTION", Value("FT232R USB UART"), "Ftdi device description").asString().c_str());
75  strcpy(ftdiSetting.serial, config.check("FTDI_SERIAL", Value("A7003MhG"), "Ftdi device serial").asString().c_str());
76  strcpy(ftdiSetting.manufacturer, config.check("FTDI_MANUFACTURER", Value("FTDI"), "Ftdi device manufacturer").asString().c_str());
77  ftdiSetting.baudrate = config.check("baudrate", Value(57600), "Specifies the baudrate at which the communication port operates.").asInt32();
78  ftdiSetting.vendor = config.check("ftdivendor", Value(0x0403), "USB device vendor. 0x0403 normally. Can be found by lsusb on linux").asInt32();
79  ftdiSetting.product = config.check("ftdiproduct", Value(0x6001), "USB device product number. 0x6001 normally. Can be found by lsusb on linux").asInt32();
80  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();
81  ftdiSetting.write_chunksize = 3;
82  ftdiSetting.read_chunksize = 256;
83 
84  yCTrace(DYNAMIXELAX12FTDIDRIVER, "DynamixelAx12Driver::initialize");
85  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Opening DynamixelAx12 Device");
86 
87  int retCode;
88 
89  char manufacturer[128], description[128];
90  char serial[128];
91  //int n = 0; // number of devices found
92 
93  retCode = ftdi_usb_find_all(&ftdic, &devlist, ftdiSetting.vendor, ftdiSetting.product);
94  switch (retCode) {
95  case -1:
96  yCError(DYNAMIXELAX12FTDIDRIVER, "usb_find_busses() failed");
97  return BOOL_EXIT_FAILURE;
98  case -2:
99  yCError(DYNAMIXELAX12FTDIDRIVER, "usb_find_devices() failed");
100  return BOOL_EXIT_FAILURE;
101  case -3:
102  yCError(DYNAMIXELAX12FTDIDRIVER, "out of memory");
103  return BOOL_EXIT_FAILURE;
104  case 0:
105  yCError(DYNAMIXELAX12FTDIDRIVER, "No device is found. Check connection.");
106  return BOOL_EXIT_FAILURE;
107  default:
108  yCInfo(DYNAMIXELAX12FTDIDRIVER, "%d devices have been found.", retCode);
109  break;
110  }
111 
112  int ret = 0;
113  int i = 0;
114 
115  for (curdev = devlist; curdev != NULL; i++) {
116  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Checking device: %d", i);
117 
118  if ((retCode = ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, serial, 128)) < 0) {
119  yCError(DYNAMIXELAX12FTDIDRIVER, "ftdi_usb_get_strings failed: %d (%s)", ret, ftdi_get_error_string(&ftdic));
120  }
121  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Manufacturer: %s, Description: %s, Serial %s", manufacturer, description, serial);
122 
123  // check if the current device is the right one
124  if (strcmp(serial, ftdiSetting.serial) == 0) {
125  break;
126  }
127  curdev = curdev->next;
128  }
129 
130  if (curdev == NULL) {
131  yCError(DYNAMIXELAX12FTDIDRIVER, "No Dynamixel device is found. Check connection.");
132  return BOOL_EXIT_FAILURE;
133  }
134 
135  // open and reset everything in case we messed everything up with a control-c..
136  if ((retCode = ftdi_usb_open_dev(&ftdic, curdev->dev)) < 0) {
137  yCError(DYNAMIXELAX12FTDIDRIVER, "unable to open ftdi device: %d (%s)", retCode, ftdi_get_error_string(&ftdic));
138  return BOOL_EXIT_FAILURE;
139  }
140  deviceOpen = true; // Only set to be able to do close()
141 
142  this->close();
143 
144  // Now open again
145  if ((retCode = ftdi_usb_open_dev(&ftdic, curdev->dev)) < 0) {
146  yCError(DYNAMIXELAX12FTDIDRIVER, "unable to open ftdi device: %d (%s)", retCode, ftdi_get_error_string(&ftdic));
147  return BOOL_EXIT_FAILURE;
148  }
149 
150  // To test connection, read out FTDIChip-ID of R type chips
151  if (ftdic.type == TYPE_R) {
152  unsigned int chipid;
153  if (ftdi_read_chipid(&ftdic, &chipid) == 0) {
154  yCInfo(DYNAMIXELAX12FTDIDRIVER, "FTDI Device open. FTDI chipid: %X", chipid);
155  } else {
156  yCError(DYNAMIXELAX12FTDIDRIVER, "Unable to access FTDI device!");
157  return BOOL_EXIT_FAILURE;
158  }
159  }
160  deviceOpen = true;
161 
162  // We have an open device and it is accessible, so set parameters
163 
164  if ((retCode = ftdi_set_baudrate(&ftdic, ftdiSetting.baudrate)) != 0)
165  yCError(DYNAMIXELAX12FTDIDRIVER, "Error setting baudrate, ret=%d", retCode);
166  if (ftdi_set_line_property(&ftdic, BITS_8, STOP_BIT_1, NONE) == -1)
167  yCError(DYNAMIXELAX12FTDIDRIVER, "Error setting connection properties");
168  if (ftdi_setflowctrl(&ftdic, SIO_DISABLE_FLOW_CTRL) == -1)
169  yCError(DYNAMIXELAX12FTDIDRIVER, "Error setting flow control");
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++) chksum += body[i];
294  if (body[retCode - 1] != (unsigned char) ~(chksum + header[2] + header[3])) {
295  badAnswer = true;
296  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Received data with wrong checksum (%X != %X): ", body[retCode - 1], (unsigned char) ~(chksum + header[2] + header[3]));
297  } else {
298  // Packet ok, so return the instruction part without checksum
299  for (i = 0; i < retCode - 1; i++) {
300  ret[i] = body[i];
301  }
302  // retSize = retCode; // Sven's original code.
303  retSize = retCode - 1; // retSize should be retCode - 1, as checksum is not included
304  return 1;
305  }
306  }
307  }
308  }
309 
310  // Print packet if something was wrong
311  if (badAnswer) {
312  for (i = 0; i < 4; i++) {
313  yCInfo(DYNAMIXELAX12FTDIDRIVER, "%X ", header[i]);
314  }
315  for (i = 0; i < retCode; i++) {
316  yCInfo(DYNAMIXELAX12FTDIDRIVER, "%X ", body[i]);
317  }
318  return 0;
319  }
320  }
321 
322  return 1;
323 }
324 
325 ErrorCode DynamixelAX12FtdiDriver::checkAnswerPacket(unsigned char* packet, const char*& message) {
326  if (packet[0] & 1) {
327  message = "Voltage out of operating voltage range!";
328  return VOLTAGE_ERROR;
329  }
330  if (packet[0] & 2) {
331  message = "Goal position outside angle limits!";
332  return ANGLE_ERROR;
333  }
334  if (packet[0] & 4) {
335  message = "Current temperature outside operating temperature!";
336  return OVERHEATING_ERROR;
337  }
338  if (packet[0] & 8) {
339  message = "Instruction out of defined range!";
340  return RANGE_ERROR;
341  }
342  if (packet[0] & 16) {
343  message = "Checksum of instruction package incorrect!";
344  return CHECKSUM_ERROR;
345  }
346  if (packet[0] & 32) {
347  message = "Specified torque can't control the applied load!";
348  return OVERLOAD_ERROR;
349  }
350  if (packet[0] & 64) {
351  message = "Undefined instruction or missing Reg_Write instruction!";
352  return INSTRUCTION_ERROR;
353  }
354  message = "";
355  return OK;
356 }
357 
360 int DynamixelAX12FtdiDriver::readParameter(unsigned char id, unsigned char param) {
361  // Read instruction has 2 parameters: The starting address of the parameter and the number of bytes to read
362  // Both are encoded in param (> 100 = 2 bytes)
363  unsigned char packet[] = {INST_READ, 0, 1};
364 
365  unsigned char answerPacket[256];
366  int answerSize;
367  const char* errorMessage;
368  ErrorCode errCode;
369 
370  if (param > 99) {
371  // We have to read 2 bytes
372  packet[1] = param - 100;
373  packet[2] = 2;
374  } else {
375  // We have to read 1 bytes
376  packet[1] = param;
377  }
378 
379  // Send request
380  //sendCommand(id, packet, 3, answerPacket, answerSize);
381  syncSendCommand(id, packet, 3, answerPacket, answerSize);
382  // Check for submitted error code
383  if ((errCode = checkAnswerPacket(answerPacket, errorMessage)) != OK) {
384  // We received an error code
385  return -1;
386  } else {
387  // No error
388  return 1;
389  }
390 }
391 
393  *ax = numOfAxes;
394  return true;
395 }
396 
397 bool DynamixelAX12FtdiDriver::positionMove(int j, double ref) {
398  double speed;
399  int blankReturnSize = -1;
400  unsigned char blankReturn[] = {0, 0, 0};
401  getRefSpeed(j, &speed);
402  const int instl = 5 + 1;
403 
404  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)};
405 
406  positions[j] = ref;
407 
408  return syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
409 }
410 
414 bool DynamixelAX12FtdiDriver::positionMove(const double *refs) {
415  bool t = true;
416  for (int k = 0; k < numOfAxes; k++) {
417  if (!this->positionMove(k, refs[k]))
418  t = false;
419  }
420  return t;
421 }
422 
423 bool DynamixelAX12FtdiDriver::relativeMove(int j, double delta) {
424  double v = positions[j];
425  if (getEncoder(j, &v)) {
426  return this->positionMove(j, v + delta);
427  } else
428  return false;
429 }
430 
431 bool DynamixelAX12FtdiDriver::relativeMove(const double *deltas) {
432  bool t = true;
433  for (int k = 0; k < numOfAxes; k++) {
434  if (!this->positionMove(k, positions[k] + deltas[k]))
435  t = false;
436  }
437  return t;
438 }
439 
441  double v = 0;
442  bool t = true;
443 
444  t = getEncoder(j, &v);
445  *flag = (std::fabs(v - positions[j]) < MOTION_COMPLETION_TOLERANCE);
446  return t;
447 }
448 
450  bool t = true;
451  bool tmp_done(false), all_done(true);
452  for (int k = 0; k < numOfAxes; k++)
453  {
454  if (!this->checkMotionDone(k, &tmp_done))
455  t = false;
456  all_done &= tmp_done;
457  }
458  *flag = all_done;
459  return t;
460 }
461 
462 bool DynamixelAX12FtdiDriver::setRefSpeed(int j, double sp) {
463  if (sp < 1) {
464  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid speed value, should be from 1 to 114");
465  speeds[j] = 1;
466  return false;
467  } else if (sp > 114) {
468  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid speed value, should be from 1 to 114");
469  speeds[j] = 114;
470  return false;
471  } else {
472  speeds[j] = sp;
473  return true;
474  }
475 }
476 
477 bool DynamixelAX12FtdiDriver::setRefSpeeds(const double *spds) {
478  bool t = true;
479  for (int k = 0; k < numOfAxes; k++) {
480  if (!setRefSpeed(k, spds[k]))
481  t = false;
482  }
483  return t;
484 }
485 
490  return NOT_YET_IMPLEMENTED("setRefAcceleration");
491 }
492 
497  return NOT_YET_IMPLEMENTED("setRefAccelerations");
498 }
499 
500 bool DynamixelAX12FtdiDriver::getRefSpeed(int j, double *ref) {
501  *ref = speeds[j];
502  return true;
503 }
504 
506  for (int k = 0; k < numOfAxes; k++) {
507  spds[k] = speeds[k];
508  }
509  return true;
510 }
511 
516  return NOT_YET_IMPLEMENTED("getRefAcceleration");
517 }
518 
523  return NOT_YET_IMPLEMENTED("getRefAccelerations");
524 }
525 
527  return NOT_YET_IMPLEMENTED("stop");
528 }
529 
531  for (int i = 0; i < numOfAxes; i++) {
532  if (!stop(i))
533  return false;
534  }
535  return true;
536 }
537 
538 int DynamixelAX12FtdiDriver::normalisePosition(double position) {
539  if (position < 0) {
540  position = 0;
541  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid position value, should be from 0 to 300");
542  } else if (position > 300) {
543  position = 300;
544  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid position value, should be from 0 to 300");
545  }
546 
547  return (int) (1024 * position / 301);
548 }
549 
550 int DynamixelAX12FtdiDriver::normaliseSpeed(double speed) {
551  // speed -> [1 114] RPM
552  // when speed is 0, it is maximum possible speed, no speed control. so it is not useful here
553  if (speed < 1) {
554  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid speed value, should be from 1 to 114");
555  speed = 1;
556  } else if (speed > 114) {
557  yCInfo(DYNAMIXELAX12FTDIDRIVER, "Invalid speed value, should be from 1 to 114");
558  speed = 114;
559  }
560  return (int) (1024 * speed / 114 - 1);
561 }
562 
564  for (int k = 0; k < numOfAxes; k++) {
565  t[k] = torques[k];
566  }
567  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is just the MAX tourque set for the ax12 servo.");
568  return true;
569 }
570 
572  *t = torques[j];
573  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is just the MAX tourque set for the ax12 servo.");
574  return true;
575 }
576 
578  bool tt = true;
579  for (int k = 0; k < numOfAxes; k++) {
580  if (!this->setTorque(k, t[k]))
581  tt = false;
582  }
583  return tt;
584 }
585 
591  if (t < 0) {
592  yCError(DYNAMIXELAX12FTDIDRIVER, "torque (%d) should in range [0 1023] or [0 0x3FF]. t is set to 0 here", (int)t);
593  t = 0;
594  } else if (t > 1023) {
595  yCError(DYNAMIXELAX12FTDIDRIVER, "torque (%d) should in range [0 1023] or [0 0x3FF]. t is set to 1023 here", (int)t);
596  t = 1023;
597  }
598 
599  int blankReturnSize = -1;
600  unsigned char blankReturn[] = {0, 0, 0};
601  const int instl = 3 + 1;
602 
603  unsigned char inst[instl] = {INST_WRITE, CT_MAX_TORQUE, (unsigned char) ((int) t & 0xFF), (unsigned char) (((int) t << 8) & 0x03)};
604  //return sendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
605  return syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
606 }
607 
609  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
610  return NOT_YET_IMPLEMENTED("setTorquePid");
611 }
612 
613 bool DynamixelAX12FtdiDriver::getTorque(int j, double *t) {
614  bool ret;
615 
616  int blankReturnSize = -1;
617  unsigned char blankReturn[] = {0, 0, 0};
618 
619  const int instl = 3;
620  unsigned char inst[instl] = {INST_READ, (unsigned char) CT_PRESENT_LOAD, (unsigned char) 2};
621  //ret = sendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
622  ret = syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
623 
624  const char* message = "";
625  if (checkAnswerPacket(blankReturn, message) == OK) {
626  //int load = (blankReturn[2]&0b00000011)*256 + blankReturn[1];
627  int load = (blankReturn[2]&0X03)*256 + blankReturn[1];
628  //load *= (((blankReturn[2] >> 2)&0b000001) ? -1 : 1);
629  load *= (((blankReturn[2] >> 2)&0X01) ? -1 : 1);
630  *t = load;
631  } else {
632  yCError(DYNAMIXELAX12FTDIDRIVER, "%s", message);
633  return false;
634  }
635  return ret;
636 }
637 
639  int k = 0;
640  bool tt = true;
641  for (k = 0; k < numOfAxes; k++) {
642  if (!getTorque(k, &t[k]))
643  tt = false;
644  }
645  return tt;
646 }
647 
649  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
650  return NOT_YET_IMPLEMENTED("setTorquePids");
651 }
652 
654  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
655  return NOT_YET_IMPLEMENTED("setTorqueErrorLimit");
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("setTorqueErrorLimits");
661 }
662 
663 bool DynamixelAX12FtdiDriver::getTorqueError(int j, double *err) {
664  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
665  return NOT_YET_IMPLEMENTED("getTorqueError");
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("getTorqueErrors");
671 }
672 
674  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
675  return NOT_YET_IMPLEMENTED("getTorquePidOutput");
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("getTorquePidOutputs");
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("getTorquePid");
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("getTorquePids");
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("getTorqueErrorLimit");
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("getTorqueErrorLimits");
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("resetTorquePid");
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("disableTorquePid");
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("enableTorquePid");
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("setTorqueOffset");
721 }
722 
723 bool DynamixelAX12FtdiDriver::getBemfParam(int j, double *bemf) {
724  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
725  return NOT_YET_IMPLEMENTED("getBemfParam");
726 }
727 
728 bool DynamixelAX12FtdiDriver::setBemfParam(int j, double bemf) {
729  yCError(DYNAMIXELAX12FTDIDRIVER, "Note: AX12 does not support torque control mode. This is only used to get torque feedback.");
730  return NOT_YET_IMPLEMENTED("setBemfParam");
731 }
732 
734  return NOT_YET_IMPLEMENTED("resetEncoder");
735 }
736 
738  return NOT_YET_IMPLEMENTED("resetEncoders");
739 }
740 
741 bool DynamixelAX12FtdiDriver::setEncoder(int j, double val) {
742  return NOT_YET_IMPLEMENTED("setEncoder");
743 }
744 
745 bool DynamixelAX12FtdiDriver::setEncoders(const double *vals) {
746  return NOT_YET_IMPLEMENTED("setEncoders");
747 }
748 
750  return NOT_YET_IMPLEMENTED("setRefTorques");
751 }
752 
754  return NOT_YET_IMPLEMENTED("setRefTorque");
755 }
756 
757 bool DynamixelAX12FtdiDriver::getTorqueRange(int j, double* min, double* max) {
758  return NOT_YET_IMPLEMENTED("getTorqueRange");
759 }
760 
761 bool DynamixelAX12FtdiDriver::getTorqueRanges(double* min, double* max) {
762  return NOT_YET_IMPLEMENTED("getTorqueRanges");
763 }
764 
765 bool DynamixelAX12FtdiDriver::getEncoder(int j, double *v) {
766  *v = -1; // invalid value for encoder of AX12 motor
767  int ret = 1;
768 
769  int blankReturnSize = -1;
770  unsigned char blankReturn[] = {0, 0, 0};
771 
772  const int instl = 3;
773  unsigned char inst[instl] = {INST_READ, (unsigned char) CT_PRESENT_POSITION, (unsigned char) 2};
774  //ret = sendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
775  ret = syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
776 
777  int pos = 0;
778  if (ret == 1) {
779  const char* message = "";
780  if (checkAnswerPacket(blankReturn, message) == OK) {
781  pos = ((int) blankReturn[2])*256 + blankReturn[1];
782  *v = ((double) pos)*300.0 / 1024.0;
783  return true;
784  } else {
785  yCError(DYNAMIXELAX12FTDIDRIVER, "%s", message);
786  return false;
787  }
788 
789  } // pos = (blankReturn[1]&0b00000011)*0x100 + blankReturn[0];
790  else
791  return false;
792 }
793 
795  int k = 0;
796  bool tt = true;
797 
798  for (k = 0; k < numOfAxes; k++) {
799  if (!getEncoder(k, &encs[k])) {
800  tt = false;
801  }
802  }
803  return tt;
804 }
805 
807  bool ret;
808 
809  int blankReturnSize = -1;
810  unsigned char blankReturn[] = {0, 0, 0};
811  const int instl = 3;
812  unsigned char inst[instl] = {INST_READ, (unsigned char) CT_PRESENT_SPEED, (unsigned char) 2};
813  //ret = sendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
814  ret = syncSendCommand(jointNumbers[j], inst, instl, blankReturn, blankReturnSize);
815 
816  double speed = 0;
817  const char* message = "";
818  if (checkAnswerPacket(blankReturn, message) == OK) {
819  //speed = (blankReturn[2]&0b00000011)*0xFF + blankReturn[1];
820  speed = (blankReturn[2]&0X03)*0xFF + blankReturn[1];
821 
822  //speed *= (((blankReturn[1] >> 2)&0b000001) ? -1 : 1);
823  speed *= (((blankReturn[1] >> 2)&0X01) ? -1 : 1);
824 
825  *sp = speed * 113 / 1024 + 1;
826  } else {
827  yCError(DYNAMIXELAX12FTDIDRIVER, "%s", message);
828  return false;
829  }
830  return ret;
831 }
832 
834  int k = 0;
835  bool tt = true;
836  for (k = 0; k < numOfAxes; k++) {
837  if (!getEncoderSpeed(k, &spds[k]))
838  tt = false;
839  }
840  return tt;
841 }
842 
844  return NOT_YET_IMPLEMENTED("getEncoderAcceleration");
845 }
846 
848  return NOT_YET_IMPLEMENTED("getEncoderAccelerations");
849 }
850 
851 bool DynamixelAX12FtdiDriver::initMotorIndex(yarp::os::Bottle *sensorIndex) {
852  int s = sensorIndex->size() - 1;
853  if (s != sensorIndex->get(0).asInt32()) {
854  yCError(DYNAMIXELAX12FTDIDRIVER, "sensor number does not match the real number in configuration file");
855  return false;
856  }
857  numOfAxes = s;
858  unsigned char *tmp = NULL;
859  tmp = (unsigned char *) realloc(jointNumbers, numOfAxes * sizeof (unsigned char));
860  if (tmp != NULL) {
861  // jointNumbers = {0x65, 0x74, 0x84, 0x66, 0x75, 0x85, 0x67, 0x76, 0x86, 0x6B, 0x77, 0x87, 0x6A, 0x68, 0x69, 0x6C};
862  jointNumbers = tmp;
863  } else {
864  return false;
865  }
866  double *tmpp = NULL;
867  tmpp = (double *) realloc(positions, numOfAxes * sizeof (double));
868  if (tmpp != NULL) {
869  positions = tmpp;
870  } else {
871  return false;
872  }
873 
874  double *tmps = NULL;
875  tmps = (double *) realloc(speeds, numOfAxes * sizeof (double));
876  if (tmps != NULL) {
877  speeds = tmps;
878  } else {
879  return false;
880  }
881 
882  int *tmpt = NULL;
883  tmpt = (int *) realloc(torques, numOfAxes * sizeof (int));
884  if (tmpt != NULL) {
885  torques = tmpt;
886  } else {
887  return false;
888  }
889 
890  for (int i = 0; i < numOfAxes; i++) {
891  jointNumbers[i] = (unsigned char) (sensorIndex->get(i + 1).asInt32());
892  }
893  return true;
894 }
895 
896 bool DynamixelAX12FtdiDriver::positionMove(const int n_joint, const int *joints, const double *refs)
897 {
898  bool ret = true;
899  for(int j=0; j<n_joint; j++)
900  {
901  ret &= positionMove(joints[j], refs[j]);
902  }
903  return ret;
904 }
905 
906 bool DynamixelAX12FtdiDriver::relativeMove(const int n_joint, const int *joints, const double *deltas)
907 {
908  bool ret = true;
909  for(int j=0; j<n_joint; j++)
910  {
911  ret &= relativeMove(joints[j], deltas[j]);
912  }
913  return ret;
914 }
915 
916 bool DynamixelAX12FtdiDriver::checkMotionDone(const int n_joint, const int *joints, bool *flag)
917 {
918  bool ret = true;
919  bool tmp_joint(false), tmp_device(true);
920  for(int j=0; j<n_joint; j++)
921  {
922  ret &= checkMotionDone(joints[j], &tmp_joint);
923  tmp_device &= tmp_joint;
924  }
925  *flag = tmp_device;
926  return ret;
927 }
928 
929 bool DynamixelAX12FtdiDriver::setRefSpeeds(const int n_joint, const int *joints, const double *spds)
930 {
931  bool ret = true;
932  for(int j=0; j<n_joint; j++)
933  {
934  ret &= setRefSpeed(joints[j], spds[j]);
935  }
936  return ret;
937 }
938 
939 bool DynamixelAX12FtdiDriver::setRefAccelerations(const int n_joint, const int *joints, const double *accs)
940 {
941  bool ret = true;
942  for(int j=0; j<n_joint; j++)
943  {
944  ret &= setRefAcceleration(joints[j], accs[j]);
945  }
946  return ret;
947 }
948 
949 bool DynamixelAX12FtdiDriver::getRefSpeeds(const int n_joint, const int *joints, double *spds)
950 {
951  bool ret = true;
952  for(int j=0; j<n_joint; j++)
953  {
954  ret &= getRefSpeed(joints[j], &spds[j]);
955  }
956  return ret;
957 }
958 
959 bool DynamixelAX12FtdiDriver::getRefAccelerations(const int n_joint, const int *joints, double *accs)
960 {
961  bool ret = true;
962  for(int j=0; j<n_joint; j++)
963  {
964  ret &= getRefSpeed(joints[j], &accs[j]);
965  }
966  return ret;
967 }
968 
969 bool DynamixelAX12FtdiDriver::stop(const int n_joint, const int *joints)
970 {
971  bool ret = true;
972  for(int j=0; j<n_joint; j++)
973  {
974  ret &= stop(joints[j]);
975  }
976  return ret;
977 }
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:73
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:254
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
A base class for nested structures that can be searched.
Definition: Searchable.h:69
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:47
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:207
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:243
#define yCInfo(component,...)
Definition: LogComponent.h:135
#define yCError(component,...)
Definition: LogComponent.h:157
#define yCTrace(component,...)
Definition: LogComponent.h:88
#define yCDebug(component,...)
Definition: LogComponent.h:112
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
An interface for the device drivers.
An interface to the operating system, including Port based communication.