00001
00002 #ifndef INCLUDED_Config_h
00003 #define INCLUDED_Config_h
00004
00005 #include "Shared/plist.h"
00006 #include "Shared/string_util.h"
00007 #include "Shared/RobotInfo.h"
00008 extern "C" {
00009 #include <jpeglib.h>
00010 }
00011 #ifdef PLATFORM_APERIOS
00012 # include <OPENR/OPrimitiveControl.h>
00013 #else
00014 typedef unsigned int OSpeakerVolume;
00015 const OSpeakerVolume ospkvolinfdB = 0x8000;
00016 const OSpeakerVolume ospkvol25dB = 0xe700;
00017 const OSpeakerVolume ospkvol18dB = 0xee00;
00018 const OSpeakerVolume ospkvol10dB = 0xf600;
00019 #endif
00020 #include <vector>
00021 #include <string>
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 class ConfigDictionary : public plist::Dictionary {
00037 public:
00038 ConfigDictionary() : plist::Dictionary(false)
00039 {
00040 if(curModel.size()==0)
00041 curModel=RobotName;
00042 }
00043
00044 protected:
00045
00046 virtual bool loadXMLNode(const std::string& key, xmlNode* val, const std::string& comment);
00047 virtual bool saveOverXMLNode(xmlNode* k, xmlNode* val, const std::string& key, std::string comment, const std::string& indentStr, std::set<std::string>& seen) const;
00048
00049
00050 static bool matchNoCase(const std::string& model, const std::string& pattern);
00051
00052 static const std::string msPrefix;
00053 static const std::string msSep;
00054
00055 static std::string curModel;
00056 static void initCurModel();
00057 };
00058
00059
00060
00061
00062
00063 template<typename T>
00064 class OutputConfig : public ConfigDictionary {
00065 public:
00066
00067 OutputConfig(unsigned int firstOffset, unsigned int numOutputsToStore, const T& defValue)
00068 : ConfigDictionary(), offset(firstOffset), outputs(numOutputsToStore,defValue)
00069 {
00070 for(unsigned int i=0; i<numOutputsToStore; ++i)
00071 addEntry(outputNames[i+firstOffset],outputs[i]);
00072 }
00073
00074 virtual ObjectBase& getEntry(const std::string& name) {
00075 std::string::size_type n = name.find_last_not_of('~')+1;
00076 return ConfigDictionary::getEntry((n==name.size()) ? name : name.substr(0,n));
00077 }
00078
00079 T& getEntry(size_t index) { return outputs[index]; }
00080
00081 T& operator[](size_t index) { return outputs[index]; }
00082 using ConfigDictionary::operator[];
00083
00084
00085 void saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const;
00086 using ConfigDictionary::saveXML;
00087
00088 protected:
00089
00090 bool loadXMLNode(const std::string& key, xmlNode* val, const std::string& comment) {
00091 std::string::size_type n = key.find_last_not_of('~')+1;
00092 return ConfigDictionary::loadXMLNode((n==key.size()) ? key : key.substr(0,n), val, comment);
00093 }
00094
00095 unsigned int offset;
00096 std::vector<T> outputs;
00097 };
00098
00099
00100 class Config : public ConfigDictionary {
00101 public:
00102 Config(const std::string& filename="") : ConfigDictionary(),
00103 behaviors(), wireless(), main(), controller(), vision(), motion(this), sound(this), fsRoot()
00104 {
00105 addEntry("wireless",wireless);
00106 addEntry("vision",vision);
00107 addEntry("main",main);
00108 addEntry("behaviors",behaviors);
00109 addEntry("controller",controller);
00110 addEntry("motion",motion);
00111 addEntry("sound",sound);
00112 if(filename.size()!=0)
00113 loadFile(filename.c_str());
00114 }
00115
00116 enum transports { UDP, TCP };
00117 static const unsigned int NUM_TRANSPORTS=2;
00118 static const char * transport_names[NUM_TRANSPORTS+1];
00119
00120 void setFileSystemRoot(const std::string& fsr);
00121 const std::string& getFileSystemRoot() const { return fsRoot; }
00122
00123
00124 std::string portPath(const std::string& path) const;
00125
00126
00127 std::string makePath(const std::string& name) const { return searchPath(name,"config"); }
00128
00129
00130 std::string searchPath(const std::string& name, const std::string& root) const;
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 class behaviors_config : public ConfigDictionary {
00146 public:
00147
00148 behaviors_config() : ConfigDictionary(), flash_bytes(4), flash_on_start(true)
00149 {
00150
00151
00152 setUnusedWarning(false);
00153
00154 addEntry("flash_bytes",flash_bytes,"how many bytes of the address to flash\n"
00155 "You probably already know the first 3 bytes for your network,\n"
00156 "so you might only want the last byte for brevity.\n"
00157 "(valid values are 1 through 4) ");
00158 addEntry("flash_on_start",flash_on_start,"whether or not to automatically trigger on boot\n"
00159 "Will use a priority of kEmergencyPriority+1 in order to override\n"
00160 "the emergency stop's status animation ");
00161 }
00162 plist::Primitive<unsigned int> flash_bytes;
00163 plist::Primitive<bool> flash_on_start;
00164 } behaviors;
00165
00166
00167
00168
00169
00170
00171 class wireless_config : public ConfigDictionary {
00172 public:
00173
00174 wireless_config () : ConfigDictionary(), id(1) {
00175 addEntry("id",id,"id number (in case you have more than one AIBO)");
00176 }
00177 plist::Primitive<int> id;
00178 } wireless;
00179
00180
00181
00182
00183
00184
00185 class main_config : public ConfigDictionary {
00186 public:
00187
00188 main_config()
00189 : ConfigDictionary(), seed_rng(true), console_port(10001), consoleMode(CONTROLLER,consoleModeNames), stderr_port(10002),
00190 wsjoints_port(10031),wspids_port(10032),headControl_port(10052),armControl_port(10054),
00191 walkControl_port(10050),estopControl_port(10053),stewart_port(10055),aibo3d_port(10051),
00192 wmmonitor_port(10061), use_VT100(true), worldState_interval(0)
00193 {
00194 addEntry("seed_rng",seed_rng,"if true, will call srand with timestamp data, mangled by current sensor data");
00195 addEntry("console_port",console_port,"port to send/receive \"console\" information on (separate from system console)");
00196 addEntry("consoleMode",consoleMode,"determines how input on console_port is interpreted\n"+consoleMode.getDescription()+"\n"
00197 " 'controller' will pass it as input to the Controller (assumes same syntax as ControllerGUI)\n"
00198 " 'textmsg' will broadcast it as a TextMsgEvent (textmsgEGID)\n"
00199 " 'auto' is the original mode, which uses 'textmsg' if the ControllerGUI is connected, and 'controller' otherwise ");
00200 addEntry("stderr_port",stderr_port,"port to send error information to");
00201 addEntry("wsjoints_port",wsjoints_port,"port to send joint positions on");
00202 addEntry("wspids_port",wspids_port,"port to send pid info on");
00203 addEntry("headControl_port",headControl_port,"port for receiving head commands");
00204 addEntry("armControl_port",armControl_port,"port for receiving arm commands");
00205 addEntry("walkControl_port",walkControl_port,"port for receiving walk commands");
00206 addEntry("estopControl_port",estopControl_port,"port for receiving walk commands");
00207 addEntry("stewart_port",stewart_port,"port for running a stewart platform style of control");
00208 addEntry("aibo3d_port",aibo3d_port,"port for send/receive of joint positions from Aibo 3D GUI");
00209 addEntry("wmmonitor_port",wmmonitor_port,"port for monitoring Watchable Memory");
00210 addEntry("use_VT100",use_VT100,"if true, enables VT100 console codes (currently only in Controller menus - 1.3)");
00211 addEntry("worldState_interval",worldState_interval,"time (in milliseconds) to wait between sending WorldState updates over wireless");
00212 }
00213 plist::Primitive<bool> seed_rng;
00214 plist::Primitive<int> console_port;
00215
00216 enum consoleMode_t {
00217 CONTROLLER,
00218 TEXTMSG,
00219 AUTO
00220 };
00221 static const unsigned int NUM_CONSOLE_MODES=3;
00222 static const char* consoleModeNames[NUM_CONSOLE_MODES+1];
00223
00224 plist::NamedEnumeration<consoleMode_t> consoleMode;
00225 plist::Primitive<int> stderr_port;
00226 plist::Primitive<int> wsjoints_port;
00227 plist::Primitive<int> wspids_port;
00228 plist::Primitive<int> headControl_port;
00229 plist::Primitive<int> armControl_port;
00230 plist::Primitive<int> walkControl_port;
00231 plist::Primitive<int> estopControl_port;
00232 plist::Primitive<int> stewart_port;
00233 plist::Primitive<int> aibo3d_port;
00234 plist::Primitive<int> wmmonitor_port;
00235 plist::Primitive<bool> use_VT100;
00236 plist::Primitive<unsigned int> worldState_interval;
00237 } main;
00238
00239
00240
00241
00242
00243
00244 class controller_config : public ConfigDictionary {
00245 public:
00246
00247 controller_config() : ConfigDictionary(), gui_port(10020), select_snd(), next_snd(), prev_snd(), read_snd(), cancel_snd(), error_snd()
00248 {
00249 addEntry("gui_port",gui_port,"port to listen for the GUI to connect to aibo on");
00250 addEntry("select_snd",select_snd,"sound file to use for \"select\" action");
00251 addEntry("next_snd",next_snd,"sound file to use for \"next\" action");
00252 addEntry("prev_snd",prev_snd,"sound file to use for \"prev\" action");
00253 addEntry("read_snd",read_snd,"sound file to use for \"read from std-in\" action");
00254 addEntry("cancel_snd",cancel_snd,"sound file to use for \"cancel\" action");
00255 addEntry("error_snd",error_snd,"sound file to use to signal errors");
00256 }
00257
00258 plist::Primitive<int> gui_port;
00259 plist::Primitive<std::string> select_snd;
00260 plist::Primitive<std::string> next_snd;
00261 plist::Primitive<std::string> prev_snd;
00262 plist::Primitive<std::string> read_snd;
00263 plist::Primitive<std::string> cancel_snd;
00264 plist::Primitive<std::string> error_snd;
00265 } controller;
00266
00267
00268
00269
00270
00271
00272 class vision_config : public ConfigDictionary {
00273 public:
00274
00275 vision_config() : ConfigDictionary(),
00276 white_balance(WB_FLUORESCENT), gain(GAIN_MID), shutter_speed(SHUTTER_MID), resolution(1),
00277 thresh(), colors("config/default.col"), restore_image(true), region_calc_total(true),
00278 jpeg_dct_method(JDCT_IFAST,dct_method_names), aspectRatio(CameraResolutionX/(float)CameraResolutionY),
00279 x_range(), y_range(), x_focalLen(), y_focalLen(),
00280 rawcam(), depthcam(), segcam(), regioncam(),
00281 aspectRatioListener(aspectRatio,*this,&vision_config::aspectRatioChanged)
00282 {
00283 white_balance.addNameForVal("indoor",WB_INDOOR);
00284 white_balance.addNameForVal("outdoor",WB_OUTDOOR);
00285 white_balance.addNameForVal("fluorescent",WB_FLUORESCENT);
00286 white_balance.addNameForVal("flourescent",WB_FLUORESCENT);
00287 addEntry("white_balance",white_balance,"white balance shifts color spectrum in the image\n"+white_balance.getDescription());
00288
00289 gain.addNameForVal("low",GAIN_LOW);
00290 gain.addNameForVal("mid",GAIN_MID);
00291 gain.addNameForVal("med",GAIN_MID);
00292 gain.addNameForVal("medium",GAIN_MID);
00293 gain.addNameForVal("high",GAIN_HIGH);
00294 addEntry("gain",gain,"Increasing gain will brighten the image, at the expense of more graininess/noise\n"+gain.getDescription());
00295
00296 shutter_speed.addNameForVal("slow",SHUTTER_SLOW);
00297 shutter_speed.addNameForVal("low",SHUTTER_SLOW);
00298 shutter_speed.addNameForVal("mid",SHUTTER_MID);
00299 shutter_speed.addNameForVal("med",SHUTTER_MID);
00300 shutter_speed.addNameForVal("medium",SHUTTER_MID);
00301 shutter_speed.addNameForVal("fast",SHUTTER_FAST);
00302 shutter_speed.addNameForVal("high",SHUTTER_FAST);
00303 addEntry("shutter_speed",shutter_speed,"slower shutter will brighten image, but increases motion blur\n"+shutter_speed.getDescription());
00304
00305 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. ");
00306 addEntry("thresh",thresh,"Threshold (.tm) files define the mapping from full color to indexed color.\n"
00307 "You can uncomment more than one of these - they will be loaded into separate\n"
00308 "channels of the segmenter. The only cost of loading multiple threshold files is\n"
00309 "memory - the CPU cost of performing segmentation is only incurred if/when\n"
00310 "the channel is actually accessed for the first time for a given frame. ");
00311 addEntry("colors",colors,"The colors definition (.col) file gives names and a \"typical\" color for display.\n"
00312 "The indexes numbers it contains correspond to indexes in the .tm file\n"
00313 "This file is common to all .tm files; when doing new color segmentations,\n"
00314 "make sure you define colors in the same order as listed here! ");
00315 addEntry("restore_image",restore_image,"Apparently someone at Sony thought it would be a good idea to replace some\n"
00316 "pixels in each camera image with information like the frame number and CDT count.\n"
00317 "If non-zero, will replace those pixels with the actual image pixel value in RawCamGenerator ");
00318 addEntry("region_calc_total",region_calc_total,"When true, this will fill in the CMVision::color_class_state::total_area\n"
00319 "field for each color following region labeling. If false, the total_area\n"
00320 "will stay 0 (or whatever the last value was), but you save a little CPU. ");
00321 addEntry("jpeg_dct_method",jpeg_dct_method,"pick between dct methods for jpeg compression\n"+jpeg_dct_method.getDescription());
00322
00323
00324
00325
00326
00327
00328
00329 addEntry("rawcam",rawcam);
00330 addEntry("depthcam", depthcam);
00331 addEntry("segcam",segcam);
00332 addEntry("regioncam",regioncam);
00333 }
00334
00335 #ifdef PLATFORM_APERIOS
00336
00337 enum white_balance_levels {
00338 WB_INDOOR=ocamparamWB_INDOOR_MODE,
00339 WB_OUTDOOR=ocamparamWB_OUTDOOR_MODE,
00340 WB_FLUORESCENT=ocamparamWB_FL_MODE
00341 };
00342 #else
00343
00344 enum white_balance_levels { WB_INDOOR=1, WB_OUTDOOR, WB_FLUORESCENT };
00345 #endif
00346 plist::NamedEnumeration<white_balance_levels> white_balance;
00347
00348 #ifdef PLATFORM_APERIOS
00349
00350 enum gain_levels {
00351 GAIN_LOW=ocamparamGAIN_LOW,
00352 GAIN_MID=ocamparamGAIN_MID,
00353 GAIN_HIGH=ocamparamGAIN_HIGH
00354 };
00355 #else
00356
00357 enum gain_levels { GAIN_LOW=1, GAIN_MID, GAIN_HIGH };
00358 #endif
00359 plist::NamedEnumeration<gain_levels> gain;
00360
00361 #ifdef PLATFORM_APERIOS
00362
00363 enum shutter_speeds {
00364 SHUTTER_SLOW=ocamparamSHUTTER_SLOW,
00365 SHUTTER_MID=ocamparamSHUTTER_MID,
00366 SHUTTER_FAST=ocamparamSHUTTER_FAST
00367 };
00368 #else
00369
00370 enum shutter_speeds { SHUTTER_SLOW=1, SHUTTER_MID, SHUTTER_FAST };
00371 #endif
00372 plist::NamedEnumeration<shutter_speeds> shutter_speed;
00373
00374 enum encoding_t {
00375 ENCODE_COLOR,
00376 ENCODE_SINGLE_CHANNEL,
00377 ENCODE_DEPTH,
00378 };
00379 static const unsigned int NUM_ENCODINGS=3;
00380 static const char * encoding_names[NUM_ENCODINGS+1];
00381
00382 plist::Primitive<int> resolution;
00383 plist::ArrayOf<plist::Primitive<std::string> > thresh;
00384 plist::Primitive<std::string> colors;
00385 plist::Primitive<bool> restore_image;
00386 plist::Primitive<bool> region_calc_total;
00387 static const char * dct_method_names[];
00388 plist::NamedEnumeration<J_DCT_METHOD> jpeg_dct_method;
00389 plist::Primitive<float> aspectRatio;
00390 float x_range;
00391 float y_range;
00392 float x_focalLen;
00393 float y_focalLen;
00394
00395
00396 class StreamingConfig : public ConfigDictionary {
00397 public:
00398 explicit StreamingConfig(int portNum) : ConfigDictionary(), port(portNum), transport(Config::UDP,transport_names), interval(0)
00399 {
00400 addEntry("port",port,"the port number to open for sending data over");
00401 addEntry("transport",transport,"the IP protocol to use when sending data");
00402 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");
00403 }
00404 plist::Primitive<unsigned short> port;
00405 plist::NamedEnumeration<Config::transports> transport;
00406 plist::Primitive<unsigned int> interval;
00407 };
00408
00409
00410 class RawCamConfig : public StreamingConfig {
00411 public:
00412 RawCamConfig() : StreamingConfig(10011),
00413 encoding(ENCODE_COLOR,encoding_names), channel(0), compression(COMPRESS_JPEG,compression_names), compress_quality(85), y_skip(2), uv_skip(3)
00414 {
00415 addEntry("encoding",encoding,"holds whether to send color or single channel\n"+encoding.getDescription());
00416 addEntry("channel",channel,"if encoding is single channel, this indicates the channel to send");
00417 addEntry("compression",compression,"the type of compression to apply the image\n"+compression.getDescription());
00418 addEntry("compress_quality",compress_quality,"0-100, compression quality (currently only used by jpeg)");
00419 addEntry("y_skip",y_skip,"resolution level to transmit y channel\nAlso used as the resolution level when in single-channel encoding mode ");
00420 addEntry("uv_skip",uv_skip,"resolution level to transmit uv channel at when using 'color' encoding mode");
00421 }
00422
00423
00424 plist::NamedEnumeration<Config::vision_config::encoding_t> encoding;
00425 plist::Primitive<int> channel;
00426
00427
00428 enum compression_t {
00429 COMPRESS_NONE,
00430 COMPRESS_JPEG,
00431 COMPRESS_PNG,
00432 };
00433 static const unsigned int NUM_COMPRESSIONS=4;
00434 static const char * compression_names[NUM_COMPRESSIONS+1];
00435 plist::NamedEnumeration<compression_t> compression;
00436
00437 plist::Primitive<unsigned int> compress_quality;
00438 plist::Primitive<unsigned int> y_skip;
00439 plist::Primitive<unsigned int> uv_skip;
00440 } rawcam;
00441
00442 class DepthCamConfig : public StreamingConfig {
00443 public:
00444 DepthCamConfig() : StreamingConfig(10014), compression(COMPRESS_JPEG, compression_names), compress_quality(85), y0_skip(2), y1_skip(2)
00445 {
00446 transport = Config::TCP;
00447 addEntry("compression",compression,"what compression to use on the segmented image"+compression.getDescription());
00448 addEntry("compress_quality",compress_quality,"0-100, compression quality (currently only used by jpeg)");
00449 addEntry("y0_skip",y0_skip,"resolution level to transmit y channel\nAlso used as the resolution level when in single-channel encoding mode ");
00450 addEntry("y1_skip",y1_skip,"resolution level to transmit uv channel at when using 'color' encoding mode");
00451 }
00452
00453 enum compression_t {
00454 COMPRESS_NONE,
00455 COMPRESS_JPEG,
00456 COMPRESS_PNG
00457 };
00458 static const unsigned int NUM_COMPRESSIONS=4;
00459 static const char * compression_names[NUM_COMPRESSIONS+1];
00460 plist::NamedEnumeration<compression_t> compression;
00461 plist::Primitive<unsigned int> compress_quality;
00462 plist::Primitive<unsigned int> y0_skip;
00463 plist::Primitive<unsigned int> y1_skip;
00464 } depthcam;
00465
00466
00467 class SegCamConfig : public StreamingConfig {
00468 public:
00469 SegCamConfig() : StreamingConfig(10012), skip(1), channel(0), compression(COMPRESS_RLE, compression_names)
00470 {
00471 addEntry("skip",skip,"resolution level to transmit segmented images at");
00472 addEntry("channel",channel,"channel of RLEGenerator to send (i.e. which threshold map to use");
00473 addEntry("compression",compression,"what compression to use on the segmented image"+compression.getDescription());
00474 }
00475 plist::Primitive<unsigned int> skip;
00476 plist::Primitive<unsigned int> channel;
00477
00478
00479 enum compression_t {
00480 COMPRESS_NONE,
00481 COMPRESS_RLE
00482 };
00483 static const unsigned int NUM_COMPRESSIONS=4;
00484 static const char * compression_names[NUM_COMPRESSIONS+1];
00485 plist::NamedEnumeration<compression_t> compression;
00486 } segcam;
00487
00488
00489 class RegionCamConfig : public StreamingConfig {
00490 public:
00491 RegionCamConfig() : StreamingConfig(10013), skip(1) {
00492 addEntry("skip",skip,"resolution level to extract regions from");
00493 }
00494 plist::Primitive<unsigned int> skip;
00495 } regioncam;
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 void computeRay(float x, float y, float& r_x, float& r_y, float& r_z);
00510
00511
00512
00513
00514
00515
00516
00517 void computePixel(float r_x, float r_y, float r_z, float& x, float& y);
00518
00519
00520
00521
00522
00523
00524
00525
00526 void computePixelCorrected(float r_x, float r_y, float r_z, float& x, float &y);
00527
00528 protected:
00529 void aspectRatioChanged();
00530 plist::PrimitiveCallbackMember<vision_config> aspectRatioListener;
00531
00532 } vision;
00533
00534
00535
00536
00537 class motion_config : public ConfigDictionary {
00538 public:
00539
00540 motion_config(Config* c)
00541 : ConfigDictionary(), thisconfig(c), root("data/motion"), walk("walk.prm"), kinematics(std::string(RobotInfo::RobotName).append(".kin")),
00542 calibration_scale(PIDJointOffset, NumPIDJoints,1), calibration_offset(PIDJointOffset, NumPIDJoints, 0),
00543 estop_on_snd(), estop_off_snd(),
00544 max_head_tilt_speed(0), max_head_pan_speed(0), max_head_roll_speed(0), inf_walk_accel(false),
00545 console_port(10003), stderr_port(10004)
00546 {
00547 addEntry("root",root,"path on memory stick to \"motion\" files - for instance, position (.pos) and motion sequence (.mot)\n"
00548 "Any motion related paths which are not absolute (i.e. do not start with '/')\n"
00549 "will be assumed to be relative to this directory ");
00550 addEntry("walk",walk,"the walk parameter file to load by default for new WalkMC's");
00551 addEntry("kinematics",kinematics,"the ROBOOP format kinematics description file to load");
00552 addEntry("calibration_scale",calibration_scale,"Multiplier from desired position to command for each PID joint, applied after calibration_offset.");
00553 addEntry("calibration_offset",calibration_offset,"These values indicate the offset from user specified zero point to the\n"
00554 "physical system's zero point. Added before calibration_scale when\n"
00555 "converting from user's desired position to command to send to hardware.");
00556 addEntry("estop_on_snd",estop_on_snd,"sound file to use when e-stop turned on");
00557 addEntry("estop_off_snd",estop_off_snd,"sound file to use when e-stop turned off");
00558 addEntry("max_head_tilt_speed",max_head_tilt_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00559 addEntry("max_head_pan_speed",max_head_pan_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00560 addEntry("max_head_roll_speed",max_head_roll_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00561 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");
00562 addEntry("console_port",console_port,"port to send/receive \"console\" information on (separate from system console)");
00563 addEntry("stderr_port",stderr_port,"port to send error information to");
00564 }
00565
00566
00567 std::string makePath(const std::string& name) { return thisconfig->searchPath(name, root); }
00568
00569 Config* thisconfig;
00570 plist::Primitive<std::string> root;
00571 plist::Primitive<std::string> walk;
00572 plist::Primitive<std::string> kinematics;
00573 OutputConfig<plist::Primitive<float> > calibration_scale;
00574 OutputConfig<plist::Primitive<float> > calibration_offset;
00575 plist::Primitive<std::string> estop_on_snd;
00576 plist::Primitive<std::string> estop_off_snd;
00577 plist::Primitive<float> max_head_tilt_speed;
00578 plist::Primitive<float> max_head_pan_speed;
00579 plist::Primitive<float> max_head_roll_speed;
00580 plist::Primitive<bool> inf_walk_accel;
00581 plist::Primitive<int> console_port;
00582 plist::Primitive<int> stderr_port;
00583
00584 private:
00585 motion_config(const motion_config&);
00586 motion_config& operator=(const motion_config&);
00587 } motion;
00588
00589
00590
00591
00592 class sound_config : public ConfigDictionary {
00593 public:
00594
00595 sound_config(Config* c) : ConfigDictionary(), thisconfig(c), root("data/sound"), verbose(0), volume(HIGH), sample_rate(16000),
00596 sample_bits(16), preload(), pitchConfidenceThreshold(.6f), streaming()
00597 {
00598 addEntry("root",root,"path to sound clips");
00599 addEntry("verbose",verbose,"Controls diagnostic information on the console:\n 0 - none\n 1 - report when sounds begin to play\n 2 - also report when sounds finish playing\n 3- also report when sounds are preloaded and released");
00600 volume.addNameForVal("mute",MUTE);
00601 volume.addNameForVal("level_1",LOW);
00602 volume.addNameForVal("low",LOW);
00603 volume.addNameForVal("level_2",MID);
00604 volume.addNameForVal("mid",MID);
00605 volume.addNameForVal("level_3",HIGH);
00606 volume.addNameForVal("high",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
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;
00631 plist::Primitive<std::string> root;
00632
00633
00634
00635
00636
00637
00638 plist::Primitive<int> verbose;
00639
00640
00641
00642 enum volume_levels { MUTE=ospkvolinfdB, LOW=ospkvol25dB, MID=ospkvol18dB, HIGH=ospkvol10dB };
00643 plist::NamedEnumeration<volume_levels> volume;
00644
00645 plist::Primitive<unsigned int> sample_rate;
00646 plist::Primitive<unsigned int> sample_bits;
00647 plist::ArrayOf<plist::Primitive<std::string> > preload;
00648 plist::Primitive<float> pitchConfidenceThreshold;
00649
00650
00651 class streaming_config : public ConfigDictionary {
00652 public:
00653
00654 streaming_config() : ConfigDictionary(), mic_port(10070), mic_sample_rate(16000),
00655 mic_sample_bits(16), mic_stereo(true),
00656 speaker_port(10071), speaker_frame_length(64),
00657 speaker_max_delay(1000)
00658 {
00659 addEntry("mic_port",mic_port,"port for streaming microphone samples");
00660 addEntry("mic_sample_rate",mic_sample_rate,"sample rate from the microphone");
00661 addEntry("mic_sample_bits",mic_sample_bits,"sample bit depth from the microphone (either 8 or 16)");
00662 addEntry("mic_stereo",mic_stereo,"whether to stream stereo or mono from the microphone");
00663
00664 addEntry("speaker_port",speaker_port,"port for streaming speaker samples");
00665 addEntry("speaker_frame_length",speaker_frame_length,"length of frame sent to the speaker (ms)");
00666 addEntry("speaker_max_delay",speaker_max_delay,"maximum delay (ms) during playback");
00667 }
00668 plist::Primitive<unsigned int> mic_port;
00669 plist::Primitive<unsigned int> mic_sample_rate;
00670 plist::Primitive<unsigned int> mic_sample_bits;
00671 plist::Primitive<bool> mic_stereo;
00672
00673 plist::Primitive<unsigned int> speaker_port;
00674 plist::Primitive<unsigned int> speaker_frame_length;
00675 plist::Primitive<unsigned int> speaker_max_delay;
00676 } streaming;
00677 private:
00678 sound_config(const sound_config&);
00679 sound_config& operator=(const sound_config&);
00680 } sound;
00681
00682
00683
00684 virtual void saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const;
00685 using ConfigDictionary::saveXML;
00686 virtual unsigned int loadBuffer(const char buf[], unsigned int len, const char* filename=NULL);
00687 virtual unsigned int loadFile(const char* filename);
00688 virtual unsigned int loadFileStream(FILE* f, const char* filename=NULL);
00689
00690
00691
00692 void* setValue(const std::string& section, std::string key, const std::string& value);
00693
00694 protected:
00695 static const char * xmlIntro1;
00696 static const char * xmlIntro2;
00697 static const char * xmlIntro3;
00698
00699 static const std::locale& curLocale;
00700 static char localeToLower(char c) { return std::tolower(c,curLocale); };
00701
00702 unsigned int loadOldFormat(const char buf[], unsigned int len);
00703 unsigned int loadOldFormat(FILE* f);
00704 void parseLine(const char buf[], unsigned int lineno, std::vector<std::string>& modelStack, bool& ignoring, std::string& section);
00705
00706
00707
00708 std::string fsRoot;
00709 };
00710
00711 template<typename T>
00712 void OutputConfig<T>::saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const {
00713
00714 ConfigDictionary::saveXML(node,true,seen);
00715
00716 if(!onlyOverwrite && seen.size()!=dict.size()) {
00717
00718 for(xmlNode* cur=xNodeGetLastChild(node); cur!=NULL && xNodeIsText(cur); cur=xNodeGetLastChild(node)) {
00719 xmlUnlinkNode(cur);
00720 xmlFreeNode(cur);
00721 }
00722 size_t longestKeyLen = getLongestKeyLen(NULL,1);
00723 std::string indentStr=getIndentationPrefix(node);
00724
00725 for(unsigned int i=0; i<outputs.size(); ++i) {
00726 if(seen.find(outputNames[i+offset])==seen.end())
00727 saveXMLNode(node,outputNames[i+offset],&outputs[i],indentStr,longestKeyLen);
00728 }
00729 std::string parentIndent;
00730 if(indentStr.size()>=perIndent().size())
00731 parentIndent=indentStr.substr(perIndent().size());
00732 xmlAddChild(node,xmlNewText((const xmlChar*)("\n"+parentIndent).c_str()));
00733 }
00734 }
00735
00736
00737 extern Config* config;
00738
00739
00740
00741
00742
00743
00744
00745 #endif