ping.cpp
Go to the documentation of this file.
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 // The >> operator disappeared in yaml-cpp 0.5, so this function is
00029 // added to provide support for code written under the yaml-cpp 0.3 API.
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 // Protocol version
00039 #define PROTOCOL_VERSION                2.0                 // See which protocol version is used in the Dynamixel
00040 
00041 // Default setting
00042 
00043 #define BAUDRATE                        57600
00044 #define DEVICENAME                      "/dev/ttyUSB0"      // Check which port is being used on your controller
00045 // ex) Windows: "COM1"   Linux: "/dev/ttyUSB0" Mac: "/dev/tty.usbserial-*"
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         // Load the basic specs of this motor type
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         //packetHandler->printTxRxResult(dxl_comm_result);
00158         return false;
00159     }
00160     else if(dxl_error != 0) {
00161         // packetHandler->printRxPacketError(dxl_error);
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;                // addParam result
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             //  ROS_ERROR("[ID:%03d] groupSyncRead addparam failed", i);
00187             return false;
00188 
00189         }
00190     }
00191 
00192     dxl_comm_result_ = GroupBulkWrite.txPacket();
00193 
00194     if (dxl_comm_result_ != COMM_SUCCESS)
00195     {
00196         // ROS_ERROR("txPacket Error");
00197         // packetHandler->printTxRxResult(dxl_comm_result_);
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;                // addParam result
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             //ROS_ERROR("[ID:%03d] groupSyncRead addparam failed", i);
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         // ROS_ERROR("txRxPacket Error");
00230         //  packetHandler->printTxRxResult(dxl_comm_result);
00231         return false;
00232     }
00233 
00234     for (int i=0;i<num_motors;i++) {
00235         bool dxl_getdata_result = false; // GetParam result
00236         // Check if groupsyncread data of Dynamixels are available
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             // ROS_ERROR("[ID:%03d] groupSyncRead isAvailable failed\n", i);
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             // ROS_INFO("[ID:%03d] Read sync pos value: %d",i,value);
00250 
00251         }
00252     }
00253     return true;
00254 }
00255 
00256 bool ping(struct motor &motor) {
00257 
00258     int dxl_comm_result = COMM_TX_FAIL;             // Communication result
00259     uint8_t dxl_error = 0;                          // Dynamixel error
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         // ROS_ERROR("[ID:%03d] Ping TXRX error: ",id);
00267         //  packetHandler->printTxRxResult(dxl_comm_result);
00268         return false;
00269     }
00270     else if (dxl_error != 0)
00271     {
00272         // ROS_ERROR("[ID:%03d] Ping error: ",id);
00273         //  packetHandler->printRxPacketError(dxl_error);
00274         return false;
00275 
00276     }
00277     else {
00278         //  printf("[ID:%03d] ping Succeeded.\n", motors[id].id);
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     //ros::AsyncSpinner spinner(2);
00324     //spinner.start();
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     // Open port
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     // Set port baudrate
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     // Set timeout
00346     //portHandler->setPacketTimeout(111111111.0);
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             //ROS_WARN("[ID:%03d] ping error",motors[i].id);
00365             ros::Rate(5).sleep();
00366             // ros::spinOnce();
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             // ROS_WARN("[ID:%03d] setTorque error",i);
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             //ROS_INFO("Read OK");
00393             for (int i=0;i<num_motors;i++) {
00394                 printf("%.3f, ",motors[i].position);
00395             }
00396             puts("");
00397         }
00398         else {
00399             //  ROS_ERROR("Read error");
00400         }
00401         //ros::Rate(200).sleep();
00402 
00403         bool write_ok=1;//bulk_write(portHandler,packetHandler);
00404         if (write_ok) {
00405             //ROS_INFO("Write OK");
00406         }
00407         else ROS_ERROR("Write error");
00408 
00409 
00410         ros::Rate(200).sleep();
00411         ros::spinOnce();
00412     }
00413 
00414     // Close port
00415     portHandler->closePort();
00416     free(motors);
00417     return 0;
00418 }


robotican_hardware_interface
Author(s):
autogenerated on Fri Oct 27 2017 03:02:48