YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
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>
11
12#include <cstdio>
13
14using namespace yarp::os;
15using namespace yarp::dev;
16
17#define BOOL_EXIT_FAILURE false
18
19YARP_LOG_COMPONENT(DYNAMIXELAX12FTDIDRIVER, "yarp.devices.DynamixelAX12FtdiDriver")
20
21
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
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
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");
205 this->initMotorIndex(indexBottle);
206 return true;
207}
208
209int 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
220int 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
327ErrorCode 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
362int 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;
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
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
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
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
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 }
463 }
464 *flag = all_done;
465 return t;
466}
467
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
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
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
546int 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
558int 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
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
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
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
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
752 return NOT_YET_IMPLEMENTED("setEncoder");
753}
754
756 return NOT_YET_IMPLEMENTED("setEncoders");
757}
758
760 return NOT_YET_IMPLEMENTED("setRefTorques");
761}
762
764 return NOT_YET_IMPLEMENTED("setRefTorque");
765}
766
767bool DynamixelAX12FtdiDriver::getTorqueRange(int j, double* min, double* max) {
768 return NOT_YET_IMPLEMENTED("getTorqueRange");
769}
770
771bool DynamixelAX12FtdiDriver::getTorqueRanges(double* min, double* max) {
772 return NOT_YET_IMPLEMENTED("getTorqueRanges");
773}
774
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
863bool 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
908bool 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
918bool 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 {
924 }
925 return ret;
926}
927
929{
930 bool ret = true;
931 bool tmp_joint(false), tmp_device(true);
932 for(int j=0; j<n_joint; j++)
933 {
936 }
937 *flag = tmp_device;
938 return ret;
939}
940
941bool 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
951bool 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 {
957 }
958 return ret;
959}
960
961bool 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
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
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}
const yarp::os::LogComponent & DYNAMIXELAX12FTDIDRIVER()
bool NOT_YET_IMPLEMENTED(const char *txt)
#define BOOL_EXIT_FAILURE
#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
#define INST_READ
#define MOTION_COMPLETION_TOLERANCE
#define CT_MAX_TORQUE
#define CT_PRESENT_POSITION
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 setTorqueOffset(int j, double v)
bool close() override
Close device Closes the device and shuts down connection.
bool configure(yarp::os::Searchable &config)
Configure device online Configures parts of the device that can be configures online.
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 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 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...
virtual std::string id() const
Return the id assigned to the PolyDriver.
Contains the parameters for a PID.
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
A mini-server for performing network communication in the background.
A base class for nested structures that can be searched.
Definition Searchable.h:31
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
A single value (typically within a Bottle).
Definition Value.h:43
#define yCInfo(component,...)
#define yCError(component,...)
#define yCTrace(component,...)
#define yCDebug(component,...)
#define YARP_LOG_COMPONENT(name,...)
For streams capable of holding different kinds of content, check what they actually have.
An interface to the operating system, including Port based communication.