Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

CommonInfo.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_CommonInfo_h_
00003 #define INCLUDED_CommonInfo_h_
00004 
00005 #include <map>
00006 #include <set>
00007 #include <string>
00008 #include <stdexcept>
00009 
00010 namespace RobotInfo {
00011 
00012   //! Defines the indexes to use as indices to access the min and max entries of joint limit specifications (e.g. ERS7Info::outputRanges and ERS7Info::mechanicalLimits)
00013   enum MinMaxRange_t { MinRange,MaxRange };
00014   
00015   //! Some target models, such as ERS2xxInfo, may be dual-booting compatability modes.  This function returns the actual robot name (e.g. ERS210Info::TargetName or ERS220Info::TargetName)
00016   /*! This function should return the actual RobotInfo::TargetName and not a hard coded string.
00017    *  This way, we can rely on testing equality with a direct pointer comparison instead of strcmp().
00018    *  (Also eliminates chance of typo or missing refactorization if renamed!).
00019    *
00020    *  The result of this function is stored in #RobotName, so you don't need to call
00021    *  this function -- the only reason it's declared in the header is so you can call
00022    *  it during static initialization, when you can't rely on RobotName having been
00023    *  initialized yet. */
00024   const char* const detectModel();
00025   
00026   //! Name of the robot which is actually running
00027   /*! This is usually set to the TargetName, but if the target model is a "compatability" target,
00028    *  where the actual host hardware may be a different (more restrictive) configuration,
00029    *  then RobotName will be set to the TargetName of that configuration.
00030    *
00031    *  Note that you should be able to rely on doing pointer comparisons
00032    *  between RobotName and various TargetNames to test for different robot models,
00033    *  instead of using strcmp() for each. 
00034    *
00035    *  However, a std::string is used on Aperios to transparently trigger the strcmp because
00036    *  of the way the process model is handled there screws up the pointer comparison
00037    *  (a different process does the static initialization, so we get a pointer relative to its
00038    *  memory space instead of the one we're executing in.  Unix-based platforms don't
00039    *  have this problem by using a "real" fork() operation.) */
00040 #ifndef PLATFORM_APERIOS
00041   extern const char* const RobotName;
00042 #else // have to use a string because aperios is annoying like that
00043   extern const std::string RobotName;
00044 #endif
00045   
00046   //! Allows behaviors to lookup output/button/sensor names from other models to support basic cross-model portability
00047   /*! Use the getCapabilities() function to look up the Capabalities instance for a given model based on its string robot name */
00048   class Capabilities {
00049     friend Capabilities* getCapabilities(const std::string& robName);
00050   public:
00051     //! constructor, pass the robot name this is regarding, and outputs, buttons, and sensor names
00052     Capabilities(const char* robName, size_t numOut, const char * const outNames[], size_t numBut, const char * const butNames[], size_t numSen, const char * const senNames[], size_t pidOff, size_t numPID, size_t ledOff, size_t numLED);
00053     //! shallow copy (explicit to satisfy warning)
00054     Capabilities(const Capabilities& cap)
00055       : name(cap.name), numOutputs(cap.numOutputs), numButtons(cap.numButtons), numSensors(cap.numSensors),
00056       outputs(cap.outputs), buttons(cap.buttons), sensors(cap.sensors),
00057       outputToIndex(cap.outputToIndex), buttonToIndex(cap.buttonToIndex), sensorToIndex(cap.sensorToIndex),
00058       pidJointOffset(cap.pidJointOffset), numPIDJoints(cap.numPIDJoints), ledOffset(cap.ledOffset), numLEDs(cap.numLEDs),
00059       fakeOutputs() {}
00060     //! shallow assign (explicit to satisfy warning)
00061     Capabilities& operator=(const Capabilities& cap) {
00062       name=cap.name;
00063       numOutputs=cap.numOutputs; numButtons=cap.numButtons; numSensors=cap.numSensors;
00064       outputs=cap.outputs; buttons=cap.buttons; sensors=cap.sensors;
00065       outputToIndex=cap.outputToIndex; buttonToIndex=cap.buttonToIndex; sensorToIndex=cap.sensorToIndex;
00066       pidJointOffset=cap.pidJointOffset; numPIDJoints=cap.numPIDJoints; ledOffset=cap.ledOffset; numLEDs=cap.numLEDs;
00067       fakeOutputs=cap.fakeOutputs;
00068       return *this;
00069     }
00070     //! destructor, explicit just to avoid warning when used as base class
00071     virtual ~Capabilities() {}
00072     
00073     //! returns the name of the robot this corresponds to
00074     inline const char * getRobotName() const { return name; }
00075     
00076     //! returns the number of unique outputs (i.e. not counting aliases)
00077     inline unsigned int getNumOutputs() const { return numOutputs; }
00078     //! returns the number of unique buttons (i.e. not counting aliases)
00079     inline unsigned int getNumButtons() const { return numButtons; }
00080     //! returns the number of unique sensors (i.e. not counting aliases)
00081     inline unsigned int getNumSensors() const { return numSensors; }
00082     
00083     //! look up the name corresponding to an offset, returns NULL if not found/available
00084     inline const char * getOutputName(unsigned int i) const { return i<numOutputs ? outputs[i] : NULL; }
00085     //! look up the name corresponding to an offset, returns NULL if not found/available
00086     inline const char * getButtonName(unsigned int i) const { return i<numButtons ? buttons[i] : NULL; }
00087     //! look up the name corresponding to an offset, returns NULL if not found/available
00088     inline const char * getSensorName(unsigned int i) const { return i<numSensors ? sensors[i] : NULL; }
00089     
00090     //! Look up the offset corresponding to a output name, throws std::invalid_argument if not found
00091     /*! Identical to findOutputOffset(), except throws an exception instead of returning an invalid value.
00092      *  Use this if you expect that the output is available, and want a noisy fail-fast if something's wrong (e.g. typo in name?) */
00093     inline unsigned int getOutputOffset(const char* out) const { return lookupT("output",outputToIndex,out); }
00094     //! look up the offset corresponding to a button name, throws std::invalid_argument if not found
00095     /*! Identical to findButtonOffset(), except throws an exception instead of returning an invalid value.
00096      *  Use this if you expect that the output is available, and want a noisy fail-fast if something's wrong (e.g. typo in name?) */
00097     inline unsigned int getButtonOffset(const char* but) const { return lookupT("button",buttonToIndex,but); }
00098     //! look up the offset corresponding to a sensor name, throws std::invalid_argument if not found
00099     /*! Identical to findSensorOffset(), except throws an exception instead of returning an invalid value.
00100      *  Use this if you expect that the output is available, and want a noisy fail-fast if something's wrong (e.g. typo in name?) */
00101     inline unsigned int getSensorOffset(const char* sen) const { return lookupT("sensor",sensorToIndex,sen); }
00102     
00103     //! look up the offset corresponding to a output name, returns -1U if not found/available
00104     /*! Identical to getOutputOffset(), except returns an invalid value instead of throwing an exception.
00105      *  Use this if you are testing to see if a capability exists, and don't want to incur exception handling if it isn't (say you're doing a lot of testing) */ 
00106     inline unsigned int findOutputOffset(const char* out) const { return lookup(outputToIndex,out); }
00107     //! look up the offset corresponding to a button name, returns -1U if not found/available
00108     /*! Identical to getButtonOffset(), except returns an invalid value instead of throwing an exception.
00109      *  Use this if you are testing to see if a capability exists, and don't want to incur exception handling if it isn't (say you're doing a lot of testing) */ 
00110     inline unsigned int findButtonOffset(const char* but) const { return lookup(buttonToIndex,but); }
00111     //! look up the offset corresponding to a sensor name, returns -1U if not found/available
00112     /*! Identical to getSensorOffset(), except returns an invalid value instead of throwing an exception.
00113      *  Use this if you are testing to see if a capability exists, and don't want to incur exception handling if it isn't (say you're doing a lot of testing) */ 
00114     inline unsigned int findSensorOffset(const char* sen) const { return lookup(sensorToIndex,sen); }
00115     
00116     inline unsigned int getPIDJointOffset() const { return pidJointOffset; } //!< returns the offset of the block of 'PID' joints in an output array
00117     inline unsigned int getNumPIDJoints() const { return numPIDJoints; } //!< returns the number of 'PID' joints
00118     inline unsigned int getLEDOffset() const { return ledOffset; } //!< returns the offset of the block of LEDs in an output array
00119     inline unsigned int getNumLEDs() const { return numLEDs; } //!< returns the number of LEDs
00120     
00121     //! returns the offsets of "fake" outputs, see #fakeOutputs
00122     inline const std::set<unsigned int>& getFakeOutputs() const { return fakeOutputs; }
00123     
00124   protected:
00125     //! helper function, does the work of the get..Offset functions
00126     inline unsigned int lookupT(const char * errStr, const std::map<std::string,unsigned int>& nameToIndex, const char * capname) const {
00127       std::map<std::string,unsigned int>::const_iterator it=nameToIndex.find(capname);
00128       if(it==nameToIndex.end()) {
00129         std::string str; str.append(name).append("::capabilities could not find ").append(errStr).append(" named ").append(capname);
00130         throw std::invalid_argument(str);
00131       }
00132       return it->second;
00133     }
00134     //! helper function, does the work of the find..Offset functions
00135     inline unsigned int lookup(const std::map<std::string,unsigned int>& nameToIndex, const char * capname) const {
00136       std::map<std::string,unsigned int>::const_iterator it=nameToIndex.find(capname);
00137       return it==nameToIndex.end() ? -1U : it->second;
00138     }
00139     
00140     const char* name; //!< name of robot model
00141     size_t numOutputs; //!< length of #outputs
00142     size_t numButtons; //!< length of #buttons
00143     size_t numSensors; //!< length of #sensors
00144     const char * const * outputs; //!< array of names for outputs -- this is the "primary" name for each output, #outputToIndex may contain additional aliases
00145     const char * const * buttons; //!< array of names for buttons -- this is the "primary" name for each button, #buttonToIndex may contain additional aliases
00146     const char * const * sensors; //!< array of names for sensors -- this is the "primary" name for each sensor, #sensorToIndex may contain additional aliases
00147     std::map<std::string,unsigned int> outputToIndex; //!< maps output names to offset values
00148     std::map<std::string,unsigned int> buttonToIndex; //!< maps button names to offset values
00149     std::map<std::string,unsigned int> sensorToIndex; //!< maps sensor names to offset values
00150     
00151     size_t pidJointOffset; //!< the offset of the PID joints
00152     size_t numPIDJoints; //!< the number of PID joints
00153     size_t ledOffset; //!< the offset of the LEDs
00154     size_t numLEDs; //!< the number of LEDs
00155     
00156     //! Offsets of "fake" outputs, which don't correspond to any physical device on the robot
00157     /*! This is used in compatability modes, where some outputs may not be available on the
00158      *  host hardware, or for meta-outputs, which control the interpretation of other outputs.
00159      *  (such as the A/B LED mode setting for the ERS-7, where a "virtual" LED switches
00160      *  the system's intepretation of the face panel LEDs).
00161      *
00162      *  Most robots can probably just leave this empty -- on Aperios the "fake" outputs are
00163      *  skipped when interfacing with the system and their values receive feedback from
00164      *  the motion process.  When using the tekkotsu executable under unix-based systems,
00165      *  the HAL layer handles this functionality via its own configuration settings, and these
00166      *  values are ignored. */
00167     std::set<unsigned int> fakeOutputs;
00168     
00169     //! returns a static map from robot names to capability instances, which are externally allocated
00170     /*! The Capabilties base class will automatically insert entries into this collection. */
00171     static std::map<std::string, class Capabilities*>& getCaps();
00172   };
00173 
00174 }
00175 
00176 /*! @file
00177  * @brief 
00178  * @author ejt (Creator)
00179  *
00180  * $Author: ejt $
00181  * $Name: tekkotsu-4_0 $
00182  * $Revision: 1.7 $
00183  * $State: Exp $
00184  * $Date: 2007/11/09 19:01:13 $
00185  */
00186 
00187 #endif

Tekkotsu v4.0
Generated Thu Nov 22 00:54:51 2007 by Doxygen 1.5.4