00001 #include <math.h>
00002
00003 #include "HeadPointerMC.h"
00004 #include "Kinematics.h"
00005 #include "Shared/debuget.h"
00006 #include "Shared/WorldState.h"
00007 #include "MotionManager.h"
00008 #include "Shared/Config.h"
00009 #include "Wireless/Socket.h"
00010
00011 HeadPointerMC::HeadPointerMC()
00012 : MotionCommand(), dirty(true), hold(true), tolerance(.05),
00013 targetReached(true), targetTimestamp(0), timeout(2000),
00014 headkin(::config->motion.makePath(::config->motion.kinematics),"Camera")
00015 {
00016 setWeight(1);
00017 defaultMaxSpeed();
00018 takeSnapshot();
00019 }
00020
00021 void HeadPointerMC::freezeMotion() {
00022 for(unsigned int i=0; i<NumHeadJoints; i++)
00023 headTargets[i]=headCmds[i].value;
00024 dirty=false;
00025 }
00026
00027 void HeadPointerMC::takeSnapshot() {
00028 for(unsigned int i=0; i<NumHeadJoints; i++)
00029 headTargets[i]=headCmds[i].value=state->outputs[HeadOffset+i];
00030 dirty=true;
00031 }
00032
00033 void HeadPointerMC::defaultMaxSpeed(float x) {
00034 maxSpeed[TiltOffset]=config->motion.max_head_tilt_speed*FrameTime*x/1000;
00035 maxSpeed[PanOffset]=config->motion.max_head_pan_speed*FrameTime*x/1000;
00036 maxSpeed[RollOffset]=config->motion.max_head_roll_speed*FrameTime*x/1000;
00037 }
00038
00039 void HeadPointerMC::setWeight(float w) {
00040 for(unsigned int x=0; x<NumHeadJoints; x++)
00041 headCmds[x].weight=w;
00042 markDirty();
00043 }
00044
00045 void HeadPointerMC::setJoints(float j1, float j2, float j3) {
00046 headTargets[TiltOffset]=clipAngularRange(HeadOffset+TiltOffset,j1);
00047 headTargets[PanOffset]=clipAngularRange(HeadOffset+PanOffset,j2);
00048 headTargets[RollOffset]=clipAngularRange(HeadOffset+RollOffset,j3);
00049 markDirty();
00050 }
00051
00052 bool HeadPointerMC::lookAtPoint(float x, float y, float z) {
00053 NEWMAT::ColumnVector Pobj(4),Plink(4);
00054 Pobj(1)=x; Pobj(2)=y; Pobj(3)=z; Pobj(4)=1;
00055 Plink=0; Plink(3)=1;
00056 bool conv=false;
00057 NEWMAT::ColumnVector q=headkin.inv_kin_pos(Pobj,0,headkin.get_dof(),Plink,conv);
00058
00059 NEWMAT::ColumnVector poE=headkin.convertLink(0,headkin.get_dof())*Pobj;
00060 poE=poE.SubMatrix(1,3,1,1);
00061
00062
00063 NEWMAT::ColumnVector plE=Plink.SubMatrix(1,3,1,1);
00064 float plE2=plE.SumSquare();
00065 float plE_len=sqrt(plE2);
00066 float obj_comp_link=NEWMAT::DotProduct(plE,poE)/plE_len;
00067 if(obj_comp_link<plE_len)
00068 obj_comp_link=obj_comp_link*.975;
00069 else
00070 obj_comp_link=obj_comp_link/.975;
00071 NEWMAT::ColumnVector obj_proj_link(4);
00072 obj_proj_link.SubMatrix(1,3,1,1)=obj_comp_link*plE/plE_len;
00073 obj_proj_link(4)=1;
00074 q=headkin.inv_kin_pos(Pobj,0,headkin.get_dof(),obj_proj_link,conv);
00075
00076 for(unsigned int i=0; i<NumHeadJoints; i++)
00077 setJointValue(i,headkin.get_q(2+i));
00078
00079
00080
00081
00082 return isReachable(Pobj);
00083 }
00084
00085 bool HeadPointerMC::lookAtPoint(float x, float y, float z, float d) {
00086 NEWMAT::ColumnVector Pobj(4),Plink(4);
00087 Pobj(1)=x; Pobj(2)=y; Pobj(3)=z; Pobj(4)=1;
00088 Plink=0; Plink(3)=d; Plink(4)=1;
00089 bool conv=false;
00090 NEWMAT::ColumnVector q=headkin.inv_kin_pos(Pobj,0,headkin.get_dof(),Plink,conv);
00091 for(unsigned int i=0; i<NumHeadJoints; i++)
00092 setJointValue(i,headkin.get_q(2+i));
00093
00094 return isReachable(Pobj);
00095 }
00096
00097 bool HeadPointerMC::lookInDirection(float x, float y, float z) {
00098 NEWMAT::ColumnVector Pobj(4),Plink(4);
00099 Pobj(1)=x; Pobj(2)=y; Pobj(3)=z; Pobj(4)=0;
00100 Plink=0; Plink(3)=1;
00101 bool conv=false;
00102 NEWMAT::ColumnVector q=headkin.inv_kin_pos(Pobj,0,headkin.get_dof(),Plink,conv);
00103 for(unsigned int i=0; i<NumHeadJoints; i++)
00104 setJointValue(i,headkin.get_q(2+i));
00105
00106 return isReachable(Pobj);
00107 }
00108
00109
00110 int HeadPointerMC::updateOutputs() {
00111 int tmp=isDirty();
00112 if(tmp || hold) {
00113 dirty=false;
00114 for(unsigned int i=0; i<NumHeadJoints; i++) {
00115 if(maxSpeed[i]<=0) {
00116 headCmds[i].value=headTargets[i];
00117 motman->setOutput(this,i+HeadOffset,headCmds[i]);
00118 } else {
00119 unsigned int f=0;
00120 while(headTargets[i]>headCmds[i].value+maxSpeed[i] && f<NumFrames) {
00121 headCmds[i].value+=maxSpeed[i];
00122 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00123 f++;
00124 }
00125 while(headTargets[i]<headCmds[i].value-maxSpeed[i] && f<NumFrames) {
00126 headCmds[i].value-=maxSpeed[i];
00127 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00128 f++;
00129 }
00130 if(f<NumFrames) {
00131 headCmds[i].value=headTargets[i];
00132 for(;f<NumFrames;f++)
00133 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00134 } else
00135 dirty=true;
00136 }
00137 }
00138 if(!dirty && !targetReached) {
00139 postEvent(EventBase(EventBase::motmanEGID,getID(),EventBase::statusETID));
00140 targetReached=true;
00141 targetTimestamp=get_time();
00142 }
00143 }
00144 return tmp;
00145 }
00146
00147 int HeadPointerMC::isAlive() {
00148 if(dirty || !targetReached)
00149 return true;
00150 if(targetReached && (!hold || get_time()-targetTimestamp>timeout)) {
00151 if(get_time()-targetTimestamp>timeout && getAutoPrune())
00152 serr->printf("WARNING: HeadPointerMC (mcid %d) timed out - possible joint conflict or out-of-range target\n",getID());
00153 return false;
00154 }
00155 float maxdiff=0;
00156 for(unsigned int i=0; i<NumHeadJoints; i++) {
00157 float diff=fabsf(state->outputs[HeadOffset+i]-headTargets[i]);
00158 if(diff>maxdiff)
00159 maxdiff=diff;
00160 }
00161 return (maxdiff>tolerance);
00162 }
00163
00164 void HeadPointerMC::markDirty() {
00165 dirty=true;
00166 targetReached=false;
00167 for(unsigned int i=0; i<NumHeadJoints; i++)
00168 headCmds[i].value=motman->getOutputCmd(HeadOffset+i).value;
00169 }
00170
00171 bool HeadPointerMC::ensureValidJoint(unsigned int& i) {
00172 if(i<NumHeadJoints)
00173 return true;
00174 if(i>=HeadOffset && i<HeadOffset+NumHeadJoints) {
00175 i-=HeadOffset;
00176 serr->printf("WARNING: HeadPointerMC received a joint index of %d (HeadOffset+%d).\n",i+HeadOffset,i);
00177 serr->printf(" Since all parameters are assumed to be relative to HeadOffset,\n");
00178 serr->printf(" you should just pass %d directly.\n",i);
00179 serr->printf("WARNING: Assuming you meant %d...\n",i);
00180 return true;
00181 }
00182 serr->printf("ERROR: HeadPointerMC received a joint index of %d (HeadOffset%+d).\n",i,i-HeadOffset);
00183 serr->printf("ERROR: This does not appear to be a head joint. HeadPointerMC only controls\n");
00184 serr->printf(" head joints, and assumes its arguments are relative to HeadOffset\n");
00185 return false;
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199