00001
00002
00003 #ifdef __linux__
00004 #include "ros/ros.h"
00005 #include <unistd.h>
00006 #include <fcntl.h>
00007 #include <getopt.h>
00008 #include <termios.h>
00009 #elif defined(_WIN32) || defined(_WIN64)
00010 #include <conio.h>
00011 #endif
00012
00013 #define _USE_MATH_DEFINES // for C++
00014
00015 #include <cmath>
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <string>
00019 #include <vector>
00020 #include <time.h>
00021
00022
00023 #include "dynamixel_sdk/dynamixel_sdk.h"
00024
00025
00026
00027 #define ADDR_MX_MODEL_NUM 0
00028 #define ADDR_MX_TORQUE_ENABLE 24 // Control table address is different in Dynamixel model
00029 #define ADDR_MX_GOAL_POSITION 30
00030 #define ADDR_MX_GOAL_SPEED 32
00031 #define ADDR_MX_PRESENT_POSITION 36
00032 #define ADDR_MX_PRESENT_SPEED 38
00033 #define ADDR_MX_PRESENT_LOAD 40
00034 #define ADDR_MX_PRESENT_TEMPERATURE 43
00035 #define ADDR_MX_MOVING 46
00036 #define ADDR_MX_GOAL_ACCELERATION 73
00037
00038
00039 #define ADDR_PRO_MODEL_NUM 0
00040 #define ADDR_PRO_TORQUE_ENABLE 562 // Control table address is different in Dynamixel model
00041 #define ADDR_PRO_GOAL_POSITION 596
00042 #define ADDR_PRO_GOAL_SPEED 600
00043 #define ADDR_PRO_GOAL_ACCELERATION 606
00044 #define ADDR_PRO_PRESENT_POSITION 611
00045 #define ADDR_PRO_PRESENT_SPEED 615
00046 #define ADDR_PRO_PRESENT_CURRENT 621
00047 #define ADDR_PRO_PRESENT_TEMPERATURE 43
00048 #define ADDR_PRO_MOVING 46
00049 #define ADDR_PRO_HARDWARE_ERROR 892
00050
00051
00052
00053 #define ADDR_XH_MODEL_NUM 0
00054 #define ADDR_XH_TORQUE_ENABLE 64 // Control table address is different in Dynamixel model
00055 #define ADDR_XH_GOAL_POSITION 116
00056 #define ADDR_XH_GOAL_SPEED 104
00057 #define ADDR_XH_GOAL_ACCELERATION 40
00058 #define ADDR_XH_PRESENT_POSITION 132
00059 #define ADDR_XH_PRESENT_SPEED 128
00060 #define ADDR_XH_PRESENT_CURRENT 126
00061 #define ADDR_XH_PRESENT_TEMPERATURE 146
00062 #define ADDR_XH_MOVING 123
00063 #define ADDR_XH_HARDWARE_ERROR 70
00064
00065
00066 #define PROTOCOL_VERSION1 1.0 // See which protocol version is used in the Dynamixel
00067 #define PROTOCOL_VERSION2 2.0
00068
00069
00070 #define DEVICENAME "/dev/USB2DYNAMIXEL" // Check which port is being used on your controller
00071 #define BAUDRATE 1000000
00072
00073 struct motor
00074 {
00075 uint8_t id;
00076 uint16_t model;
00077 bool torque;
00078 double position;
00079 double velocity;
00080 double current;
00081 double command_position;
00082 double command_velocity;
00083 uint8_t error;
00084 int cpr;
00085 double gear_reduction;
00086 float protocol_ver;
00087 std::string joint_name;
00088 };
00089 struct motor *motors;
00090 int num_motors = 0;
00091
00092 dynamixel::PacketHandler *packetHandler;
00093 dynamixel::PortHandler *portHandler;
00094
00095
00096 int getch()
00097 {
00098 #ifdef __linux__
00099 struct termios oldt, newt;
00100 int ch;
00101 tcgetattr(STDIN_FILENO, &oldt);
00102 newt = oldt;
00103 newt.c_lflag &= ~(ICANON | ECHO);
00104 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
00105 ch = getchar();
00106 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
00107 return ch;
00108 #elif defined(_WIN32) || defined(_WIN64)
00109 return _getch();
00110 #endif
00111 }
00112
00113 int kbhit(void)
00114 {
00115 #ifdef __linux__
00116 struct termios oldt, newt;
00117 int ch;
00118 int oldf;
00119
00120 tcgetattr(STDIN_FILENO, &oldt);
00121 newt = oldt;
00122 newt.c_lflag &= ~(ICANON | ECHO);
00123 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
00124 oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
00125 fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
00126
00127 ch = getchar();
00128
00129 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
00130 fcntl(STDIN_FILENO, F_SETFL, oldf);
00131
00132 if (ch != EOF)
00133 {
00134 ungetc(ch, stdin);
00135 return 1;
00136 }
00137
00138 return 0;
00139 #elif defined(_WIN32) || defined(_WIN64)
00140 return _kbhit();
00141 #endif
00142 }
00143
00144
00145 double ticks2rads(int32_t ticks, struct motor &motor) {
00146 if (motor.protocol_ver == 2.0) {
00147 const double FromTicks = 1.0 / (motor.cpr / 2.0);
00148 return static_cast<double>(ticks) * FromTicks * M_PI;
00149 }
00150 else {
00151 double cprDev2 = motor.cpr / 2.0f;
00152 return (static_cast<double>(ticks) - cprDev2) * M_PI / cprDev2;
00153 }
00154 }
00155
00156 int32_t rads2ticks(double rads, struct motor &motor) {
00157
00158 if (motor.protocol_ver == 2.0) {
00159 double cprDev2 = motor.cpr / 2.0f;
00160 return static_cast<int32_t>(round((rads / M_PI) * cprDev2));
00161 }
00162 else {
00163 double cprDev2 = motor.cpr / 2.0f;
00164 return static_cast<int32_t>(round(cprDev2 + (rads * cprDev2 / M_PI)));
00165 }
00166 }
00167
00168 int32_t rad_s2ticks_s(double rads, struct motor &motor) {
00169 if (motor.protocol_ver == 2.0)
00170 return static_cast<int32_t >(rads / 2.0 / M_PI * 60.0 * motor.gear_reduction);
00171 else {
00172
00173 return static_cast<int32_t >(83.49f * (rads)-0.564f);
00174 }
00175
00176 }
00177
00178 double ticks_s2rad_s(int32_t ticks, struct motor &motor) {
00179 if (motor.protocol_ver == 2.0) {
00180 return ((double)ticks) * 2.0 * M_PI / 60.0 / motor.gear_reduction;
00181 }
00182 else {
00183 return (100.0f / 8349.0f) * ((double)ticks) + (94.0f / 13915.0f);
00184 }
00185 }
00186
00187 bool ping(struct motor &motor) {
00188
00189 int dxl_comm_result = COMM_TX_FAIL;
00190 uint8_t dxl_error = 0;
00191
00192
00193
00194 dxl_comm_result = packetHandler->ping(portHandler, motor.id, &(motor.model), &dxl_error);
00195 if (dxl_comm_result != COMM_SUCCESS)
00196 {
00197
00198
00199 return false;
00200 }
00201 else if (dxl_error != 0)
00202 {
00203
00204
00205 return false;
00206
00207 }
00208 else {
00209
00210 return true;
00211 }
00212
00213 }
00214
00215
00216 bool setTorque(struct motor &motor, bool onoff)
00217 {
00218 uint8_t dxl_error = 0;
00219 int dxl_comm_result = COMM_TX_FAIL;
00220 uint16_t addr = ADDR_PRO_TORQUE_ENABLE;
00221 if (motor.model == 1040) addr = ADDR_XH_TORQUE_ENABLE;
00222
00223 dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, motor.id, addr, onoff, &dxl_error);
00224
00225 if (dxl_comm_result != COMM_SUCCESS) {
00226
00227 return false;
00228 }
00229 else if (dxl_error != 0) {
00230
00231 return false;
00232 }
00233 else {
00234 return true;
00235 }
00236 }
00237
00238 bool bulk_write() {
00239
00240
00241 int8_t dxl_comm_result_ = 0;
00242
00243 dynamixel::GroupBulkWrite GroupBulkWrite(portHandler, packetHandler);
00244 for (int i = 0; i<num_motors; i++) {
00245 bool dxl_addparam_result = false;
00246 uint16_t addr = ADDR_PRO_GOAL_POSITION;
00247 if (motors[i].model == 1040) addr = ADDR_XH_GOAL_POSITION;
00248 int32_t pos = rads2ticks(motors[i].command_position, motors[i]);
00249 dxl_addparam_result = GroupBulkWrite.addParam(motors[i].id, addr, 4, (uint8_t*)&pos);
00250 if (dxl_addparam_result != true)
00251 {
00252 printf("[ID:%03d] 1GroupBulkWrite addparam failed", motors[i].id);
00253 return false;
00254 }
00255
00256
00257 }
00258
00259 dxl_comm_result_ = GroupBulkWrite.txPacket();
00260
00261 if (dxl_comm_result_ != COMM_SUCCESS)
00262 {
00263
00264
00265 return false;
00266 }
00267
00268 GroupBulkWrite.clearParam();
00269
00270 for (int i = 0; i < num_motors; i++) {
00271 bool dxl_addparam_result = false;
00272 uint16_t addr = ADDR_PRO_GOAL_SPEED;
00273 if (motors[i].model == 1040) addr = ADDR_XH_GOAL_SPEED;
00274 int32_t vel = rad_s2ticks_s(motors[i].command_velocity, motors[i]);
00275 dxl_addparam_result = GroupBulkWrite.addParam(motors[i].id, addr, 4, (uint8_t*)&vel);
00276 if (dxl_addparam_result != true)
00277 {
00278 printf("[ID:%03d] 2GroupBulkWrite addparam failed", motors[i].id);
00279 return false;
00280
00281 }
00282 }
00283 dxl_comm_result_ = GroupBulkWrite.txPacket();
00284
00285 if (dxl_comm_result_ != COMM_SUCCESS)
00286 {
00287
00288
00289 return false;
00290 }
00291
00292 GroupBulkWrite.clearParam();
00293
00294
00295 return true;
00296
00297 }
00298
00299 bool bulk_read_err() {
00300
00301
00302 dynamixel::GroupBulkRead GroupBulkRead(portHandler, packetHandler);
00303 for (int i = 0; i<num_motors; i++) {
00304 bool dxl_addparam_result = false;
00305 uint16_t addr = ADDR_PRO_HARDWARE_ERROR;
00306 if (motors[i].model == 1040) addr = ADDR_XH_HARDWARE_ERROR;
00307 dxl_addparam_result = GroupBulkRead.addParam(motors[i].id, addr, 1);
00308 if (dxl_addparam_result != true)
00309 {
00310
00311 return false;
00312 }
00313 }
00314
00315 int dxl_comm_result = COMM_TX_FAIL;
00316 dxl_comm_result = GroupBulkRead.txRxPacket();
00317 if (dxl_comm_result != COMM_SUCCESS)
00318 {
00319
00320
00321 return false;
00322 }
00323
00324 for (int i = 0; i<num_motors; i++) {
00325 bool dxl_getdata_result = false;
00326
00327 uint16_t addr = ADDR_PRO_HARDWARE_ERROR;
00328 if (motors[i].model == 1040) addr = ADDR_XH_HARDWARE_ERROR;
00329 dxl_getdata_result = GroupBulkRead.isAvailable(motors[i].id, addr, 1);
00330 if (dxl_getdata_result != true)
00331 {
00332
00333 return false;
00334 }
00335 else {
00336 uint16_t addr = ADDR_PRO_HARDWARE_ERROR;
00337 if (motors[i].model == 1040) addr = ADDR_XH_HARDWARE_ERROR;
00338 motors[i].error = ticks2rads(GroupBulkRead.getData(motors[i].id, addr, 1), motors[i]);
00339
00340
00341 }
00342 }
00343 return true;
00344 }
00345
00346 bool bulk_read_pos() {
00347
00348
00349 dynamixel::GroupBulkRead GroupBulkRead(portHandler, packetHandler);
00350 for (int i = 0; i<num_motors; i++) {
00351 bool dxl_addparam_result = false;
00352 uint16_t addr = ADDR_PRO_PRESENT_POSITION;
00353 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_POSITION;
00354 dxl_addparam_result = GroupBulkRead.addParam(motors[i].id, addr, 4);
00355 if (dxl_addparam_result != true)
00356 {
00357
00358 return false;
00359 }
00360 }
00361
00362 int dxl_comm_result = COMM_TX_FAIL;
00363 dxl_comm_result = GroupBulkRead.txRxPacket();
00364 if (dxl_comm_result != COMM_SUCCESS)
00365 {
00366
00367 packetHandler->printTxRxResult(dxl_comm_result);
00368 return false;
00369 }
00370
00371 for (int i = 0; i<num_motors; i++) {
00372 bool dxl_getdata_result = false;
00373
00374 uint16_t addr = ADDR_PRO_PRESENT_POSITION;
00375 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_POSITION;
00376 dxl_getdata_result = GroupBulkRead.isAvailable(motors[i].id, addr, 4);
00377 if (dxl_getdata_result != true)
00378 {
00379
00380 return false;
00381 }
00382 else {
00383 uint16_t addr = ADDR_PRO_PRESENT_POSITION;
00384 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_POSITION;
00385 motors[i].position = ticks2rads(GroupBulkRead.getData(motors[i].id, addr, 4), motors[i]);
00386
00387
00388 }
00389 }
00390 return true;
00391 }
00392
00393
00394 bool bulk_read_vel() {
00395
00396
00397 dynamixel::GroupBulkRead GroupBulkRead(portHandler, packetHandler);
00398 for (int i = 0; i<num_motors; i++) {
00399 bool dxl_addparam_result = false;
00400 uint16_t addr = ADDR_PRO_PRESENT_SPEED;
00401 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_SPEED;
00402 dxl_addparam_result = GroupBulkRead.addParam(motors[i].id, addr, 4);
00403 if (dxl_addparam_result != true)
00404 {
00405
00406 return false;
00407 }
00408 }
00409
00410 int dxl_comm_result = COMM_TX_FAIL;
00411 dxl_comm_result = GroupBulkRead.txRxPacket();
00412 if (dxl_comm_result != COMM_SUCCESS)
00413 {
00414
00415
00416 return false;
00417 }
00418
00419 for (int i = 0; i<num_motors; i++) {
00420 bool dxl_getdata_result = false;
00421
00422 uint16_t addr = ADDR_PRO_PRESENT_SPEED;
00423 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_SPEED;
00424 dxl_getdata_result = GroupBulkRead.isAvailable(motors[i].id, addr, 4);
00425 if (dxl_getdata_result != true)
00426 {
00427
00428 return false;
00429 }
00430 else {
00431 uint16_t addr = ADDR_PRO_PRESENT_SPEED;
00432 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_SPEED;
00433 motors[i].velocity = ticks_s2rad_s(GroupBulkRead.getData(motors[i].id, addr, 4), motors[i]);
00434
00435
00436 }
00437 }
00438 return true;
00439 }
00440
00441
00442 bool bulk_read_load() {
00443
00444
00445 dynamixel::GroupBulkRead GroupBulkRead(portHandler, packetHandler);
00446 for (int i = 0; i<num_motors; i++) {
00447 bool dxl_addparam_result = false;
00448 uint16_t addr = ADDR_PRO_PRESENT_CURRENT;
00449 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_CURRENT;
00450 dxl_addparam_result = GroupBulkRead.addParam(motors[i].id, addr, 2);
00451 if (dxl_addparam_result != true)
00452 {
00453
00454 return false;
00455 }
00456 }
00457
00458 int dxl_comm_result = COMM_TX_FAIL;
00459 dxl_comm_result = GroupBulkRead.txRxPacket();
00460 if (dxl_comm_result != COMM_SUCCESS)
00461 {
00462
00463
00464 return false;
00465 }
00466
00467 for (int i = 0; i<num_motors; i++) {
00468 bool dxl_getdata_result = false;
00469
00470 uint16_t addr = ADDR_PRO_PRESENT_CURRENT;
00471 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_CURRENT;
00472 dxl_getdata_result = GroupBulkRead.isAvailable(motors[i].id, addr, 2);
00473 if (dxl_getdata_result != true)
00474 {
00475
00476 return false;
00477 }
00478 else {
00479 uint16_t addr = ADDR_PRO_PRESENT_CURRENT;
00480 if (motors[i].model == 1040) addr = ADDR_XH_PRESENT_CURRENT;
00481 motors[i].current = (int16_t)GroupBulkRead.getData(motors[i].id, addr, 2) ;
00482 if (motors[i].model == 53768 || motors[i].model == 54024) motors[i].current *= 33000.0 / 2048.0 / 1000.0;
00483 else if (motors[i].model == 51200) motors[i].current *= 8250.0 / 2048.0 / 1000.0;
00484 else if (motors[i].model == 1040) motors[i].current *= 2.69/1000.0;
00485
00486
00487 }
00488 }
00489 return true;
00490 }
00491
00492
00493 int main(int argc, char *argv[])
00494 {
00495
00496 ros::init(argc, argv, "dxl");
00497 ros::NodeHandle nh;
00498
00499
00500 packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOCOL_VERSION2);
00501
00502 fprintf(stderr, "\n***********************************************************************\n");
00503 fprintf(stderr, "* DXL Test *\n");
00504 fprintf(stderr, "***********************************************************************\n\n");
00505
00506 char *dev_name = (char*)DEVICENAME;
00507
00508
00509
00510
00511 portHandler = dynamixel::PortHandler::getPortHandler(dev_name);
00512
00513
00514 if (portHandler->openPort())
00515 {
00516 portHandler->setBaudRate(BAUDRATE);
00517 printf("Succeeded to open the port!\n\n");
00518 printf(" - Device Name : %s\n", dev_name);
00519 printf(" - Baudrate : %d\n\n", portHandler->getBaudRate());
00520 }
00521 else
00522 {
00523 printf("Failed to open the port! [%s]\n", dev_name);
00524 printf("Press any key to terminate...\n");
00525 getch();
00526 return 0;
00527 }
00528
00529
00530
00531 uint8_t ids[] = { 1,2,3,4,5,6,7,8};
00532
00533 num_motors = sizeof(ids) / sizeof(uint8_t);
00534 motors = (struct motor *)malloc(sizeof(struct motor)*num_motors);
00535 for (int i = 0; i<num_motors; i++) {
00536 motors[i].id = ids[i];
00537 motors[i].model = 0;
00538 motors[i].protocol_ver = 2.0;
00539 motors[i].command_position = 0.0;
00540 motors[i].command_velocity = 0.05;
00541 }
00542
00543
00544
00545 puts("Pinging motors...");
00546 for (int i = 0; i<num_motors; i++) {
00547 while ((!ping(motors[i]) || motors[i].model == 0)&&ros::ok()) {
00548 printf("[ID:%03d] ping error\n",motors[i].id);
00549 ros::Rate(5).sleep();
00550 }
00551 printf("[ID:%03d] Ping OK, model: %d\n", motors[i].id, motors[i].model);
00552 switch (motors[i].model) {
00553 case 54024:
00554 motors[i].cpr = 501900;
00555 motors[i].gear_reduction = 502.0;
00556 break;
00557 case 53768:
00558 motors[i].cpr = 502000;
00559 motors[i].gear_reduction = 502.0;
00560 break;
00561 case 51200:
00562 motors[i].cpr = 303800;
00563 motors[i].gear_reduction = 304.0;
00564 break;
00565 case 29:
00566 motors[i].cpr = 4096;
00567 motors[i].gear_reduction = 1.0;
00568 break;
00569 case 1040:
00570 motors[i].cpr = 4096;
00571 motors[i].gear_reduction = 353.5;
00572 break;
00573
00574 }
00575 }
00576 if (!ros::ok()) exit(1);
00577
00578 puts("Enabling motors torque...");
00579 for (int i = 0; i<num_motors; i++) {
00580 while (!setTorque(motors[i], true) && ros::ok()) {
00581
00582
00583 ros::Rate(5).sleep();
00584 }
00585 printf("[ID:%03d] Torque ON\n", i);
00586 motors[i].torque = true;
00587 }
00588
00589 if (!ros::ok()) exit(1);
00590
00591 puts("Read Write loop started");
00592
00593 int i = 0;
00594 bool first = true;
00595 ros::Time pre_time;
00596 double rate = 0;
00597
00598 while(ros::ok())
00599 {
00600
00601 pre_time=ros::Time::now();
00602 bool read_ok = bulk_read_pos() && bulk_read_vel() && bulk_read_load() && bulk_read_err();
00603 if (read_ok) {
00604
00605 printf("POS: ");
00606 for (int i = 0; i<num_motors; i++) {
00607 printf("%.3f, ", motors[i].position);
00608 }
00609 puts("");
00610 printf("VEL: ");
00611 for (int i = 0; i<num_motors; i++) {
00612 printf("%.3f, ", motors[i].velocity);
00613 }
00614 puts("");
00615 printf("CUR: ");
00616 for (int i = 0; i<num_motors; i++) {
00617 printf("%.3f, ", motors[i].current);
00618 }
00619 puts("");
00620 printf("ERR: ");
00621 for (int i = 0; i<num_motors; i++) {
00622 printf("%d, ", motors[i].error);
00623 }
00624 puts("");
00625 }
00626 else {
00627 puts("Read error");
00628 if (first) continue;
00629 }
00630
00631 if (first) {
00632 for (int i = 0; i < num_motors; i++) {
00633 motors[i].command_position = 0;
00634 }
00635 first = false;
00636 }
00637
00638
00639 static float s = 1;
00640 for (int i = 0; i < num_motors; i++) {
00641 motors[i].command_position+= 0.0005*s;
00642 if (motors[i].command_position > 0.1) s = -1;
00643 else if (motors[i].command_position < -0.1) s = 1;
00644 }
00645
00646 printf("DIF: ");
00647 for (int i = 0; i<num_motors; i++) {
00648 printf("%.3f, ", motors[i].command_position-motors[i].position);
00649 }
00650 puts("");
00651
00652
00653 bool write_ok = bulk_write();
00654 if (write_ok) {
00655
00656 }
00657 else puts("Write error");
00658
00659 ros::Rate(100).sleep();
00660
00661 double dt = (ros::Time::now() - pre_time).toSec();
00662 if (dt > 0)
00663 rate=1.0/dt;
00664 std::cout << "rate: "<<rate<<std::endl;
00665 puts("");
00666 ros::spinOnce();
00667 }
00668 portHandler->closePort();
00669 }