Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

SineMC.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_SineMC_h_
00003 #define INCLUDED_SineMC_h_
00004 
00005 #include "Motion/MotionCommand.h"
00006 #include "Motion/MotionManager.h"
00007 #include <cmath>
00008 
00009 //! Moves one or more outputs through a sinusoidal pattern
00010 class SineMC : public MotionCommand {
00011 public:
00012   //! constructor, sets default parameters to use full range of each joint, with a period of 2 seconds, but all weights to zero
00013   SineMC() : MotionCommand(), lastUpdate(get_time()+FrameTime*NumFrames) {
00014     for(unsigned int i=0; i<NumOutputs; ++i) {
00015       amp[i] = (outputRanges[i][MaxRange] - outputRanges[i][MinRange]) / 2;
00016       period[i]=2000;
00017       offset[i] = (outputRanges[i][MaxRange] + outputRanges[i][MinRange]) / 2;
00018       sync(i,lastUpdate);
00019     }
00020   }
00021 
00022   //! sets the weight of an output, zero-weighted outputs are ignored
00023   virtual void setWeight(unsigned int i, float w) { cmds[i].weight=w; }
00024   //! gets the weight of an output, zero-weighted outputs are ignored
00025   virtual float getWeight(unsigned int i) const { return cmds[i].weight; }
00026   
00027   //! sets the sine wave parameters
00028   /*! @param i the index of the output
00029    *  @param amplitude the peak-to-center amplitude
00030    *  @param period_time the period of the oscillation (milliseconds)
00031    *  @param offset_value sets the center position of the oscillation
00032    *  @param offset_time sets the phase shift of the oscillation
00033    *
00034    *  If the output weight is 0, it is set to 1. */
00035   virtual void setParams(unsigned int i, float amplitude, unsigned int period_time, float offset_value, unsigned int offset_time) {
00036     amp[i]=amplitude;
00037     period[i]=period_time;
00038     offset[i]=offset_value;
00039     start[i]=offset_time;
00040     if(cmds[i].weight<=0)
00041       cmds[i].weight=1;
00042   }
00043   //! sets the sine wave parameters
00044   /*! @param i the index of the output
00045    *  @param amplitude the peak-to-center amplitude
00046    *  @param period_time the period of the oscillation (milliseconds)
00047    *  @param offset_value sets the center position of the oscillation
00048    *  
00049    *  The offset time is synced to maintain current position.  If the output weight is 0, it is set to 1. */
00050   virtual void setParams(unsigned int i, float amplitude, unsigned int period_time, float offset_value) {
00051     amp[i]=amplitude;
00052     period[i]=period_time;
00053     offset[i]=offset_value;
00054     if(cmds[i].weight<=0)
00055       cmds[i].weight=1;
00056     sync(i);
00057   }
00058   //! gets the peak-to-center amplitude
00059   virtual float getAmplitude(unsigned int i) const { return amp[i]; }
00060   //! gets the period of the oscillation (milliseconds)
00061   virtual unsigned int getPeriod(unsigned int i) const { return period[i]; }
00062   //! gets the center position of the oscillation
00063   virtual float getOffsetValue(unsigned int i) const { return offset[i]; }
00064   //! gets the phase shift of the oscillation
00065   virtual unsigned int getOffsetTime(unsigned int i) const { return start[i]; }
00066   
00067   //! returns the percent of period completed
00068   virtual float getPhase(unsigned int i) const { float x = getCount(i); return x-std::floor(x); }
00069   //! returns the percent of period completed
00070   virtual float getCount(unsigned int i) const { unsigned int t=get_time(); return float(t-start[i])/period[i]; }
00071   
00072   //! returns the current target position of the specified output
00073   virtual float getPosition(unsigned int i) const { return cmds[i].value; }
00074   //! returns the current target speed of the specified output (radians/sec)
00075   virtual float getSpeed(unsigned int i) const {
00076     if(cmds[i].weight<=0)
00077       return 0;
00078     float scale = 2*static_cast<float>(M_PI)/period[i];
00079     return std::cos((lastUpdate-start[i])*scale)*amp[i]*scale*1000;
00080   }
00081   //! returns the current target acceleration of the specified output (radians/sec^2)
00082   virtual float getAcceleration(unsigned int i) const {
00083     if(cmds[i].weight<=0)
00084       return 0;
00085     float scale = 2*static_cast<float>(M_PI)/period[i];
00086     return -std::sin((lastUpdate-start[i])*scale)*amp[i]*scale*scale*1000*1000;
00087   }
00088   
00089   //! sets the offset_time of a specified output to match its current position so it won't suddenly snap to a new position
00090   virtual void sync(unsigned int i) { sync(i,get_time()); }
00091   
00092   //! sets the offset_time of a specified output to match its current position so it won't suddenly snap to a new position
00093   virtual void sync(unsigned int i, unsigned int t) {
00094     const float TWOPI = 2*static_cast<float>(M_PI);
00095     float x = (state->outputs[i]-offset[i])/amp[i];
00096     if(x>1)
00097       x=1;
00098     else if(x<-1)
00099       x=-1;
00100     start[i] = (unsigned int)rintf(t - std::asin(x)/TWOPI*period[i]);
00101   }
00102   
00103   //! sets the offset_time of all non-zero weighted joints to use the closest common phase, keeping all outputs in phase
00104   virtual void syncAll() {
00105     unsigned int t=get_time();
00106     float avg=0, totw=0;
00107     for(unsigned int i=0; i<NumOutputs; ++i) {
00108       sync(i,t);
00109       avg+=cmds[i].weight * start[i];
00110       totw+=cmds[i].weight;
00111     }
00112     avg/=totw;
00113     for(unsigned int i=0; i<NumOutputs; ++i)
00114       start[i]=(unsigned int)rintf(avg);
00115   }
00116   
00117   virtual int updateOutputs() {
00118     const float TWOPI = 2*static_cast<float>(M_PI);
00119     unsigned int t=get_time();
00120     unsigned int cnt=0;
00121     // this is probably overkill to split these cases, but anyway...
00122     if(NumFrames==1) {
00123       // single frame, make direct calls to avoid extra copy
00124       for(unsigned int i=0; i<NumOutputs; ++i) {
00125         if(cmds[i].weight>0) {
00126           cmds[i].value=std::sin((t-start[i])*TWOPI/period[i])*amp[i]+offset[i];
00127           motman->setOutput(this,i,cmds[i]);
00128           ++cnt;
00129         }
00130       }
00131     } else {
00132       // multiple frames, do them in bulk for efficiency
00133       OutputCmd tmp[NumFrames];
00134       for(unsigned int i=0; i<NumOutputs; ++i) {
00135         if(cmds[i].weight>0) {
00136           for(unsigned int f=0; f<NumFrames; ++f) {
00137             tmp[i].value=std::sin((t-start[i]+f*FrameTime)*TWOPI/period[i])*amp[i]+offset[i];
00138             tmp[i].weight=cmds[i].weight;
00139           }
00140           motman->setOutput(this,i,tmp);
00141           cmds[i].value = tmp[i].value;
00142           ++cnt;
00143         }
00144       }
00145     }
00146     lastUpdate=t+(NumFrames-1)*FrameTime;
00147     return cnt;
00148   }
00149     
00150   virtual int isDirty() { return true; }
00151   virtual int isAlive() { return true; }
00152 
00153 protected:
00154   OutputCmd cmds[NumOutputs];
00155   float amp[NumOutputs];
00156   unsigned int period[NumOutputs];
00157   float offset[NumOutputs];
00158   unsigned int start[NumOutputs];
00159   unsigned int lastUpdate;
00160 };
00161 
00162 /*! @file
00163  * @brief Defines SineMC, which DESCRIPTION
00164  * @author Ethan Tira-Thompson (ejt) (Creator)
00165  */
00166 
00167 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:51 2016 by Doxygen 1.6.3