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   markDirty();
00066 #endif
00067 }
00068 
00069 void ArmMC::setWeight(int i, float w) {
00070 #ifdef TGT_HAS_ARMS
00071   armCmds[i].weight=w;
00072   markDirty();
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   std::auto_ptr<KinematicJoint> root(effector->getRoot());
00130   
00131   // do the IK
00132   bool conv = effector->getIK().solve(offset,*effector,IKSolver::Point(tgt));
00133   
00134   // copy results to member storage
00135   while(effector!=NULL) {
00136     if(effector->outputOffset<NumOutputs)
00137       setOutputCmd(effector->outputOffset, effector->getQ());
00138     effector = effector->getParent();
00139   }
00140   return conv;
00141 #endif  
00142 }
00143 
00144 bool ArmMC::moveOffsetToPointWithOrientation(const fmat::Column<3>& offset, const fmat::Column<3>& tgt, const fmat::Quaternion& ori) {
00145 #ifndef TGT_HAS_ARMS
00146   return false;
00147 #else
00148   const KinematicJoint * kinEff=NULL;
00149   unsigned int effIdx = capabilities.findFrameOffset("GripperFrame");
00150   if(effIdx!=-1U) // does it have the "pure" reference frame?
00151     kinEff = kine->getKinematicJoint(effIdx); // yes, try that
00152   if(kinEff==NULL) // if nothing has worked yet, try the last joint
00153     kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00154   if(kinEff==NULL) // if that didn't work, give up
00155     return false;
00156   KinematicJoint * effector = kinEff->cloneBranch(); // make a local copy so we can do thread-safe IK
00157   std::auto_ptr<KinematicJoint> root(effector->getRoot());
00158   
00159   // do the IK
00160   bool conv = effector->getIK().solve(offset, IKSolver::Rotation(fmat::Quaternion()), *effector, IKSolver::Point(tgt), 1, IKSolver::Rotation(ori), 0);
00161   
00162   // copy results to member storage
00163   while(effector!=NULL) {
00164     if(effector->outputOffset<NumOutputs)
00165       setOutputCmd(effector->outputOffset, effector->getQ());
00166     effector = effector->getParent();
00167   }
00168   return conv;
00169 #endif  
00170 }
00171 
00172 int ArmMC::updateOutputs() {
00173   int prevDirty=isDirty();
00174   if(prevDirty || hold) {  // we have joints to command
00175     dirty=false;
00176 #ifdef TGT_HAS_ARMS
00177     for(unsigned int i=0; i < NumArmJoints; i++) {
00178       if(maxSpeed[i]<=0) {
00179         armCmds[i].value=armTargets[i];
00180         motman->setOutput(this,i+ArmOffset,armCmds[i]);
00181       } else { // we may be trying to exceeded maxSpeed
00182         unsigned int f=0;
00183         while(armTargets[i]>armCmds[i].value+maxSpeed[i] && f<NumFrames) {
00184           armCmds[i].value+=maxSpeed[i];
00185           motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00186           f++;
00187         }
00188         while(armTargets[i]<armCmds[i].value-maxSpeed[i] && f<NumFrames) {
00189           armCmds[i].value-=maxSpeed[i];
00190           motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00191           f++;
00192         }
00193         if(f<NumFrames) { //we reached target value, fill in rest of frames
00194           armCmds[i].value=armTargets[i];
00195           for(;f<NumFrames;f++)
00196             motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00197         } else // we didn't reach target value, still dirty
00198           dirty=true;
00199       }
00200     }
00201 #endif
00202     if(!dirty && !completionReported) {
00203       postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID));
00204       completionReported=true;
00205       targetTimestamp=get_time();
00206     }
00207   }
00208   return prevDirty;
00209 }
00210 
00211 int ArmMC::isAlive() {
00212 #ifdef TGT_HAS_ARMS
00213   if(dirty || !completionReported)
00214     return true;
00215 
00216   if(completionReported && (!hold || get_time()-targetTimestamp>timeout)) { //prevents a conflicted ArmPointerMC's from fighting forever
00217     if(get_time()-targetTimestamp>timeout && getAutoPrune())
00218       serr->printf("WARNING: ArmPointerMC (mcid %d) timed out - possible joint conflict or out-of-range target\n",getID());
00219     return false;
00220   }
00221   float maxdiff=0;
00222   for(unsigned int i=0; i<NumArmJoints; i++) {
00223     float diff=fabsf(state->outputs[ArmOffset+i]-armTargets[i]);
00224     if(diff>maxdiff)
00225       maxdiff=diff;
00226   }
00227   return (maxdiff>tolerance);
00228 #else
00229   return false;
00230 #endif
00231 }
00232 
00233 void ArmMC::markDirty() {
00234   dirty=true;
00235   completionReported=false;
00236 #ifdef TGT_HAS_ARMS
00237   for(unsigned int i=0; i<NumArmJoints; i++)
00238     armCmds[i].value=motman->getOutputCmd(ArmOffset+i).value; //not state->outputs[armOffset+i]; - see function documentation
00239 #endif
00240 }
00241 
00242 bool ArmMC::ensureValidJoint(unsigned int& i) {
00243 #ifdef TGT_HAS_ARMS
00244   if(i<NumArmJoints)
00245     return true;
00246   if(i>=ArmOffset && i<ArmOffset+NumArmJoints) {
00247     i-=ArmOffset;
00248     serr->printf("WARNING: ArmMC received a joint index of %d (ArmOffset+%d).\n",i+ArmOffset,i);
00249     serr->printf("         Since all parameters are assumed to be relative to ArmOffset,\n");
00250     serr->printf("         you should just pass %d directly.\n",i);
00251     serr->printf("WARNING: Assuming you meant %d...\n",i);
00252     return true;
00253   }
00254   serr->printf("ERROR: ArmMC received a joint index of %d (ArmOffset%+d).\n",i,i-ArmOffset);
00255   serr->printf("ERROR: This does not appear to be a arm joint.  ArmPointerMC only controls\n");
00256   serr->printf("       arm joints, and assumes its arguments are relative to ArmOffset\n");
00257 #endif
00258   return false;
00259 }

Tekkotsu v5.1CVS
Generated Fri Mar 16 05:26:34 2012 by Doxygen 1.6.3