00001
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;
00014 const OSpeakerVolume ospkvolinfdB = 0x8000;
00015 const OSpeakerVolume ospkvol25dB = 0xe700;
00016 const OSpeakerVolume ospkvol18dB = 0xee00;
00017 const OSpeakerVolume ospkvol10dB = 0xf600;
00018 #endif
00019 #include <vector>
00020 #include <string>
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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
00049 static bool matchNoCase(const std::string& model, const std::string& pattern);
00050
00051 static const std::string msPrefix;
00052 static const std::string msSep;
00053
00054 static std::string curModel;
00055 static void initCurModel();
00056 };
00057
00058
00059
00060
00061
00062 template<typename T>
00063 class OutputConfig : public ConfigDictionary {
00064 public:
00065
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
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
00078 T& getEntry(size_t index) { return outputs[index]; }
00079
00080 T& operator[](size_t index) { return outputs[index]; }
00081 using ConfigDictionary::operator[];
00082
00083
00084 void saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const;
00085 using ConfigDictionary::saveXML;
00086
00087 protected:
00088
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;
00095 std::vector<T> outputs;
00096 };
00097
00098
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 };
00116 static const unsigned int NUM_TRANSPORTS=2;
00117 static const char * transport_names[NUM_TRANSPORTS+1];
00118
00119 void setFileSystemRoot(const std::string& fsr);
00120 const std::string& getFileSystemRoot() const { return fsRoot; }
00121 std::string portPath(const std::string& path) const;
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 class behaviors_config : public ConfigDictionary {
00137 public:
00138
00139 behaviors_config() : ConfigDictionary(), flash_bytes(4), flash_on_start(true)
00140 {
00141
00142
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;
00154 plist::Primitive<bool> flash_on_start;
00155 } behaviors;
00156
00157
00158
00159
00160
00161
00162 class wireless_config : public ConfigDictionary {
00163 public:
00164
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;
00169 } wireless;
00170
00171
00172
00173
00174
00175
00176 class main_config : public ConfigDictionary {
00177 public:
00178
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;
00204 plist::Primitive<int> console_port;
00205
00206 enum consoleMode_t {
00207 CONTROLLER,
00208 TEXTMSG,
00209 AUTO
00210 };
00211 static const unsigned int NUM_CONSOLE_MODES=3;
00212 static const char* consoleModeNames[NUM_CONSOLE_MODES+1];
00213
00214 plist::NamedEnumeration<consoleMode_t> consoleMode;
00215 plist::Primitive<int> stderr_port;
00216 plist::Primitive<int> wsjoints_port;
00217 plist::Primitive<int> wspids_port;
00218 plist::Primitive<int> headControl_port;
00219 plist::Primitive<int> walkControl_port;
00220 plist::Primitive<int> estopControl_port;
00221 plist::Primitive<int> stewart_port;
00222 plist::Primitive<int> aibo3d_port;
00223 plist::Primitive<int> wmmonitor_port;
00224 plist::Primitive<bool> use_VT100;
00225 plist::Primitive<unsigned int> worldState_interval;
00226 } main;
00227
00228
00229
00230
00231
00232
00233 class controller_config : public ConfigDictionary {
00234 public:
00235
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;
00248 plist::Primitive<std::string> select_snd;
00249 plist::Primitive<std::string> next_snd;
00250 plist::Primitive<std::string> prev_snd;
00251 plist::Primitive<std::string> read_snd;
00252 plist::Primitive<std::string> cancel_snd;
00253 plist::Primitive<std::string> error_snd;
00254 } controller;
00255
00256
00257
00258
00259
00260
00261 class vision_config : public ConfigDictionary {
00262 public:
00263
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);
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
00312
00313
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
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
00330 enum white_balance_levels { WB_INDOOR=1, WB_OUTDOOR, WB_FLUORESCENT };
00331 #endif
00332 plist::NamedEnumeration<white_balance_levels> white_balance;
00333
00334 #ifdef PLATFORM_APERIOS
00335
00336 enum gain_levels {
00337 GAIN_LOW=ocamparamGAIN_LOW,
00338 GAIN_MID=ocamparamGAIN_MID,
00339 GAIN_HIGH=ocamparamGAIN_HIGH
00340 };
00341 #else
00342
00343 enum gain_levels { GAIN_LOW=1, GAIN_MID, GAIN_HIGH };
00344 #endif
00345 plist::NamedEnumeration<gain_levels> gain;
00346
00347 #ifdef PLATFORM_APERIOS
00348
00349 enum shutter_speeds {
00350 SHUTTER_SLOW=ocamparamSHUTTER_SLOW,
00351 SHUTTER_MID=ocamparamSHUTTER_MID,
00352 SHUTTER_FAST=ocamparamSHUTTER_FAST
00353 };
00354 #else
00355
00356 enum shutter_speeds { SHUTTER_SLOW=1, SHUTTER_MID, SHUTTER_FAST };
00357 #endif
00358 plist::NamedEnumeration<shutter_speeds> shutter_speed;
00359
00360 plist::Primitive<int> resolution;
00361 plist::ArrayOf<plist::Primitive<std::string> > thresh;
00362 plist::Primitive<std::string> colors;
00363 plist::Primitive<bool> restore_image;
00364 plist::Primitive<bool> region_calc_total;
00365 static const char * dct_method_names[];
00366 plist::NamedEnumeration<J_DCT_METHOD> jpeg_dct_method;
00367 plist::Primitive<float> aspectRatio;
00368 plist::Primitive<float> x_range;
00369 plist::Primitive<float> y_range;
00370
00371
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
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
00399 enum encoding_t {
00400 ENCODE_COLOR,
00401 ENCODE_SINGLE_CHANNEL,
00402 };
00403 static const unsigned int NUM_ENCODINGS=2;
00404 static const char * encoding_names[NUM_ENCODINGS+1];
00405 plist::NamedEnumeration<encoding_t> encoding;
00406 plist::Primitive<int> channel;
00407
00408
00409 enum compression_t {
00410 COMPRESS_NONE,
00411 COMPRESS_JPEG,
00412 COMPRESS_PNG,
00413 };
00414 static const unsigned int NUM_COMPRESSIONS=4;
00415 static const char * compression_names[NUM_COMPRESSIONS+1];
00416 plist::NamedEnumeration<compression_t> compression;
00417
00418 plist::Primitive<int> compress_quality;
00419 plist::Primitive<int> y_skip;
00420 plist::Primitive<int> uv_skip;
00421 } rawcam;
00422
00423
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;
00433 plist::Primitive<int> channel;
00434
00435
00436 enum compression_t {
00437 COMPRESS_NONE,
00438 COMPRESS_RLE
00439 };
00440 static const unsigned int NUM_COMPRESSIONS=4;
00441 static const char * compression_names[NUM_COMPRESSIONS+1];
00442 plist::NamedEnumeration<compression_t> compression;
00443 } segcam;
00444
00445
00446 class RegionCamConfig : public StreamingConfig {
00447 public: