Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Config.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_Config_h
00003 #define INCLUDED_Config_h
00004 
00005 #include "Shared/plist.h"
00006 #include "Shared/RobotInfo.h"
00007 extern "C" {
00008 #include <jpeglib.h>
00009 }
00010 #ifdef PLATFORM_APERIOS
00011 #  include <OPENR/OPrimitiveControl.h>
00012 #else
00013 typedef unsigned int OSpeakerVolume; //!< provides an OPEN-R type of the same name for compatability, see Config::sound_config::volume
00014 const OSpeakerVolume ospkvolinfdB = 0x8000; //!< 'muted' volume level, see Config::sound_config::volume
00015 const OSpeakerVolume ospkvol25dB  = 0xe700; //!< low volume, see Config::sound_config::volume
00016 const OSpeakerVolume ospkvol18dB  = 0xee00; //!< mid volume, see Config::sound_config::volume
00017 const OSpeakerVolume ospkvol10dB  = 0xf600; //!< high volume, see Config::sound_config::volume
00018 #endif
00019 #include <vector>
00020 #include <string>
00021 
00022 //! a subclass of plist::Dictionary which adds support for filtering settings by robot model, each configuration section is based on this
00023 /*! As a slight extension to standard plists, you can specify
00024  *  model-specific settings by prepending a key with:
00025  *     Model:MODEL_PATTERN:KEY_NAME
00026  *  For example, to use different 'thresh' settings on the ERS-2xx
00027  *  series vs. the ERS-7 model, you would use the keys:
00028  *   - Model:ERS-2*:thresh
00029  *   - Model:ERS-7:thresh
00030  *  You can filter several items as a group by leaving off the second
00031  *  ':' and name, and providing a dictionary as the value.  If the
00032  *  model matches, all entries from the dictionary are imported into
00033  *  the parent dictionary.
00034  */
00035 class ConfigDictionary : public plist::Dictionary {
00036 public:
00037   ConfigDictionary() : plist::Dictionary(false)
00038   {
00039     if(curModel.size()==0)
00040       curModel=RobotName;
00041   }
00042   
00043 protected:
00044   
00045   virtual bool loadXMLNode(const std::string& key, xmlNode* val, const std::string& comment);
00046   virtual bool saveOverXMLNode(xmlNode* k, xmlNode* val, const std::string& key, std::string comment, const std::string& indentStr, std::set<std::string>& seen) const;
00047 
00048   //! returns true if pattern matches model - pattern may have up to 1 '*', case insensitive
00049   static bool matchNoCase(const std::string& model, const std::string& pattern);
00050   
00051   static const std::string msPrefix; //!< the prefix indicating a model-specific key
00052   static const std::string msSep; //!< the separator string which splits the key into the prefix, model pattern, and (optionally) a single key name
00053   //static const std::string msNum;
00054   static std::string curModel; //!< will be set to the model identifier of the currently running hardware
00055   static void initCurModel(); //!< function to initialize #curModel
00056 };
00057 
00058 //! Stores an item for each joint, can be accessed via joint name or array offset
00059 /*! Two main reasons for this class are to keep outputs in offset order (not alphabetic by name),
00060  *  and to strip '~' from output names for backward compatability (used to pad output names
00061  *  to ensure constant string length. */
00062 template<typename T>
00063 class OutputConfig : public ConfigDictionary {
00064 public:
00065   //! constructor
00066   OutputConfig(unsigned int firstOffset, unsigned int numOutputsToStore, const T& defValue)
00067   : ConfigDictionary(), offset(firstOffset), outputs(numOutputsToStore,defValue)
00068   {
00069     for(unsigned int i=0; i<numOutputsToStore; ++i)
00070       addEntry(outputNames[i+firstOffset],outputs[i]);
00071   }
00072   //! strips trailing '~' characters from name before doing usual lookup
00073   virtual ObjectBase& getEntry(const std::string& name) {
00074     std::string::size_type n = name.find_last_not_of('~')+1;
00075     return ConfigDictionary::getEntry((n==name.size()) ? name : name.substr(0,n));
00076   }
00077   //! return the value at position @a index, which must exist (no range checking)
00078   T& getEntry(size_t index) { return outputs[index]; }
00079   //! return the value at position @a index, which must exist (no range checking, equivalent to getEntry(index))
00080   T& operator[](size_t index) { return outputs[index]; }
00081   using ConfigDictionary::operator[];
00082   
00083   //! small trick -- override to save outputs in indexed order instead of alphabetical order
00084   void saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const;
00085   using ConfigDictionary::saveXML;
00086   
00087 protected:
00088   //! strips trailing '~' characters from name before doing usual lookup
00089   bool loadXMLNode(const std::string& key, xmlNode* val, const std::string& comment) {
00090     std::string::size_type n = key.find_last_not_of('~')+1;
00091     return ConfigDictionary::loadXMLNode((n==key.size()) ? key : key.substr(0,n), val, comment);
00092   }
00093   
00094   unsigned int offset; //!< the index offset of the first entry in #outputs
00095   std::vector<T> outputs; //!< storage of data for each output
00096 };
00097 
00098 //! the root configuration object, provides some global functionality like porting pathnames (portPath())
00099 class Config : public ConfigDictionary {
00100 public:
00101   Config(const std::string& filename="") : ConfigDictionary(),
00102     behaviors(), wireless(), main(), controller(), vision(), motion(this), sound(this), fsRoot()
00103   {
00104     addEntry("wireless",wireless);
00105     addEntry("vision",vision);
00106     addEntry("main",main);
00107     addEntry("behaviors",behaviors);
00108     addEntry("controller",controller);
00109     addEntry("motion",motion);
00110     addEntry("sound",sound);
00111     if(filename.size()!=0)
00112       loadFile(filename.c_str());
00113   }
00114   
00115   enum transports { UDP, TCP }; //!< types of network transport protocols supported
00116   static const unsigned int NUM_TRANSPORTS=2; //!< number of #transports available
00117   static const char * transport_names[NUM_TRANSPORTS+1]; //!< string names for #transports
00118   
00119   void setFileSystemRoot(const std::string& fsr); //!< sets #fsRoot
00120   const std::string& getFileSystemRoot() const { return fsRoot; } //!< returns #fsRoot
00121   std::string portPath(const std::string& path) const; //!< returns a portable version of @a path which should be usable on either the simulator or the robot
00122   
00123   
00124   
00125   // **************************************** //
00126   //! place for users to put their own configuration
00127   // **************************************** //
00128   /*! you can dynamically "link in" external configuration settings by passing them to the addEntry() of the
00129    *  plist::Dictionary superclass.  You may want to call writeParseTree() first to flush current settings,
00130    *  and then readParseTree() afterward to pull any pre-existing values from the configuration
00131    *  file into the instances you've just registered.
00132    *
00133    *  Of course, you could also just write your values into the configuration file first, and just rely
00134    *  on getEntry/setEntry to read/write the value.  This may be more convenient if you use the
00135    *  value infrequently and don't need an instance of it sitting around. */
00136   class behaviors_config : public ConfigDictionary {
00137   public:
00138     //! constructor
00139     behaviors_config() : ConfigDictionary(), flash_bytes(4), flash_on_start(true)
00140     {
00141       //users may want to dynamically link in their own settings when running, so don't warn if there are
00142       // unused items in this section
00143       setUnusedWarning(false);
00144       
00145       addEntry("flash_bytes",flash_bytes,"how many bytes of the address to flash\n"
00146                "You probably already know the first 3 bytes for your network,\n"
00147                "so you might only want the last byte for brevity.\n"
00148                "(valid values are 1 through 4) ");
00149       addEntry("flash_on_start",flash_on_start,"whether or not to automatically trigger on boot\n"
00150                "Will use a priority of kEmergencyPriority+1 in order to override\n"
00151                "the emergency stop's status animation ");
00152     }
00153     plist::Primitive<unsigned int> flash_bytes; //!< how many bytes of the IP to flash
00154     plist::Primitive<bool> flash_on_start;      //!< whether or not to trigger flashing when initially started
00155   } behaviors;
00156 
00157   
00158   
00159   // **************************************** //
00160   //! wireless configuration options
00161   // **************************************** //
00162   class wireless_config : public ConfigDictionary {
00163   public:
00164     //! constructor
00165     wireless_config () : ConfigDictionary(), id(1) {
00166       addEntry("id",id,"id number (in case you have more than one AIBO)");
00167     }
00168     plist::Primitive<int> id; //!< id number (in case you have more than one AIBO)
00169   } wireless;
00170   
00171   
00172   
00173   // **************************************** //
00174   //! general configuration options
00175   // **************************************** //
00176   class main_config : public ConfigDictionary {
00177   public:
00178     //!constructor
00179     main_config()
00180       : ConfigDictionary(), seed_rng(true), console_port(10001), consoleMode(CONTROLLER,consoleModeNames), stderr_port(10002),
00181       wsjoints_port(10031),wspids_port(10032),headControl_port(10052),
00182       walkControl_port(10050),estopControl_port(10053),stewart_port(10055),aibo3d_port(10051),
00183       wmmonitor_port(10061), use_VT100(true), worldState_interval(0)
00184     {
00185       addEntry("seed_rng",seed_rng,"if true, will call srand with timestamp data, mangled by current sensor data");
00186       addEntry("console_port",console_port,"port to send/receive \"console\" information on (separate from system console)");
00187       addEntry("consoleMode",consoleMode,"determines how input on console_port is interpreted\n"+consoleMode.getDescription()+"\n"
00188                "  'controller' will pass it as input to the Controller (assumes same syntax as ControllerGUI)\n"
00189                "  'textmsg' will broadcast it as a TextMsgEvent (textmsgEGID)\n"
00190                "  'auto' is the original mode, which uses 'textmsg' if the ControllerGUI is connected, and 'controller' otherwise ");
00191       addEntry("stderr_port",stderr_port,"port to send error information to");
00192       addEntry("wsjoints_port",wsjoints_port,"port to send joint positions on");
00193       addEntry("wspids_port",wspids_port,"port to send pid info on");
00194       addEntry("headControl_port",headControl_port,"port for receiving head commands");
00195       addEntry("walkControl_port",walkControl_port,"port for receiving walk commands");
00196       addEntry("estopControl_port",estopControl_port,"port for receiving walk commands");
00197       addEntry("stewart_port",stewart_port,"port for running a stewart platform style of control");
00198       addEntry("aibo3d_port",aibo3d_port,"port for send/receive of joint positions from Aibo 3D GUI");
00199       addEntry("wmmonitor_port",wmmonitor_port,"port for monitoring Watchable Memory");
00200       addEntry("use_VT100",use_VT100,"if true, enables VT100 console codes (currently only in Controller menus - 1.3)");
00201       addEntry("worldState_interval",worldState_interval,"time (in milliseconds) to wait between sending WorldState updates over wireless");
00202     }
00203     plist::Primitive<bool> seed_rng;     //!< if true, will call srand with timestamp data, mangled by current sensor data
00204     plist::Primitive<int> console_port;  //!< port to send/receive "console" information on (separate from system console)
00205     //! types that #consoleMode can take on
00206     enum consoleMode_t {
00207       CONTROLLER, //!< all input is interpreted as Controller commands, using same syntax as the GUI sends
00208       TEXTMSG, //!< all input is broadcast as a text message event
00209       AUTO //!< if the GUI is connected, interpret as text messages, otherwise as controller commands.  This was the historical behavior, but seems to be more confusing than helpful.
00210     };
00211     static const unsigned int NUM_CONSOLE_MODES=3; //!< the number of consoleMode_t values available
00212     static const char* consoleModeNames[NUM_CONSOLE_MODES+1]; //!< string names for #consoleMode_t
00213     //! determines how input on #console_port is interpreted
00214     plist::NamedEnumeration<consoleMode_t> consoleMode; 
00215     plist::Primitive<int> stderr_port;   //!< port to send error information to
00216     plist::Primitive<int> wsjoints_port; //!< port to send joint positions on
00217     plist::Primitive<int> wspids_port;   //!< port to send pid info on
00218     plist::Primitive<int> headControl_port;    //!< port for receiving head commands
00219     plist::Primitive<int> walkControl_port;    //!< port for receiving walk commands
00220     plist::Primitive<int> estopControl_port;     //!< port for receiving walk commands
00221     plist::Primitive<int> stewart_port;  //!< port for running a stewart platform style of control
00222     plist::Primitive<int> aibo3d_port;   //!< port for send/receive of joint positions from Aibo 3D GUI
00223     plist::Primitive<int> wmmonitor_port; //!< port for monitoring Watchable Memory
00224     plist::Primitive<bool> use_VT100;    //!< if true, enables VT100 console codes (currently only in Controller menus - 1.3)
00225     plist::Primitive<unsigned int> worldState_interval; //!< time (in milliseconds) to wait between sending WorldState updates over wireless
00226   } main;
00227 
00228   
00229   
00230   // **************************************** //
00231   //! controller information
00232   // **************************************** //
00233   class controller_config : public ConfigDictionary {
00234   public:
00235     //!constructor
00236     controller_config() : ConfigDictionary(), gui_port(10020), select_snd(), next_snd(), prev_snd(), read_snd(), cancel_snd(), error_snd()
00237     {
00238       addEntry("gui_port",gui_port,"port to listen for the GUI to connect to aibo on");
00239       addEntry("select_snd",select_snd,"sound file to use for \"select\" action");
00240       addEntry("next_snd",next_snd,"sound file to use for \"next\" action");
00241       addEntry("prev_snd",prev_snd,"sound file to use for \"prev\" action");
00242       addEntry("read_snd",read_snd,"sound file to use for \"read from std-in\" action");
00243       addEntry("cancel_snd",cancel_snd,"sound file to use for \"cancel\" action");
00244       addEntry("error_snd",error_snd,"sound file to use to signal errors");
00245     }
00246   
00247     plist::Primitive<int> gui_port;        //!< port to listen for the GUI to connect to aibo on
00248     plist::Primitive<std::string> select_snd; //!< sound file to use for "select" action
00249     plist::Primitive<std::string> next_snd;   //!< sound file to use for "next" action
00250     plist::Primitive<std::string> prev_snd;   //!< sound file to use for "prev" action
00251     plist::Primitive<std::string> read_snd;   //!< sound file to use for "read from std-in" action
00252     plist::Primitive<std::string> cancel_snd; //!< sound file to use for "cancel" action
00253     plist::Primitive<std::string> error_snd; //!< sound file to use to signal errors
00254   } controller;
00255 
00256   
00257   
00258   // **************************************** //
00259   //! vision configuration options (this is a *big* section, with sub-sections)
00260   // **************************************** //
00261   class vision_config : public ConfigDictionary {
00262   public:
00263     //!constructor
00264     vision_config() : ConfigDictionary(), 
00265       white_balance(WB_FLUORESCENT), gain(GAIN_MID), shutter_speed(SHUTTER_MID),
00266       resolution(1),
00267       thresh(), colors("config/default.col"), restore_image(true), region_calc_total(true),
00268       jpeg_dct_method(JDCT_IFAST,dct_method_names), aspectRatio(CameraResolutionX/(float)CameraResolutionY),
00269       x_range(aspectRatio>1?1:*aspectRatio), y_range(aspectRatio>1?1/aspectRatio:1),
00270       rawcam(), segcam(), regioncam(), calibration()
00271     {
00272       white_balance.addNameForVal("indoor",WB_INDOOR);
00273       white_balance.addNameForVal("outdoor",WB_OUTDOOR);
00274       white_balance.addNameForVal("fluorescent",WB_FLUORESCENT);
00275       white_balance.addNameForVal("flourescent",WB_FLUORESCENT); //catch common typo
00276       addEntry("white_balance",white_balance,"white balance shifts color spectrum in the image\n"+white_balance.getDescription());
00277       
00278       gain.addNameForVal("low",GAIN_LOW);
00279       gain.addNameForVal("mid",GAIN_MID);
00280       gain.addNameForVal("med",GAIN_MID);
00281       gain.addNameForVal("medium",GAIN_MID);
00282       gain.addNameForVal("high",GAIN_HIGH);
00283       addEntry("gain",gain,"Increasing gain will brighten the image, at the expense of more graininess/noise\n"+gain.getDescription());
00284       
00285       shutter_speed.addNameForVal("slow",SHUTTER_SLOW);
00286       shutter_speed.addNameForVal("low",SHUTTER_SLOW);
00287       shutter_speed.addNameForVal("mid",SHUTTER_MID);
00288       shutter_speed.addNameForVal("med",SHUTTER_MID);
00289       shutter_speed.addNameForVal("medium",SHUTTER_MID);
00290       shutter_speed.addNameForVal("fast",SHUTTER_FAST);
00291       shutter_speed.addNameForVal("high",SHUTTER_FAST);
00292       addEntry("shutter_speed",shutter_speed,"slower shutter will brighten image, but increases motion blur\n"+shutter_speed.getDescription());
00293       
00294       addEntry("resolution",resolution,"the resolution that object recognition system will run at.\nThis counts down from the maximum resolution layer, so higher numbers mean lower resolution. ");
00295       addEntry("thresh",thresh,"Threshold (.tm) files define the mapping from full color to indexed color.\n"
00296                "You can uncomment more than one of these - they will be loaded into separate\n"
00297                "channels of the segmenter.  The only cost of loading multiple threshold files is\n"
00298                "memory - the CPU cost of performing segmentation is only incurred if/when\n"
00299                "the channel is actually accessed for the first time for a given frame. ");
00300       addEntry("colors",colors,"The colors definition (.col) file gives names and a \"typical\" color for display.\n"
00301                "The indexes numbers it contains correspond to indexes in the .tm file\n"
00302                "This file is common to all .tm files; when doing new color segmentations,\n"
00303                "make sure you define colors in the same order as listed here! ");
00304       addEntry("restore_image",restore_image,"Apparently someone at Sony thought it would be a good idea to replace some\n"
00305                "pixels in each camera image with information like the frame number and CDT count.\n"
00306                "If non-zero, will replace those pixels with the actual image pixel value in RawCamGenerator ");
00307       addEntry("region_calc_total",region_calc_total,"When true, this will fill in the CMVision::color_class_state::total_area\n"
00308                "field for each color following region labeling.  If false, the total_area\n"
00309                "will stay 0 (or whatever the last value was), but you save a little CPU. ");
00310       addEntry("jpeg_dct_method",jpeg_dct_method,"pick between dct methods for jpeg compression\n"+jpeg_dct_method.getDescription());
00311       //addEntry("aspectRatio",aspectRatio,"ratio of width to height (x_res/y_res); this is *not* read from configuration file, but set from most recent camera image (or RobotInfo namespace values if no camera image has been received)");
00312       //addEntry("x_range",x_range,"range of values for the x axis when using generalized coordinates; this is *not* read from configuration file, but set from most recent camera image (or RobotInfo namespace values if no camera image has been received)");
00313       //addEntry("y_range",y_range,"range of values for the x axis when using generalized coordinates; this is *not* read from configuration file, but set from most recent camera image (or RobotInfo namespace values if no camera image has been received)");
00314       
00315       addEntry("calibration",calibration,"Lens distortion correction parameters\nComputated by 'Camera Calibration Toolbox for Matlab', by Jean-Yves Bouguet");
00316       addEntry("rawcam",rawcam);
00317       addEntry("segcam",segcam);
00318       addEntry("regioncam",regioncam);
00319     }
00320     
00321 #ifdef PLATFORM_APERIOS
00322     //! white balance levels supported by the Aibo's camera
00323     enum white_balance_levels {
00324       WB_INDOOR=ocamparamWB_INDOOR_MODE,
00325       WB_OUTDOOR=ocamparamWB_OUTDOOR_MODE,
00326       WB_FLUORESCENT=ocamparamWB_FL_MODE
00327     };
00328 #else
00329     //! white balance levels supported by the Aibo's camera
00330     enum white_balance_levels { WB_INDOOR=1, WB_OUTDOOR, WB_FLUORESCENT };
00331 #endif
00332     plist::NamedEnumeration<white_balance_levels> white_balance; //!< white balance shifts color spectrum in the image
00333     
00334 #ifdef PLATFORM_APERIOS
00335     //! gain levels supported by the Aibo's camera
00336     enum gain_levels {
00337       GAIN_LOW=ocamparamGAIN_LOW,
00338       GAIN_MID=ocamparamGAIN_MID,
00339       GAIN_HIGH=ocamparamGAIN_HIGH
00340     };
00341 #else
00342     //! gain levels supported by the Aibo's camera
00343     enum gain_levels { GAIN_LOW=1, GAIN_MID, GAIN_HIGH };
00344 #endif
00345     plist::NamedEnumeration<gain_levels> gain; //!< Increasing gain will brighten the image, at the expense of more graininess/noise
00346 
00347 #ifdef PLATFORM_APERIOS
00348     //! shutter speeds supported by the Aibo's camera
00349     enum shutter_speeds {
00350       SHUTTER_SLOW=ocamparamSHUTTER_SLOW,
00351       SHUTTER_MID=ocamparamSHUTTER_MID,
00352       SHUTTER_FAST=ocamparamSHUTTER_FAST
00353     };
00354 #else
00355     //! shutter speeds supported by the Aibo's camera
00356     enum shutter_speeds { SHUTTER_SLOW=1, SHUTTER_MID, SHUTTER_FAST };
00357 #endif
00358     plist::NamedEnumeration<shutter_speeds> shutter_speed; //!< slower shutter will brighten image, but increases motion blur
00359     
00360     plist::Primitive<int> resolution;       //!< the resolution that object recognition system will run at -- this counts down from the maximum resolution layer, so higher numbers mean lower resolution
00361     plist::ArrayOf<plist::Primitive<std::string> > thresh;      //!< threshold file names
00362     plist::Primitive<std::string> colors;      //!< colors definition (.col) file
00363     plist::Primitive<bool> restore_image;   //!< if true, replaces pixels holding image info with actual image pixels (as much as possible anyway)
00364     plist::Primitive<bool> region_calc_total; //!< if true, RegionGenerator will calculate total area for each color (has to run through the region list for each color)
00365     static const char * dct_method_names[]; //!< string names for #J_DCT_METHOD
00366     plist::NamedEnumeration<J_DCT_METHOD> jpeg_dct_method;  //!< pick between dct methods for jpeg compression
00367     plist::Primitive<float> aspectRatio;    //!< ratio of width to height (x_res/y_res); this is *not* read from configuration file, but set from most recent camera image (or RobotInfo namespace values if no camera image has been received)
00368     plist::Primitive<float> x_range;        //!< range of values for the x axis when using generalized coordinates; this is *not* read from configuration file, but set from most recent camera image (or RobotInfo namespace values if no camera image has been received)
00369     plist::Primitive<float> y_range;        //!< range of values for the x axis when using generalized coordinates; this is *not* read from configuration file, but set from most recent camera image (or RobotInfo namespace values if no camera image has been received)
00370     
00371     //! contains settings related to streaming video over the network
00372     class StreamingConfig : public ConfigDictionary {
00373     public:
00374       explicit StreamingConfig(int portNum) : ConfigDictionary(), port(portNum), transport(Config::UDP,transport_names), interval(0)
00375       {
00376         addEntry("port",port,"the port number to open for sending data over");
00377         addEntry("transport",transport,"the IP protocol to use when sending data");
00378         addEntry("interval",interval,"minimum amount of time (in milliseconds) which must pass between frames\nE.g. 200 yields just under 5 frames per second, 0 is as fast as possible");
00379       }
00380       plist::Primitive<int> port;
00381       plist::NamedEnumeration<Config::transports> transport;
00382       plist::Primitive<unsigned int> interval;
00383     };
00384     
00385     //! contains settings specific to the "RawCam" (original camera images) for streaming video over the network
00386     class RawCamConfig : public StreamingConfig {
00387     public:
00388       RawCamConfig() : StreamingConfig(10011),
00389         encoding(ENCODE_COLOR,encoding_names), channel(0), compression(COMPRESS_JPEG,compression_names), compress_quality(85), y_skip(2), uv_skip(3)
00390       {
00391         addEntry("encoding",encoding,"holds whether to send color or single channel\n"+encoding.getDescription());
00392         addEntry("channel",channel,"if encoding is single channel, this indicates the channel to send");
00393         addEntry("compression",compression,"the type of compression to apply the image\n"+compression.getDescription());
00394         addEntry("compress_quality",compress_quality,"0-100, compression quality (currently only used by jpeg)");
00395         addEntry("y_skip",y_skip,"resolution level to transmit y channel\nAlso used as the resolution level when in single-channel encoding mode ");
00396         addEntry("uv_skip",uv_skip,"resolution level to transmit uv channel at when using 'color' encoding mode");
00397       }
00398       //! type of information to send, stored in #encoding
00399       enum encoding_t {
00400         ENCODE_COLOR, //!< send Y, U, and V channels
00401         ENCODE_SINGLE_CHANNEL, //!< send only a single channel (which channel to send is stored in #channel) This is also used for all seg cam images
00402       };
00403       static const unsigned int NUM_ENCODINGS=2; //!< number of encodings available
00404       static const char * encoding_names[NUM_ENCODINGS+1]; //!< string names for #encoding_t
00405       plist::NamedEnumeration<encoding_t> encoding; //!< holds whether to send color or single channel
00406       plist::Primitive<int> channel;    //!< RawCameraGenerator::channel_id_t, if #encoding is single channel, this indicates the channel to send
00407 
00408       //! compression format to use, stored in Config::vision_config::RawCamConfig::compression
00409       enum compression_t {
00410         COMPRESS_NONE, //!< no compression (other than subsampling)
00411         COMPRESS_JPEG, //!< JPEG compression
00412         COMPRESS_PNG, //!< PNG compression
00413       };
00414       static const unsigned int NUM_COMPRESSIONS=4; //!< number of compression algorithms available
00415       static const char * compression_names[NUM_COMPRESSIONS+1]; //!< string names for #compression_t
00416       plist::NamedEnumeration<compression_t> compression;//!< holds whether to send jpeg compression
00417 
00418       plist::Primitive<int> compress_quality;//!< 0-100, compression quality (currently only used by jpeg)
00419       plist::Primitive<int> y_skip;     //!< resolution level to transmit y channel at
00420       plist::Primitive<int> uv_skip;    //!< resolution level to transmit uv channel at
00421     } rawcam;
00422     
00423     //! contains settings specific to the "SegCam" (segmented color images) for streaming video over the network
00424     class SegCamConfig : public StreamingConfig {
00425     public:
00426       SegCamConfig() : StreamingConfig(10012), skip(1), channel(0), compression(COMPRESS_RLE, compression_names)
00427       {
00428         addEntry("skip",skip,"resolution level to transmit segmented images at");
00429         addEntry("channel",channel,"channel of RLEGenerator to send (i.e. which threshold map to use");
00430         addEntry("compression",compression,"what compression to use on the segmented image"+compression.getDescription());
00431       }
00432       plist::Primitive<int> skip;       //!< resolution level to transmit segmented images at
00433       plist::Primitive<int> channel;    //!< channel of RLEGenerator to send (i.e. which threshold map to use)
00434       
00435       //! compression format to use, stored in Config::vision_config::RawCamConfig::compression
00436       enum compression_t {
00437         COMPRESS_NONE, //!< no compression (other than subsampling)
00438         COMPRESS_RLE   //!< RLE compression
00439       };
00440       static const unsigned int NUM_COMPRESSIONS=4; //!< number of compression algorithms available
00441       static const char * compression_names[NUM_COMPRESSIONS+1]; //!< string names for #compression_t
00442       plist::NamedEnumeration<compression_t> compression;//!< what compression to use on the segmented image
00443     } segcam;
00444     
00445     //! contains settings specific to the "RegionCam" (only display a box for each blob of color) for streaming over the network
00446     class RegionCamConfig : public StreamingConfig {
00447     public:
00448       RegionCamConfig() : StreamingConfig(10013), skip(1) {
00449         addEntry("skip",skip,"resolution level to extract regions from");
00450       }
00451       plist::Primitive<int> skip; //!< resolution level to transmit segmented images at 
00452     } regioncam;
00453     
00454     //!These values represent a "Plumb Bob" model introduced by Brown in 1966
00455     /*!Lens Distortion for Close-Range Photogrammetry -  D.C. Brown, Photometric Engineering, pages 855-866, Vol. 37, No. 8, 1971.
00456      * 
00457      * Can be computated by 'Camera Calibration Toolbox for Matlab', by Jean-Yves Bouguet:
00458      * http://www.vision.caltech.edu/bouguetj/calib_doc/ */
00459     class CameraCalibration : public ConfigDictionary {
00460     public:
00461       CameraCalibration() : ConfigDictionary(),
00462         focal_len_x(CameraResolutionX),focal_len_y(CameraResolutionX),principle_point_x(CameraResolutionX/2),
00463         principle_point_y(CameraResolutionY/2),skew(0),kc1_r2(0),kc2_r4(0),kc5_r6(0),kc3_tan1(0),kc4_tan2(0),
00464         calibration_res_x(CameraResolutionX), calibration_res_y(CameraResolutionY)
00465       {
00466         addEntry("focal_len_x",focal_len_x,"focal length of camera, in pixels, K11");
00467         addEntry("focal_len_y",focal_len_y,"focal length of camera, in pixels, K22");
00468         addEntry("principle_point_x",principle_point_x,"center of optical projection, K13");
00469         addEntry("principle_point_y",principle_point_y,"center of optical projection, K23");
00470         addEntry("skew",skew,"CCD skew, K12 = skew*focal_len_x");
00471         addEntry("kc1_r2",kc1_r2,"r-squared radial distortion");
00472         addEntry("kc2_r4",kc2_r4,"r to the 4 radial distortion");
00473         addEntry("kc5_r6",kc5_r6,"r to the 6 radial distortion");
00474         addEntry("kc3_tan1",kc3_tan1,"first tangential correction term");
00475         addEntry("kc4_tan2",kc4_tan2,"second tangential correctiont term");
00476         addEntry("calibration_res_x",calibration_res_x,"x resolution of images used during calibration");
00477         addEntry("calibration_res_y",calibration_res_y,"y resolution of images used during calibration");
00478       }
00479       plist::Primitive<float> focal_len_x; //!< focal length of camera, in pixels, K11
00480       plist::Primitive<float> focal_len_y; //!< focal length of camera, in pixels, K22
00481       plist::Primitive<float> principle_point_x; //!< center of optical projection, K13
00482       plist::Primitive<float> principle_point_y; //!< center of optical projection, K23
00483       plist::Primitive<float> skew; //!< CCD skew, K12 = skew*focal_len_x
00484       plist::Primitive<float> kc1_r2; //!< r-squared radial distortion
00485       plist::Primitive<float> kc2_r4; //!< r to the 4 radial distortion
00486       plist::Primitive<float> kc5_r6; //!< r to the 6 radial distortion
00487       plist::Primitive<float> kc3_tan1; //!< first tangential correction term
00488       plist::Primitive<float> kc4_tan2; //!< second tangential correctiont term
00489       plist::Primitive<unsigned int> calibration_res_x; //!< x resolution of images used during calibration
00490       plist::Primitive<unsigned int> calibration_res_y; //!< y resolution of images used during calibration
00491     } calibration;
00492     
00493     //!provides a ray from camera through pixel in image; where possible, use computePixel for better accuracy (i.e. try to always move from world to camera instead of the other way around)
00494     /*! We can't precisely undo some terms of the distortion model -- this is an estimate.
00495      *  @todo Might be able to redo the vision calibration in reverse to get another set of parameters dedicated to the inverse computation?
00496      *  @param[in] x x position in range [-1,1]
00497      *  @param[in] y y position in range [-1,1]
00498      *  @param[out] r_x x value of the ray
00499      *  @param[out] r_y y value of the ray
00500      *  @param[out] r_z z value of the ray (always 1) */
00501     void computeRay(float x, float y, float& r_x, float& r_y, float& r_z);
00502       
00503     //!provides a pixel hit in image by a ray going through the camera frame
00504     /*! @param[in] r_x x value of the ray
00505      *  @param[in] r_y y value of the ray
00506      *  @param[in] r_z z value of the ray
00507      *  @param[out] x x position in range [-1,1]
00508      *  @param[out] y y position in range [-1,1] */
00509     void computePixel(float r_x, float r_y, float r_z, float& x, float& y);
00510     //@}
00511         
00512   } vision;
00513   
00514   
00515   
00516   //!motion information
00517   class motion_config : public ConfigDictionary {
00518   public:
00519     //!constructor
00520     motion_config(Config* c)
00521       : ConfigDictionary(), thisconfig(c), root("data/motion"), walk("walk.prm"), kinematics(), kinematic_chains(),
00522         calibration_scale(PIDJointOffset, NumPIDJoints,1), calibration_offset(PIDJointOffset, NumPIDJoints, 0), 
00523         estop_on_snd(), estop_off_snd(), 
00524       max_head_tilt_speed(0), max_head_pan_speed(0), max_head_roll_speed(0), inf_walk_accel(false),
00525       console_port(10003), stderr_port(10004)
00526 #ifdef TGT_HAS_WHEELS
00527       , wheelBaseWidth(140), wheelRadius(26)
00528 #endif
00529     {
00530       addEntry("root",root,"path on memory stick to \"motion\" files - for instance, position (.pos) and motion sequence (.mot)\n"
00531                "Any motion related paths which are not absolute (i.e. do not start with '/')\n"
00532                "will be assumed to be relative to this directory ");
00533       addEntry("walk",walk,"the walk parameter file to load by default for new WalkMC's");
00534       addEntry("kinematics",kinematics,"the ROBOOP format kinematics description file to load");
00535       addEntry("kinematic_chains",kinematic_chains,"list of chain names to load from the file specified by 'kinematics'");
00536       addEntry("calibration_scale",calibration_scale,"Multiplier from desired position to command for each PID joint, applied after calibration_offset.");
00537       addEntry("calibration_offset",calibration_offset,"These values indicate the offset from user specified zero point to the\n"
00538                "physical system's zero point.  Added before calibration_scale when\n"
00539                "converting from user's desired position to command to send to hardware.");
00540       addEntry("estop_on_snd",estop_on_snd,"sound file to use when e-stop turned on");
00541       addEntry("estop_off_snd",estop_off_snd,"sound file to use when e-stop turned off");
00542       addEntry("max_head_tilt_speed",max_head_tilt_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00543       addEntry("max_head_pan_speed",max_head_pan_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00544       addEntry("max_head_roll_speed",max_head_roll_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00545       addEntry("inf_walk_accel",inf_walk_accel,"if true, walks should attempt to switch directions immediately; otherwise they should do some kind of software acceleration to more smoothly switch direction");
00546       addEntry("console_port",console_port,"port to send/receive \"console\" information on (separate from system console)");
00547       addEntry("stderr_port",stderr_port,"port to send error information to");
00548 #ifdef TGT_HAS_WHEELS
00549       addEntry("wheelBaseWidth",wheelBaseWidth,"distance between left and right wheel, in millimeters");
00550       addEntry("wheelRadius",wheelRadius,"radius of drive wheels, in millimeters");
00551 #endif
00552     }
00553     
00554     //!returns an absolute path if @a is relative (to root), otherwise just @a name
00555     std::string makePath(const std::string& name) { 
00556       if(name[0]=='/')
00557         return thisconfig->portPath(name);
00558       if(root[root.size()-1]=='/')
00559         return thisconfig->portPath(root+name);
00560       else
00561         return thisconfig->portPath(root+"/"+name);
00562     }
00563     
00564     Config* thisconfig;  //!<pointer back to the containing config object
00565     plist::Primitive<std::string> root;       //!< path on memory stick to "motion" files - for instance, position (.pos) and motion sequence (.mot)
00566     plist::Primitive<std::string> walk;       //!< the walk parameter file to load by default for new WalkMC's
00567     plist::Primitive<std::string> kinematics;  //!< the kinematics description file to load
00568     plist::ArrayOf<plist::Primitive<std::string> > kinematic_chains; //!< list of chain names to load from #kinematics
00569     OutputConfig<plist::Primitive<float> > calibration_scale; //!< Multiplier from desired position to command for each PID joint, applied after calibration_offset.
00570     OutputConfig<plist::Primitive<float> > calibration_offset; //!< Indicates the offset from user specified zero point to the physical system's zero point.  Added before calibration_scale when converting from user's desired position to command to send to hardware.
00571     plist::Primitive<std::string> estop_on_snd;  //!< sound file to use when e-stop turned on
00572     plist::Primitive<std::string> estop_off_snd; //!< sound file to use when e-stop turned off
00573     plist::Primitive<float> max_head_tilt_speed; //!< max speed for the head joints, used by HeadPointerMC; rad/s
00574     plist::Primitive<float> max_head_pan_speed; //!< max speed for the head joints, used by HeadPointerMC; rad/s
00575     plist::Primitive<float> max_head_roll_speed; //!< max speed for the head joints, used by HeadPointerMC; rad/s
00576     plist::Primitive<bool> inf_walk_accel; //!< if true, walks should attempt to switch directions immediately; otherwise they should do some kind of software acceleration to more smoothly switch direction
00577     plist::Primitive<int> console_port;  //!< port to send/receive "console" information on (separate from system console)
00578     plist::Primitive<int> stderr_port;   //!< port to send error information to
00579 #ifdef TGT_HAS_WHEELS
00580     plist::Primitive<float> wheelBaseWidth; //!< distance between left and right wheel, in millimeters
00581     plist::Primitive<float> wheelRadius; //!< radius of drive wheels, in millimeters
00582 #endif
00583     
00584     
00585   private:
00586     motion_config(const motion_config&); //!< don't call
00587     motion_config& operator=(const motion_config&); //!< don't call
00588   } motion;
00589 
00590   
00591   
00592   //!sound information
00593   class sound_config : public ConfigDictionary {
00594   public:
00595     //!constructor
00596     sound_config(Config* c) : ConfigDictionary(), thisconfig(c), root("data/sound"), volume(HIGH), sample_rate(16000),
00597       sample_bits(16), preload(), pitchConfidenceThreshold(.6f), streaming()
00598     {
00599       addEntry("root",root,"path to sound clips");
00600       volume.addNameForVal("mute",MUTE);
00601       volume.addNameForVal("low",LOW);
00602       volume.addNameForVal("level_1",LOW);
00603       volume.addNameForVal("mid",MID);
00604       volume.addNameForVal("level_2",MID);
00605       volume.addNameForVal("high",HIGH);
00606       volume.addNameForVal("level_3",HIGH);
00607       volume.setStrict(false);
00608       addEntry("volume",volume,"volume in decibels - the value is interpreted as a signed short, where\n"
00609           "0x8000 is mute, 0xFFFF is full volume (low=0xE700, mid=0xEE00, high=0xF600)\n"
00610           "If you directly set the decibel level, be warned sony recommends against going above 0xF600\n"
00611           "However, I believe the commercial software on the ERS-7 runs at 0xFF00.\n"
00612           "Going above 0xF800 on a ERS-210 causes distortion (clipping) - full volume on a ERS-7 sounds fine though.\n"+volume.getDescription());
00613       addEntry("sample_rate",sample_rate,"sample rate to send to system, currently only 8000 or 16000 supported");
00614       addEntry("sample_bits",sample_bits,"sample bit depth, either 8 or 16");
00615       addEntry("preload",preload,"list of sounds to preload at boot");
00616       addEntry("pitchConfidenceThreshold",pitchConfidenceThreshold,"confidence threshold required to generate a pitch event [0-1]");
00617       addEntry("streaming",streaming);
00618     }
00619   
00620     //!returns an absolute path if @a is relative (to root), otherwise just @a name
00621     std::string makePath(const std::string& name) { 
00622       if(name[0]=='/')
00623         return thisconfig->portPath(name);
00624       if(root[root.size()-1]=='/')
00625         return thisconfig->portPath(root+name);
00626       else
00627         return thisconfig->portPath(root+"/"+name);
00628     }
00629   
00630     Config* thisconfig;  //!<pointer back to the containing config object
00631     plist::Primitive<std::string> root;         //!< path to sound clips
00632     
00633     //! Provides some symbolic volume levels, although values are based on actual volume in decibels.
00634     /*! The value is interpreted as a signed short, where 0 is full volume, 0x8000 is mute */
00635     enum volume_levels { MUTE=ospkvolinfdB, LOW=ospkvol25dB, MID=ospkvol18dB, HIGH=ospkvol10dB };
00636     plist::NamedEnumeration<volume_levels> volume;      //!< volume in decibels - the value is interpreted as a signed short, where 0 is full volume, 0x8000 is mute
00637     
00638     plist::Primitive<unsigned int> sample_rate; //!< sample rate to send to system, currently only 8000 or 16000 supported
00639     plist::Primitive<unsigned int> sample_bits; //!< sample bit depth, either 8 or 16
00640     plist::ArrayOf<plist::Primitive<std::string> > preload; //!< list of sounds to preload at boot
00641     plist::Primitive<float> pitchConfidenceThreshold; //!< confidence threshold required to generate a pitch event [0-1]
00642     
00643     //! audio streaming configuration
00644     class streaming_config : public ConfigDictionary {
00645     public:
00646       //! constructor
00647       streaming_config() : ConfigDictionary(), mic_port(10070), mic_sample_rate(16000),
00648         mic_sample_bits(16), mic_stereo(true),
00649         speaker_port(10071), speaker_frame_length(64),
00650         speaker_max_delay(1000)
00651       {
00652         addEntry("mic_port",mic_port,"port for streaming microphone samples");
00653         addEntry("mic_sample_rate",mic_sample_rate,"sample rate from the microphone");
00654         addEntry("mic_sample_bits",mic_sample_bits,"sample bit depth from the microphone (either 8 or 16)");
00655         addEntry("mic_stereo",mic_stereo,"whether to stream stereo or mono from the microphone");
00656         
00657         addEntry("speaker_port",speaker_port,"port for streaming speaker samples");
00658         addEntry("speaker_frame_length",speaker_frame_length,"length of frame sent to the speaker (ms)");
00659         addEntry("speaker_max_delay",speaker_max_delay,"maximum delay (ms) during playback");
00660       }
00661       plist::Primitive<unsigned int> mic_port;        //!< port for streaming microphone samples
00662       plist::Primitive<unsigned int> mic_sample_rate; //!< sample rate from the microphone
00663       plist::Primitive<unsigned int> mic_sample_bits; //!< sample bit depth from the microphone (either 8 or 16)
00664       plist::Primitive<bool> mic_stereo; //!< whether to stream stereo or mono from the microphone
00665       
00666       plist::Primitive<unsigned int> speaker_port;    //!< port for streaming speaker samples
00667       plist::Primitive<unsigned int> speaker_frame_length; //!< length of frame sent to the speaker (ms)
00668       plist::Primitive<unsigned int> speaker_max_delay; //!< maximum delay (ms) during playback
00669     } streaming;
00670   private:
00671     sound_config(const sound_config&); //!< don't call
00672     sound_config& operator=(const sound_config&); //!< don't call
00673   } sound;
00674 
00675   
00676   
00677   virtual void saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const;
00678   using ConfigDictionary::saveXML;
00679   virtual unsigned int loadBuffer(const char buf[], unsigned int len);
00680   virtual unsigned int loadFile(const char* filename);
00681   virtual unsigned int loadFileStream(FILE* f);
00682   
00683   //! pass the section, item name string, item value string - sets the value and returns pointer to the item changed
00684   /*! this is the older deprecated interface -- use the inherited resolveEntry() instead to support sub-sections */
00685   void* setValue(const std::string& section, std::string key, const std::string& value);
00686   
00687 protected:
00688   static const char * xmlIntro1;
00689   static const char * xmlIntro2;
00690   static const char * xmlIntro3;
00691   
00692   static const std::locale& curLocale;
00693   static char localeToLower(char c) { return std::tolower(c,curLocale); };
00694   
00695   unsigned int loadOldFormat(const char buf[], unsigned int len);
00696   unsigned int loadOldFormat(FILE* f);
00697   void parseLine(const char buf[], unsigned int lineno, std::vector<std::string>& modelStack, bool& ignoring, std::string& section);
00698   
00699   //! a prefix representing the file system root, usually indicating the robot's storage root.
00700   /*! When running in the simulator, this is used to pretend that a subdirectory in the project folder (e.g. 'ms') is the root file system */
00701   std::string fsRoot;
00702 };
00703 
00704 template<typename T>
00705 void OutputConfig<T>::saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const {
00706   // first just overwrite what's already there as we normally do
00707   ConfigDictionary::saveXML(node,true,seen);
00708   // now if there's anything left...
00709   if(!onlyOverwrite && seen.size()!=dict.size()) {
00710     // clear text nodes from end of dictionary back to last entry
00711     for(xmlNode* cur=xNodeGetLastChild(node); cur!=NULL && xNodeIsText(cur); cur=xNodeGetLastChild(node)) {
00712       xmlUnlinkNode(cur);
00713       xmlFreeNode(cur);
00714     }
00715     std::string indentStr=getIndentationPrefix(node);
00716     // this is the customized part -- save in "natural" output order instead of alphabetically by key
00717     for(unsigned int i=0; i<outputs.size(); ++i) {
00718       if(seen.find(outputNames[i+offset])==seen.end())
00719         saveXMLNode(node,outputNames[i+offset],&outputs[i],indentStr);
00720     }
00721     std::string parentIndent;
00722     if(indentStr.size()>=perIndent().size())
00723       parentIndent=indentStr.substr(perIndent().size());
00724     xmlAddChild(node,xmlNewText((const xmlChar*)("\n"+parentIndent).c_str()));
00725   }
00726 }
00727 
00728 //!allows global access to current settings
00729 extern Config* config;
00730 
00731 /*! @file
00732  * @brief Describes Config, which provides global access to system configuration information
00733  * @author ejt (Creator)
00734  * @author alokl (Original configuration system)
00735  *
00736  * $Author: ejt $
00737  * $Name: tekkotsu-4_0 $
00738  * $Revision: 1.64 $
00739  * $State: Exp $
00740  * $Date: 2007/11/16 15:53:49 $
00741  */
00742 
00743 #endif

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