diff --git a/include/dynamixel_servo.h b/include/dynamixel_servo.h index bd15fb6dbdecd4311416add58f60a391087bb4cc..bd043068e4903ff0c0716a3a40c7e00baa0366b8 100644 --- a/include/dynamixel_servo.h +++ b/include/dynamixel_servo.h @@ -21,11 +21,21 @@ namespace dynamixel_robot_gazebo CComplianceControl *compliance; unsigned char id; std::string model; + unsigned int encoder_res; + double max_angle; + double gear_ratio; + double max_torque; + double max_speed; unsigned char memory[SERVO_MEM_SIZE]; protected: void init_pid(const std::string &joint_name,ros::NodeHandle &controller_nh); - void init_compliance(const std::string &joint_name,ros::NodeHandle &controller_nh,double max_torque,unsigned int enc_res,double max_angle); + void init_compliance(const std::string &joint_name,ros::NodeHandle &controller_nh); void init_memory(void); + void set_current_angle(double angle); + void set_current_speed(double speed); + void set_current_effort(double effort); + double get_target_angle(void); + double get_target_speed(void); void on_ping(void); unsigned char on_read(unsigned short int address, unsigned short int length, unsigned char *data); unsigned char on_write(unsigned short int address, unsigned short int length, unsigned char *data); diff --git a/src/dynamixel_servo.cpp b/src/dynamixel_servo.cpp index 21a71ff682ec42229d713fb4c561b27e5cf43b8c..e976ea39898b4c60179e67bbbfd68008a00c53b6 100644 --- a/src/dynamixel_servo.cpp +++ b/src/dynamixel_servo.cpp @@ -24,42 +24,92 @@ namespace dynamixel_robot_gazebo } if(model=="AX12W") { - this->init_compliance(joint_name,controller_nh,1.5,1024,300.0); + this->encoder_res=1023; + this->max_angle=300.0; + this->gear_ratio=32.0; + this->max_torque=1.5; + this->max_speed=324.0; + this->init_compliance(joint_name,controller_nh); } else if(model=="AX12A") { - this->init_compliance(joint_name,controller_nh,1.5,1024,300.0); + this->encoder_res=1023; + this->max_angle=300.0; + this->gear_ratio=254.0; + this->max_torque=1.5; + this->max_speed=354.0; + this->init_compliance(joint_name,controller_nh); } else if(model=="AX18A") { - this->init_compliance(joint_name,controller_nh,1.8,1024,300.0); + this->encoder_res=1023; + this->max_angle=300.0; + this->gear_ratio=254.0; + this->max_torque=1.8; + this->max_speed=582.0; + this->init_compliance(joint_name,controller_nh); } else if(model=="MX12W") { + this->encoder_res=4095; + this->max_angle=360.0; + this->gear_ratio=32.0; + this->max_torque=1.5; + this->max_speed=2820.0; this->init_pid(joint_name,controller_nh); } else if(model=="MX28v1") { + this->encoder_res=4095; + this->max_angle=360.0; + this->gear_ratio=193.0; + this->max_torque=2.5; + this->max_speed=330.0; this->init_pid(joint_name,controller_nh); } else if(model=="MX64v1") { + this->encoder_res=4095; + this->max_angle=360.0; + this->gear_ratio=200.0; + this->max_torque=6.0; + this->max_speed=378.0; this->init_pid(joint_name,controller_nh); } else if(model=="MX106v1") { + this->encoder_res=4095; + this->max_angle=360.0; + this->gear_ratio=225.0; + this->max_torque=8.4; + this->max_speed=270.0; this->init_pid(joint_name,controller_nh); } else if(model=="MX28v2") { + this->encoder_res=4095; + this->max_angle=360.0; + this->gear_ratio=193.0; + this->max_torque=2.5; + this->max_speed=330.0; this->init_pid(joint_name,controller_nh); } else if(model=="MX64v2") { + this->encoder_res=4095; + this->max_angle=360.0; + this->gear_ratio=200.0; + this->max_torque=6.0; + this->max_speed=378.0; this->init_pid(joint_name,controller_nh); } else if(model=="MX106v2") { + this->encoder_res=4095; + this->max_angle=360.0; + this->gear_ratio=225.0; + this->max_torque=8.4; + this->max_speed=270.0; this->init_pid(joint_name,controller_nh); } else if(model=="XL320") @@ -119,11 +169,11 @@ namespace dynamixel_robot_gazebo } } - void CDynServo::init_compliance(const std::string &joint_name,ros::NodeHandle &controller_nh,double max_torque,unsigned int enc_res,double max_angle) + void CDynServo::init_compliance(const std::string &joint_name,ros::NodeHandle &controller_nh) { ros::NodeHandle params_nh(controller_nh,joint_name+std::string("/params")); this->compliance=new CComplianceControl(); - if(!this->compliance->init(params_nh,max_torque,enc_res,max_angle)) + if(!this->compliance->init(params_nh,this->max_torque,this->encoder_res,this->max_angle)) { ROS_WARN_STREAM("Dynamixel gazebo plugin: Failed to initialize Complaince params from ROS parameter server."); delete this->compliance; @@ -166,7 +216,9 @@ namespace dynamixel_robot_gazebo this->memory[26]=4; this->memory[27]=4; this->memory[28]=64; - this->memory[28]=64; + this->memory[29]=64; + this->memory[30]=255; + this->memory[31]=1; this->memory[34]=255; this->memory[35]=3; this->memory[48]=32; @@ -183,7 +235,9 @@ namespace dynamixel_robot_gazebo this->memory[26]=1; this->memory[27]=1; this->memory[28]=32; - this->memory[28]=32; + this->memory[29]=32; + this->memory[30]=255; + this->memory[31]=1; this->memory[34]=255; this->memory[35]=3; this->memory[48]=32; @@ -199,7 +253,9 @@ namespace dynamixel_robot_gazebo this->memory[26]=1; this->memory[27]=1; this->memory[28]=32; - this->memory[28]=32; + this->memory[29]=32; + this->memory[30]=255; + this->memory[31]=1; this->memory[34]=255; this->memory[35]=3; this->memory[48]=32; @@ -216,6 +272,8 @@ namespace dynamixel_robot_gazebo // initialize RAM this->memory[26]=8; this->memory[28]=8; + this->memory[30]=255; + this->memory[31]=7; this->memory[34]=255; this->memory[35]=3; this->memory[48]=32; @@ -230,6 +288,8 @@ namespace dynamixel_robot_gazebo this->memory[22]=1; // initialize RAM this->memory[28]=32; + this->memory[30]=255; + this->memory[31]=7; this->memory[34]=255; this->memory[35]=3; } @@ -244,6 +304,8 @@ namespace dynamixel_robot_gazebo this->memory[22]=1; // initialize RAM this->memory[28]=32; + this->memory[30]=255; + this->memory[31]=7; this->memory[34]=255; this->memory[35]=3; } @@ -258,6 +320,8 @@ namespace dynamixel_robot_gazebo this->memory[22]=1; // initialize RAM this->memory[28]=32; + this->memory[30]=255; + this->memory[31]=7; this->memory[34]=255; this->memory[35]=3; } @@ -292,6 +356,8 @@ namespace dynamixel_robot_gazebo this->memory[78]=100; this->memory[84]=52; this->memory[85]=3; + this->memory[116]=255; + this->memory[117]=7; } else if(model=="MX64v2") { @@ -314,6 +380,8 @@ namespace dynamixel_robot_gazebo this->memory[78]=100; this->memory[84]=52; this->memory[85]=3; + this->memory[116]=255; + this->memory[117]=7; } else if(model=="MX106v2") { @@ -335,25 +403,147 @@ namespace dynamixel_robot_gazebo this->memory[78]=100; this->memory[84]=52; this->memory[85]=3; + this->memory[116]=255; + this->memory[117]=7; } } } + void CDynServo::set_current_angle(double angle) + { + unsigned int value; + + value=((((angle*180.0)/3.14159)+(this->max_angle/2.0))*this->encoder_res)/this->max_angle; + if(model=="AX12W" || model=="AX12A" || model=="AX18A" || model=="MX12W" || model=="MX28v1" || model=="MX64v1" || model=="MX106v1") + { + this->memory[36]=value&0x000000FF; + this->memory[37]=(value>>8)&0x000000FF; + } + else + { + this->memory[132]=value&0x000000FF; + this->memory[133]=(value>>8)&0x000000FF; + this->memory[134]=(value>>16)&0x000000FF; + this->memory[135]=(value>>24)&0x000000FF; + } + } + + void CDynServo::set_current_speed(double speed) + { + unsigned int value; + + value=((speed*180.0)/3.14159)/6.0;//RPM + if(model=="AX12W" || model=="AX12A" || model=="AX18A") + { + value/=0.111; + this->memory[38]=value&0x000000FF; + this->memory[39]=(value>>8)&0x000000FF; + } + else if (model=="MX12W") + { + value/=0.916; + this->memory[38]=value&0x000000FF; + this->memory[39]=(value>>8)&0x000000FF; + } + else if(model=="MX28v1" || model=="MX64v1" || model=="MX106v1") + { + value/=0.114; + this->memory[38]=value&0x000000FF; + this->memory[39]=(value>>8)&0x000000FF; + } + else + { + value/=0.229; + this->memory[128]=value&0x000000FF; + this->memory[129]=(value>>8)&0x000000FF; + this->memory[130]=(value>>16)&0x000000FF; + this->memory[131]=(value>>24)&0x000000FF; + } + } + + void CDynServo::set_current_effort(double effort) + { + unsigned int value; + + if(effort<0.0) + value=((fabs(effort)*1023.0)/this->max_torque)+1024; + else + value=((fabs(effort)*1023.0)/this->max_torque); + if(model=="AX12W" || model=="AX12A" || model=="AX18A" || model=="MX12W" || model=="MX28v1" || model=="MX64v1" || model=="MX106v1") + { + this->memory[40]=value&0x000000FF; + this->memory[41]=(value>>8)&0x000000FF; + } + else + { + this->memory[124]=value&0x000000FF; + this->memory[125]=(value>>8)&0x000000FF; + } + } + + double CDynServo::get_target_angle(void) + { + unsigned int value=0; + double angle; + + if(model=="AX12W" || model=="AX12A" || model=="AX18A" || model=="MX12W" || model=="MX28v1" || model=="MX64v1" || model=="MX106v1") + value=this->memory[30]+(this->memory[31]<<8); + else + value=this->memory[116]+(this->memory[133]<<8)+(this->memory[134]<<16)+(this->memory[135]<<24); + angle=(((((value*this->max_angle)/this->encoder_res))-this->max_angle/2.0)*3.14159)/180.0; + + return angle; + } + + double CDynServo::get_target_speed(void) + { + unsigned int value=0; + double speed; + + if(model=="AX12W" || model=="AX12A" || model=="AX18A" || model=="MX12W" || model=="MX28v1" || model=="MX64v1" || model=="MX106v1") + { + this->memory[32]=value&0x000000FF; + this->memory[33]=(value>>8)&0x000000FF; + } + else + { + this->memory[104]=value&0x000000FF; + this->memory[105]=(value>>8)&0x000000FF; + this->memory[106]=(value>>16)&0x000000FF; + this->memory[107]=(value>>24)&0x000000FF; + } + if(model=="AX12W" || model=="AX12A" || model=="AX18A") + value*=0.111; + else if (model=="MX12W") + value*=0.916; + else if(model=="MX28v1" || model=="MX64v1" || model=="MX106v1") + value*=0.114; + else + value*=0.229; + speed=((value*6.0)*3.14159)/180.0; + + return speed; + } + void CDynServo::on_ping(void) { - std::cout << "Servo " << this->id << " pinged" << std::endl; + std::cout << "Servo " << (int)this->id << " pinged" << std::endl; } unsigned char CDynServo::on_read(unsigned short int address, unsigned short int length, unsigned char *data) { for(unsigned int i=0;i<length;i++) data[i]=this->memory[address+i]; + + return 0; } unsigned char CDynServo::on_write(unsigned short int address, unsigned short int length, unsigned char *data) { for(unsigned int i=0;i<length;i++) this->memory[address+i]=data[i]; + + return 0; } void CDynServo::update(const ros::Duration& period) @@ -361,9 +551,14 @@ namespace dynamixel_robot_gazebo double real_angle,target_angle,command; real_angle=this->joint.getPosition(); - target_angle=0.0;//((manager_servos[i+1].current_angle*3.14159)/180.0)/128.0; + this->set_current_angle(real_angle); + this->set_current_speed(this->joint.getVelocity()); + this->set_current_effort(this->joint.getEffort()); + target_angle=this->get_target_angle(); if(this->pid!=NULL) command=this->pid->computeCommand(target_angle-real_angle,period); + else if(this->compliance!=NULL) + command=this->compliance->control(target_angle-real_angle); this->joint.setCommand(command); }