Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

PostureEngine.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_PostureEngine_h
00003 #define INCLUDED_PostureEngine_h
00004 
00005 #include "Motion/OutputCmd.h"
00006 #include "Motion/Kinematics.h"
00007 #include "Shared/RobotInfo.h"
00008 #include "Shared/LoadSave.h"
00009 
00010 class WorldState;
00011 
00012 //! A class for storing a set of positions and weights for all the outputs
00013 /*! Handy for any class which wants to deal with setting joints and postures without writing a custom class
00014  *  @see PostureMC
00015  *  @see <a href="http://www.cs.cmu.edu/~tekkotsu/Kinematics.html">Tekkotsu's Kinematics page</a>
00016  *  @see <a href="http://www.cs.cmu.edu/~dst/Tekkotsu/Tutorial/postures.shtml">David Touretzky's "Postures and Motion Sequences" Chapter</a>
00017  *  @see <a href="http://www.cs.cmu.edu/~dst/Tekkotsu/Tutorial/forwardkin.shtml">David Touretzky's "Forward Kinematics" Chapter</a>
00018  *  @see <a href="http://www.cs.cmu.edu/afs/cs/academic/class/15494-s06/www/lectures/postures.pdf">CMU's Cognitive Robotics posture slides</a>
00019  *  @see <a href="http://www.cs.cmu.edu/afs/cs/academic/class/15494-s06/www/lectures/kinematics.pdf">CMU's Cognitive Robotics kinematics slides</a>
00020  */
00021 class PostureEngine : public LoadSave, public Kinematics {
00022 public:
00023 
00024   //!@name Constructors
00025   
00026   //!constructor
00027   PostureEngine() : LoadSave(), Kinematics(*kine), saveFormatCondensed(false), loadSaveSensors(NULL) {}
00028   //!constructor, loads a position from a file
00029   /*! @todo might want to make a library stored in memory of common positions so they don't have to be loaded repeatedly from memstick */
00030   PostureEngine(const std::string& filename) : LoadSave(), Kinematics(*kine), saveFormatCondensed(false), loadSaveSensors(NULL) { loadFile(filename.c_str()); }
00031   //!constructor, initializes joint positions to the current state of the outputs as defined by @a state
00032   PostureEngine(const WorldState* st) : LoadSave(), Kinematics(*kine), saveFormatCondensed(false), loadSaveSensors(NULL) { if(st!=NULL) takeSnapshot(*st); }
00033 
00034   //! copy constructor
00035   PostureEngine(const PostureEngine& pe)
00036     : LoadSave(pe), Kinematics(pe), saveFormatCondensed(pe.saveFormatCondensed), loadSaveSensors(pe.loadSaveSensors)
00037   {
00038     for(unsigned int i=0; i<NumOutputs; i++)
00039       cmds[i]=pe.cmds[i];
00040   }
00041     
00042   //! assignment operator
00043   PostureEngine& operator=(const PostureEngine& pe) {
00044     LoadSave::operator=(pe);
00045     Kinematics::operator=(pe);
00046     saveFormatCondensed=pe.saveFormatCondensed;
00047     loadSaveSensors=pe.loadSaveSensors;
00048     for(unsigned int i=0; i<NumOutputs; i++)
00049       cmds[i]=pe.cmds[i];
00050     return *this;
00051   }
00052 
00053   //! destructor
00054   virtual ~PostureEngine();
00055   //@}
00056 
00057 
00058 
00059   //! You should be able to call the non-virtual functions without checking out, just a MotionManager::peekMotion().  Theoretically.
00060   //!@name Output Value Access/Control
00061   virtual void takeSnapshot(); //!< sets the values of #cmds to the current state of the outputs (doesn't change the weights)
00062   virtual void takeSnapshot(const WorldState& st); //!< sets the values of #cmds to the current state of the outputs as defined by @a state (doesn't change the weights)
00063   virtual void setWeights(float w) { setWeights(w,0,NumOutputs); } //!< set the weights of all #cmds
00064   virtual void setWeights(float w, unsigned int lowjoint, unsigned int highjoint); //!< the the weights of a range of #cmds
00065   virtual void clear(); //!< sets all joints to unused
00066   inline PostureEngine& setOutputCmd(unsigned int i, const OutputCmd& c) { cmds[i]=c; return *this; } //!<sets output @a i to OutputCmd @a c, returns @c *this so you can chain them; also remember that OutputCmd support implicit conversion from floats (so you can just pass a float)
00067   inline OutputCmd& operator()(unsigned int i) { return cmds[i]; } //!< returns output @a i, returns a reference so you can also set through an assignment to this call, e.g. pose(MouthOffset)=.1; (remember that OutputCmd support implicit conversion from floats)
00068   inline const OutputCmd& operator()(unsigned int i) const { return cmds[i]; } //!< returns output @a i
00069   inline OutputCmd& getOutputCmd(unsigned int i) { return cmds[i]; } //!< returns output @a i, returns a reference so you can also set through an assignment
00070   inline const OutputCmd& getOutputCmd(unsigned int i) const { return cmds[i]; } //!< returns output @a i
00071   //@}
00072 
00073 
00074 
00075   //!Uses LoadSave interface so you can load/save to files, uses a human-readable storage format
00076   //!@name LoadSave
00077   virtual void setSaveFormat(bool condensed, WorldState* ws); //!< sets #saveFormatCondensed and #loadSaveSensors (pass ::state for @a ws if you want to use current sensor values)
00078   virtual void setLoadedSensors(WorldState* ws) { loadSaveSensors=ws; } //!< if @a ws is non-NULL, any sensor values in loaded postures will be stored there (otherwise they are ignored)
00079   virtual WorldState* getLoadedSensors() const { return loadSaveSensors; } //!< returns value previously stored by setLoadSensors()
00080   virtual unsigned int getBinSize() const;
00081   virtual unsigned int loadBuffer(const char buf[], unsigned int len);
00082   virtual unsigned int saveBuffer(char buf[], unsigned int len) const;
00083   virtual unsigned int loadFile(const char filename[]);
00084   virtual unsigned int saveFile(const char filename[]) const;
00085   //@}
00086 
00087 
00088 
00089   //!@name Kinematics
00090 
00091   //! Performs inverse kinematics to solve for positioning @a Peff on link @a j as close as possible to @a Ptgt (base coordinates in homogenous form); if solution found, stores result in this posture and returns true
00092   /*! @param Ptgt the target point, in base coordinates
00093    *  @param link the output offset of the joint to move
00094    *  @param Peff the point (relative to @a link) which you desire to have moved to @a Ptgt (it's the desired "effector")
00095    *
00096    *  The difference between solveLinkPosition() and solveLinkVector() is typically small,
00097    *  but critical when you're trying to look at something -- the solution obtained by
00098    *  simplying trying to solve for the position may not align the vector with the target --
00099    *  solveLinkVector() tries to ensure the vector is aligned with the target, even if that
00100    *  isn't the closest solution position-wise.
00101    */
00102   virtual bool solveLinkPosition(const NEWMAT::ColumnVector& Ptgt, unsigned int link, const NEWMAT::ColumnVector& Peff);
00103 
00104   //! Performs inverse kinematics to solve for positioning Peff on link @a j as close as possible to @a Ptgt (base coordinates); if solution found, stores result in this posture and returns true
00105   /*! @param Ptgt_x the target x position (relative to base frame)
00106    *  @param Ptgt_y the target y position (relative to base frame)
00107    *  @param Ptgt_z the target z position (relative to base frame)
00108    *  @param link the output offset of the joint to move
00109    *  @param Peff_x the x position (relative to @a link) which you desire to have moved to @a Ptgt (it's the desired "effector")
00110    *  @param Peff_y the y position (relative to @a link) which you desire to have moved to @a Ptgt (it's the desired "effector")
00111    *  @param Peff_z the z position (relative to @a link) which you desire to have moved to @a Ptgt (it's the desired "effector")
00112    *
00113    *  The difference between solveLinkPosition() and solveLinkVector() is typically small,
00114    *  but critical when you're trying to look at something -- the solution obtained by
00115    *  simplying trying to solve for the position may not align the vector with the target --
00116    *  solveLinkVector() tries to ensure the vector is aligned with the target, even if that
00117    *  isn't the closest solution position-wise.
00118    */
00119   virtual bool solveLinkPosition(float Ptgt_x, float Ptgt_y, float Ptgt_z, unsigned int link, float Peff_x, float Peff_y, float Peff_z)
00120   { return solveLinkPosition(pack(Ptgt_x,Ptgt_y,Ptgt_z),link,pack(Peff_x,Peff_y,Peff_z)); }
00121 
00122   //! Performs inverse kinematics to solve for aligning the vector through Peff on link @a j and the link's origin to point at @a Ptgt (base coordinates in homogenous form); if solution found, stores result in this posture and returns true
00123   /*! @param Ptgt the target point, in base coordinates
00124    *  @param link the output offset of the joint to move
00125    *  @param Peff the point (relative to @a link) which you desire to have moved to @a Ptgt (it's the desired "effector")
00126    *
00127    *  The difference between solveLinkPosition() and solveLinkVector() is typically small,
00128    *  but critical when you're trying to look at something -- the solution obtained by
00129    *  simplying trying to solve for the position may not align the vector with the target --
00130    *  solveLinkVector() tries to ensure the vector is aligned with the target, even if that
00131    *  isn't the closest solution position-wise.
00132    */
00133   virtual bool solveLinkVector(const NEWMAT::ColumnVector& Ptgt, unsigned int link, const NEWMAT::ColumnVector& Peff);
00134 
00135   //! Performs inverse kinematics to solve for aligning the vector through Peff on link @a j and the link's origin to point at @a Ptgt (base coordinates); if solution found, stores result in this posture and returns true
00136   /*! @param Ptgt_x the target x position (relative to base frame)
00137    *  @param Ptgt_y the target y position (relative to base frame)
00138    *  @param Ptgt_z the target z position (relative to base frame)
00139    *  @param link the output offset of the joint to move
00140    *  @param Peff_x the x position (relative to @a link) which you desire to have moved to @a Ptgt (it's the desired "effector")
00141    *  @param Peff_y the y position (relative to @a link) which you desire to have moved to @a Ptgt (it's the desired "effector")
00142    *  @param Peff_z the z position (relative to @a link) which you desire to have moved to @a Ptgt (it's the desired "effector")
00143    *
00144    *  @todo this method is an approximation, could be more precise, and perhaps faster, although this is pretty good.
00145    *
00146    *  The difference between solveLinkPosition() and solveLinkVector() is typically small,
00147    *  but critical when you're trying to look at something -- the solution obtained by
00148    *  simplying trying to solve for the position may not align the vector with the target --
00149    *  solveLinkVector() tries to ensure the vector is aligned with the target, even if that
00150    *  isn't the closest solution position-wise.
00151    */
00152   virtual bool solveLinkVector(float Ptgt_x, float Ptgt_y, float Ptgt_z, unsigned int link, float Peff_x, float Peff_y, float Peff_z)
00153   { return solveLinkVector(pack(Ptgt_x,Ptgt_y,Ptgt_z),link,pack(Peff_x,Peff_y,Peff_z)); }
00154 
00155   //@}
00156 
00157 
00158 
00159   //!@name Combining Postures
00160   
00161   //! sets joints of this to all joints of @a pe which are not equal to unused (layers @a pe over this) stores into this
00162   virtual PostureEngine& setOverlay(const PostureEngine& pe);
00163   //! sets joints of this to all joints of @a pe which are not equal to unused (layers @a pe over this) returns new PostureEngine
00164   virtual PostureEngine createOverlay(const PostureEngine& pe) const;
00165 
00166   //! sets joints of this which are equal to unused to @a pe, (layers this over @a pe) stores into this
00167   virtual PostureEngine& setUnderlay(const PostureEngine& pe);
00168   //! sets joints of this which are equal to unused to @a pe, (layers this over @a pe) returns new PostureEngine
00169   virtual PostureEngine createUnderlay(const PostureEngine& pe) const;
00170 
00171   //! computes a weighted average of this vs. @a pe, @a w being the weight towards @a pe (so @a w==1 just copies @a pe)
00172   virtual PostureEngine& setAverage(const PostureEngine& pe,float w=0.5);
00173   //! computes a weighted average of this vs. @a pe, @a w being the weight towards @a pe (so @a w==1 just copies @a pe)
00174   virtual PostureEngine createAverage(const PostureEngine& pe,float w=0.5) const;
00175 
00176   //! computes a weighted average of this vs. @a pe, using the weight values of the joints, storing the total weight in the result's weight value
00177   virtual PostureEngine& setCombine(const PostureEngine& pe);
00178   //! computes a weighted average of this vs. @a pe, using the weight values of the joints, storing the total weight in the result's weight value
00179   virtual PostureEngine createCombine(const PostureEngine& pe) const;
00180 
00181   //! returns the sum squared error between this and pe's output values, but only between outputs which are both not unused
00182   /*! @todo create a version which does weighted summing?  This treats weights as all or nothing */
00183   virtual float diff(const PostureEngine& pe) const;
00184   
00185   //! returns the average sum squared error between this and pe's output values for outputs which are both not unused
00186   /*! @todo create a version which does weighted summing?  This treats weights as all or nothing */
00187   virtual float avgdiff(const PostureEngine& pe) const;
00188   
00189   //! returns the max error between this and pe's output values for outputs which are both not unused
00190   /*! @todo create a version which does weighted summing?  This treats weights as all or nothing */
00191   virtual float maxdiff(const PostureEngine& pe) const;
00192   
00193   //@}
00194 
00195 protected:
00196   //all updates come from this posture engine's own state, not WorldState
00197   virtual void update(unsigned int c, unsigned int l);
00198 
00199   //!the table of outputs' values and weights, can be accessed through setOutputCmd() and getOutputCmd()
00200   OutputCmd cmds[NumOutputs];
00201 
00202   bool saveFormatCondensed;      //!< requests a condensed file format, smaller but less readable
00203   WorldState* loadSaveSensors;   //!< If non-null, saves will include sensor readings from here, and loads will store any read sensors into here
00204 };
00205 
00206 /*! @file
00207  * @brief Describes PostureEngine, a base class for managing the values and weights of all the outputs
00208  * @author ejt (Creator)
00209  *
00210  * $Author: ejt $
00211  * $Name: tekkotsu-3_0 $
00212  * $Revision: 1.23 $
00213  * $State: Exp $
00214  * $Date: 2006/10/04 02:57:12 $
00215  */
00216 
00217 #endif

Tekkotsu v3.0
Generated Wed Oct 4 00:03:45 2006 by Doxygen 1.4.7