00001 #include "HeadPointerMC.h"
00002 #include "Kinematics.h"
00003 #include "Shared/debuget.h"
00004 #include "Shared/WorldState.h"
00005 #include "MotionManager.h"
00006 #include "Shared/Config.h"
00007 #include "Wireless/Socket.h"
00008 #include "Shared/ERS7Info.h"
00009 #include "Shared/ERS210Info.h"
00010 #include "Motion/IKSolver.h"
00011 #include "Shared/get_time.h"
00012 #include "Events/EventBase.h"
00013 #include "DualCoding/VRmixin.h"
00014 #include "Crew/MapBuilder.h"
00015 #include "DualCoding/Point.h"
00016
00017 #include <memory>
00018 #include <cmath>
00019
00020 HeadPointerMC::HeadPointerMC()
00021 : MotionCommand(), dirty(true), hold(true), tolerance(.05f),
00022 targetReached(true), targetTimestamp(0), timeout(2000)
00023 {
00024 setWeight(1);
00025 defaultMaxSpeed();
00026 takeSnapshot();
00027 }
00028
00029 void HeadPointerMC::freezeMotion() {
00030 #ifdef TGT_HAS_HEAD
00031 for(unsigned int i=0; i<NumHeadJoints; i++)
00032 headTargets[i]=headCmds[i].value;
00033 dirty=false;
00034 #endif
00035 }
00036
00037 void HeadPointerMC::takeSnapshot() {
00038 #ifdef TGT_HAS_HEAD
00039 for(unsigned int i=0; i<NumHeadJoints; i++)
00040 headTargets[i]=headCmds[i].value=state->outputs[HeadOffset+i];
00041 dirty=true;
00042 #endif
00043 }
00044
00045 void HeadPointerMC::defaultMaxSpeed(float x) {
00046 #ifdef TGT_HAS_HEAD
00047 const char* n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::TiltOffset];
00048 unsigned int i = capabilities.findOutputOffset(n);
00049 if(i!=-1U)
00050 maxSpeed[i-HeadOffset]=config->motion.max_head_tilt_speed*FrameTime*x/1000;
00051 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::PanOffset];
00052 i = capabilities.findOutputOffset(n);
00053 if(i!=-1U)
00054 maxSpeed[i-HeadOffset]=config->motion.max_head_pan_speed*FrameTime*x/1000;
00055 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::NodOffset];
00056 i = capabilities.findOutputOffset(n);
00057 if(i!=-1U)
00058 maxSpeed[i-HeadOffset]=config->motion.max_head_roll_speed*FrameTime*x/1000;
00059 n = ERS210Info::outputNames[ERS210Info::HeadOffset+ERS210Info::RollOffset];
00060 i = capabilities.findOutputOffset(n);
00061 if(i!=-1U)
00062 maxSpeed[i-HeadOffset]=config->motion.max_head_roll_speed*FrameTime*x/1000;
00063 #endif
00064 }
00065
00066 void HeadPointerMC::setWeight(float w) {
00067 #ifdef TGT_HAS_HEAD
00068 for(unsigned int x=0; x<NumHeadJoints; x++)
00069 headCmds[x].weight=w;
00070 setDirty();
00071 #endif
00072 }
00073
00074 void HeadPointerMC::setJoints(float tilt1, float pan, float tilt2) {
00075 #ifdef TGT_HAS_HEAD
00076 #ifdef TGT_IS_AIBO
00077 headTargets[TiltOffset]=clipAngularRange(HeadOffset+TiltOffset,tilt1);
00078 headTargets[PanOffset]=clipAngularRange(HeadOffset+PanOffset,pan);
00079 headTargets[NodOffset]=clipAngularRange(HeadOffset+NodOffset,tilt2);
00080 #else
00081 const char* n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::TiltOffset];
00082 unsigned int i = capabilities.findOutputOffset(n);
00083 if(i!=-1U)
00084 headTargets[i-HeadOffset]=clipAngularRange(i,tilt1);
00085 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::PanOffset];
00086 i = capabilities.findOutputOffset(n);
00087 if(i!=-1U)
00088 headTargets[i-HeadOffset]=clipAngularRange(i,pan);
00089 n = ERS7Info::outputNames[ERS7Info::HeadOffset+ERS7Info::NodOffset];
00090 i = capabilities.findOutputOffset(n);
00091 if(i!=-1U)
00092 headTargets[i-HeadOffset]=clipAngularRange(i,tilt2);
00093 #endif
00094 setDirty();
00095 #endif
00096 }
00097
00098 void HeadPointerMC::setJoints(float pan, float shoulder, float elbow, float pitch) {
00099 setMaxSpeed(0, 0.2f);
00100 setMaxSpeed(1, 0.2f);
00101 setMaxSpeed(2, 0.2f);
00102 setMaxSpeed(3, 0.2f);
00103 setJointValue(0, pan);
00104 setJointValue(1, shoulder);
00105 setJointValue(2, elbow);
00106 setJointValue(3, pitch);
00107 }
00108
00109 #include <iostream>
00110 using namespace std;
00111
00112 bool HeadPointerMC::lookAtPoint(float x, float y, float z) {
00113 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00114 return false;
00115 #else
00116 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00117 if(kinEff==NULL) {
00118 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00119 return false;
00120 }
00121 KinematicJoint * effector = kinEff->cloneBranch();
00122 std::auto_ptr<KinematicJoint> root(effector->getRoot());
00123
00124
00125
00126
00127 effector->qmax = std::numeric_limits<float>::infinity();
00128
00129 bool conv = effector->getIK().solve(IKSolver::Point(),*effector,IKSolver::Point(x,y,z));
00130 do {
00131 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00132 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00133 effector = effector->getParent();
00134 } while(effector!=NULL);
00135 setDirty();
00136
00137 return conv;
00138 #endif
00139
00140 }
00141
00142 bool HeadPointerMC::lookAtPoint(const DualCoding::Point &p) {
00143 DualCoding::Point p2 = p;
00144 switch ( p2.getRefFrameType() ) {
00145 case DualCoding::camcentric:
00146
00147 cout << "Error: HeadPointerMC::lookAtPoint cannot accept point " << p2 << " in camera-centric coordinates\n";
00148 return false;
00149 case DualCoding::allocentric: {
00150 if ( DualCoding::VRmixin::mapBuilder == NULL ) {
00151 cout << "Error: HeadPointerMC:lookAtPoint can't convert allocentric point " << p2
00152 << " to egocentric because MapBuilder is not running\n";
00153 return false;
00154 }
00155 fmat::Column<3> q = DualCoding::VRmixin::mapBuilder->worldToLocalMatrix * p2.getCoords();
00156 p2.setCoords(q[0], q[1], q[2]);
00157 }
00158
00159 case DualCoding::egocentric:
00160 case DualCoding::unspecified:
00161 return lookAtPoint(p2.coordX(), p2.coordY(), p2.coordZ());
00162 }
00163 cerr << "Error: HeadPointerMC::lookAtPoint given DualCoding::Point with invalid reference frame " << p2.getRefFrameType() << endl;
00164 return false;
00165 }
00166
00167 bool HeadPointerMC::lookAtPoint(const fmat::Column<3> &p) {
00168 return lookAtPoint(p[0], p[1], p[2]);
00169 }
00170
00171 bool HeadPointerMC::lookAtPoint(float x, float y, float z, float d) {
00172 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00173 return false;
00174 #else
00175 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00176 if(kinEff==NULL) {
00177 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00178 return false;
00179 }
00180 KinematicJoint * effector = kinEff->cloneBranch();
00181 std::auto_ptr<KinematicJoint> root(effector->getRoot());
00182
00183
00184
00185 bool conv = effector->getIK().solve(IKSolver::Point(0,0,d),*effector,IKSolver::Point(x,y,z));
00186 do {
00187 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00188 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00189 effector = effector->getParent();
00190 } while(effector!=NULL);
00191 setDirty();
00192
00193 return conv;
00194 #endif
00195 }
00196
00197 bool HeadPointerMC::lookInDirection(float x, float y, float z) {
00198 #if !defined(TGT_HAS_HEAD) || !defined(TGT_HAS_CAMERA)
00199 return false;
00200 #else
00201 const KinematicJoint * kinEff = kine->getKinematicJoint(CameraFrameOffset);
00202 if(kinEff==NULL) {
00203 cout<<"HeadPointerMC: Could not find CameraFrameOffset"<<endl;
00204 return false;
00205 }
00206 KinematicJoint * effector = kinEff->cloneBranch();
00207 std::auto_ptr<KinematicJoint> root(effector->getRoot());
00208
00209
00210
00211 bool conv = effector->getIK().solve(IKSolver::Rotation(),*effector,IKSolver::Parallel(x,y,z));
00212 do {
00213 if(effector->outputOffset>=HeadOffset && effector->outputOffset<HeadOffset+NumHeadJoints)
00214 headTargets[effector->outputOffset - HeadOffset] = effector->getQ();
00215 effector = effector->getParent();
00216 } while(effector!=NULL);
00217 setDirty();
00218
00219 return conv;
00220 #endif
00221 }
00222
00223 bool HeadPointerMC::lookAtJoint(unsigned int j) {
00224 const fmat::Column<3> jointPos = kine->linkToBase(j).translation();
00225 return lookAtPoint(jointPos);
00226 }
00227
00228 int HeadPointerMC::updateOutputs() {
00229 int tmp=isDirty();
00230 if(tmp || hold) {
00231 dirty=false;
00232 #ifdef TGT_HAS_HEAD
00233 for(unsigned int i=0; i<NumHeadJoints; i++) {
00234 if(maxSpeed[i]<=0) {
00235 headCmds[i].value=headTargets[i];
00236 motman->setOutput(this,i+HeadOffset,headCmds[i]);
00237 } else {
00238 unsigned int f=0;
00239 while(headTargets[i]>headCmds[i].value+maxSpeed[i] && f<NumFrames) {
00240 headCmds[i].value+=maxSpeed[i];
00241 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00242 f++;
00243 }
00244 while(headTargets[i]<headCmds[i].value-maxSpeed[i] && f<NumFrames) {
00245 headCmds[i].value-=maxSpeed[i];
00246 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00247 f++;
00248 }
00249 if(f<NumFrames) {
00250 headCmds[i].value=headTargets[i];
00251 for(;f<NumFrames;f++)
00252 motman->setOutput(this,i+HeadOffset,headCmds[i],f);
00253 } else
00254 dirty=true;
00255 }
00256 }
00257 #endif
00258 if(!dirty && !targetReached) {
00259 postEvent(EventBase(EventBase::motmanEGID, getID(),EventBase::statusETID));
00260 targetReached=true;
00261 targetTimestamp=get_time();
00262 }
00263 }
00264 return tmp;
00265 }
00266
00267 int HeadPointerMC::isAlive() {
00268 #ifndef TGT_HAS_HEAD
00269 return false;
00270 #else
00271 if(dirty || !targetReached)
00272 return true;
00273 if(targetReached && (!hold || get_time()-targetTimestamp>timeout)) {
00274 if(get_time()-targetTimestamp>timeout && getAutoPrune())
00275 serr->printf("WARNING: HeadPointerMC (mcid %d) timed out - possible joint conflict or out-of-range target\n",getID());
00276 return false;
00277 }
00278 float maxdiff=0;
00279 for(unsigned int i=0; i<NumHeadJoints; i++) {
00280 float diff=fabsf(state->outputs[HeadOffset+i]-headTargets[i]);
00281 if(diff>maxdiff)
00282 maxdiff=diff;
00283 }
00284 return (maxdiff>tolerance);
00285 #endif
00286 }
00287
00288 void HeadPointerMC::setDirty() {
00289 dirty=true;
00290 targetReached=false;
00291 #ifdef TGT_HAS_HEAD
00292 for(unsigned int i=0; i<NumHeadJoints; i++)
00293 headCmds[i].value=motman->getOutputCmd(HeadOffset+i).value;
00294 #endif
00295 }
00296
00297 bool HeadPointerMC::ensureValidJoint(unsigned int& i) {
00298 #ifndef TGT_HAS_HEAD
00299 serr->printf("ERROR: HeadPointerMC received a joint index of %d on headless target.\n",i);
00300 #else
00301 if(i<NumHeadJoints)
00302 return true;
00303 if(i>=HeadOffset && i<HeadOffset+NumHeadJoints) {
00304 i-=HeadOffset;
00305 serr->printf("WARNING: HeadPointerMC received a joint index of %d (HeadOffset+%d).\n",i+HeadOffset,i);
00306 serr->printf(" Since all parameters are assumed to be relative to HeadOffset,\n");
00307 serr->printf(" you should just pass %d directly.\n",i);
00308 serr->printf("WARNING: Assuming you meant %d...\n",i);
00309 return true;
00310 }
00311 serr->printf("ERROR: HeadPointerMC received a joint index of %d (HeadOffset%+d).\n",i,i-HeadOffset);
00312 serr->printf("ERROR: This does not appear to be a head joint. HeadPointerMC only controls\n");
00313 serr->printf(" head joints, and assumes its arguments are relative to HeadOffset\n");
00314 #endif
00315 return false;
00316 }
00317
00318
00319
00320
00321
00322