diff --git a/include/arm_control.h b/include/arm_control.h index d4a7360e4e6ad18c80717dc1441e7c9f9ada887e..ac08784425122e20574dc9c205acf05adfcc6ede 100644 --- a/include/arm_control.h +++ b/include/arm_control.h @@ -1,7 +1,7 @@ #ifndef _ARM_CONTROL_H #define _ARM_CONTROL_H -#include "dynamixelserver_ftdi.h" +#include "dynamixelserver_serial.h" #include "dynamixel_motor.h" #include "threadserver.h" #include "eventserver.h" @@ -28,14 +28,24 @@ class CArmControl CEventServer *event_server; std::string finish_thread_event_id; std::vector<CDynamixelMotor *> motors; - CDynamixelServerFTDI *dyn_server; + unsigned char pan_id; + unsigned char tilt_id; + unsigned char roll_id; + CDynamixelServerSerial *dyn_server; CJoystick joy; std::vector<bool> current_button_state; double max_speed; + double max_accel; TJoints max_angles; TJoints min_angles; TJoints max_torques; TJoints target_torques; + TJoints target_angles; + TJoints target_stop_angles; + TJoints target_speeds; + TJoints target_accels; + TJoints target_dir; + bool target_run; std::vector<TJoints> stored_poses; std::string poses_file; CBNO055IMUDriver imu; @@ -43,6 +53,7 @@ class CArmControl TJoints imu_zero; protected: static void *position_monitor_thread(void *param); + void move_joints(void); public: CArmControl(const std::string &joy_device,const std::string &imu_device,std::string &dyn_serial, unsigned int baudrate,unsigned char pan_id, unsigned char tilt_id, unsigned char roll_id); bool get_button_state(unsigned int button_id); diff --git a/src/arm_control.cpp b/src/arm_control.cpp index 7d9552849e5dec94defe53f527708d1895b36c66..efa834ddc9cd3e2704a78d06be3123844cb2a1f3 100644 --- a/src/arm_control.cpp +++ b/src/arm_control.cpp @@ -1,5 +1,6 @@ #include "arm_control.h" #include "exceptions.h" +#include "eventexceptions.h" #include <iostream> #include <fstream> #include <unistd.h> @@ -17,6 +18,8 @@ #define IMU_MODE 23 #define IMU_CAL 21 +#define IMU_NUM_SAMPLES 5 + void button_callback(void *param,unsigned int button_id,bool level) { CArmControl *arm=(CArmControl *)param; @@ -24,58 +27,58 @@ void button_callback(void *param,unsigned int button_id,bool level) try{ switch(button_id) { - case 3: if(level) + case 9: if(level) arm->toggle_imu(); break; - case 4: if(level) - arm->increase_max_speed(); - break; + case 13: if(level) + arm->increase_max_speed(); + break; + case 14: if(level) + arm->decrease_max_speed(); + break; case 6: if(level) - arm->decrease_max_speed(); - break; - case 8: if(level) arm->enable_torque(false); else arm->enable_torque(true); break; - case 10: if(!level) - { - // button rear left 1 released -> keep position - arm->stop(); - } - break; - case 12: if(level) - { - if(arm->get_button_state(11)) - arm->update_pose(0);// update circle pose - else - arm->execute_pose(0);// execute circle pose - } - break; - case 13: if(level) - { - if(arm->get_button_state(11)) - arm->update_pose(1);// update circle pose - else - arm->execute_pose(1);// execute circle pose - } - break; - case 14: if(level) - { - if(arm->get_button_state(11)) - arm->update_pose(2);// update circle pose - else - arm->execute_pose(2);// execute circle pose - } - break; - case 15: if(level) - { - if(arm->get_button_state(11)) - arm->update_pose(3);// update circle pose - else - arm->execute_pose(3);// execute circle pose - } - break; + case 4: if(!level) + { + // button rear left 1 released -> keep position + arm->stop(); + } + break; + case 2: if(level) + { + if(arm->get_button_state(5)) + arm->update_pose(0);// update circle pose + else + arm->execute_pose(0);// execute circle pose + } + break; + case 1: if(level) + { + if(arm->get_button_state(5)) + arm->update_pose(1);// update circle pose + else + arm->execute_pose(1);// execute circle pose + } + break; + case 0: if(level) + { + if(arm->get_button_state(5)) + arm->update_pose(2);// update circle pose + else + arm->execute_pose(2);// execute circle pose + } + break; + case 3: if(level) + { + if(arm->get_button_state(5)) + arm->update_pose(3);// update circle pose + else + arm->execute_pose(3);// execute circle pose + } + break; } }catch(CException &e){ std::cout << e.what() << std::endl; @@ -89,13 +92,13 @@ void axis_callback(void *param,unsigned int axis_id, float value) try{ switch(axis_id) { - case 0: if(arm->get_button_state(10)) + case 0: if(arm->get_button_state(4)) arm->move(PAN,value); break; - case 1: if(arm->get_button_state(10)) + case 1: if(arm->get_button_state(4)) arm->move(TILT,value); break; - case 2: if(arm->get_button_state(10)) + case 3: if(arm->get_button_state(4)) arm->move(ROLL,value); break; } @@ -117,29 +120,43 @@ CArmControl::CArmControl(const std::string &joy_device,const std::string &imu_de digitalWrite(OK_LED,LOW); this->exit_flag=false; // detect and initialize servos - this->dyn_server=CDynamixelServerFTDI::instance(); - if(this->dyn_server->get_num_buses()>0) - { - this->dyn_server->config_bus(dyn_serial,baudrate); - sleep(1); - this->motors.resize(3); - name="arm_control_pan"; - this->motors[PAN] = new CDynamixelMotor(name,this->dyn_server,pan_id); - this->set_max_angles(PAN,90.0,-90.0); - this->set_max_torque(PAN,50.0); - name="arm_control_tilt"; - this->motors[TILT] = new CDynamixelMotor(name,this->dyn_server,tilt_id); - this->set_max_angles(TILT,90.0,-90.0); - this->set_max_torque(TILT,50.0); - name="arm_control_roll"; - this->motors[ROLL] = new CDynamixelMotor(name,this->dyn_server,roll_id); - this->set_max_angles(ROLL,90.0,-90.0); - this->set_max_torque(ROLL,50.0); - } - else - throw CException(_HERE_,"No Dynamixel buses available"); + this->dyn_server=CDynamixelServerSerial::instance(); + this->dyn_server->config_bus(dyn_serial,baudrate); + this->motors.resize(3); + name="arm_control_pan"; + this->motors[PAN] = new CDynamixelMotor(name,this->dyn_server,pan_id); + this->motors[PAN]->set_position_range(-150.0,150.0); + this->set_max_angles(PAN,90.0,-90.0); + this->set_max_torque(PAN,50.0); + this->pan_id=pan_id; + name="arm_control_tilt"; + this->motors[TILT] = new CDynamixelMotor(name,this->dyn_server,tilt_id); + this->motors[PAN]->set_position_range(-150.0,150.0); + this->set_max_angles(TILT,90.0,-90.0); + this->set_max_torque(TILT,50.0); + this->tilt_id=tilt_id; + name="arm_control_roll"; + this->motors[ROLL] = new CDynamixelMotor(name,this->dyn_server,roll_id); + this->motors[PAN]->set_position_range(-150.0,150.0); + this->set_max_angles(ROLL,90.0,-90.0); + this->set_max_torque(ROLL,50.0); + this->roll_id=roll_id; this->stored_poses.resize(4); this->max_speed=50.0; + this->max_accel=100.0; + this->target_angles.pan=this->motors[PAN]->get_current_angle(); + this->target_speeds.pan=this->max_speed; + this->target_accels.pan=this->max_accel; + this->target_dir.pan=1.0; + this->target_angles.tilt=this->motors[TILT]->get_current_angle(); + this->target_speeds.tilt=this->max_speed; + this->target_accels.tilt=this->max_accel; + this->target_dir.tilt=1.0; + this->target_angles.roll=this->motors[ROLL]->get_current_angle(); + this->target_speeds.roll=this->max_speed; + this->target_accels.roll=this->max_accel; + this->target_dir.roll=1.0; + this->target_run=false; this->enable_torque(true); // initialize IMU this->imu.open(imu_device); @@ -153,18 +170,18 @@ CArmControl::CArmControl(const std::string &joy_device,const std::string &imu_de for(unsigned int i=0;i<this->joy.get_num_buttons();i++) this->current_button_state[i]=this->joy.get_button_state(i); // assign callbacks - this->joy.enable_button_callback(3,button_callback,this); this->joy.enable_button_callback(4,button_callback,this); - this->joy.enable_button_callback(6,button_callback,this); - this->joy.enable_button_callback(8,button_callback,this); - this->joy.enable_button_callback(10,button_callback,this); - this->joy.enable_button_callback(12,button_callback,this); this->joy.enable_button_callback(13,button_callback,this); this->joy.enable_button_callback(14,button_callback,this); - this->joy.enable_button_callback(15,button_callback,this); + this->joy.enable_button_callback(6,button_callback,this); + this->joy.enable_button_callback(9,button_callback,this); + this->joy.enable_button_callback(0,button_callback,this); + this->joy.enable_button_callback(1,button_callback,this); + this->joy.enable_button_callback(2,button_callback,this); + this->joy.enable_button_callback(3,button_callback,this); this->joy.enable_position_change_callback(0,axis_callback,this); this->joy.enable_position_change_callback(1,axis_callback,this); - this->joy.enable_position_change_callback(2,axis_callback,this); + this->joy.enable_position_change_callback(3,axis_callback,this); // create threads and events this->thread_server=CThreadServer::instance(); this->position_monitor_thread_id="arm_control_position_monitor_thread"; @@ -183,9 +200,13 @@ void *CArmControl::position_monitor_thread(void *param) double current_pos,pan,tilt,roll; bool accel_cal,mag_cal,gyro_cal; CArmControl *arm=(CArmControl *)param; - std::vector<double> euler; + std::vector<double> euler[IMU_NUM_SAMPLES]; + unsigned int current_sample=0,count=0; + std::string name; - // initiate IMU calibration + for(unsigned int i=0;i<IMU_NUM_SAMPLES;i++) + euler[i].resize(3); + // initiate IMU calibration try{ arm->imu.load_calibration("/home/pi/bno055.cal"); arm->imu.set_operation_mode(ndof_mode); @@ -222,68 +243,270 @@ void *CArmControl::position_monitor_thread(void *param) else { try{ - if(arm->get_button_state(10)) + if(arm->get_button_state(4)) { arm->access.enter(); current_pos=arm->motors[PAN]->get_current_angle(); - if(current_pos>arm->max_angles.pan && arm->target_torques.pan>0.0) + if(current_pos>arm->max_angles.pan && arm->target_torques.pan<0.0) arm->motors[PAN]->move_absolute_angle(current_pos,50.0); - else if(current_pos<arm->min_angles.pan && arm->target_torques.pan<0.0) + else if(current_pos<arm->min_angles.pan && arm->target_torques.pan>0.0) arm->motors[PAN]->move_absolute_angle(current_pos,50.0); else - arm->motors[PAN]->move_torque(arm->target_torques.pan); + arm->motors[PAN]->move_torque(-arm->target_torques.pan); current_pos=arm->motors[TILT]->get_current_angle(); - if(current_pos>arm->max_angles.tilt && arm->target_torques.tilt>0.0) + if(current_pos>arm->max_angles.tilt && arm->target_torques.tilt<0.0) arm->motors[TILT]->move_absolute_angle(current_pos,50.0); - else if(current_pos<arm->min_angles.tilt && arm->target_torques.tilt<0.0) + else if(current_pos<arm->min_angles.tilt && arm->target_torques.tilt>0.0) arm->motors[TILT]->move_absolute_angle(current_pos,50.0); else - arm->motors[TILT]->move_torque(arm->target_torques.tilt); + arm->motors[TILT]->move_torque(-arm->target_torques.tilt); current_pos=arm->motors[ROLL]->get_current_angle(); - if(current_pos>arm->max_angles.roll && arm->target_torques.roll>0.0) - arm->motors[ROLL]->move_absolute_angle(current_pos,50.0); - else if(current_pos<arm->min_angles.roll && arm->target_torques.roll<0.0) + if(current_pos>arm->max_angles.roll && arm->target_torques.roll<0.0) + arm->motors[ROLL]->move_absolute_angle(current_pos,50.0); + else if(current_pos<arm->min_angles.roll && arm->target_torques.roll>0.0) arm->motors[ROLL]->move_absolute_angle(current_pos,50.0); else - arm->motors[ROLL]->move_torque(arm->target_torques.roll); + arm->motors[ROLL]->move_torque(-arm->target_torques.roll); arm->access.exit(); - } + } else if(arm->imu_enabled && imu_calibrated) { - arm->access.enter(); - euler=arm->imu.get_orientation_euler(); - pan=arm->imu_zero.pan-euler[0]; - tilt=-euler[2]; - roll=euler[1]; - if(pan>arm->max_angles.pan) - pan=arm->max_angles.pan; - else if(pan<arm->min_angles.pan) - pan=arm->min_angles.pan; - arm->motors[PAN]->move_absolute_angle(pan,arm->max_speed); - if(tilt>arm->max_angles.tilt) - tilt=arm->max_angles.tilt; - else if(tilt<arm->min_angles.tilt) - tilt=arm->min_angles.tilt; - arm->motors[TILT]->move_absolute_angle(tilt,arm->max_speed); - if(roll>arm->max_angles.roll) - roll=arm->max_angles.roll; - else if(roll<arm->min_angles.roll) - roll=arm->min_angles.roll; - arm->motors[ROLL]->move_absolute_angle(roll,arm->max_speed); - arm->access.exit(); + count++; + if(count==10) + { + count=0; + arm->access.enter(); + euler[current_sample]=arm->imu.get_orientation_euler(); + if(current_sample==(IMU_NUM_SAMPLES-1)) + current_sample=0; + else + current_sample++; + pan=0; + for(unsigned int i=0;i<IMU_NUM_SAMPLES;i++) + pan+=arm->imu_zero.pan-(euler[i])[0]; + pan/=IMU_NUM_SAMPLES; + if(pan>arm->max_angles.pan) + pan=arm->max_angles.pan; + else if(pan<arm->min_angles.pan) + pan=arm->min_angles.pan; + arm->motors[PAN]->move_absolute_angle(pan,arm->max_speed); + tilt=0; + for(unsigned int i=0;i<IMU_NUM_SAMPLES;i++) + tilt+=-euler[i][2]; + tilt/=IMU_NUM_SAMPLES; + if(tilt>arm->max_angles.tilt) + tilt=arm->max_angles.tilt; + else if(tilt<arm->min_angles.tilt) + tilt=arm->min_angles.tilt; + arm->motors[TILT]->move_absolute_angle(tilt,arm->max_speed); + roll=0; + for(unsigned int i=0;i<IMU_NUM_SAMPLES;i++) + roll+=euler[i][1]; + roll/=IMU_NUM_SAMPLES; + if(roll>arm->max_angles.roll) + roll=arm->max_angles.roll; + else if(roll<arm->min_angles.roll) + roll=arm->min_angles.roll; + arm->motors[ROLL]->move_absolute_angle(roll,arm->max_speed); + arm->access.exit(); + } } - if(arm->get_button_state(0)) - arm->exit_flag=true; + else + arm->move_joints(); }catch(CException &e){ + std::cout << e.what() << std::endl; arm->access.exit(); } + if(arm->get_button_state(8)) + arm->exit_flag=true; } - usleep(100000); + usleep(10000); } pthread_exit(NULL); } +void CArmControl::move_joints(void) +{ + static TJoints current_speeds={0.0}; + static TJoints current_angles={0.0}; + static bool first=true; + bool moving=false; + std::string name; + + if(this->target_run) + { + if(first) + { + first=false; + current_angles.pan=this->motors[PAN]->get_current_angle(); + current_angles.tilt=this->motors[TILT]->get_current_angle(); + current_angles.roll=this->motors[ROLL]->get_current_angle(); + } + if(abs(this->target_angles.pan-current_angles.pan)>=1.0) + { + moving=true; + if(current_speeds.pan!=(this->target_dir.pan*this->target_speeds.pan))// it is necessary to change the current speed + { + current_angles.pan+=current_speeds.pan*0.01/2.0; + if(current_speeds.pan>this->target_dir.pan*this->target_speeds.pan) + { + current_speeds.pan-=this->target_accels.pan*0.01;// reduce speed + if(current_speeds.pan<this->target_dir.pan*this->target_speeds.pan) + current_speeds.pan=this->target_dir.pan*this->target_speeds.pan; + } + else + { + current_speeds.pan+=this->target_accels.pan*0.01;// increase speed + if(current_speeds.pan>this->target_dir.pan*this->target_speeds.pan) + current_speeds.pan=this->target_dir.pan*this->target_speeds.pan; + } + current_angles.pan+=current_speeds.pan*0.01/2.0; + if(this->target_dir.pan==1.0 && current_angles.pan>this->target_angles.pan) + current_angles.pan=this->target_angles.pan; + if(this->target_dir.pan==-1.0 && current_angles.pan<this->target_angles.pan) + current_angles.pan=this->target_angles.pan; + } + else + { + if(abs(this->target_angles.pan-current_angles.pan)>this->target_stop_angles.pan)// constant speed phase + { + current_angles.pan+=current_speeds.pan*0.01; + if(this->target_dir.pan==1.0 && current_angles.pan>this->target_angles.pan) + current_angles.pan=this->target_angles.pan; + if(this->target_dir.pan==-1.0 && current_angles.pan<this->target_angles.pan) + current_angles.pan=this->target_angles.pan; + } + else// deceleration phase + { + current_angles.pan=current_angles.pan+current_speeds.pan*0.01/2.0; + this->target_speeds.pan=this->target_speeds.pan-this->target_accels.pan*0.01; + if(this->target_speeds.pan<0) + this->target_speeds.pan=0; + current_speeds.pan=this->target_dir.pan*this->target_speeds.pan; + current_angles.pan=current_angles.pan+current_speeds.pan*0.01/2.0; + if(this->target_dir.pan==1.0 && current_angles.pan>this->target_angles.pan) + current_angles.pan=this->target_angles.pan; + if(this->target_dir.pan==-1.0 && current_angles.pan<this->target_angles.pan) + current_angles.pan=this->target_angles.pan; + } + } + } + else + current_speeds.pan=0; + if(abs(this->target_angles.tilt-current_angles.tilt)>=1.0) + { + moving=true; + if(current_speeds.tilt!=(this->target_dir.tilt*this->target_speeds.tilt))// it is necessary to change the current speed + { + current_angles.tilt+=current_speeds.tilt*0.01/2.0; + if(current_speeds.tilt>this->target_dir.tilt*this->target_speeds.tilt) + { + current_speeds.tilt-=this->target_accels.tilt*0.01;// reduce speed + if(current_speeds.tilt<this->target_dir.tilt*this->target_speeds.tilt) + current_speeds.tilt=this->target_dir.tilt*this->target_speeds.tilt; + } + else + { + current_speeds.tilt+=this->target_accels.tilt*0.01;// increase speed + if(current_speeds.tilt>this->target_dir.tilt*this->target_speeds.tilt) + current_speeds.tilt=this->target_dir.tilt*this->target_speeds.tilt; + } + current_angles.tilt+=current_speeds.tilt*0.01/2.0; + if(this->target_dir.tilt==1.0 && current_angles.tilt>this->target_angles.tilt) + current_angles.tilt=this->target_angles.tilt; + if(this->target_dir.tilt==-1.0 && current_angles.tilt<this->target_angles.tilt) + current_angles.tilt=this->target_angles.tilt; + } + else + { + if(abs(this->target_angles.tilt-current_angles.tilt)>this->target_stop_angles.tilt)// constant speed phase + { + current_angles.tilt+=current_speeds.tilt*0.01; + if(this->target_dir.tilt==1.0 && current_angles.tilt>this->target_angles.tilt) + current_angles.tilt=this->target_angles.tilt; + if(this->target_dir.tilt==-1.0 && current_angles.tilt<this->target_angles.tilt) + current_angles.tilt=this->target_angles.tilt; + } + else// deceleration phase + { + current_angles.tilt=current_angles.tilt+current_speeds.tilt*0.01/2.0; + this->target_speeds.tilt=this->target_speeds.tilt-this->target_accels.tilt*0.01; + if(this->target_speeds.tilt<0) + this->target_speeds.tilt=0; + current_speeds.tilt=this->target_dir.tilt*this->target_speeds.tilt; + current_angles.tilt=current_angles.tilt+current_speeds.tilt*0.01/2.0; + if(this->target_dir.tilt==1.0 && current_angles.tilt>this->target_angles.tilt) + current_angles.tilt=this->target_angles.tilt; + if(this->target_dir.tilt==-1.0 && current_angles.tilt<this->target_angles.tilt) + current_angles.tilt=this->target_angles.tilt; + } + } + } + else + current_speeds.tilt=0; + if(abs(this->target_angles.roll-current_angles.roll)>=1.0) + { + moving=true; + if(current_speeds.roll!=(this->target_dir.roll*this->target_speeds.roll))// it is necessary to change the current speed + { + current_angles.roll+=current_speeds.roll*0.01/2.0; + if(current_speeds.roll>this->target_dir.roll*this->target_speeds.roll) + { + current_speeds.roll-=this->target_accels.roll*0.01;// reduce speed + if(current_speeds.roll<this->target_dir.roll*this->target_speeds.roll) + current_speeds.roll=this->target_dir.roll*this->target_speeds.roll; + } + else + { + current_speeds.roll+=this->target_accels.roll*0.01;// increase speed + if(current_speeds.roll>this->target_dir.roll*this->target_speeds.roll) + current_speeds.roll=this->target_dir.roll*this->target_speeds.roll; + } + current_angles.roll+=current_speeds.roll*0.01/2.0; + if(this->target_dir.roll==1.0 && current_angles.roll>this->target_angles.roll) + current_angles.roll=this->target_angles.roll; + if(this->target_dir.roll==-1.0 && current_angles.roll<this->target_angles.roll) + current_angles.roll=this->target_angles.roll; + } + else + { + if(abs(this->target_angles.roll-current_angles.roll)>this->target_stop_angles.roll)// constant speed phase + { + current_angles.roll+=current_speeds.roll*0.01; + if(this->target_dir.roll==1.0 && current_angles.roll>this->target_angles.roll) + current_angles.roll=this->target_angles.roll; + if(this->target_dir.roll==-1.0 && current_angles.roll<this->target_angles.roll) + current_angles.roll=this->target_angles.roll; + } + else// deceleration phase + { + current_angles.roll=current_angles.roll+current_speeds.roll*0.01/2.0; + this->target_speeds.roll=this->target_speeds.roll-this->target_accels.roll*0.01; + if(this->target_speeds.roll<0) + this->target_speeds.roll=0; + current_speeds.roll=this->target_dir.roll*this->target_speeds.roll; + current_angles.roll=current_angles.roll+current_speeds.roll*0.01/2.0; + if(this->target_dir.roll==1.0 && current_angles.roll>this->target_angles.roll) + current_angles.roll=this->target_angles.roll; + if(this->target_dir.roll==-1.0 && current_angles.roll<this->target_angles.roll) + current_angles.roll=this->target_angles.roll; + } + } + } + else + current_speeds.roll=0; + if(!moving) + { + this->target_run=false; + first=true; + } + this->motors[PAN]->move_absolute_angle(current_angles.pan,0); + this->motors[TILT]->move_absolute_angle(current_angles.tilt,0); + this->motors[ROLL]->move_absolute_angle(current_angles.roll,0); + } +} + bool CArmControl::get_button_state(unsigned int button_id) { if(button_id>this->current_button_state.size()) @@ -301,42 +524,18 @@ void CArmControl::set_max_angles(unsigned int axis_id, double max, double min) { if(axis_id==PAN) { - try{ - this->max_angles.pan=max; - this->min_angles.pan=min; - this->access.enter(); - this->motors[PAN]->set_position_range(min,max); - this->access.exit(); - }catch(CException &e){ - this->access.exit(); - throw e; - } + this->max_angles.pan=max; + this->min_angles.pan=min; } else if(axis_id==TILT) { - try{ - this->max_angles.tilt=max; - this->min_angles.tilt=min; - this->access.enter(); - this->motors[TILT]->set_position_range(min,max); - this->access.exit(); - }catch(CException &e){ - this->access.exit(); - throw e; - } + this->max_angles.tilt=max; + this->min_angles.tilt=min; } else if(axis_id==ROLL) { - try{ - this->max_angles.roll=max; - this->min_angles.roll=min; - this->access.enter(); - this->motors[ROLL]->set_position_range(min,max); - this->access.exit(); - }catch(CException &e){ - this->access.exit(); - throw e; - } + this->max_angles.roll=max; + this->min_angles.roll=min; } else throw CException(_HERE_,"Invalid axis ID"); @@ -480,8 +679,8 @@ void CArmControl::stop(void) void CArmControl::increase_max_speed(void) { this->max_speed+=10.0; - if(this->max_speed>100.0) - this->max_speed=100.0; + if(this->max_speed>300.0) + this->max_speed=300.0; } void CArmControl::decrease_max_speed(void) @@ -600,8 +799,8 @@ void CArmControl::update_pose(unsigned int pose_id) void CArmControl::execute_pose(unsigned int pose_id) { - double diff_pan, diff_tilt, diff_roll; - double vel_pan, vel_tilt, vel_roll; + double diff_pan,diff_tilt,diff_roll; + double current_pan,current_tilt,current_roll; if(pose_id>3) throw CException(_HERE_,"Invalid pose ID"); @@ -609,42 +808,122 @@ void CArmControl::execute_pose(unsigned int pose_id) { try{ this->access.enter(); - diff_pan=fabs(this->motors[PAN]->get_current_angle()-this->stored_poses[pose_id].pan); - diff_tilt=fabs(this->motors[TILT]->get_current_angle()-this->stored_poses[pose_id].tilt); - diff_roll=fabs(this->motors[ROLL]->get_current_angle()-this->stored_poses[pose_id].roll); + current_pan=this->motors[PAN]->get_current_angle(); + if(this->stored_poses[pose_id].pan>this->max_angles.pan) + this->target_angles.pan=this->max_angles.pan; + else if(this->stored_poses[pose_id].pan<this->min_angles.pan) + this->target_angles.pan=this->min_angles.pan; + else + this->target_angles.pan=this->stored_poses[pose_id].pan; + diff_pan=fabs(current_pan-this->stored_poses[pose_id].pan); + current_tilt=this->motors[TILT]->get_current_angle(); + if(this->stored_poses[pose_id].tilt>this->max_angles.tilt) + this->target_angles.tilt=this->max_angles.tilt; + else if(this->stored_poses[pose_id].tilt<this->min_angles.tilt) + this->target_angles.tilt=this->min_angles.tilt; + else + this->target_angles.tilt=this->stored_poses[pose_id].tilt; + diff_tilt=fabs(current_tilt-this->stored_poses[pose_id].tilt); + current_roll=this->motors[ROLL]->get_current_angle(); + if(this->stored_poses[pose_id].roll>this->max_angles.roll) + this->target_angles.roll=this->max_angles.roll; + else if(this->stored_poses[pose_id].roll<this->min_angles.roll) + this->target_angles.roll=this->min_angles.roll; + else + this->target_angles.roll=this->stored_poses[pose_id].roll; + diff_roll=fabs(current_roll-this->stored_poses[pose_id].roll); if(diff_pan>diff_tilt) { if(diff_pan>diff_roll) { - vel_pan=this->max_speed; - vel_tilt=(diff_tilt/diff_pan)*this->max_speed; - vel_roll=(diff_roll/diff_pan)*this->max_speed; + this->target_speeds.pan=this->max_speed; + this->target_speeds.tilt=(diff_tilt/diff_pan)*this->max_speed; + this->target_speeds.roll=(diff_roll/diff_pan)*this->max_speed; } else { - vel_tilt=this->max_speed; - vel_pan=(diff_pan/diff_tilt)*this->max_speed; - vel_roll=(diff_roll/diff_tilt)*this->max_speed; + if(diff_tilt>diff_roll) + { + this->target_speeds.tilt=this->max_speed; + this->target_speeds.pan=(diff_pan/diff_tilt)*this->max_speed; + this->target_speeds.roll=(diff_roll/diff_tilt)*this->max_speed; + } + else + { + this->target_speeds.roll=this->max_speed; + this->target_speeds.pan=(diff_pan/diff_roll)*this->max_speed; + this->target_speeds.tilt=(diff_tilt/diff_roll)*this->max_speed; + } } } else { if(diff_tilt>diff_roll) { - vel_tilt=this->max_speed; - vel_pan=(diff_pan/diff_tilt)*this->max_speed; - vel_roll=(diff_roll/diff_tilt)*this->max_speed; + this->target_speeds.tilt=this->max_speed; + this->target_speeds.pan=(diff_pan/diff_tilt)*this->max_speed; + this->target_speeds.roll=(diff_roll/diff_tilt)*this->max_speed; } else { - vel_roll=this->max_speed; - vel_pan=(diff_pan/diff_roll)*this->max_speed; - vel_tilt=(diff_tilt/diff_roll)*this->max_speed; + if(diff_roll>diff_pan) + { + this->target_speeds.roll=this->max_speed; + this->target_speeds.pan=(diff_pan/diff_roll)*this->max_speed; + this->target_speeds.tilt=(diff_tilt/diff_roll)*this->max_speed; + } + else + { + this->target_speeds.pan=this->max_speed; + this->target_speeds.tilt=(diff_tilt/diff_pan)*this->max_speed; + this->target_speeds.roll=(diff_roll/diff_pan)*this->max_speed; + } } } - this->motors[PAN]->move_absolute_angle(this->stored_poses[pose_id].pan,vel_pan); - this->motors[TILT]->move_absolute_angle(this->stored_poses[pose_id].tilt,vel_tilt); - this->motors[ROLL]->move_absolute_angle(this->stored_poses[pose_id].roll,vel_roll); + // check the parameters + if(diff_pan>=1.0) + { + if((this->target_speeds.pan*this->target_speeds.pan)/this->max_accel>diff_pan) + this->target_accels.pan=(this->target_speeds.pan*this->target_speeds.pan)/diff_pan; + else + this->target_accels.pan=this->max_accel; + } + // stop angles + this->target_stop_angles.pan=this->target_speeds.pan*this->target_speeds.pan/(2.0*this->target_accels.pan); + // the current angles, speeds and accelerations are in RAM + if(this->target_angles.pan>=current_pan) + this->target_dir.pan=1.0; + else + this->target_dir.pan=-1.0; + if(diff_tilt>=1.0) + { + if((this->target_speeds.tilt*this->target_speeds.tilt)/this->max_accel>diff_tilt) + this->target_accels.tilt=(this->target_speeds.tilt*this->target_speeds.tilt)/diff_tilt; + else + this->target_accels.tilt=this->max_accel; + } + // stop angles + this->target_stop_angles.tilt=this->target_speeds.tilt*this->target_speeds.tilt/(2.0*this->target_accels.tilt); + // the current angles, speeds and accelerations are in RAM + if(this->target_angles.tilt>=current_tilt) + this->target_dir.tilt=1.0; + else + this->target_dir.tilt=-1.0; + if(diff_roll>=1.0) + { + if((this->target_speeds.roll*this->target_speeds.roll)/this->max_accel>diff_roll) + this->target_accels.roll=(this->target_speeds.roll*this->target_speeds.roll)/diff_roll; + else + this->target_accels.roll=this->max_accel; + } + // stop angles + this->target_stop_angles.roll=this->target_speeds.roll*this->target_speeds.roll/(2.0*this->target_accels.roll); + // the current angles, speeds and accelerations are in RAM + if(this->target_angles.roll>=current_roll) + this->target_dir.roll=1.0; + else + this->target_dir.roll=-1.0; + this->target_run=true; this->access.exit(); }catch(CException &e){ this->access.exit(); diff --git a/src/examples/arm_control_test.cpp b/src/examples/arm_control_test.cpp index 35538f97ca18ffa687c8b5d3cb1e604e9b9d8ebf..b496c5f2b4549b2ec786e410296a9426c225329b 100644 --- a/src/examples/arm_control_test.cpp +++ b/src/examples/arm_control_test.cpp @@ -2,14 +2,14 @@ #include "exceptions.h" #include <iostream> -std::string dyn_serial="FT2FWOYO"; +std::string dyn_device="/dev/ttyUSB0"; std::string joy_device="/dev/input/js0"; std::string imu_device="/dev/ttyAMA0"; int main(int argc, char *argv[]) { try{ - CArmControl arm(joy_device,imu_device,dyn_serial,1000000,6,5,4); + CArmControl arm(joy_device,imu_device,dyn_device,1000000,6,5,4); arm.load_poses("/home/pi/code/arm_control/src/xml/poses.xml"); arm.set_max_angles(PAN,90.0,-90.0); diff --git a/src/xml/poses.xml b/src/xml/poses.xml index 912bddcc0527c2d96319eb25fca3386a51316b79..d122a2b2e26b55089b646bba5955a5d0a01fb07e 100644 --- a/src/xml/poses.xml +++ b/src/xml/poses.xml @@ -2,26 +2,26 @@ <arm_motions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="arm_motions_cfg.xsd"> <arm_motion> <button_name>triangle</button_name> - <pan>2.49267</pan> - <tilt>1.6129</tilt> - <roll>-64.6628</roll> + <pan>90.176</pan> + <tilt>2.78592</tilt> + <roll>-3.37243</roll> </arm_motion> <arm_motion> <button_name>circle</button_name> - <pan>-6.59824</pan> - <tilt>-3.07918</tilt> + <pan>-98.9736</pan> + <tilt>-8.06452</tilt> <roll>-2.49267</roll> </arm_motion> <arm_motion> <button_name>cross</button_name> - <pan>-82.5513</pan> - <tilt>-7.77126</tilt> - <roll>28.2991</roll> + <pan>-3.37243</pan> + <tilt>-4.2522</tilt> + <roll>-92.8152</roll> </arm_motion> <arm_motion> <button_name>square</button_name> - <pan>-42.9619</pan> - <tilt>38.563</tilt> - <roll>-58.2111</roll> + <pan>-4.54545</pan> + <tilt>41.4956</tilt> + <roll>-90.7625</roll> </arm_motion> </arm_motions>