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
00021
00022
00023
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;
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)
00123 kinEff = kine->getKinematicJoint(effIdx);
00124 if(kinEff==NULL)
00125 kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00126 if(kinEff==NULL)
00127 return false;
00128 KinematicJoint * effector = kinEff->cloneBranch();
00129
00130
00131 bool conv = effector->getIK().solve(offset,*effector,IKSolver::Point(tgt));
00132
00133
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)
00150 kinEff = kine->getKinematicJoint(effIdx);
00151 if(kinEff==NULL)
00152 kinEff = kine->getKinematicJoint(ArmOffset+NumArmJoints-1);
00153 if(kinEff==NULL)
00154 return false;
00155 KinematicJoint * effector = kinEff->cloneBranch();
00156
00157
00158 bool conv = effector->getIK().solve(offset, IKSolver::Rotation(fmat::Quaternion()), *effector, IKSolver::Point(tgt), 1, IKSolver::Rotation(ori), 0);
00159
00160
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 )
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) {
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 {
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) {
00228 armCmds[i].value=armTargets[i];
00229 for(;f<NumFrames;f++)
00230 motman->setOutput(this,i+ArmOffset,armCmds[i],f);
00231 } else
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)) {
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;
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 }