Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

HeadPointerMC.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_HeadPointerMC_h
00003 #define INCLUDED_HeadPointerMC_h
00004 
00005 #include "Shared/RobotInfo.h"
00006 #include "MotionCommand.h"
00007 #include "OutputCmd.h"
00008 #include "Shared/mathutils.h"
00009 
00010 namespace DualCoding {
00011   class Point;
00012 }
00013 
00014 //! This class gives some quick and easy functions to point the head at things
00015 class HeadPointerMC : public MotionCommand {
00016 public:
00017   //! Constructor, defaults to all joints to current value in ::state (i.e. calls takeSnapshot() automatically)
00018   HeadPointerMC();
00019   
00020   //! Destructor
00021   virtual ~HeadPointerMC() {}
00022   
00023   //!Sets #hold - if this is set to false, it will allow a persistent motion to behave the same as a pruned motion, without being pruned
00024   virtual void setHold(bool h=true) { hold=h; }
00025   virtual bool getHold() { return hold; } //!< return #hold
00026 
00027   virtual void setTolerance(float t) { tolerance=t; } //!< sets #tolerance
00028   virtual float getTolerance() { return tolerance; } //!< returns #tolerance
00029   virtual void setTimeout(unsigned int delay) { timeout=delay; } //!< sets #timeout
00030   virtual unsigned int getTimeout() { return timeout; } //!< returns #timeout
00031   
00032   //! sets the target to last sent commands, and dirty to false; essentially freezes motion in place
00033   /*! This is very similar to takeSnapshot(), but will do the "right thing" (retain current position) when motion blending is involved.
00034    *  A status event will be generated if/when the joints reach the currently commanded position.
00035    *  Probably should use freezeMotion() if you want to stop a motion underway, but takeSnapshot() if you want to reset/intialize to the current joint positions. */
00036   virtual void freezeMotion();
00037   //! sets the target joint positions to current sensor values
00038   /*! Similar to freezeMotion() when a motion is underway, but only if no other MotionCommands are using neck joints.
00039    *  A status event will @e not be generated unless a motion was already underway.
00040    *  Probably should use freezeMotion() if you want to stop a motion underway, but takeSnapshot() if you want to reset/intialize to the current joint positions. */
00041   virtual void takeSnapshot();
00042 
00043   //!@name Speed Control
00044   
00045   //! Sets #maxSpeed to 0 (no maximum)
00046   void noMaxSpeed() { for(unsigned int i=0; i<NumHeadJoints; i++) maxSpeed[i]=0; }
00047   
00048   //! Restores #maxSpeed to default settings from Config::Motion_Config
00049   /*! @param x ratio of the max speed to use; so 0.5 would limit motion to half the recommended upper limit */
00050   void defaultMaxSpeed(float x=1);
00051   
00052   //! Sets #maxSpeed in rad/sec
00053   /*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
00054    *  @param x maximum radians per second to move */
00055   void setMaxSpeed(unsigned int i, float x) { maxSpeed[i]=x*FrameTime/1000; }
00056   
00057   //! Returns #maxSpeed in rad/sec
00058   /*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
00059    *  @return the maximum speed of joint @a i in radians per second */
00060   float getMaxSpeed(unsigned int i) { return maxSpeed[i]*1000/FrameTime; }
00061   
00062   //@}
00063   
00064   //!@name Joint Accessors
00065   
00066   //! Sets the weight values for all the neck joints
00067   void setWeight(float w);
00068   
00069   //! Request a set of neck joint values
00070   /*! Originally this corresponded directly to the neck joints of the aibo, however
00071    *  on other platforms it will use capabilties mapping to try to set correspnding joints if available.
00072    *  (we're not doing kinematics here, trying to set joint values directly.  If your
00073    *  want a more generic/abstract interface, use lookAtPoint()/lookInDirection().
00074    *
00075    *  Note that for a "pan-tilt" camera, you actually want to set the @em last two parameters,
00076    *  @em not the first two!
00077    * 
00078    *  @param tilt value - this is an initial rotation about the camera x axis
00079    *  @param pan value - this is a rotation about the camera y axis
00080    *  @param tilt2 value - a second rotation about the camera x axis ("nod")
00081    *
00082    *  On ERS-210 and 220, the tilt2 is actually a roll about camera z (ugly, but no one's using those anymore, so moot issue) */
00083   void setJoints(float tilt, float pan, float tilt2);
00084   void setJoints(float pan, float shoulder, float elbow, float pitch);
00085   
00086   //! Directly set a single neck joint value
00087   /*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
00088    *  @param value the value to be assigned to join @a i, in radians */
00089   void setJointValue(unsigned int i, float value) {
00090 #ifdef TGT_HAS_HEAD
00091     if(!ensureValidJoint(i))
00092       return;
00093     headTargets[i]=clipAngularRange(HeadOffset+i,value);
00094     markDirty();
00095 #endif
00096   }
00097   
00098   //! Returns the target value of joint @a i.  Use this if you want to know the current @b commanded joint value; To get the current joint @b position, look in WorldState::outputs
00099   /*! @param i joint offset relative to HeadOffset (i.e. one of TPROffset_t) */
00100   float getJointValue(unsigned int i) const {
00101     if(ensureValidJoint(i))
00102       return headTargets[i];
00103     else
00104       return 0;
00105   }
00106   
00107   //! Centers the camera on a point in space, attempting to keep the camera as far away from the point as possible
00108   /*! Point should be relative to the body reference frame (see ::BaseFrameOffset).  Returns true if the target is reachable.
00109    *  @param x location in millimeters
00110    *  @param y location in millimeters
00111    *  @param z location in millimeters
00112    *
00113    *  @todo this method is an approximation, could be more precise, and perhaps faster, although this is pretty good. */
00114   bool lookAtPoint(float x, float y, float z);
00115   
00116   //! Centers the camera on a point in space, attempting to keep the camera as far away from the point as possible
00117   /*! Point should be relative to the body reference frame (see ::BaseFrameOffset).  Returns true if the target is reachable.
00118    *  @param p point to look at */
00119   bool lookAtPoint(const DualCoding::Point &p);
00120 
00121   //! Centers the camera on a point in space, attempting to move the camera @a d millimeters away from the point
00122   /*! Point should be relative to the body reference frame (see ::BaseFrameOffset).  Returns true if the target is reachable.
00123    *  @param x location in millimeters
00124    *  @param y location in millimeters
00125    *  @param z location in millimeters
00126    *  @param d target distance from point in millimeters */
00127   bool lookAtPoint(float x, float y, float z, float d);
00128   
00129   //! Points the camera in a given direction
00130   /*! Vector should be relative to the body reference frame (see ::BaseFrameOffset).  Returns true if the target is reachable.
00131    *  @param x component of the direction vector
00132    *  @param y component of the direction vector
00133    *  @param z component of the direction vector */
00134   bool lookInDirection(float x, float y, float z);
00135 
00136 
00137   
00138   //@}
00139   
00140 public: 
00141   //!@name Inherited:
00142   virtual int updateOutputs(); //!< Updates where the head is looking
00143   virtual int isDirty() { return (dirty || !targetReached)?3:0; } //!< true if a change has been made since the last updateJointCmds() and we're active
00144   virtual int isAlive(); //!< Alive while target is not reached
00145   virtual void doStart() { MotionCommand::doStart(); markDirty(); } //!< marks this as dirty each time it is added
00146   //@}
00147 
00148 protected:
00149   //! puts x in the range (-pi,pi)
00150   static float normalizeAngle(float x) { return x - static_cast<float>( rint(x/(2*M_PI)) * (2*M_PI) ); }
00151   
00152   //! if @a x is outside of the range of joint @a i, it is set to either the min or the max, whichever is closer
00153   static float clipAngularRange(unsigned int i, float x) {
00154     float min=outputRanges[i][MinRange];
00155     float max=outputRanges[i][MaxRange];
00156     if(x<min || x>max) {
00157       float mn_dist=std::abs(normalizeAngle(min-x));
00158       float mx_dist=std::abs(normalizeAngle(max-x));
00159       if(mn_dist<mx_dist)
00160   return min;
00161       else
00162   return max;
00163     } else
00164       return x;
00165   }
00166   //! if targetReached, reassigns headCmds from MotionManager::getOutputCmd(), then sets dirty to true and targetReached to false
00167   /*! should be called each time a joint value gets modified in case
00168    *  the head isn't where it's supposed to be, it won't jerk around
00169    * 
00170    *  MotionManager::getOutputCmd() is called instead of
00171    *  WorldState::outputs[] because if this is being called rapidly
00172    *  (i.e. after every sensor reading) using the sensor values will
00173    *  cause problems with very slow acceleration due to sensor lag
00174    *  continually resetting the current position.  Using the last
00175    *  value sent by the MotionManager fixes this.*/
00176   void markDirty();
00177 
00178   //! Makes sure @a i is in the range (0,NumHeadJoints).  If it is instead in the range (HeadOffset,HeadOffset+NumHeadJoints), output a warning and reset @a i to the obviously intended value.
00179   /*! @param[in] i joint offset relative to either HeadOffset (i.e. one of TPROffset_t) or 0
00180    *  @param[out] i joint offset relative to HeadOffset (i.e. one of TPROffset_t)
00181    *  @return true if the intended joint could be ascertained, false otherwise */
00182   static bool ensureValidJoint(unsigned int& i);
00183 
00184   bool dirty;                          //!< true if a change has been made since last call to updateJointCmds()
00185   bool  hold;                          //!< if set to true, the posture will be kept active; otherwise joints will be marked unused after each posture is achieved (as if the posture was pruned); set through setHold()
00186   float tolerance;                     //!< when autopruning, if the maxdiff() of this posture and the robot's current position is below this value, isAlive() will be false, defaults to 0.05 radian (2.86 degree error)
00187   bool targetReached;                  //!< false if the head is still moving towards its target
00188   unsigned int targetTimestamp;        //!< time at which the targetReached flag was set
00189   unsigned int timeout;                //!< number of milliseconds to wait before giving up on a target that should have already been reached, a value of -1U will try forever
00190   float headTargets[NumHeadJoints];    //!< stores the target value of each joint
00191   OutputCmd headCmds[NumHeadJoints];   //!< stores the last values we sent from updateOutputs
00192   float maxSpeed[NumHeadJoints];       //!< initialized from Config::motion_config, but can be overridden by setMaxSpeed(); rad per frame
00193 };
00194 
00195 /*! @file
00196  * @brief Describes HeadPointerMC, a class for various ways to control where the head is looking
00197  * @author ejt (Creator)
00198  */
00199 
00200 #endif

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