Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
ControlBase.hGo to the documentation of this file.00001 //-*-c++-*- 00002 #ifndef INCLUDED_ControlBase_h 00003 #define INCLUDED_ControlBase_h 00004 00005 #include "Motion/MotionManagerMsg.h" 00006 #include <string> 00007 #include <vector> 00008 #include <map> 00009 class Socket; 00010 00011 //! Creates name token for the auto registration variable, have to do a layer of indirection to get line number into token so that a behavior can be registered in multiple menus 00012 #define AUTO_REGISTER_NAME_INDIRECT(className, line) autoRegister ## className ## line 00013 //! Creates name token for the auto registration variable, have to do a layer of indirection to get line number into token so that a behavior can be registered in multiple menus 00014 #define AUTO_REGISTER_NAME(className, line) AUTO_REGISTER_NAME_INDIRECT(className, line) 00015 00016 //! Should be called in the global namespace of a translation unit (i.e. a '.cc' file) in order to register a control in the controller menu system. See also #REGISTER_CONTROL and #REGISTER_BEHAVIOR for behaviors 00017 /*! Specify the menu name (use '/' to demark submenus) and allows you to pass optional flags */ 00018 #define REGISTER_CONTROL_INSTANCE_OPT(className, controlInstance, menu, flags) \ 00019 const ControlBase* AUTO_REGISTER_NAME(className,__LINE__) = ControlBase::registerControllerEntry(controlInstance,menu,flags) 00020 00021 //! Should be called in the global namespace of a translation unit (i.e. a '.cc' file) in order to register a control in the controller menu system. See also #REGISTER_CONTROL and #REGISTER_BEHAVIOR for behaviors 00022 /*! Specify the menu name (use '/' to demark submenus) */ 00023 #define REGISTER_CONTROL_INSTANCE(className, controlInstance, menu) REGISTER_CONTROL_INSTANCE_OPT(className, controlInstance, menu, ControlBase::DEFAULTS) 00024 00025 //! Should be called in the global namespace of a translation unit (i.e. a '.cc' file) in order to register a control in the controller menu system. See also #REGISTER_CONTROL_INSTANCE and #REGISTER_BEHAVIOR for behaviors 00026 /*! Specify the menu name (use '/' to demark submenus) and allows you to pass optional flags. */ 00027 #define REGISTER_CONTROL_OPT(className, menu, flags) REGISTER_CONTROL_INSTANCE_OPT(className, new className, menu, flags) 00028 00029 //! Should be called in the global namespace of a translation unit (i.e. a '.cc' file) in order to register a control in the controller menu system. See also #REGISTER_CONTROL_INSTANCE and #REGISTER_BEHAVIOR for behaviors 00030 /*! Specify the menu name (use '/' to demark submenus). */ 00031 #define REGISTER_CONTROL(className, menu) REGISTER_CONTROL_INSTANCE(className, new className, menu) 00032 00033 00034 //! Base class for all items in the Controller hierarchy. 00035 /*! These are similar to behaviors in that they can do processing and 00036 * are told when to start and stop. 00037 * 00038 * However, the important difference is that these have to follow a 00039 * much tighter set of guidelines for a more refined purpose - user 00040 * interface. Controls do not directly receive events - the 00041 * Controller will process events for them and call the appropriate 00042 * functions at the appropriate times. Controls are expected to fit 00043 * into a heirarchical scheme, where each control (except the root) 00044 * has a parent which created it, and may return its own children 00045 * where appropriate. 00046 * 00047 * Controls can be very powerful, and a class can be both a behavior 00048 * and a control. This allows integrated user interface to 00049 * controlling a complex behavior. Some controls may simply need 00050 * EventListener access instead to perform a few tricks. Mix and 00051 * match as you see fit. (multiple inheritance can be nice if it's 00052 * planned for, as these have been) 00053 * 00054 * This base class will do most of the work of maintaining submenus 00055 * for you, and will call appropriate virtual functions which you are 00056 * expected to override. Controls generally live in 00057 * <tt>Behaviors/Controls/</tt> as the Controller itself is a 00058 * behavior, and these controls merely its tools. 00059 * 00060 * The ControlBase pointers which are returned at various points are the 00061 * responsibility of the creator. Controller will not delete them upon 00062 * deactivation. 00063 * 00064 * GUI Theory: \n 00065 * There are 3 levels to the user interface. 00066 * -# Robot/Local: Uses the buttons for input, and LEDs and sounds for immediate feedback. No external resources needed 00067 * -# Text: Uses a console to display/request information. 00068 * -# GUI: Uses a graphical interface on a desktop machine 00069 * 00070 * Obviously, higher levels require more technological resources, which also 00071 * means there's more to go wrong and debug. However, another important 00072 * distinction between the first level and the others is that the first level 00073 * does not require the user to lose direct contact with the robot. Requiring 00074 * the user to move back and forth from robot to computer can be much more 00075 * frustrating than decoding LED signals or press head buttons. There are also 00076 * safety issues when triggering behaviors remotely if the robot is out of 00077 * immediate reach. But of course, having a GUI and text output is extremely 00078 * valuable in terms of ease of use and efficiency. 00079 * 00080 * So, the lesson is to try to support all 3 levels so that your interfaces 00081 * will be robust and efficient in a variety of environments. You'll thank 00082 * yourself when you're demoing on the road and you can't get wavelan up, or 00083 * the guest machine you're supposed to use doesn't have Java, or whatever. 00084 * 00085 * @todo ControlBase's should use ReferenceCounter so memory management is not an issue 00086 * @see Controller, NullControl */ 00087 class ControlBase { 00088 public: 00089 //! Typically would use MotionManager::MC_ID, but re-specified here for convenience and to avoid dependence on MotionManager.h 00090 typedef MotionManagerMsg::MC_ID MC_ID; 00091 //! Typically would use MotionManager::invalid_MC_ID, but re-specified here for convenience and to avoid dependence on MotionManager.h 00092 static const MC_ID invalid_MC_ID=MotionManagerMsg::invalid_MC_ID; 00093 00094 //! @name Constructors/Destructors 00095 00096 ControlBase() : name("(null name)"), description(), hilights(), options(), doRewrite(false), display_id(invalid_MC_ID), gui_comm(NULL) {} //!< Contructor 00097 ControlBase(const std::string& n) : name(n), description((n.size()>16)?n:std::string()), hilights(), options(), doRewrite(false), display_id(invalid_MC_ID), gui_comm(NULL) {} //!< Contructor, initializes with a name 00098 ControlBase(const std::string& n, const std::string& d) : name(n), description(d), hilights(), options(), doRewrite(false), display_id(invalid_MC_ID), gui_comm(NULL) {} //!< Contructor, initializes with a name 00099 00100 //! Destructor 00101 virtual ~ControlBase() { 00102 // deactivate(); 00103 //cout << "~ControlBase(): " << name << endl; 00104 clearSlots(); 00105 } 00106 00107 //@} 00108 00109 //! You probably want to override some of these, call the ControlBase functions from your code if you want default sound effects (or look in Config::controller_config). 00110 //! @name Controller Functions 00111 00112 //! Called when the control is activated (or the control system is reactivating) 00113 /*! Takes the id number of a LedMC which the control should use, maintained by Controller. 00114 * Controls share the display which is passed, and may use the socket @a gui to communicate with the GUI controller, if it is connected. 00115 * @return a ControlBase pointer. Return: @li @a this if the control should stay active (if it's not a one-shot command) @li @c NULL to return to parent @li other address to spawn a child control*/ 00116 virtual ControlBase * activate(MC_ID disp_id, Socket * gui); 00117 virtual void pause(); //!< called when a control is being overriden by a child, or the control system is deactivating (e-stop being turned off) 00118 virtual void refresh(); //!< called when the child has deactivated and this control should refresh its display, or some other event (such as the user pressing the refresh button) has happened to cause a refresh to be needed 00119 virtual void deactivate(); //!< called when this control is being popped from the control stack 00120 00121 //! when the user has trigger an "open selection" - default is to return the hilighted control*/ 00122 /*! The value which is returned is then activate()ed and pushed on the Controller's stack*/ 00123 virtual ControlBase * doSelect(); 00124 //! when the user wants to increment the control - default is to hilight the first non-null slot after the last hilight, and return @c this 00125 /*! The value which is returned is then activate()ed and pushed on the Controller's stack, so you probably want to return @c this */ 00126 virtual ControlBase * doNextItem(); 00127 //! when the user wants to decrement the control - default is to hilight the last non-null slot before the first hilight, and return @c this 00128 /*! The value which is returned is then activate()ed and pushed on the Controller's stack, so you probably want to return @c this */ 00129 virtual ControlBase * doPrevItem(); 00130 //! when the user wants to cancel - you should almost always return NULL now unless you need to override the cancel in order to confirm something (e.g. "Save changes?") 00131 /*! The value which is returned is then activate()ed and pushed on the Controller's stack, you probably want to return @c NULL */ 00132 virtual ControlBase * doCancel(); 00133 //! prompt the user for text input on the current input device (cin, tekkotsu console (sout), or GUI) 00134 /*! The value which is returned is then activate()ed and pushed on the Controller's stack, so you probably want to return @c this */ 00135 virtual ControlBase * doReadStdIn(const std::string& prompt=std::string()); 00136 //! called when the user has supplied a text string (may or may not have been prompted by doReadStdIn()! May not even be active yet - the user can direct the same input to a set of hilighted menus) 00137 /*! The value which is returned is then activate()ed and pushed on the Controller's stack*/ 00138 virtual ControlBase * takeInput(const std::string& msg); 00139 //! may be called before takeInput to verify this Control can make sense of msg 00140 virtual bool validInput(const std::string& msg); 00141 //! Called when the control is picked up from the control registry (implies it is now safe to access global resources, such as erouter) 00142 virtual void registered() {} 00143 //@} 00144 00145 //! @name Accessors 00146 00147 virtual ControlBase& setName(const std::string& n) { name=n; return *this; } //!< sets the name of the control 00148 virtual std::string getName() const { return name; } //!< returns the name of the control 00149 00150 virtual ControlBase& setDescription(const std::string d) { description=d; return *this; } //!< sets the description of the control 00151 virtual std::string getDescription() const { return description; } //!< returns a short description of what the control does 00152 00153 virtual const std::vector<ControlBase*>& getSlots() const { return options; } //!< returns the vector of sub-controls 00154 virtual ControlBase* findSlot(const std::string& name) const; 00155 virtual std::string getSlotName(unsigned int i) const; //!< returns the string that will appear in slot @a i 00156 virtual unsigned int slotsSize() const { return options.size(); } //!< returns the number of options available 00157 virtual void setSlot(unsigned int i,ControlBase* o); //!< sets @a i'th element of #options to @a o 00158 virtual void pushSlot(ControlBase* o); //!< sets next unused element of #options to @a o 00159 virtual void clearSlots(); //!< deletes each slot item and clears the slots 00160 00161 virtual const std::vector<unsigned int>& getHilights() const { return hilights; } //!< returns a vector of the indicies of hilighted slots 00162 virtual void setHilights(const std::vector<unsigned int>& hi); //!< sets the hilighted slots 00163 virtual void hilightFirst(); //!< sets the hilight to the first non-null slot 00164 00165 virtual MC_ID getDisplay() { return display_id; } //!< returns display being used 00166 virtual ControlBase& setDisplay(MC_ID d) { display_id=d; return *this; } //!< sets display to use 00167 00168 //@} 00169 00170 00171 //! provides options for registerControllerEntry() and by extension #REGISTER_CONTROLLER_OPT and #REGISTER_CONTROLLER_MENU 00172 enum RegisterControllerFlags_t { 00173 DEFAULTS=0, //!< indicates default options (behavior will not be started automatically), see also #BEH_DEFAULTS macro 00174 BEH_START=1, //!< indicates the behavior should be activated at launch instead of waiting for the user to do it manually, see also #BEH_START macro 00175 BEH_RETAIN=2, //!< the behavior's memory allocation will *not* be freed between activations, so state will be maintained, see also #BEH_RETAIN macro 00176 BEH_NONEXCLUSIVE=4 //!< the behavior be able to run in parallel with other behaviors, see also #BEH_NONEXCLUSIVE macro 00177 }; 00178 00179 //! Registers a ControlBase to be added to the specified Controller menu, use '/' to specify sub-menus, see REGISTER_CONTROLLER macro. 00180 /*! This only works when called as an initializer to a static variable. Once the menus have been initialized, later calls to this function won't update the menus. */ 00181 static ControlBase* registerControllerEntry(ControlBase* c, const std::string& menu, int flags=ControlBase::DEFAULTS); 00182 00183 typedef std::map<std::string,std::pair<ControlBase*,int> > ControlRegistryEntry_t; // !< shorthand for the map between original control names and their instances with flags, see getControllerEntries() 00184 typedef std::map<std::string, ControlRegistryEntry_t > ControlRegistry_t; //!< shorthand for the map between menu names and associated map of entries, see getControllerEntries() 00185 00186 //! Provides static/global storage of behaviors requesting to be added to controller menus. 00187 /*! This collection is processed by the startup behavior to build the menu structure. */ 00188 static ControlRegistry_t& getControllerEntries() { 00189 static ControlRegistry_t entries; 00190 return entries; 00191 } 00192 00193 00194 00195 protected: 00196 00197 //! clears the display (if use_VT100 is on) 00198 virtual void clearMenu(); 00199 00200 //! called by takeInput if the input doesn't match any slots or matches multiple slots -- the ControlBase implementation displays an error and returns itself 00201 /*! @param msg the input originally sent to takeInput() 00202 * @param ambiguous true if the input matched more than one item, false if it didn't match any */ 00203 virtual ControlBase* invalidInput(const std::string& msg, bool ambiguous); 00204 00205 //! returns the average of the hilighted indicies - used to know to play the "next" sound, or the "prev" sound when the hilight changes 00206 float hilightsAvg() const; 00207 00208 std::string name; //!< the name of this control 00209 std::string description; //!< the description of this control 00210 std::vector<unsigned int> hilights; //!< keep sorted - index(es) of current selection - can have multiple if using GUI 00211 std::vector<ControlBase*> options; //!< vector of controls to select from 00212 bool doRewrite; //!< toggles using VT100 codes to reposition the cursor at the beginning of the menu 00213 /*!< we don't always want to do this, any time someone else might have written to 00214 * the display we set this to false so we don't overwrite it. */ 00215 00216 MC_ID display_id; //!< LedMC to use for displaying selection 00217 Socket * gui_comm; //!< socket to communicate with the GUI, if it is connected 00218 00219 private: 00220 ControlBase(const ControlBase&); //!< you can override, but don't call this... 00221 ControlBase& operator=(const ControlBase&); //!< you can override, but don't call this... 00222 }; 00223 00224 /*! @file 00225 * @brief Defines ControlBase from which all items in the control system should inherit 00226 * @author ejt (Creator) 00227 */ 00228 #endif |
Tekkotsu v5.1CVS |
Generated Mon May 9 04:58:37 2016 by Doxygen 1.6.3 |