diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e813a86cca753328a61110daf4bdbdc7a9aa083..830e2d7a6966698a366ad6098a5b91247164359f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,9 @@ ADD_SUBDIRECTORY(xml) # edit the following line to add all the source code files of the library -SET(sources dynamixel_motor.cpp dynamixel_motor_group.cpp) +SET(sources dynamixel_motor.cpp dynamixel_motor_group.cpp dynamixel_motor_exceptions.cpp) # edit the following line to add all the header files of the library -SET(headers dynamixel_motor.h dynamixel_motor_group.h) +SET(headers dynamixel_motor.h dynamixel_motor_group.h dynamixel_motor_exceptions.h) FIND_PACKAGE(comm REQUIRED) diff --git a/src/dynamixel_motor.cpp b/src/dynamixel_motor.cpp index 0441f25414fe6c1a70caaa34077f678fbb2e42c3..1db90d287811f207704fdb93023c85d79fa9fa7e 100644 --- a/src/dynamixel_motor.cpp +++ b/src/dynamixel_motor.cpp @@ -1,3 +1,4 @@ +#include "dynamixel_motor_exceptions.h" #include "dynamixelexceptions.h" #include "dynamixelserver.h" #include "eventexceptions.h" @@ -76,6 +77,7 @@ void CDynamixelMotor::angles_to_controller(std::vector<float>& angles,std::vecto if(angles.size()!=1) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element)."); } else { @@ -89,6 +91,7 @@ void CDynamixelMotor::speeds_to_controller(std::vector<float>& speeds,std::vecto if(speeds.size()!=1) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element)."); } else { @@ -105,6 +108,7 @@ void CDynamixelMotor::accels_to_controller(std::vector<float>& accels,std::vecto if(accels.size()!=1) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element)."); } else { @@ -118,6 +122,7 @@ void CDynamixelMotor::controller_to_angles(std::vector<float>& counts,std::vecto if(counts.size()!=1) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element)."); } else { @@ -131,6 +136,7 @@ void CDynamixelMotor::controller_to_speeds(std::vector<float>& counts,std::vecto if(counts.size()!=1) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element)."); } else { @@ -144,6 +150,7 @@ void CDynamixelMotor::controller_to_accels(std::vector<float>& counts,std::vecto if(counts.size()!=1) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid input vector size (it must have only one element)."); } else { @@ -157,12 +164,14 @@ void CDynamixelMotor::cont_set_position_range(std::vector<float>& min, std::vect if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { if(min[0]<0 || max[0]>(this->dyn_enc_res-1)) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The desired range is outside the valid range of the servo."); } else { @@ -188,6 +197,7 @@ void CDynamixelMotor::cont_get_position_range(std::vector<float>& min, std::vect if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -220,6 +230,7 @@ std::vector<float> CDynamixelMotor::cont_get_position(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -246,6 +257,7 @@ std::vector<float> CDynamixelMotor::cont_get_velocity(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -270,6 +282,7 @@ void CDynamixelMotor::cont_enable(std::vector<bool> &enable) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -295,6 +308,7 @@ void CDynamixelMotor::cont_disable(std::vector<bool> &disable) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -320,6 +334,7 @@ void CDynamixelMotor::cont_load(std::vector<float>& position, std::vector<float> if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -357,10 +372,12 @@ void CDynamixelMotor::cont_load(std::vector<float>& velocity, std::vector<float> if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Velocity control is not supported. Use torque control instead."); // velocity control is not supported } } @@ -377,6 +394,7 @@ void CDynamixelMotor::cont_stop(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -486,6 +504,7 @@ int CDynamixelMotor::get_baudrate(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -510,6 +529,7 @@ unsigned char CDynamixelMotor::get_node_address(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -531,6 +551,7 @@ void CDynamixelMotor::set_node_address(unsigned char dev_id) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -552,6 +573,7 @@ std::string CDynamixelMotor::get_model(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -599,6 +621,14 @@ std::string CDynamixelMotor::get_model(void) // set resolution this->dyn_enc_res=4096; break; + case 0x001D: this->info.model="MX-28"; + // set maximum angle + this->dyn_max_angle=360; + // set maximum speed + this->dyn_max_speed=54; + // set resolution + this->dyn_enc_res=4096; + break; default: this->info.model="unknown"; break; } @@ -619,6 +649,7 @@ unsigned char CDynamixelMotor::get_firmware_version(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -642,6 +673,7 @@ int CDynamixelMotor::get_temperature_limit(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -664,12 +696,14 @@ void CDynamixelMotor::set_temperature_limit(int limit) if(limit<0 && limit>255) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The desired temperatura limit is out of range."); } else { if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -692,6 +726,7 @@ int CDynamixelMotor::get_current_temperature(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -715,6 +750,7 @@ void CDynamixelMotor::get_voltage_limits(float *min, float *max) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -739,18 +775,21 @@ void CDynamixelMotor::set_voltage_limits(float min, float max) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { if(min>max) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The maximum voltage is lower than the minimum voltage."); } else { if(min<5.0 || min>25.0 || max<5.0 || max>25.0) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The desired voltage range is outside the valid range."); } else { @@ -777,6 +816,7 @@ float CDynamixelMotor::get_current_voltage(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -800,6 +840,7 @@ unsigned char CDynamixelMotor::get_led_alarms(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -822,12 +863,14 @@ void CDynamixelMotor::set_led_alarms(unsigned char alarms) if(alarms&0x80) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid alarm mask"); } else { if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -850,6 +893,7 @@ unsigned char CDynamixelMotor::get_turn_off_alarms(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -872,12 +916,14 @@ void CDynamixelMotor::set_turn_off_alarms(unsigned char alarms) if(alarms&0x80) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid alarm mask."); } else { if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -899,6 +945,7 @@ void CDynamixelMotor::turn_led_on(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -919,6 +966,7 @@ void CDynamixelMotor::turn_led_off(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -938,23 +986,33 @@ void CDynamixelMotor::get_compliance_margin(unsigned char *cw_margin, unsigned c if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { - if(cw_margin==NULL || ccw_margin==NULL) + if(this->info.model=="MX-28" || this->info.model=="EX-106") { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"This servo model does not support compliance margin."); } else { - try{ - this->dynamixel_dev->read_byte_register(cw_comp_margin,cw_margin); - this->dynamixel_dev->read_byte_register(ccw_comp_margin,ccw_margin); - }catch(CDynamixelAlarmException &e){ - /* handle dynamixel exception */ - if(e.get_alarm()&this->alarms) - this->reset_motor(); - throw; + if(cw_margin==NULL || ccw_margin==NULL) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid complinace margin."); + } + else + { + try{ + this->dynamixel_dev->read_byte_register(cw_comp_margin,cw_margin); + this->dynamixel_dev->read_byte_register(ccw_comp_margin,ccw_margin); + }catch(CDynamixelAlarmException &e){ + /* handle dynamixel exception */ + if(e.get_alarm()&this->alarms) + this->reset_motor(); + throw; + } } } } @@ -965,25 +1023,36 @@ void CDynamixelMotor::set_compliance_margin(unsigned char cw_margin, unsigned ch if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { - if(cw_margin>254) + if(this->info.model=="MX-28" || this->info.model=="EX-106") { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"This servo model does not support compliance margin."); } - if(ccw_margin>254) + else { - /* handle exceptions */ - } - try{ - this->dynamixel_dev->write_byte_register(cw_comp_margin,cw_margin); - this->dynamixel_dev->write_byte_register(ccw_comp_margin,ccw_margin); - }catch(CDynamixelAlarmException &e){ - /* handle dynamixel exception */ - if(e.get_alarm()&this->alarms) - this->reset_motor(); - throw; + if(cw_margin>254) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid clockwise compliance margin."); + } + if(ccw_margin>254) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid counterclockwise compliance margin."); + } + try{ + this->dynamixel_dev->write_byte_register(cw_comp_margin,cw_margin); + this->dynamixel_dev->write_byte_register(ccw_comp_margin,ccw_margin); + }catch(CDynamixelAlarmException &e){ + /* handle dynamixel exception */ + if(e.get_alarm()&this->alarms) + this->reset_motor(); + throw; + } } } } @@ -993,23 +1062,33 @@ void CDynamixelMotor::get_compliance_slope(unsigned char *cw_slope, unsigned cha if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { - if(cw_slope==NULL || ccw_slope==NULL) + if(this->info.model=="MX-28" || this->info.model=="EX-106") { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"This servo model does not support compliance slope."); } else { - try{ - this->dynamixel_dev->read_byte_register(cw_comp_slope,cw_slope); - this->dynamixel_dev->read_byte_register(ccw_comp_slope,ccw_slope); - }catch(CDynamixelAlarmException &e){ - /* handle dynamixel exception */ - if(e.get_alarm()&this->alarms) - this->reset_motor(); - throw; + if(cw_slope==NULL || ccw_slope==NULL) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid compliance slope."); + } + else + { + try{ + this->dynamixel_dev->read_byte_register(cw_comp_slope,cw_slope); + this->dynamixel_dev->read_byte_register(ccw_comp_slope,ccw_slope); + }catch(CDynamixelAlarmException &e){ + /* handle dynamixel exception */ + if(e.get_alarm()&this->alarms) + this->reset_motor(); + throw; + } } } } @@ -1020,41 +1099,52 @@ void CDynamixelMotor::set_compliance_slope(unsigned char cw_slope, unsigned char if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { - if(cw_slope>=1 && cw_slope<=5) cw_slope=4; - else if(cw_slope>=6 && cw_slope<=11) cw_slope=8; - else if(cw_slope>=12 && cw_slope<=23) cw_slope=16; - else if(cw_slope>=24 && cw_slope<=47) cw_slope=32; - else if(cw_slope>=48 && cw_slope<=95) cw_slope=64; - else if(cw_slope>=96 && cw_slope<=191) cw_slope=128; - else if(cw_slope>=192 && cw_slope<=254) cw_slope=254; - else + if(this->info.model=="MX-28" || this->info.model=="EX-106") { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"This servo model does not support compliance slope."); } - if(ccw_slope>=1 && ccw_slope<=5) ccw_slope=4; - else if(ccw_slope>=6 && ccw_slope<=11) ccw_slope=8; - else if(ccw_slope>=12 && ccw_slope<=23) ccw_slope=16; - else if(ccw_slope>=24 && ccw_slope<=47) ccw_slope=32; - else if(ccw_slope>=48 && ccw_slope<=95) ccw_slope=64; - else if(ccw_slope>=96 && ccw_slope<=191) ccw_slope=128; - else if(ccw_slope>=192 && ccw_slope<=254) ccw_slope=254; else { - /* handle exceptions */ - } - try{ - this->dynamixel_dev->write_byte_register(cw_comp_slope,cw_slope); - this->dynamixel_dev->write_byte_register(ccw_comp_slope,ccw_slope); - }catch(CDynamixelAlarmException &e){ - /* handle dynamixel exception */ - if(e.get_alarm()&this->alarms) - this->reset_motor(); - throw; + if(cw_slope>=1 && cw_slope<=5) cw_slope=4; + else if(cw_slope>=6 && cw_slope<=11) cw_slope=8; + else if(cw_slope>=12 && cw_slope<=23) cw_slope=16; + else if(cw_slope>=24 && cw_slope<=47) cw_slope=32; + else if(cw_slope>=48 && cw_slope<=95) cw_slope=64; + else if(cw_slope>=96 && cw_slope<=191) cw_slope=128; + else if(cw_slope>=192 && cw_slope<=254) cw_slope=254; + else + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid clockwise compliance slope."); + } + if(ccw_slope>=1 && ccw_slope<=5) ccw_slope=4; + else if(ccw_slope>=6 && ccw_slope<=11) ccw_slope=8; + else if(ccw_slope>=12 && ccw_slope<=23) ccw_slope=16; + else if(ccw_slope>=24 && ccw_slope<=47) ccw_slope=32; + else if(ccw_slope>=48 && ccw_slope<=95) ccw_slope=64; + else if(ccw_slope>=96 && ccw_slope<=191) ccw_slope=128; + else if(ccw_slope>=192 && ccw_slope<=254) ccw_slope=254; + else + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid counterclockwise compliance slope."); + } + try{ + this->dynamixel_dev->write_byte_register(cw_comp_slope,cw_slope); + this->dynamixel_dev->write_byte_register(ccw_comp_slope,ccw_slope); + }catch(CDynamixelAlarmException &e){ + /* handle dynamixel exception */ + if(e.get_alarm()&this->alarms) + this->reset_motor(); + throw; + } } - } + } } short int CDynamixelMotor::get_punch(void) @@ -1064,6 +1154,7 @@ short int CDynamixelMotor::get_punch(void) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { @@ -1085,12 +1176,14 @@ void CDynamixelMotor::set_punch(short int punch_value) if(this->dynamixel_dev==NULL) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { if(punch<0 || punch>1023) { /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid punch value."); } try{ this->dynamixel_dev->write_word_register(punch,punch_value); @@ -1101,7 +1194,52 @@ void CDynamixelMotor::set_punch(short int punch_value) throw; } } +} + +void CDynamixelMotor::get_pid(unsigned char *p,unsigned char *i,unsigned char *d) +{ + if(this->dynamixel_dev==NULL) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); + } + else + { + if(this->info.model=="MX-28" || this->info.model=="EX-106") + { + this->dynamixel_dev->read_byte_register(pid_p,p); + this->dynamixel_dev->read_byte_register(pid_i,i); + this->dynamixel_dev->read_byte_register(pid_d,d); + } + else + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"This servo model does not support PID."); + } + } +} +void CDynamixelMotor::set_pid(unsigned char p,unsigned char i,unsigned char d) +{ + if(this->dynamixel_dev==NULL) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); + } + else + { + if(this->info.model=="MX-28" || this->info.model=="EX-106") + { + this->dynamixel_dev->write_byte_register(pid_p,p); + this->dynamixel_dev->write_byte_register(pid_i,i); + this->dynamixel_dev->write_byte_register(pid_d,d); + } + else + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"This servo model does not support PID."); + } + } } bool CDynamixelMotor::is_locked(void) @@ -1118,23 +1256,39 @@ void CDynamixelMotor::enable_torque_control(void) { std::vector<float> min,max; - min.push_back(0.0); - max.push_back(0.0); - this->set_position_range(min,max); - this->disable_position_feedback(); - this->torque_control=true; + if(this->dynamixel_dev==NULL) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); + } + else + { + min.push_back(0.0); + max.push_back(0.0); + this->set_position_range(min,max); + this->disable_position_feedback(); + this->torque_control=true; + } } void CDynamixelMotor::disable_torque_control(void) { std::vector<float> min,max; - min.push_back(0.0); - max.push_back(300.0); - this->set_position_range(min,max); - this->config_position_feedback(fb_polling,100.0); - this->enable_position_feedback(); - this->torque_control=false; + if(this->dynamixel_dev==NULL) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); + } + else + { + min.push_back(0.0); + max.push_back(this->dyn_max_angle); + this->set_position_range(min,max); + this->config_position_feedback(fb_polling,100.0); + this->enable_position_feedback(); + this->torque_control=false; + } } bool CDynamixelMotor::is_torque_control_enabled(void) @@ -1146,34 +1300,44 @@ void CDynamixelMotor::set_torque(float torque_ratio) { unsigned short int torque=0x0000; - if(this->torque_control) + if(this->dynamixel_dev==NULL) { - if(torque_ratio>100.0 || torque_ratio<-100.0) - { - /* handle exceptions */ - } - else - { - if(torque_ratio<0.0) - torque+=0x0400; - torque+=((unsigned short int)(fabs(torque_ratio)*1023.0/100.0))&0x03FF; - this->dynamixel_dev->write_word_register(goal_speed,torque); - } + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"The dynamixel device is not properly configured."); } else { - if(torque_ratio>100.0 || torque_ratio<0.0) + if(this->torque_control) { - /* handle exceptions */ + if(torque_ratio>100.0 || torque_ratio<-100.0) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid torque ratio."); + } + else + { + if(torque_ratio<0.0) + torque+=0x0400; + torque+=((unsigned short int)(fabs(torque_ratio)*1023.0/100.0))&0x03FF; + this->dynamixel_dev->write_word_register(goal_speed,torque); + } } else { - // set the maximum torque of the servo - torque=((unsigned short int)(fabs(torque_ratio)*1023.0/100.0))&0x03FF; - // save the value to EEPROM - this->dynamixel_dev->write_word_register(max_torque,torque); - // update the current value - this->dynamixel_dev->write_word_register(torque_limit,torque); + if(torque_ratio>100.0 || torque_ratio<0.0) + { + /* handle exceptions */ + throw CDynamixelMotorException(_HERE_,"Invalid torque ratio."); + } + else + { + // set the maximum torque of the servo + torque=((unsigned short int)(fabs(torque_ratio)*1023.0/100.0))&0x03FF; + // save the value to EEPROM + this->dynamixel_dev->write_word_register(max_torque,torque); + // update the current value + this->dynamixel_dev->write_word_register(torque_limit,torque); + } } } } diff --git a/src/dynamixel_motor.h b/src/dynamixel_motor.h index 320d63ede9f8ee9a0674a9abbd9907c7a842664c..ccf412aabfb9aaadf8957d6b59cb681ec10fd2f8 100644 --- a/src/dynamixel_motor.h +++ b/src/dynamixel_motor.h @@ -30,6 +30,9 @@ typedef enum { up_cal=0x16, torque_en=0x18, led=0x19, + pid_p=0x1A, + pid_i=0x1B, + pid_d=0x1C, cw_comp_margin=0x1A, ccw_comp_margin=0x1B, cw_comp_slope=0x1C, @@ -356,6 +359,16 @@ class CDynamixelMotor : public CMotorControl * */ void set_punch(short int punch_value); + /** + * \brief + * + */ + void get_pid(unsigned char *p,unsigned char *i,unsigned char *d); + /** + * \brief + * + */ + void set_pid(unsigned char p,unsigned char i,unsigned char d); /** * \brief * diff --git a/src/dynamixel_motor_group.cpp b/src/dynamixel_motor_group.cpp index ca331b4e072ae39dccbf17c424058f107e7cf93b..4443ce90dd3a62891ef5d251f8ee590b2ab1e99b 100644 --- a/src/dynamixel_motor_group.cpp +++ b/src/dynamixel_motor_group.cpp @@ -1,19 +1,18 @@ -#include "dynamixelexceptions.h" +#include "dynamixel_motor_exceptions.h" #include "dynamixelserver.h" #include "eventexceptions.h" #include "dynamixel_motor_group.h" +#include "dynamixel_motor.h" #include "ftdiserver.h" #include <math.h> #include <iostream> - - CDynamixelMotorGroup::CDynamixelMotorGroup(std::string &group_id):CMotorGroup(group_id) { if(group_id.size()==0) { /* handle exceptions */ - throw CDynamixelServerException(_HERE_,"Invalid group identifier - empty string"); + throw CDynamixelMotorGroupException(_HERE_,"Invalid group identifier - empty string"); } else { @@ -23,40 +22,31 @@ CDynamixelMotorGroup::CDynamixelMotorGroup(std::string &group_id):CMotorGroup(gr this->servo_id[1]=0x04; this->servo_id[2]=0x03; this->servo_id[3]=0x05; - + } } - - - - - void CDynamixelMotorGroup::move(std::vector<float> &position,std::vector<float> &velocity,std::vector<float> &acceleration) { - + std::vector< std::vector<unsigned char> > data; unsigned char star_addrs; - unsigned int i=0; - int num_instruc=4; - unsigned char const goal_pos=0x1E; - std::vector< std::vector<unsigned char> > data; - - + + if(position.size()!=this->servo_id.size()) { /* handle errors */ - throw CDynamixelServerException(_HERE_,"The number of position commands does not coincide with the total number of motors in the group"); + throw CDynamixelMotorGroupException(_HERE_,"The number of position commands does not coincide with the total number of motors in the group"); } else if(velocity.size()!=this->servo_id.size()) { /* handle exceptions */ - throw CDynamixelServerException(_HERE_,"The number of velocity commands does not coincide with the total number of motors in the group"); + throw CDynamixelMotorGroupException(_HERE_,"The number of velocity commands does not coincide with the total number of motors in the group"); } else if(acceleration.size()!=this->servo_id.size()) { /* handle exceptions */ - throw CDynamixelServerException(_HERE_,"The number of acceleration commands does not coincide with the total number of motors in the group"); + throw CDynamixelMotorGroupException(_HERE_,"The number of acceleration commands does not coincide with the total number of motors in the group"); } else { @@ -65,34 +55,29 @@ void CDynamixelMotorGroup::move(std::vector<float> &position,std::vector<float> data.resize(servo_id.size()); for(i=0;i<servo_id.size();i++) { - /* Number of instructions in bytes: - - goal_pos: 2 bytes - - goal_speed: 2 bytes */ - data[i].resize(num_instruc); - } - for(i=0;i<servo_id.size();i++) - { - - data[i][0]=((int)position[i])%256; - data[i][1]=position[i]/256; - data[i][2]=0xFF; - data[i][3]=0x03; - } - - dyn_server->write_sync(servo_id,star_addrs,data); - - - }catch(CException &e){ - - std::cout << "Movement aborted" << std::endl; - } - - } - + /* Number of instructions in bytes: + - goal_pos: 2 bytes + - goal_speed: 2 bytes */ + data[i].resize(4); + } + for(i=0;i<servo_id.size();i++) + { + + data[i][0]=((int)position[i])%256; + data[i][1]=position[i]/256; + data[i][2]=0xFF; + data[i][3]=0x03; + } + dyn_server->write_sync(servo_id,star_addrs,data); + }catch(CException &e){ + /* handle exceptions */ + throw; + } + } } CDynamixelMotorGroup::~CDynamixelMotorGroup() { - + } diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index e37c14a68768fbaa9f55715ad4b5e022c4fdc2e5..0843898674d206ab2b5e622d22d67df39777d05f 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -21,3 +21,9 @@ ADD_EXECUTABLE(test_dynamixel_motor_group test_dynamixel_motor_group.cpp) # edit the following line to add the necessary libraries TARGET_LINK_LIBRARIES(test_dynamixel_motor_group dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY}) + +# edit the following line to add the source code for the example and the name of the executable +ADD_EXECUTABLE(test_dynamixel_motor_open_loop test_dynamixel_motor_open_loop.cpp) + +# edit the following line to add the necessary libraries +TARGET_LINK_LIBRARIES(test_dynamixel_motor_open_loop dynamixel_motor_cont ${comm_LIBRARY} ${motor_control_LIBRARY}) diff --git a/src/examples/test_dynamixel_motor.cpp b/src/examples/test_dynamixel_motor.cpp index d010360a456c99b314d43a4865304d92ea084c56..39c5e5926b2910ebb74020a9beace5eddb8a8f2f 100755 --- a/src/examples/test_dynamixel_motor.cpp +++ b/src/examples/test_dynamixel_motor.cpp @@ -23,10 +23,10 @@ int main(int argc, char *argv[]) try{ if(dyn_server->get_num_buses()>0) { - cont2=new CDynamixelMotor(cont2_name,0,1000000,1); + cont2=new CDynamixelMotor(cont2_name,0,1000000,11); cont2->close(); delete cont2; - cont2=new CDynamixelMotor(cont2_name,0,1000000,1); + cont2=new CDynamixelMotor(cont2_name,0,1000000,11); enable[0]=true; cont2->enable(enable); #ifdef _HAVE_XSD @@ -35,8 +35,8 @@ int main(int argc, char *argv[]) #else events2.push_back(cont2->config_position_feedback(fb_polling,100.0)); #endif - cont2->set_torque(10.0); - cont3=new CDynamixelMotor(cont3_name,0,1000000,2); + cont2->set_torque(100.0); + cont3=new CDynamixelMotor(cont3_name,0,1000000,21); enable[0]=true; cont3->enable(enable); #ifdef _HAVE_XSD diff --git a/src/examples/test_dynamixel_motor_group.cpp b/src/examples/test_dynamixel_motor_group.cpp index 46989e59584aa5879355827622e7939bcf36c5d6..ef63132c2ec033eddc08e904d354e9c6a34655b4 100644 --- a/src/examples/test_dynamixel_motor_group.cpp +++ b/src/examples/test_dynamixel_motor_group.cpp @@ -19,7 +19,7 @@ int main(int argc, char *argv[]) std::vector<float> pos(4),vel(4),acc(4); CDynamixelMotor *cont1,*cont2,*cont3,*cont4; CDynamixelMotorGroup *group; - int dir=1,i=0; + unsigned int dir=1,i=0; try{ if(dyn_server->get_num_buses()>0) diff --git a/src/examples/test_dynamixel_motor_open_loop.cpp b/src/examples/test_dynamixel_motor_open_loop.cpp new file mode 100755 index 0000000000000000000000000000000000000000..6bf2c8b1e12e54059fc44c414bbf3956cfa851ad --- /dev/null +++ b/src/examples/test_dynamixel_motor_open_loop.cpp @@ -0,0 +1,146 @@ +#include "dynamixelexceptions.h" +#include "dynamixelserver.h" +#include "eventserver.h" +#include "exceptions.h" +#include "dynamixel_motor.h" +#include <iostream> + +std::string cont2_name="AX-12+_2"; +std::string cont3_name="AX-12+_3"; +std::string cont_config_file="../src/xml/base_dyn_config.xml"; + +int main(int argc, char *argv[]) +{ + CDynamixelServer *dyn_server=CDynamixelServer::instance(); + CEventServer *event_server=CEventServer::instance(); + std::list<std::string> events1,events2,events3; + CDynamixelMotor *cont2,*cont3; + std::vector<float> pos1(1),vel1(1),acc1(1),pos0(1); + std::vector<float> pos2(1),max(1),min(1); + std::vector<float> position(1); + std::vector<bool> enable(1); + int i=0; + + try{ + if(dyn_server->get_num_buses()>0) + { + cont2=new CDynamixelMotor(cont2_name,0,1000000,11); + cont2->close(); + delete cont2; + cont2=new CDynamixelMotor(cont2_name,0,1000000,11); + enable[0]=true; + cont2->enable(enable); +#ifdef _HAVE_XSD + cont2->load_config(cont_config_file); + events2.push_back(cont2->get_position_feedback_event()); +#else + events2.push_back(cont2->config_position_feedback(fb_polling,100.0)); +#endif + cont2->set_torque(100.0); + cont3=new CDynamixelMotor(cont3_name,0,1000000,21); + enable[0]=true; + cont3->enable(enable); +#ifdef _HAVE_XSD + cont3->load_config(cont_config_file); + events3.push_back(cont3->get_position_feedback_event()); +#else + events3.push_back(cont3->config_position_feedback(fb_polling,100.0)); +#endif + position=cont2->get_position(); + std::cout << "Current position of device 1: " << position[0] << std::endl; + position=cont3->get_position(); + std::cout << "Current position of device 15: " << position[0] << std::endl; + vel1[0]=40.0; + pos0[0]=150.0; + acc1[0]=vel1[0]*vel1[0]/(0.05*pos0[0]); + event_server->wait_all(events2); + std::cout << "centering ..." << std::endl; + cont2->load(pos0,vel1,acc1); + cont2->move(); + event_server->wait_all(events3); + std::cout << "centering ..." << std::endl; + cont3->load(pos0,vel1,acc1); + cont3->move(); + sleep(2); + // set open loop mode + + pos1[0]=190.0; + pos2[0]=110.0; + for(;;) + { + std::cout << "open loop control" << std::endl; + cont2->use_open_loop_control(); + cont3->use_open_loop_control(); + for(;;) + { +// event_server->wait_all(events2); + std::cout << "servo 1 moving left ..." << std::endl; + cont2->load(pos1,vel1,acc1); + cont2->move(); + sleep(1); +// event_server->wait_all(events2); + std::cout << "servo 1 moving right ..." << std::endl; + cont2->load(pos2,vel1,acc1); + cont2->move(); + sleep(2); +// event_server->wait_all(events2); + std::cout << "servo 1 centering ..." << std::endl; + cont2->load(pos0,vel1,acc1); + cont2->move(); + sleep(1); +// event_server->wait_all(events3); + std::cout << "servo 2 moving left ..." << std::endl; + cont3->load(pos1,vel1,acc1); + cont3->move(); + sleep(1); +// event_server->wait_all(events3); + std::cout << "servo 2 moving right ..." << std::endl; + cont3->load(pos2,vel1,acc1); + cont3->move(); + sleep(2); +// event_server->wait_all(events3); + std::cout << "servo 2 centering ..." << std::endl; + cont3->load(pos0,vel1,acc1); + cont3->move(); + sleep(1); + } + + std::cout << "closed loop control" << std::endl; + cont2->use_closed_loop_control(); + cont3->use_closed_loop_control(); + + for(i=0;i<1;i++) + { + event_server->wait_all(events2); + std::cout << "servo 1 moving left ..." << std::endl; + cont2->load(pos1,vel1,acc1); + cont2->move(); + event_server->wait_all(events2); + std::cout << "servo 1 moving right ..." << std::endl; + cont2->load(pos2,vel1,acc1); + cont2->move(); + event_server->wait_all(events2); + std::cout << "servo 1 centering ..." << std::endl; + cont2->load(pos0,vel1,acc1); + cont2->move(); + event_server->wait_all(events3); + std::cout << "servo 2 moving left ..." << std::endl; + cont3->load(pos1,vel1,acc1); + cont3->move(); + event_server->wait_all(events3); + std::cout << "servo 2 moving right ..." << std::endl; + cont3->load(pos2,vel1,acc1); + cont3->move(); + event_server->wait_all(events3); + std::cout << "servo 2 centering ..." << std::endl; + cont3->load(pos0,vel1,acc1); + cont3->move(); + } + sleep(1); + } + } + }catch(CException &e){ + std::cout << e.what() << std::endl; + } + return 0; +} diff --git a/src/xml/base_dyn_config.xml b/src/xml/base_dyn_config.xml index 772978d491a7c8ef1725877aff464174b49bfdc8..7011ccd0c1c1f487b5066420cf6a152adb8ce294 100755 --- a/src/xml/base_dyn_config.xml +++ b/src/xml/base_dyn_config.xml @@ -22,16 +22,17 @@ <position_feedback> <enabled>1</enabled> <mode>polling</mode> - <rate>1.0</rate> + <rate>100.0</rate> </position_feedback> <velocity_feedback> <enabled>0</enabled> <mode>polling</mode> - <rate>1.0</rate> + <rate>100.0</rate> </velocity_feedback> <limits_feedback> <enabled>0</enabled> <mode>polling</mode> <rate>1.0</rate> </limits_feedback> + <open_loop>0</open_loop> </motor_config>