Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

LedEngine.h

Go to the documentation of this file.
00001 #ifndef INCLUDED_LedEngine_h
00002 #define INCLUDED_LedEngine_h
00003 
00004 #include "Shared/RobotInfo.h"
00005 #ifdef TGT_HAS_LEDS
00006 
00007 #include "Shared/get_time.h"
00008 #include "OutputCmd.h"
00009 #include <math.h>
00010 
00011 class MotionCommand;
00012 
00013 // LEDBitMask_t and associated constants are defined in RobotInfo.h
00014 
00015 //! Provides basic LED effects via subclassing (e.g. LedMC) or embedding (e.g. EmergencyStopMC)
00016 /*! This implements a collection of LED special effects so that the code can be
00017  *  reused various places as feedback to to the user.
00018  *
00019  * The basic effects provided are:
00020  * - static brightness (set(), cset(), invert(), clear())
00021  * - temporary setting (flash(), cflash())
00022  * - pulsing/blinking (cycle(), ccycle())
00023  * - numeric display (displayNumber(), displayPercent())
00024  *
00025  * The 'c' prefix on a function (cset(), cflash(), ccycle()) means it will call clear() before doing its own setting.  This is
00026  * a quick way to replace whatever is currently displayed with whatever you are about to display.
00027  * 
00028  * A flash() will invert and override the current setting, so that it
00029  * will "reset" after the flash.  Flashes change mid-range values to
00030  * extremes to make the flash visible (ie not just (1-current)) Normal
00031  * invert() will do simple inverses (just (1-current)), and doesn't change back automatically.
00032  *
00033  * Cycling ("pulsing") and single-value setting are mutually exclusive;
00034  * one will cut off the other
00035  *
00036  * getSetting() returns value of last set();
00037  * getValue() returns what's actually being returned to Motion at the moment
00038  *
00039  * There's some nice functions for using the LEDs to display numbers.
00040  * This is handy for when you want to be free of the terminal.
00041  * <img src="NumberLEDs.jpg">
00042  *
00043  * The ERS-220 and ERS-7 have enough LEDs that they just use a "count
00044  * the lights" style of display instead of this pseudo-arabic display.
00045  * (look close to see that green bar LED at the top of the 210, which 
00046  * doesn't show up well in the camera image for some reason. )
00047  * <img src="NumberLEDs-ERS7.jpg">
00048  *
00049  * The ERS-7 also has a "mode" which controls how certain face LEDs are
00050  * interpreted.  By setting ERS7Info::LEDABModeOffset /
00051  * ERS7Info::LEDABModeMask, you can switch between the modes -- a value
00052  * of 0 is mode "A", and a value of 1 is mode "B".
00053  * <img src="ERS7-LED-Modes.png">
00054  *
00055  * Things to note for the ERS-7:
00056  * - There are many fewer LEDs than there are holes in the "grill" (the holes you see on the face are not the positions of the LEDs.
00057  * - Each LED covers several holes.
00058  * - Not all holes have LEDs behind them -- some areas of the face panel are always dark.
00059  * - Some LEDs (12 and 13) control two symmetrical physical LEDs.
00060  * - Some LEDs change color based on mode (0-1), some don't change at all (2-11), and some change position and color (12-13)
00061  * - We don't have individual names for all of the LEDs on the panel.  Instead you base off of FaceLEDPanelOffset or FaceLEDPanelMask to address the LEDs, e.g., to set the <i>n</i>th led to <i>x</i>:
00062  *   @code
00063  *   LedEngine::set(FaceLEDPanelMask << n, x)
00064  *   @endcode
00065  *   or (if using other classes, e.g. PostureEngine)
00066  *   @code
00067  *   PostureEngine::setOutputCmd(FaceLEDPanelOffset + n, x)
00068  *   @endcode
00069  */
00070 
00071 class LedEngine {
00072  public:
00073   //!constructor - don't forget to call if you inherit
00074   LedEngine();
00075   //!destructor
00076   virtual ~LedEngine() {}
00077   
00078   //! call this from a MotionCommand's updateOutputs() - makes calls to MotionManager to update LED values
00079   /*! @param caller pass the "parent" motioncommand's address here (usually will pass 'this')
00080    *  @param mask a bitmask of which leds to update (uses weight of 1) */
00081   int updateLEDs(const MotionCommand* caller,LEDBitMask_t mask=AllLEDMask);
00082   
00083   //! call this from a MotionCommand's updateOutputs() - performs the calculations to update LEDs' values
00084   /*! @param cmds on input, used for weight values - on return, holds the resulting OutputCmd's*/
00085   int updateLEDs(OutputCmd cmds[NumLEDs]);
00086 
00087   //! call this from a MotionCommand's updateOutputs() - performs the calculations to update LEDs' values
00088   /*! @param cmds on input, used for weight values - on return, holds the resulting OutputCmd's*/
00089   int updateLEDFrames(OutputCmd cmds[NumLEDs][NumFrames]);
00090   
00091   //! recalculates #nextFlashEnd so we can tell when a flash has completed
00092   void recalcFlashEnd();
00093 
00094   //! returns true if there are changes since the last updateLEDs()
00095   int isDirty();
00096 
00097   //!sets the leds specified by @a leds to the inverse of their current value
00098   void invert(LEDBitMask_t leds);
00099   //!sets the leds specified by @a leds to @a value, clears all the rest
00100   inline void cset(LEDBitMask_t leds, float value) { clear(); set(leds,value); }
00101   //!sets the leds specified by @a leds to @a value
00102   void set(LEDBitMask_t leds, float value);
00103   //!sets the leds specified by @a leds to @a value for @a ms milliseconds, then sets back.  Clears ~leds
00104   void cflash(LEDBitMask_t leds, float value, unsigned int ms);
00105   //!sets the leds specified by @a leds to @a value for @a ms milliseconds, then sets back.
00106   void flash(LEDBitMask_t leds, float value, unsigned int ms);
00107   //!sets the leds specified by @a leds to either a much higher or much lower value for @a ms milliseconds, then sets back.
00108   void flash(LEDBitMask_t leds, unsigned int ms);
00109   //!causes the leds specified by @a leds to cycle between low and high, clears others.  See cycle() for parameter documentation.
00110   inline void ccycle(LEDBitMask_t leds, unsigned int period, float amp, float offset=0, int phase=0) { clear(); cycle(leds,period,amp,offset,phase); }
00111   //!causes the leds specified by @a leds to cycle between low and high; values calculated for cycle will be clipped to [0,1] for more sensible blending of square wave approximations (high amplitude sine wave)
00112   void cycle(LEDBitMask_t leds, unsigned int period, float amp, float offset=0, int phase=0);
00113   //!sets all leds to 0.
00114   void clear();
00115   
00116   //!adds @a ms to all flash times (may resurrect previously completed flashes)
00117   void extendFlash(unsigned int ms);
00118 
00119   //!returns the current setting of the LED specified by @a led_id (the value you passed in set())
00120   float getSetting(LEDOffset_t led_id) {
00121 #ifndef TGT_HAS_LEDS
00122     (void)led_id; // avoid unused argument warning
00123     return 0;
00124 #else
00125     return infos[led_id-LEDOffset].value;
00126 #endif
00127   }
00128   //!returns the current value of the LED specified by @a led_id (the value being expressed - may change if cycling for instance)
00129   float getValue(LEDOffset_t led_id,unsigned int planahead=0) {
00130 #ifndef TGT_HAS_LEDS
00131     (void)led_id; (void)planahead; // avoid unused argument warnings
00132     return 0;
00133 #else
00134     return calcValue(led_id-LEDOffset,get_time()+planahead);
00135 #endif
00136   }
00137   
00138 #ifdef TGT_HAS_LED_PANEL
00139   //!holds a series of bit masks for the onedigit style of numerical display (-9:9 and '.')
00140   /*!the hope is that these actually resemble the shapes of the numbers so people can
00141    * recognize them more easily - without counting or converting base 2 in their heads. */
00142   static const LEDBitMask_t defaultMimicNumMasks[11];
00143   static const LEDBitMask_t ERS220numMasks[11]; //!< bit masks for the ondigit style of numberical display - just count the LEDs on the head
00144   static const LEDBitMask_t ERS7numMasks[11]; //!< bit masks for the ondigit style of numberical display - just count the LEDs on the head
00145 #endif
00146   static const LEDBitMask_t defaultCountNumMasks[11]; //!< bit masks for the ondigit style of numberical display - just count the LEDs on the head
00147   //!Use these to specify a style for displaying numbers using displayNumber()
00148   enum numStyle_t {
00149     onedigit, //!< can display a number -9 thru 9, using the current robot model's numMask.  For negative numbers, blinks the top bar - fast if it's supposed to be on, slow if it would otherwise be off
00150     twodigit  //!< can display a number -99 thru 99, using setOneOfTwo().  For negative numbers, sets the top bar to 1 (off otherwise).
00151   };
00152   //!Use these to specify a style for displaying a percentage value [0-1] using displayPercent()
00153   enum percentStyle_t {
00154     major, //!< shows overall value
00155     minor, //!< shows value within major tick
00156     none   //!< if you want to leave blank
00157   };
00158     
00159   //!Allows convenient display of numerical information to the LEDs on the face.
00160   /*!If overflow occurs, the face LEDs are set to flash on and off 3 every 333 milliseconds*/
00161   void displayNumber(int x, numStyle_t style);
00162   //!Allows convenient display of percentage information to the LEDs on the face.
00163   /*!Besides allowing a two-digit display, the 'edge' bar for each type is blinked to
00164    * denote how full it is.  So you can get up to a two-digit, base 5 display, with an
00165    * extra digit of estimated value.
00166    *
00167    * If overflow (>1) occurs, sets everything to .75. <br>
00168    * If underflow (<0) occurs, sets everything to .25.
00169    * 
00170    * The left and right columns are combined with an OR operation.  (they overlap on the top bar)
00171    * Left and right designations are <em>dog centric!</em> */
00172   void displayPercent(float x, percentStyle_t left_style, percentStyle_t right_style);
00173   
00174  protected:
00175   //!Performs the 'invert' calculation based on current value (returns 1-value)
00176   static float calcInvert(float value) {
00177     return 1-value;
00178   }
00179   //!Performs the 'flash' calculation based on current value (uses calcInvert() if value upper or lower third, 0 or 1 otherwise)
00180   static float calcFlash(float value) {
00181     if(value>.33333 && value<.66666)
00182       return (value<.5 ? 1 : 0);
00183     else
00184       return calcInvert(value);
00185   }
00186   //!Performs the 'cycle' calculation based on desired period, amplituted, amplitude offset, and time since start.  See cycle()
00187   static float calcCycle(unsigned int period, float amp, float offset, unsigned int t) {
00188     //    cout << period << ',' << amp << ',' << offset << ',' << time << " -> " << x;
00189     float x=float(cos(t*2*M_PI/period))*(-amp/2)+.5f+offset;
00190     if(x<0)
00191       return 0;
00192     if(x>1)
00193       return 1;
00194     return x;
00195   }
00196   //!Calculates the current value of led @a i for current time t
00197   float calcValue(unsigned int i, unsigned int t) {
00198     if(t<infos[i].flashtime)
00199       return infos[i].flashvalue;
00200     else if(infos[i].isCycling)
00201       return calcCycle(infos[i].period,infos[i].amp,infos[i].offset,t-infos[i].starttime);
00202     else
00203       return infos[i].value;
00204   }
00205   //!used by displayNumber() to determine settings of LEDs when using numStyle_t::twodigit
00206   void setOneOfTwo(unsigned int x, unsigned int low, unsigned int mid, unsigned int high);
00207   //!used by displayPercent() to determine settings of LEDs
00208   void setColumn(float x, unsigned int low, unsigned int mid, unsigned int high, unsigned int top);
00209 
00210   //!Holds all the information needed by each of the LEDs
00211   struct LEDInfo {
00212     float value;           //!< the current value being expressed
00213     float amp;             //!< the amplitude of the cycle (if cycling)
00214     unsigned int period;    //!< the period of the cycle (if cycling)
00215     unsigned int starttime; //!< the start time of the cycle (if cycling)
00216     float offset;          //!< the phase shift from normal of the cycle (if cycling)
00217     float flashvalue;      //!< the value being 'flashed' (only valid if current time is less than flashtime
00218     unsigned int flashtime; //!< the time the 'flash' should retire
00219     bool isCycling;         //!< true if in cycle mode
00220   };
00221   
00222   LEDInfo infos[NumLEDs]; //!< the information regarding each of the LEDs
00223   bool dirty;             //!< true if changes since last updateLEDs: either at least one LED is cycling or a flash has begun/ended
00224   unsigned int numCycling;//!< the number of LEDs currently cycling (if non-zero, always dirty)
00225   unsigned int nextFlashEnd; //!< the soonest time a flash will end (and we'll become dirty)
00226 };
00227   
00228 /*! @file
00229  * @brief Describes LedEngine, which provides basic LED effects to anything that inherits or instantiates it
00230  * @author ejt (Creator)
00231  */
00232 
00233 #endif // TGT_HAS_LEDS
00234 
00235 #endif

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