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 {
00020   // Initialize armTargets[] by calling takeSnapShot() so we
00021   // don't have astronomical garbage values in there, which
00022   // could cause the motion command to fail to complete even if
00023   // the joint weights are zero.
00024   takeSnapshot();
00025   setWeight(0);
00026   defaultMaxSpeed();
00027 }
00028 
00029 void ArmMC::freezeMotion() {
00030 #ifdef TGT_HAS_ARMS
00031   for(unsigned int i=0; i<NumArmJoints; i++)
00032     armTargets[i]=armCmds[i].value;
00033   dirty=false;
00034 #endif
00035 }
00036 
00037 void ArmMC::takeSnapshot() {
00038 #ifdef TGT_HAS_ARMS
00039   for(unsigned int i=0; i<NumArmJoints; i++)
00040     armTargets[i]=armCmds[i].value=state->outputs[ArmOffset+i];
00041   dirty=true;
00042 #endif
00043 }
00044 
00045 float ArmMC::armJointValue(unsigned int i)  {
00046 #ifdef TGT_HAS_ARMS
00047   return armTargets[i];
00048 #else
00049   serr->printf("WARNING: No Arm");
00050   return -1000.0f;
00051 #endif
00052 }
00053 
00054 void ArmMC::defaultMaxSpeed(float x) {
00055 #ifdef TGT_HAS_ARMS
00056   for(unsigned int i = 0; i<NumArmJoints; i++)
00057     maxSpeed[i] = 0.3f; // **hack** hard coded for now
00058 #endif
00059 }
00060 
00061 void ArmMC::setWeight(float w) {
00062 #ifdef TGT_HAS_ARMS
00063   for(unsigned int i=0; i<NumArmJoints; i++)
00064     armCmds[i].weight=w;
00065   setDirty();
00066 #endif
00067 }
00068 
00069 void ArmMC::setWeight(int i, float w) {
00070 #ifdef TGT_HAS_ARMS
00071   armCmds[i].weight=w;
00072   setDirty();
00073 #endif
00074 }
00075 
00076 void ArmMC::setJoints(float shoulder, float elbow, float wrist){   
00077 #ifdef TGT_HAS_ARMS
00078   setMaxSpeed(0, 0.4f);    
00079   setMaxSpeed(1, 0.4f);    
00080   setMaxSpeed(2, 0.4f);    
00081   setJointValue(0, shoulder);    
00082   setJointValue(1, elbow);   
00083   setJointValue(2, wrist);   
00084 #endif   
00085 }    
00086        
00087        
00088 void ArmMC::setJoints(float shoulder, float elbow, float yaw, float pitch, float roll, float gripper) {    
00089 #ifdef TGT_HAS_ARMS 
00090   setMaxSpeed(0, 0.4f);    
00091   setMaxSpeed(1, 0.4f);    
00092   setMaxSpeed(2, 0.4f);    
00093   setMaxSpeed(3, 0.4f);    
00094   setMaxSpeed(4, 0.4f);    
00095   setMaxSpeed(5, 0.4f);    
00096   setJointValue(0, shoulder);    
00097   setJointValue(1, elbow);   
00098   setJointValue(2, yaw);   
00099   setJointValue(3, pitch);   
00100   setJointValue(4, roll);    
00101   setJointValue(5, gripper);   
00102 #endif   
00103 }    
00104 
00105 void ArmMC::setWrist(float pitch, float roll, float gripper) {
00106 #ifdef TGT_HAS_ARMS
00107   setMaxSpeed(3, 0.4f);    
00108   setMaxSpeed(4, 0.4f);    
00109   setMaxSpeed(5, 0.4f);  
00110   setJointValue(3, pitch);   
00111   setJointValue(4, roll);    
00112   setJointValue(5, gripper);
00113 #endif
00114 }
00115 
00116 bool ArmMC::moveOffsetToPoint(const fmat::Column<3>& offset, const fmat::Column<3>& tgt) {
00117 #ifndef TGT_HAS_ARMS
00118   return false;
00119 #else
00120   const KinematicJoint * kinEff=NULL;
00121   unsigned int effIdx = capabilities.findFrameOffset("GripperFrame");
00122   if(effIdx!=-1U) // does it have the "pure" reference frame?
00123     kinEff = kine->getKinematicJoint(effIdx); // yes, try that
00124   if(kinEff==NULL) // if nothing has worked yet, try the last joint
00125     kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00126   if(kinEff==NULL) // if that didn't work, give up
00127     return false;
00128   KinematicJoint * effector = kinEff->cloneBranch(); // make a local copy so we can do thread-safe IK
00129   
00130   // do the IK
00131   bool conv = effector->getIK().solve(offset,*effector,IKSolver::Point(tgt));
00132   
00133   // copy results to member storage
00134   while(effector!=NULL) {
00135     if(effector->outputOffset<NumOutputs)
00136       setOutputCmd(effector->outputOffset, effector->getQ());
00137     effector = effector->getParent();
00138   }
00139   return conv;
00140 #endif  
00141 }
00142 
00143 bool ArmMC::moveOffsetToPointWithOrientation(const fmat::Column<3>& offset, const fmat::Column<3>& tgt, const fmat::Quaternion& ori) {
00144 #ifndef TGT_HAS_ARMS
00145   return false;
00146 #else
00147   const KinematicJoint * kinEff=NULL;
00148   unsigned int effIdx = capabilities.findFrameOffset("GripperFrame");
00149   if(effIdx!=-1U) // does it have the "pure" reference frame?
00150     kinEff = kine->getKinematicJoint(effIdx); // yes, try that
00151   if(kinEff==NULL) // if nothing has worked yet, try the last joint
00152     kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00153   if(kinEff==NULL) // if that didn't work, give up
00154     return false;
00155   KinematicJoint * effector = kinEff->cloneBranch(); // make a local copy so we can do thread-safe IK
00156   
00157   // do the IK
00158   bool conv = effector->getIK().solve(offset, IKSolver::Rotation(fmat::Quaternion()), *effector, IKSolver::Point(tgt), 1, IKSolver::Rotation(ori), 0);
00159   
00160   // copy results to member storage
00161   while(effector!=NULL) {
00162     if(effector->outputOffset<NumOutputs)
00163       setOutputCmd(effector->outputOffset, effector->getQ());
00164     effector = effector->getParent();
00165   }
00166   return conv;
00167 #endif  
00168 }
00169 
00170 bool ArmMC::setFingerGap(float dist) {
00171 #ifdef TGT_CALLIOPE5KP
00172     PostureEngine mypos;
00173     mypos.setOutputCmd(LeftFingerOffset, 0);
00174     mypos.setOutputCmd(RightFingerOffset, 0);
00175     fmat::Column<3> lf = mypos.getPosition(LeftFingerOffset);
00176     fmat::Column<3> rf = mypos.getPosition(RightFingerOffset);
00177     float c = (lf-rf).norm();
00178     fmat::Transform trans = mypos.linkToLink(LeftFingerFrameOffset, LeftFingerOffset);
00179     AngSignPi alpha = asin(trans(0,0));
00180     float r = sqrt ( trans(0,3)*trans(0,3) + trans(1,3)*trans(1,3) );
00181     if ( dist < 0 || dist > 2*r+c ) // assumes fingers can open full 180 degrees
00182       return false;
00183     AngSignPi q = asin((dist/2-c/2)/r) - alpha;
00184     setJointValue(LeftFingerOffset, -q);
00185     setJointValue(RightFingerOffset, q);
00186 #endif
00187     return true;
00188 }
00189 
00190 bool ArmMC::openGripper(float percentage) {
00191 #if defined(TGT_IS_CALLIOPE2)
00192   float gripperAngle = outputRanges[GripperOffset][MinRange] +
00193     percentage * (outputRanges[GripperOffset][MaxRange] - outputRanges[GripperOffset][MinRange]);
00194   setJointValue(GripperOffset-ArmOffset, gripperAngle);
00195 #elif defined(TGT_IS_CALLIOPE5)
00196   float gripperAngleL = outputRanges[LeftFingerOffset][MaxRange] +
00197     percentage * (outputRanges[LeftFingerOffset][MinRange] - outputRanges[LeftFingerOffset][MaxRange]);
00198   float gripperAngleR = outputRanges[RightFingerOffset][MinRange] +
00199     percentage * (outputRanges[RightFingerOffset][MaxRange] - outputRanges[RightFingerOffset][MinRange]);
00200   setJointValue(LeftFingerOffset-ArmOffset, gripperAngleL);
00201   setJointValue(RightFingerOffset-ArmOffset, gripperAngleR);
00202 #endif
00203   return true;
00204 }
00205 
00206 int ArmMC::updateOutputs() {
00207   int prevDirty=isDirty();
00208   if(prevDirty || hold) {  // we have joints to command
00209     dirty=false;
00210 #ifdef TGT_HAS_ARMS
00211     for(unsigned int i=0; i < NumArmJoints; i++) {
00212       if(maxSpeed[i]<=0) {
00213         armCmds[i].value=armTargets[i];
00214         motman->setOutput(this,i+ArmOffset,armCmds[i]);
00215       } else { // we may be trying to exceeded maxSpeed
00216         unsigned int f=0;
00217         while(armTargets[i]>armCmds[i].value+maxSpeed[i] && f<NumFrames) {
00218           armCmds[i].value+=maxSpeed[i];
00219           motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00220           f++;
00221         }
00222         while(armTargets[i]<armCmds[i].value-maxSpeed[i] && f<NumFrames) {
00223           armCmds[i].value-=maxSpeed[i];
00224           motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00225           f++;
00226         }
00227         if(f<NumFrames) { //we reached target value, fill in rest of frames
00228           armCmds[i].value=armTargets[i];
00229           for(;f<NumFrames;f++)
00230             motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00231         } else // we didn't reach target value, still dirty
00232           dirty=true;
00233       }
00234     }
00235 #endif
00236     if(!dirty && !completionReported) {
00237       postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID));
00238       completionReported=true;
00239       targetTimestamp=get_time();
00240     }
00241   }
00242   return prevDirty;
00243 }
00244 
00245 int ArmMC::isAlive() {
00246 #ifdef TGT_HAS_ARMS
00247   if(dirty || !completionReported)
00248     return true;
00249 
00250   if(completionReported && (!hold || get_time()-targetTimestamp>timeout)) { //prevents a conflicted ArmPointerMC's from fighting forever
00251     if(get_time()-targetTimestamp>timeout && getAutoPrune())
00252       serr->printf("WARNING: ArmPointerMC (mcid %d) timed out - possible joint conflict or out-of-range target\n",getID());
00253     return false;
00254   }
00255   float maxdiff=0;
00256   for(unsigned int i=0; i<NumArmJoints; i++) {
00257     float diff=fabsf(state->outputs[ArmOffset+i]-armTargets[i]);
00258     if(diff>maxdiff)
00259       maxdiff=diff;
00260   }
00261   return (maxdiff>tolerance);
00262 #else
00263   return false;
00264 #endif
00265 }
00266 
00267 void ArmMC::setDirty() {
00268   dirty=true;
00269   completionReported=false;
00270 #ifdef TGT_HAS_ARMS
00271   for(unsigned int i=0; i<NumArmJoints; i++)
00272     armCmds[i].value=motman->getOutputCmd(ArmOffset+i).value; //not state->outputs[armOffset+i]; - see function documentation
00273 #endif
00274 }
00275 
00276 bool ArmMC::ensureValidJoint(unsigned int& i) {
00277 #ifdef TGT_HAS_ARMS
00278   if(i<NumArmJoints)
00279     return true;
00280   if(i>=ArmOffset && i<ArmOffset+NumArmJoints) {
00281     i-=ArmOffset;
00282     serr->printf("WARNING: ArmMC received a joint index of %d (ArmOffset+%d).\n",i+ArmOffset,i);
00283     serr->printf("         Since all parameters are assumed to be relative to ArmOffset,\n");
00284     serr->printf("         you should just pass %d directly.\n",i);
00285     serr->printf("WARNING: Assuming you meant %d...\n",i);
00286     return true;
00287   }
00288   serr->printf("ERROR: ArmMC received a joint index of %d (ArmOffset%+d).\n",i,i-ArmOffset);
00289   serr->printf("ERROR: This does not appear to be a arm joint.  ArmPointerMC only controls\n");
00290   serr->printf("       arm joints, and assumes its arguments are relative to ArmOffset\n");
00291 #endif
00292   return false;
00293 }

Tekkotsu v5.1CVS
Generated Sat May 4 06:32:42 2013 by Doxygen 1.6.3