Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ArmMC.cc

Go to the documentation of this file.
00001 #include "ArmMC.h"
00002 #include "Kinematics.h"
00003 #include "IKSolver.h"
00004 #include "Shared/debuget.h"
00005 #include "Shared/WorldState.h"
00006 #include "MotionManager.h"
00007 #include "Shared/Config.h"
00008 #include "Wireless/Socket.h"
00009 #include "Shared/get_time.h"
00010 #include "Events/EventBase.h"
00011 
00012 #include <memory>
00013 #include <cmath>
00014 using namespace std;
00015 
00016 ArmMC::ArmMC()
00017   : MotionCommand(), dirty(true), hold(true), tolerance(.05f),
00018     completionReported(true), targetTimestamp(0), timeout(2000),
00019     pulseOnPeriod(0), pulseOffPeriod(0), pulseStartTime(0), 
00020     desiredLoad(0), angleIncrement(0.05), idleCycles(8)
00021 {
00022   // Initialize armTargets[] by calling takeSnapShot() so we
00023   // don't have astronomical garbage values in there, which
00024   // could cause the motion command to fail to complete even if
00025   // the joint weights are zero.
00026   takeSnapshot();
00027   setWeight(0);
00028   defaultMaxSpeed();
00029 }
00030 
00031 void ArmMC::freezeMotion() {
00032 #ifdef TGT_HAS_ARMS
00033   for(unsigned int i=0; i<NumArmJoints; i++)
00034     armTargets[i]=armCmds[i].value;
00035   dirty=false;
00036 #endif
00037 }
00038 
00039 void ArmMC::takeSnapshot() {
00040 #ifdef TGT_HAS_ARMS
00041   for(unsigned int i=0; i<NumArmJoints; i++)
00042     armTargets[i]=armCmds[i].value=state->outputs[ArmOffset+i];
00043   dirty=true;
00044 #endif
00045 }
00046 
00047 float ArmMC::armJointValue(unsigned int i)  {
00048 #ifdef TGT_HAS_ARMS
00049   return armTargets[i];
00050 #else
00051   serr->printf("WARNING: No Arm");
00052   return -1000.0f;
00053 #endif
00054 }
00055 
00056 void ArmMC::defaultMaxSpeed(float x) {
00057 #ifdef TGT_HAS_ARMS
00058   for(unsigned int i = 0; i<NumArmJoints; i++)
00059     maxSpeed[i] = 0.3f; // **hack** hard coded for now
00060 #endif
00061 }
00062 
00063 void ArmMC::setWeight(float w) {
00064 #ifdef TGT_HAS_ARMS
00065   for(unsigned int i=0; i<NumArmJoints; i++)
00066     armCmds[i].weight=w;
00067   setDirty();
00068 #endif
00069 }
00070 
00071 void ArmMC::setWeight(int i, float w) {
00072 #ifdef TGT_HAS_ARMS
00073   armCmds[i].weight=w;
00074   setDirty();
00075 #endif
00076 }
00077 
00078 void ArmMC::setJoints(float shoulder, float elbow, float wrist){   
00079 #ifdef TGT_HAS_ARMS
00080   setMaxSpeed(0, 0.4f);    
00081   setMaxSpeed(1, 0.4f);    
00082   setMaxSpeed(2, 0.4f);    
00083   setJointValue(0, shoulder);    
00084   setJointValue(1, elbow);   
00085   setJointValue(2, wrist);   
00086 #endif   
00087 }    
00088        
00089 void ArmMC::setJoints(float shoulder, float elbow, float yaw, float pitch, float roll, float gripper) {    
00090 #ifdef TGT_HAS_ARMS 
00091   setMaxSpeed(0, 0.4f);    
00092   setMaxSpeed(1, 0.4f);    
00093   setMaxSpeed(2, 0.4f);    
00094   setMaxSpeed(3, 0.4f);    
00095   setMaxSpeed(4, 0.4f);    
00096   setMaxSpeed(5, 0.4f);    
00097   setJointValue(0, shoulder);    
00098   setJointValue(1, elbow);   
00099   setJointValue(2, yaw);   
00100   setJointValue(3, pitch);   
00101   setJointValue(4, roll);    
00102   setJointValue(5, gripper);   
00103 #endif   
00104 }    
00105 
00106 void ArmMC::setWrist(float pitch, float roll, float gripper) {
00107 #ifdef TGT_HAS_ARMS
00108   setMaxSpeed(3, 0.4f);    
00109   setMaxSpeed(4, 0.4f);    
00110   setMaxSpeed(5, 0.4f);  
00111   setJointValue(3, pitch);   
00112   setJointValue(4, roll);    
00113   setJointValue(5, gripper);
00114 #endif
00115 }
00116 
00117 void ArmMC::setGripperSpeed(float x) {
00118 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00119   setMaxSpeed(GripperOffset-ArmOffset, x);
00120 //Ensures the parameter angleIncrement is set
00121   setGraspSpeed(x/10.0);
00122 #elif defined(TGT_IS_CALLIOPE5)
00123   setMaxSpeed(LeftFingerOffset-ArmOffset, x);
00124   setMaxSpeed(RightFingerOffset-ArmOffset, x);
00125 #else
00126   std::cerr << "ArmMC::setGripperSpeed doesn't know about this robot type." << std::endl;
00127 #endif
00128 }
00129 
00130 void ArmMC::setGripperPulse(unsigned int onPeriod, unsigned int offPeriod) {
00131   pulseOnPeriod = onPeriod;
00132   pulseOffPeriod = offPeriod;
00133   pulseStartTime = get_time();
00134   setDirty();
00135 }
00136 
00137 //--------------------New code----------------------
00138 void ArmMC::requestGripperLoad(int newLoad = -280){
00139 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00140   desiredLoad = newLoad;
00141   setDirty();
00142 #else
00143   cout << "Method \"requestGripperLoad\" is only applicable for CALLIOPE robots" << endl;
00144 #endif
00145 }
00146 
00147 int ArmMC::getGripperLoad(){
00148 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00149   return int(state->pidduties[GripperOffset]*1023);
00150 #else
00151   cout << "Method \"requestGripperLoad\" is only applicable for CALLIOPE robots" << endl;
00152   return 0;
00153 #endif
00154 }
00155 
00156 void ArmMC::setGraspSpeed( float speed){
00157 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00158   angleIncrement = speed;
00159 #else
00160   cout << "Method \"setGraspSpeed\" is only applicable for CALLIOPE robots" << endl;
00161 #endif
00162 }
00163 
00164 void ArmMC::setGraspWait(unsigned int cycles){
00165 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00166   idleCycles = cycles;
00167 #else
00168   cout << "Method \"setGraspWait\" is only applicable for CALLIOPE robots" << endl;
00169 #endif
00170 }
00171 
00172 void ArmMC::incrementGrasp(){
00173 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00174   //This is a protected helper method to close the gripper when desiredLoad != 0
00175   //It will only be executed if the robot is a Calliope-type machine
00176   static float progressiveIncrement = 0.0;
00177   static int previousLoad = 0;
00178   static unsigned int idlePeriods = 0;
00179   
00180   int currentLoad = getGripperLoad();
00181   
00182   if(currentLoad < desiredLoad){  //This means our grasp is sufficiently tight, and we don't need to close any more
00183     return;
00184   }
00185   else{
00186     //Otherwise, get the current angle of the gripper, and increment it
00187     float currentGripperAngle = state->outputs[GripperOffset];
00188     
00189     if(state->sensors[GPSXOffset] != 0.0 && currentGripperAngle <= 0.45){
00190       //If we're in mirage, and we've closed the gripper to a certain extent, exit
00191       // the method to avoid making the object glitching out
00192       return;
00193     }
00194     else if(currentGripperAngle <= 0.15){
00195       //If we've managed to close the gripper (almost) completely, we should exit
00196       return;
00197     }
00198     
00199     //This if block ensures that the gripper will get to its desired load
00200     if(previousLoad == currentLoad && currentLoad != 0){
00201         if(idlePeriods == idleCycles){
00202           progressiveIncrement += angleIncrement;
00203           idlePeriods = 0;
00204         }
00205         else { 
00206           idlePeriods++; 
00207         }
00208     } else {
00209       previousLoad = currentLoad;
00210       progressiveIncrement = 0;
00211       idlePeriods = 0;
00212     }
00213     
00214     setJointValue(GripperOffset-ArmOffset, currentGripperAngle - angleIncrement - progressiveIncrement);
00215   }
00216 #endif
00217 }
00218 //--------------------------------------------------
00219 
00220 void ArmMC::clearGripperPulse() {
00221   pulseOnPeriod = pulseOffPeriod = 0;
00222 #if defined(TGT_HAS_FINGERS)
00223   motman->setOutput(this, LeftFingerOffset, OutputPID(DefaultPIDs[LeftFingerOffset-PIDJointOffset],1));
00224   motman->setOutput(this, RightFingerOffset, OutputPID(DefaultPIDs[RightFingerOffset-PIDJointOffset],1));
00225 #elif defined(TGT_IS_MANTIS)
00226   ;
00227 #elif defined(TGT_HAS_GRIPPER)
00228   motman->setOutput(this, GripperOffset, OutputPID(DefaultPIDs[GripperOffset-PIDJointOffset],1));
00229 #endif
00230 }
00231 
00232 bool ArmMC::moveOffsetToPoint(const fmat::Column<3>& offset, const fmat::Column<3>& tgt) {
00233 #ifndef TGT_HAS_ARMS
00234   return false;
00235 #else
00236   const KinematicJoint * kinEff=NULL;
00237   unsigned int effIdx = capabilities.findFrameOffset("GripperFrame");
00238   if(effIdx!=-1U) // does it have the "pure" reference frame?
00239     kinEff = kine->getKinematicJoint(effIdx); // yes, try that
00240   if(kinEff==NULL) // if nothing has worked yet, try the last joint
00241     kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00242   if(kinEff==NULL) // if that didn't work, give up
00243     return false;
00244   KinematicJoint * effector = kinEff->cloneBranch(); // make a local copy so we can do thread-safe IK
00245   
00246   // do the IK
00247   bool conv = effector->getIK().solve(offset,*effector,IKSolver::Point(tgt));
00248   
00249   // copy results to member storage
00250   while(effector!=NULL) {
00251     if(effector->outputOffset<NumOutputs)
00252       setOutputCmd(effector->outputOffset, effector->getQ());
00253     effector = effector->getParent();
00254   }
00255   return conv;
00256 #endif  
00257 }
00258 
00259 bool ArmMC::moveOffsetToPointWithOrientation(const fmat::Column<3>& offset, const fmat::Column<3>& tgt, const fmat::Quaternion& ori) {
00260 #ifndef TGT_HAS_ARMS
00261   return false;
00262 #else
00263   const KinematicJoint * kinEff=NULL;
00264   unsigned int effIdx = capabilities.findFrameOffset("GripperFrame");
00265   if(effIdx!=-1U) // does it have the "pure" reference frame?
00266     kinEff = kine->getKinematicJoint(effIdx); // yes, try that
00267   if(kinEff==NULL) // if nothing has worked yet, try the last joint
00268     kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00269   if(kinEff==NULL) // if that didn't work, give up
00270     return false;
00271   KinematicJoint * effector = kinEff->cloneBranch(); // make a local copy so we can do thread-safe IK
00272   
00273   // do the IK
00274   bool conv = effector->getIK().solve(offset, IKSolver::Rotation(fmat::Quaternion()), *effector, IKSolver::Point(tgt), 1, IKSolver::Rotation(ori), 0);
00275   
00276   // copy results to member storage
00277   while(effector!=NULL) {
00278     if(effector->outputOffset<NumOutputs)
00279       setOutputCmd(effector->outputOffset, effector->getQ());
00280     effector = effector->getParent();
00281   }
00282   return conv;
00283 #endif  
00284 }
00285 
00286 bool ArmMC::setFingerGap(float dist) {
00287 #ifdef TGT_CALLIOPE5KP
00288     PostureEngine mypos;
00289     mypos.setOutputCmd(LeftFingerOffset, 0);
00290     mypos.setOutputCmd(RightFingerOffset, 0);
00291     fmat::Column<3> lf = mypos.getPosition(LeftFingerOffset);
00292     fmat::Column<3> rf = mypos.getPosition(RightFingerOffset);
00293     float c = (lf-rf).norm();
00294     fmat::Transform trans = mypos.linkToLink(LeftFingerFrameOffset, LeftFingerOffset);
00295     AngSignPi alpha = asin(trans(0,0));
00296     float r = sqrt ( trans(0,3)*trans(0,3) + trans(1,3)*trans(1,3) );
00297     if ( dist < 0 || dist > 2*r+c ) // assumes fingers can open full 180 degrees
00298       return false;
00299     AngSignPi q = asin((dist/2-c/2)/r) - alpha;
00300     setJointValue(LeftFingerOffset, -q);
00301     setJointValue(RightFingerOffset, q);
00302 #endif
00303     return true;
00304 }
00305 
00306 bool ArmMC::openGripper(float percentage) {
00307 #if defined(TGT_IS_CALLIOPE2) || defined(TGT_IS_CALLIOPE3)
00308   float gripperAngle = outputRanges[GripperOffset][MinRange] +
00309     percentage * (outputRanges[GripperOffset][MaxRange] - outputRanges[GripperOffset][MinRange]);
00310   setJointValue(GripperOffset-ArmOffset, gripperAngle);
00311   //Once this method is called, desiredLoad is set to zero so that the updateOutputs method won't keep closing the gripper
00312   requestGripperLoad(0);
00313 #elif defined(TGT_IS_CALLIOPE5)
00314   float gripperAngleL = outputRanges[LeftFingerOffset][MaxRange] +
00315     percentage * (outputRanges[LeftFingerOffset][MinRange] - outputRanges[LeftFingerOffset][MaxRange]);
00316   float gripperAngleR = outputRanges[RightFingerOffset][MinRange] +
00317     percentage * (outputRanges[RightFingerOffset][MaxRange] - outputRanges[RightFingerOffset][MinRange]);
00318   setJointValue(LeftFingerOffset-ArmOffset, gripperAngleL);
00319   setJointValue(RightFingerOffset-ArmOffset, gripperAngleR);
00320 #endif
00321   return true;
00322 }
00323 
00324 int ArmMC::updateOutputs() {
00325   int prevDirty = isDirty();
00326   if (prevDirty || hold) {  // we have joints to command
00327     dirty = false;
00328 #ifdef TGT_HAS_ARMS
00329     for(unsigned int i=0; i < NumArmJoints; i++) {
00330       if(maxSpeed[i]<=0) {
00331         armCmds[i].value=armTargets[i];
00332         motman->setOutput(this,i+ArmOffset,armCmds[i]);
00333       } else { // we may be trying to exceeded maxSpeed
00334         unsigned int f=0;
00335         while(armTargets[i]>armCmds[i].value+maxSpeed[i] && f<NumFrames) {
00336           armCmds[i].value+=maxSpeed[i];
00337           motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00338           f++;
00339         }
00340         while(armTargets[i]<armCmds[i].value-maxSpeed[i] && f<NumFrames) {
00341           armCmds[i].value-=maxSpeed[i];
00342           motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00343           f++;
00344         }
00345         if(f<NumFrames) { //we reached target value, fill in rest of frames
00346           armCmds[i].value=armTargets[i];
00347           for(;f<NumFrames;f++)
00348             motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00349         } else // we didn't reach target value, still dirty
00350           dirty=true;
00351       }
00352     }
00353   #if defined(TGT_IS_CALLIOPE2)
00354     if(desiredLoad != 0) incrementGrasp();
00355   #endif
00356 #endif
00357     if(!dirty && !completionReported) {
00358       postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID));
00359       completionReported=true;
00360       targetTimestamp=get_time();
00361     }
00362   }
00363 
00364 //------------------------------------------------------From here
00365 #if false
00366   // pulse gripper if requested
00367   if ( pulseOnPeriod > 0 ) {
00368     dirty = true;
00369     unsigned int t = get_time();
00370     if ( t >= pulseStartTime + pulseOnPeriod + pulseOffPeriod ) { // time to start a new cycle
00371       pulseStartTime = t;
00372     }
00373     // turn power on or off depending on where we are in the cycle
00374 #if defined(TGT_HAS_FINGERS) || defined(TGT_HAS_GRIPPER)
00375     if (t >= pulseStartTime + pulseOnPeriod) {
00376       // we're in the "off" part of the cycle
00377 #ifdef TGT_HAS_FINGERS
00378       motman->setOutput(this, LeftFingerOffset,  OutputPID(0,0,0,1));
00379       motman->setOutput(this, RightFingerOffset, OutputPID(0,0,0,1));
00380 #else
00381       motman->setOutput(this, GripperOffset, OutputPID(0,0,0,1));
00382 #endif
00383     } else {  // we're in the "on" part of the cycle
00384 #ifdef TGT_HAS_FINGERS
00385       motman->setOutput(this, LeftFingerOffset, OutputPID(DefaultPIDs[LeftFingerOffset-PIDJointOffset],1));
00386       motman->setOutput(this, RightFingerOffset, OutputPID(DefaultPIDs[RightFingerOffset-PIDJointOffset],1));
00387 #else
00388       motman->setOutput(this, GripperOffset, OutputPID(DefaultPIDs[GripperOffset-PIDJointOffset],1));
00389 #endif
00390     }
00391 #endif
00392   }//End PulseOnPeriod IF STATEMENT
00393 #endif
00394 //------------------------------------------------------To here is becoming obsolete
00395   return prevDirty;
00396 }
00397 
00398 int ArmMC::isAlive() {
00399 #ifdef TGT_HAS_ARMS
00400   if(dirty || !completionReported)
00401     return true;
00402 
00403   if(completionReported && (!hold || get_time()-targetTimestamp>timeout)) { //prevents a conflicted ArmPointerMC's from fighting forever
00404     if(get_time()-targetTimestamp>timeout && getAutoPrune())
00405       serr->printf("WARNING: ArmPointerMC (mcid %d) timed out - possible joint conflict or out-of-range target\n",getID());
00406     return false;
00407   }
00408   float maxdiff=0;
00409   for(unsigned int i=0; i<NumArmJoints; i++) {
00410     float diff=fabsf(state->outputs[ArmOffset+i]-armTargets[i]);
00411     if(diff>maxdiff)
00412       maxdiff=diff;
00413   }
00414   return (maxdiff>tolerance);
00415 #else
00416   return false;
00417 #endif
00418 }
00419 
00420 void ArmMC::setDirty() {
00421   dirty=true;
00422   completionReported=false;
00423 #ifdef TGT_HAS_ARMS
00424   for(unsigned int i=0; i<NumArmJoints; i++)
00425     armCmds[i].value=motman->getOutputCmd(ArmOffset+i).value; //not state->outputs[armOffset+i]; - see function documentation
00426 #endif
00427 }
00428 
00429 bool ArmMC::ensureValidJoint(unsigned int& i) {
00430 #ifdef TGT_HAS_ARMS
00431   if(i<NumArmJoints)
00432     return true;
00433   if(i>=ArmOffset && i<ArmOffset+NumArmJoints) {
00434     i-=ArmOffset;
00435     serr->printf("WARNING: ArmMC received a joint index of %d (ArmOffset+%d).\n",i+ArmOffset,i);
00436     serr->printf("         Since all parameters are assumed to be relative to ArmOffset,\n");
00437     serr->printf("         you should just pass %d directly.\n",i);
00438     serr->printf("WARNING: Assuming you meant %d...\n",i);
00439     return true;
00440   }
00441   serr->printf("ERROR: ArmMC received a joint index of %d (ArmOffset%+d).\n",i,i-ArmOffset);
00442   serr->printf("ERROR: This does not appear to be a arm joint.  ArmPointerMC only controls\n");
00443   serr->printf("       arm joints, and assumes its arguments are relative to ArmOffset\n");
00444 #endif
00445   return false;
00446 }

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:36 2016 by Doxygen 1.6.3