00001
00002
00003 #if defined(__linux__) || defined(__APPLE__)
00004 #include <fcntl.h>
00005 #include <termios.h>
00006 #define STDIN_FILENO 0
00007 #elif defined(_WIN32) || defined(_WIN64)
00008 #include <conio.h>
00009 #endif
00010
00011 #include <stdio.h>
00012
00013 #include <ros/ros.h>
00014 #include <sensor_msgs/JointState.h>
00015 #include <dynamixel_sdk/dynamixel_sdk.h>
00016 #include "robotican_hardware_interface/dynamixel_driver.h"
00017 #include <ros/package.h>
00018 #include "yaml-cpp/yaml.h"
00019
00020
00021 double ticks2rads(int32_t ticks, struct motor &motor);
00022 int32_t rads2ticks(double rads, struct motor &motor);
00023
00024 dynamixel::PortHandler *portHandler;
00025 dynamixel::PacketHandler *packetHandler;
00026
00027 #ifdef HAVE_NEW_YAMLCPP
00028
00029
00030 template<typename T>
00031 void operator >> (const YAML::Node& node, T& i)
00032 {
00033 i = node.as<T>();
00034 }
00035
00036 #endif
00037
00038
00039 #define PROTOCOL_VERSION 2.0 // See which protocol version is used in the Dynamixel
00040
00041
00042
00043 #define BAUDRATE 57600
00044 #define DEVICENAME "/dev/ttyUSB0" // Check which port is being used on your controller
00045
00046 struct motor
00047 {
00048 uint8_t id;
00049 uint16_t model;
00050 bool torque;
00051 double position;
00052 double command_position;
00053 double command_velocity;
00054 int cpr;
00055 double gear_reduction;
00056 float protocol_ver;
00057 std::string joint_name;
00058 };
00059 struct motor *motors;
00060 int num_motors=0;
00061
00062 struct dynamixel_spec
00063 {
00064 std::string name;
00065 uint16_t model_number;
00066 int cpr;
00067 double gear_reduction;
00068 };
00069 std::map<uint16_t, dynamixel_spec> _modelSpec;
00070
00071 void initSpecFile() {
00072 std::string path = ros::package::getPath("robotican_hardware_interface");
00073 path += "/config/motor_data.yaml";
00074 YAML::Node doc;
00075
00076 #ifdef HAVE_NEW_YAMLCPP
00077 doc = YAML::LoadFile(path);
00078 #else
00079 ifstream fin(path.c_str());
00080 YAML::Parser parser(fin);
00081 parser.GetNextDocument(doc);
00082 #endif
00083 for (int i = 0; i < doc.size(); i++)
00084 {
00085 dynamixel_spec spec;
00086
00087
00088 doc[i]["name"] >> spec.name;
00089 doc[i]["model_number"] >> spec.model_number;
00090 doc[i]["cpr"] >> spec.cpr;
00091 doc[i]["gear_reduction"] >> spec.gear_reduction;
00092
00093 _modelSpec[spec.model_number] = spec;
00094 }
00095
00096 }
00097
00098 int getch()
00099 {
00100 #if defined(__linux__) || defined(__APPLE__)
00101 struct termios oldt, newt;
00102 int ch;
00103 tcgetattr(STDIN_FILENO, &oldt);
00104 newt = oldt;
00105 newt.c_lflag &= ~(ICANON | ECHO);
00106 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
00107 ch = getchar();
00108 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
00109 return ch;
00110 #elif defined(_WIN32) || defined(_WIN64)
00111 return _getch();
00112 #endif
00113 }
00114
00115 int kbhit(void)
00116 {
00117 #if defined(__linux__) || defined(__APPLE__)
00118 struct termios oldt, newt;
00119 int ch;
00120 int oldf;
00121
00122 tcgetattr(STDIN_FILENO, &oldt);
00123 newt = oldt;
00124 newt.c_lflag &= ~(ICANON | ECHO);
00125 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
00126 oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
00127 fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
00128
00129 ch = getchar();
00130
00131 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
00132 fcntl(STDIN_FILENO, F_SETFL, oldf);
00133
00134 if (ch != EOF)
00135 {
00136 ungetc(ch, stdin);
00137 return 1;
00138 }
00139
00140 return 0;
00141 #elif defined(_WIN32) || defined(_WIN64)
00142 return _kbhit();
00143 #endif
00144 }
00145
00146
00147 bool setTorque(struct motor &motor, bool onoff)
00148 {
00149 uint8_t dxl_error = 0;
00150 int dxl_comm_result = COMM_TX_FAIL;
00151 uint16_t addr=ADDR_PRO_TORQUE_ENABLE;
00152 if (motor.model==1040) addr=ADDR_XH_TORQUE_ENABLE;
00153
00154 dxl_comm_result = packetHandler->write1ByteTxRx(portHandler, motor.id, addr, onoff, &dxl_error);
00155
00156 if(dxl_comm_result != COMM_SUCCESS) {
00157
00158 return false;
00159 }
00160 else if(dxl_error != 0) {
00161
00162 return false;
00163 }
00164 else {
00165 return true;
00166 }
00167 }
00168
00169 bool bulk_write() {
00170
00171
00172 int8_t dxl_comm_result_=0;
00173
00174
00175
00176 dynamixel::GroupBulkWrite GroupBulkWrite(portHandler, packetHandler);
00177 for (int i=0;i<num_motors;i++) {
00178 bool dxl_addparam_result = false;
00179 uint16_t addr=ADDR_PRO_GOAL_POSITION;
00180 if (motors[i].model==1040) addr=ADDR_XH_GOAL_POSITION;
00181 int32_t pos=rads2ticks(motors[i].command_position,motors[i]);
00182 dxl_addparam_result =GroupBulkWrite.addParam(motors[i].id,addr,4,(uint8_t*)&pos);
00183
00184 if (dxl_addparam_result != true)
00185 {
00186
00187 return false;
00188
00189 }
00190 }
00191
00192 dxl_comm_result_ = GroupBulkWrite.txPacket();
00193
00194 if (dxl_comm_result_ != COMM_SUCCESS)
00195 {
00196
00197
00198 return false;
00199 }
00200
00201 GroupBulkWrite.clearParam();
00202 return true;
00203
00204 }
00205
00206 bool bulk_read() {
00207
00208
00209 dynamixel::GroupBulkRead GroupBulkRead(portHandler, packetHandler);
00210 for (int i=0;i<num_motors;i++) {
00211 bool dxl_addparam_result = false;
00212 uint16_t addr=ADDR_PRO_PRESENT_POSITION;
00213 if (motors[i].model==1040) addr=ADDR_XH_PRESENT_POSITION;
00214
00215 dxl_addparam_result =GroupBulkRead.addParam(motors[i].id,addr, 4);
00216
00217 if (dxl_addparam_result != true)
00218 {
00219
00220 return false;
00221
00222 }
00223 }
00224
00225 int dxl_comm_result = COMM_TX_FAIL;
00226 dxl_comm_result = GroupBulkRead.txRxPacket();
00227 if (dxl_comm_result != COMM_SUCCESS)
00228 {
00229
00230
00231 return false;
00232 }
00233
00234 for (int i=0;i<num_motors;i++) {
00235 bool dxl_getdata_result = false;
00236
00237 uint16_t addr=ADDR_PRO_PRESENT_POSITION;
00238 if (motors[i].model==1040) addr=ADDR_XH_PRESENT_POSITION;
00239 dxl_getdata_result = GroupBulkRead.isAvailable(motors[i].id, addr, 4);
00240 if (dxl_getdata_result != true)
00241 {
00242
00243 return false;
00244 }
00245 else {
00246 uint16_t addr=ADDR_PRO_PRESENT_POSITION;
00247 if (motors[i].model==1040) addr=ADDR_XH_PRESENT_POSITION;
00248 motors[i].position = ticks2rads(GroupBulkRead.getData(motors[i].id, addr, 4),motors[i]);
00249
00250
00251 }
00252 }
00253 return true;
00254 }
00255
00256 bool ping(struct motor &motor) {
00257
00258 int dxl_comm_result = COMM_TX_FAIL;
00259 uint8_t dxl_error = 0;
00260
00261
00262
00263 dxl_comm_result = packetHandler->ping(portHandler, motor.id, &(motor.model), &dxl_error);
00264 if (dxl_comm_result != COMM_SUCCESS)
00265 {
00266
00267
00268 return false;
00269 }
00270 else if (dxl_error != 0)
00271 {
00272
00273
00274 return false;
00275
00276 }
00277 else {
00278
00279 return true;
00280 }
00281
00282 }
00283
00284 double ticks2rads(int32_t ticks, struct motor &motor) {
00285 if(motor.protocol_ver == PROTOCOL2_VERSION) {
00286 const double FromTicks = 1.0 / (motor.cpr / 2.0);
00287 return static_cast<double>(ticks) * FromTicks * M_PI;
00288 }
00289 else {
00290 double cprDev2 = motor.cpr / 2.0f;
00291 return (static_cast<double>(ticks) - cprDev2) * M_PI / cprDev2;
00292 }
00293 }
00294
00295 int32_t rads2ticks(double rads, struct motor &motor) {
00296
00297 if(motor.protocol_ver == PROTOCOL2_VERSION) {
00298 double cprDev2 = motor.cpr / 2.0f;
00299 return static_cast<int32_t>(round((rads / M_PI) * cprDev2));
00300 }
00301 else {
00302 double cprDev2 = motor.cpr / 2.0f;
00303 return static_cast<int32_t>(round(cprDev2 + (rads * cprDev2 / M_PI)));
00304 }
00305 }
00306
00307
00308 void CmdCallback(const sensor_msgs::JointStateConstPtr &msg) {
00309 int size =msg->position.size();
00310 for(int i = 0; i < size; ++i) {
00311 motors[i].command_position=msg->position[i];
00312 motors[i].command_velocity=msg->velocity[i];
00313 }
00314
00315 bulk_write();
00316 }
00317
00318
00319 int main(int argc, char** argv)
00320 {
00321 ros::init(argc, argv, "ping");
00322 ros::NodeHandle nh;
00323
00324
00325
00326 ros::Subscriber cmdListener=nh.subscribe("dxl_command", 10, &CmdCallback);
00327 initSpecFile();
00328
00329 portHandler = dynamixel::PortHandler::getPortHandler(DEVICENAME);
00330 packetHandler = dynamixel::PacketHandler::getPacketHandler(PROTOCOL_VERSION);
00331
00332
00333 if (portHandler->openPort()) printf("Succeeded to open the port!\n");
00334 else {
00335 printf("Failed to open the port!\n");
00336 return 0;
00337 }
00338
00339 if (portHandler->setBaudRate(BAUDRATE)) printf("Succeeded to change the baudrate!\n");
00340 else
00341 {
00342 printf("Failed to change the baudrate!\n");
00343 return 0;
00344 }
00345
00346
00347
00348
00349 uint8_t ids[]={1,2,3,4,5,6,7,8};
00350
00351 num_motors=sizeof(ids)/sizeof(uint8_t);
00352 motors=(struct motor *)malloc(sizeof(struct motor)*num_motors);
00353 for (int i=0;i<num_motors;i++) {
00354 motors[i].id=ids[i];
00355 motors[i].model=0;
00356 motors[i].protocol_ver=2.0;
00357 motors[i].command_position=0;
00358 motors[i].command_velocity=rads2ticks(0.5,motors[i]);
00359 }
00360
00361 ROS_INFO("Pinging motors...");
00362 for (int i=0;i<num_motors;i++) {
00363 while ((!ping(motors[i])|| motors[i].model==0)&&ros::ok()) {
00364
00365 ros::Rate(5).sleep();
00366
00367 }
00368 ROS_INFO("[ID:%03d] Ping OK, model: %d",motors[i].id,motors[i].model);
00369 bool success = _modelSpec.find(motors[i].model) != _modelSpec.end();
00370 if (success) {
00371 motors[i].cpr=_modelSpec[motors[i].model].cpr;
00372 motors[i].gear_reduction=_modelSpec[motors[i].model].gear_reduction;
00373 }
00374 }
00375
00376 ROS_INFO("Enabling motors torque...");
00377 for (int i=0;i<num_motors;i++) {
00378 while (!setTorque(motors[i],false)&&ros::ok()) {
00379
00380
00381 ros::Rate(5).sleep();
00382 }
00383 ROS_INFO("[ID:%03d] Torque ON",i);
00384 motors[i].torque=true;
00385 }
00386 ROS_INFO("Read Write loop started");
00387 while (ros::ok()) {
00388
00389
00390 bool read_ok=bulk_read();
00391 if (read_ok) {
00392
00393 for (int i=0;i<num_motors;i++) {
00394 printf("%.3f, ",motors[i].position);
00395 }
00396 puts("");
00397 }
00398 else {
00399
00400 }
00401
00402
00403 bool write_ok=1;
00404 if (write_ok) {
00405
00406 }
00407 else ROS_ERROR("Write error");
00408
00409
00410 ros::Rate(200).sleep();
00411 ros::spinOnce();
00412 }
00413
00414
00415 portHandler->closePort();
00416 free(motors);
00417 return 0;
00418 }