Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

XWalkMC.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_XWalkMC_h_
00003 #define INCLUDED_XWalkMC_h_
00004 
00005 #include "Motion/XWalkParameters.h"
00006 #include "Motion/MotionCommand.h"
00007 #include "Motion/MotionManager.h"
00008 #include "Motion/KinematicJoint.h"
00009 #include "Motion/IKSolver.h"
00010 #include "Shared/fmatSpatial.h"
00011 #include "Shared/Config.h"
00012 #include "Shared/get_time.h"
00013 #include "IPC/DriverMessaging.h"
00014 #include <set>
00015 
00016 //! Extreme walk engine handles legged locomotion on hexapods and beyond
00017 class XWalkMC : public MotionCommand, public XWalkParameters {
00018 public:
00019   //! constructor
00020   XWalkMC() : MotionCommand(), XWalkParameters(), targetVel(), targetAngVel(0), targetDisp(), targetAngDisp(0), velocityMode(true), 
00021         displacementTime(0), plantingLegs(false), initialPlacement(true), p(), transitions(), active(), startTime(get_time()), 
00022         period(0), globPhase(0), rotationCenter(), contactMsg() {
00023     if(kine==NULL) {
00024       kine = new KinematicJoint;
00025       kine->loadFile(::config->makePath(config->motion.kinematics).c_str());
00026       kine->buildChildMap(childMap,0,NumReferenceFrames);
00027     }
00028     loadFile(::config->motion.makePath("xwalk.plist").c_str());
00029     p.loadFile(::config->motion.makePath("xwalk.plist").c_str());
00030     spiderSettings(*this,p);
00031     if(kine!=NULL && kine->getBranches().size()>0)
00032       updateNeutralPos((unsigned int)startTime);
00033     setTargetVelocity(targetVel[0],targetVel[1],targetAngVel);
00034   }
00035   
00036   //! Returns the current x and y velocities in mm/sec
00037   const fmat::Column<2>& getTargetVelocity() const { return targetVel; };
00038   
00039   //! Returns the current angular velocity in radians/sec
00040   float getTargetAngVelocity() const { return targetAngVel; }
00041 
00042   //! Specify the desired body velocity in x and y (millimeters per second) and angular velocity (radians per second)
00043   virtual void getTargetVelocity(float &xvel, float &yvel, float &avel) {
00044     xvel = targetVel[0];
00045     yvel = targetVel[1];
00046     avel = targetAngVel;
00047   }
00048 
00049   //! Specify the desired body velocity in x and y (millimeters per second) and angular velocity (radians per second); does not stop automatically
00050   virtual void setTargetVelocity(float xvel, float yvel, float avel);
00051 
00052   //! Specify the desired body velocity in x and y (millimeters per second) and angular velocity (radians per second), and amount of time (seconds) before stopping
00053   virtual void setTargetVelocity(float xvel, float yvel, float avel, float time);
00054   
00055   //! Specify the desired body displacement in x and y (millimeters) and angle (radians), optionally specify time (seconds)
00056   /*! Corresponding velocity will be limited to max velocity, so setting time=0 implies max speed */
00057   virtual void setTargetDisplacement(float xdisp, float ydisp, float adisp, float time=0);
00058 
00059   virtual int updateOutputs();
00060 
00061   virtual int isDirty() { 
00062     for(unsigned int i=0; i<NumLegs; ++i)
00063       if(legStates[i].support<1)
00064         return true;
00065     return (targetVel.norm()>=EPSILON || std::abs(targetAngVel)>=EPSILON || active.size()>0);
00066   }
00067 
00068   virtual int isAlive() { return true; }
00069 
00070   virtual void start();
00071   
00072   virtual void stop();
00073 
00074   //! Posts a LocomotionEvent and sets velocities to zero. Also forces an output frame setting wheel velocities to zero; needed because if we remove a motion command there may be nothing left to zero the velocities.
00075   virtual void zeroVelocities();
00076 
00077   
00078 #if 0
00079   //! Adjusts body height to lock knees and minimize joint torque to hold position, doesn't move feet
00080   /*! Implies a call to setTargetVelocity(0,0,0); later calls to set a non-zero velocity will cancel the leg lock. */
00081   void lockLegsInPlace();
00082 #endif
00083   
00084 protected:
00085   //! recomputes each leg's LegState::neutralPos based on current values in #p
00086   void updateNeutralPos(unsigned int curTime);
00087   // updates period based on stride length parameter, returns true if no significant motion is currently requested
00088   bool resetPeriod(float time, float speed);
00089   //! recomputes LegState::downPos and LegState::liftPos based on specified state variables, such that the direction of stride rotates about the current position
00090   void resetLegState(unsigned int leg, float phase, const fmat::Column<3>& curPos, bool inAir, float speed);
00091   
00092   void updateOutputsInitial(unsigned int curTime, const fmat::Column<3>& ground, const fmat::Column<3>& gravity, IKSolver::Point tgts[]);
00093   void updateOutputsWalking(float dt, const fmat::Column<3>& ground, const fmat::Column<3>& gravity, float speed, IKSolver::Point tgts[]);
00094   void sendLoadPredictions(IKSolver::Point tgts[]);
00095   
00096   //! updates #globPhase based on specified stride time (relative to #startTime)
00097   void computePhase(float time);
00098   //! computes current leg state based on #globPhase
00099   void computeLegPhase(unsigned int leg, bool& inAir, float& phase);
00100   //! computes the leg position (in xy plane only) based on leg state
00101   void computeCurrentPosition(unsigned int leg, bool inAir, float speed, float phase, fmat::Column<3>& tgt);
00102   //! computes body position based on settings in #p, which should then be added to leg positions before projecting onto ground plane
00103   void computeCurrentBodyOffset(float* legPhases, float speed, float& offx, float& offy, float& offa);
00104   //! solves inverse kinematics and send affected output values to motion manager
00105   void solveIK(unsigned int leg, const IKSolver::Point& tgt);
00106   
00107   // Given the mass, its position x and y, and a list of contact points, stores results into @a pressures
00108   /*! @param mass being supported in kilograms
00109    *  @param massx center of mass along x axis, in millimeters
00110    *  @param massy center of mass along y axis, in millimeters
00111    *  @param contacts position of each support contact, in millimeters
00112    *  @param[out] pressures will be resized and overwritten with pressure at each corresponding point in @a contacts, in newtons
00113    *  
00114    *  Note the z position is irrelevant, all points should be projected to the same plane, normal to gravity vector.<br>
00115    *  Thanks Jacqueline K. Libby for helping figure out the free-body diagram/computation upon which this function is based. */
00116   void computePressure(float mass, float massx, float massy, const std::vector<fmat::Column<2> >& contacts, std::vector<float>& pressures);
00117   
00118   //! recursively processes contents of @a src, creating a ParameterTransition for each entry to smoothly update corresponding entries in @a dst
00119   void spiderSettings(plist::DictionaryBase& src, plist::DictionaryBase& dst);
00120   //! recursively processes contents of @a src, creating a ParameterTransition for each entry to smoothly update corresponding entries in @a dst
00121   void spiderSettings(plist::ArrayBase& src, plist::ArrayBase& dst);
00122   
00123   //! 
00124   class ParameterTransition : plist::PrimitiveListener {
00125   public:
00126     //! constructor, specify source to be monitored, destination to be kept in sync, a collection to be updated when transitions are in progress, and desired duration of transitions
00127     ParameterTransition(const plist::PrimitiveBase& srcVal, plist::PrimitiveBase& dstVal, std::set<ParameterTransition*>& activeTrans, unsigned int dur) : src(srcVal), dst(dstVal), active(activeTrans), curd(0), cura(0),
00128     startTime(), duration(dur), lastUpdate(), decelerate(false)
00129     {
00130       dst=src;
00131       src.addPrimitiveListener(this);
00132     }
00133     //! destructor
00134     ~ParameterTransition() { src.removePrimitiveListener(this); }
00135     virtual void plistValueChanged(const plist::PrimitiveBase& /*pl*/);
00136     bool update(unsigned int curTime);
00137     
00138     const plist::PrimitiveBase& src; //!< the parameter which is being monitored for changes (a member of the superclass of XWalkMC)
00139     plist::PrimitiveBase& dst; //!< the parameter which is updated with smoothly transitioning values based on #src
00140     std::set<ParameterTransition*>& active; //!< collection which ParameterTransition will insert itself when src has been changed and transition is in progress
00141     float curd; //!< current velocity of parameter (d for derivative)
00142     float cura; //!< current acceleration of parameter
00143     unsigned int startTime; //!< time at which src was changed
00144     unsigned int duration; //!< how much time to use in transitioning (#cura is then based on difference between #src and #dst, and this)
00145     unsigned int lastUpdate; //!< time of last call to update() or reset()
00146     bool decelerate; //!< set to true if in the deceleration phase of transitioning
00147   };
00148   
00149   
00150   fmat::Column<2> targetVel; //!< the requested xy velocity of the body (ignoring parameterized body motion, like sway or surge), millimeters per second
00151   float targetAngVel; //!< the requested angular velocity of the body, radians per second
00152   fmat::Column<2> targetDisp; //!< the requesed xy displacement of the body, in millimeters
00153   float targetAngDisp; //!< the requested angular displacement of the body in radians
00154   bool velocityMode; //!< True if we just want to maintain a velocity; false if we're trying to achieve a displacement
00155   unsigned int displacementTime; //!< time in msecs since setTargetDisplacement called
00156   bool plantingLegs; //!< True if we've finished a displacement and are waiting for all legs to come to ground before posting a status event
00157   bool initialPlacement; //!< set to true when legs are in an unknown configuration (e.g. following start())
00158   XWalkParameters p; //!< current parameter values, subject to smoothed transition from those as members of the superclass (see ParameterTransition)
00159   std::set<ParameterTransition*> transitions; //!< full collection of parameter listeners
00160   std::set<ParameterTransition*> active; //!< collection of those listeners which are actively transitioning their corresponding parameters in #p
00161   float startTime; //!< must be float (not unsigned int) because value can go negative: phase offset of "walk time" from system get_time() (milliseconds)
00162   float period; //!< the time between leg lifts (milliseconds), calculated value to yield target speed (#targetVel)
00163   float globPhase; //!< the current phase within the walk, in turn controls phase of individual legs via updateLegPhase()
00164   fmat::Column<2> rotationCenter; //!< if the target angular velocity (#targetAngVel) is producing a reasonable curvature vs. targetVel, this is the point about which the body is arcing
00165   DriverMessaging::FixedPoints contactMsg; //!< list of current contact points, for better Mirage simulation
00166   
00167   //! contains cached information about each leg's stride
00168   struct LegState {
00169     //! constructor
00170     LegState() : inAir(false), onGround(false), initialHeight(), support(1), reorder(-1U), neutralPos(), liftPos(), downPos() {}
00171     
00172     //! True if the leg is currently in the return flight phase, false if its xy motion is linked to the ground.
00173     /*! Note that if this is false, the leg may be in the process of raising or lowering to the ground, but not actually providing support */
00174     bool inAir;
00175     //! True if the leg is currently providing support on the ground, false if in the air (including raise or lower)
00176     bool onGround;
00177     float initialHeight; //!< during initial placement, stores the height of the leg when start() was called
00178     float support; //!< at the beginning and end of support phase, leg is lifted... this indicates how much lift has occurred/remains (range 0: in air, to 1: on ground)
00179     unsigned int reorder; //!< if a valid leg index (i.e. not -1U), indicates the index of the leg from which the phase offset parameter (XWalkParameters::LegParameters::flightPhase) should be used
00180     fmat::Column<2> neutralPos; //!< indicates the mid-stride foot position
00181     fmat::Column<2> liftPos; //!< indicates the position the leg was lifted from during flight, or the last target point during support
00182     fmat::Column<2> downPos; //!< indicates the position the leg will be placed following flight, or would have been placed to maintain continuity if target velocities change (see resetLegState())
00183   };
00184   LegState legStates[NumLegs]; //!< storage of cached stride information for each leg
00185   
00186   static KinematicJoint* kine;
00187   static KinematicJoint* childMap[NumReferenceFrames];
00188 };
00189 
00190 /*! @file
00191  * @brief Defines XWalkMC, which DESCRIPTION
00192  * @author Ethan Tira-Thompson (ejt) (Creator)
00193  */
00194 
00195 #endif

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