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

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