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),gamepadControl_port(10041),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("gamepad", gamepadControl_port, "port to receive gamepad data\n");
00204 addEntry("headControl_port",headControl_port,"port for receiving head commands");
00205 addEntry("armControl_port",armControl_port,"port for receiving arm commands");
00206 addEntry("walkControl_port",walkControl_port,"port for receiving walk commands");
00207 addEntry("estopControl_port",estopControl_port,"port for receiving walk commands");
00208 addEntry("stewart_port",stewart_port,"port for running a stewart platform style of control");
00209 addEntry("aibo3d_port",aibo3d_port,"port for send/receive of joint positions from Aibo 3D GUI");
00210 addEntry("wmmonitor_port",wmmonitor_port,"port for monitoring Watchable Memory");
00211 addEntry("use_VT100",use_VT100,"if true, enables VT100 console codes (currently only in Controller menus - 1.3)");
00212 addEntry("worldState_interval",worldState_interval,"time (in milliseconds) to wait between sending WorldState updates over wireless");
00213 }
00214 plist::Primitive<bool> seed_rng;
00215 plist::Primitive<int> console_port;
00216
00217 enum consoleMode_t {
00218 CONTROLLER,
00219 TEXTMSG,
00220 AUTO
00221 };
00222 static const unsigned int NUM_CONSOLE_MODES=3;
00223 static const char* consoleModeNames[NUM_CONSOLE_MODES+1];
00224
00225 plist::NamedEnumeration<consoleMode_t> consoleMode;
00226 plist::Primitive<int> stderr_port;
00227 plist::Primitive<int> wsjoints_port;
00228 plist::Primitive<int> wspids_port;
00229 plist::Primitive<int> gamepadControl_port;
00230 plist::Primitive<int> headControl_port;
00231 plist::Primitive<int> armControl_port;
00232 plist::Primitive<int> walkControl_port;
00233 plist::Primitive<int> estopControl_port;
00234 plist::Primitive<int> stewart_port;
00235 plist::Primitive<int> aibo3d_port;
00236 plist::Primitive<int> wmmonitor_port;
00237 plist::Primitive<bool> use_VT100;
00238 plist::Primitive<unsigned int> worldState_interval;
00239 } main;
00240
00241
00242
00243
00244
00245
00246 class controller_config : public ConfigDictionary {
00247 public:
00248
00249 controller_config() : ConfigDictionary(), gui_port(10020), select_snd(), next_snd(), prev_snd(), read_snd(), cancel_snd(), error_snd()
00250 {
00251 addEntry("gui_port",gui_port,"port to listen for the GUI to connect to aibo on");
00252 addEntry("select_snd",select_snd,"sound file to use for \"select\" action");
00253 addEntry("next_snd",next_snd,"sound file to use for \"next\" action");
00254 addEntry("prev_snd",prev_snd,"sound file to use for \"prev\" action");
00255 addEntry("read_snd",read_snd,"sound file to use for \"read from std-in\" action");
00256 addEntry("cancel_snd",cancel_snd,"sound file to use for \"cancel\" action");
00257 addEntry("error_snd",error_snd,"sound file to use to signal errors");
00258 }
00259
00260 plist::Primitive<int> gui_port;
00261 plist::Primitive<std::string> select_snd;
00262 plist::Primitive<std::string> next_snd;
00263 plist::Primitive<std::string> prev_snd;
00264 plist::Primitive<std::string> read_snd;
00265 plist::Primitive<std::string> cancel_snd;
00266 plist::Primitive<std::string> error_snd;
00267 } controller;
00268
00269
00270
00271
00272
00273
00274 class vision_config : public ConfigDictionary {
00275 public:
00276
00277 vision_config() : ConfigDictionary(),
00278 white_balance(WB_FLUORESCENT), gain(GAIN_MID), shutter_speed(SHUTTER_MID), resolution(1),
00279 thresh(), colors("config/default.col"), restore_image(true), region_calc_total(true),
00280 jpeg_dct_method(JDCT_IFAST,dct_method_names), aspectRatio(CameraResolutionX/(float)CameraResolutionY),
00281 x_range(), y_range(), x_focalLen(), y_focalLen(),
00282 rawcam(), depthcam(), segcam(), regioncam(),
00283 aspectRatioListener(aspectRatio,*this,&vision_config::aspectRatioChanged)
00284 {
00285 white_balance.addNameForVal("indoor",WB_INDOOR);
00286 white_balance.addNameForVal("outdoor",WB_OUTDOOR);
00287 white_balance.addNameForVal("fluorescent",WB_FLUORESCENT);
00288 white_balance.addNameForVal("flourescent",WB_FLUORESCENT);
00289 addEntry("white_balance",white_balance,"white balance shifts color spectrum in the image\n"+white_balance.getDescription());
00290
00291 gain.addNameForVal("low",GAIN_LOW);
00292 gain.addNameForVal("mid",GAIN_MID);
00293 gain.addNameForVal("med",GAIN_MID);
00294 gain.addNameForVal("medium",GAIN_MID);
00295 gain.addNameForVal("high",GAIN_HIGH);
00296 addEntry("gain",gain,"Increasing gain will brighten the image, at the expense of more graininess/noise\n"+gain.getDescription());
00297
00298 shutter_speed.addNameForVal("slow",SHUTTER_SLOW);
00299 shutter_speed.addNameForVal("low",SHUTTER_SLOW);
00300 shutter_speed.addNameForVal("mid",SHUTTER_MID);
00301 shutter_speed.addNameForVal("med",SHUTTER_MID);
00302 shutter_speed.addNameForVal("medium",SHUTTER_MID);
00303 shutter_speed.addNameForVal("fast",SHUTTER_FAST);
00304 shutter_speed.addNameForVal("high",SHUTTER_FAST);
00305 addEntry("shutter_speed",shutter_speed,"slower shutter will brighten image, but increases motion blur\n"+shutter_speed.getDescription());
00306
00307 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. ");
00308 addEntry("thresh",thresh,"Threshold (.tm) files define the mapping from full color to indexed color.\n"
00309 "You can uncomment more than one of these - they will be loaded into separate\n"
00310 "channels of the segmenter. The only cost of loading multiple threshold files is\n"
00311 "memory - the CPU cost of performing segmentation is only incurred if/when\n"
00312 "the channel is actually accessed for the first time for a given frame. ");
00313 addEntry("colors",colors,"The colors definition (.col) file gives names and a \"typical\" color for display.\n"
00314 "The indexes numbers it contains correspond to indexes in the .tm file\n"
00315 "This file is common to all .tm files; when doing new color segmentations,\n"
00316 "make sure you define colors in the same order as listed here! ");
00317 addEntry("restore_image",restore_image,"Apparently someone at Sony thought it would be a good idea to replace some\n"
00318 "pixels in each camera image with information like the frame number and CDT count.\n"
00319 "If non-zero, will replace those pixels with the actual image pixel value in RawCamGenerator ");
00320 addEntry("region_calc_total",region_calc_total,"When true, this will fill in the CMVision::color_class_state::total_area\n"
00321 "field for each color following region labeling. If false, the total_area\n"
00322 "will stay 0 (or whatever the last value was), but you save a little CPU. ");
00323 addEntry("jpeg_dct_method",jpeg_dct_method,"pick between dct methods for jpeg compression\n"+jpeg_dct_method.getDescription());
00324
00325
00326
00327
00328
00329
00330
00331 addEntry("rawcam",rawcam);
00332 addEntry("depthcam", depthcam);
00333 addEntry("segcam",segcam);
00334 addEntry("regioncam",regioncam);
00335 }
00336
00337 #ifdef PLATFORM_APERIOS
00338
00339 enum white_balance_levels {
00340 WB_INDOOR=ocamparamWB_INDOOR_MODE,
00341 WB_OUTDOOR=ocamparamWB_OUTDOOR_MODE,
00342 WB_FLUORESCENT=ocamparamWB_FL_MODE
00343 };
00344 #else
00345
00346 enum white_balance_levels { WB_INDOOR=1, WB_OUTDOOR, WB_FLUORESCENT };
00347 #endif
00348 plist::NamedEnumeration<white_balance_levels> white_balance;
00349
00350 #ifdef PLATFORM_APERIOS
00351
00352 enum gain_levels {
00353 GAIN_LOW=ocamparamGAIN_LOW,
00354 GAIN_MID=ocamparamGAIN_MID,
00355 GAIN_HIGH=ocamparamGAIN_HIGH
00356 };
00357 #else
00358
00359 enum gain_levels { GAIN_LOW=1, GAIN_MID, GAIN_HIGH };
00360 #endif
00361 plist::NamedEnumeration<gain_levels> gain;
00362
00363 #ifdef PLATFORM_APERIOS
00364
00365 enum shutter_speeds {
00366 SHUTTER_SLOW=ocamparamSHUTTER_SLOW,
00367 SHUTTER_MID=ocamparamSHUTTER_MID,
00368 SHUTTER_FAST=ocamparamSHUTTER_FAST
00369 };
00370 #else
00371
00372 enum shutter_speeds { SHUTTER_SLOW=1, SHUTTER_MID, SHUTTER_FAST };
00373 #endif
00374 plist::NamedEnumeration<shutter_speeds> shutter_speed;
00375
00376 enum encoding_t {
00377 ENCODE_COLOR,
00378 ENCODE_SINGLE_CHANNEL,
00379 ENCODE_DEPTH,
00380 };
00381 static const unsigned int NUM_ENCODINGS=3;
00382 static const char * encoding_names[NUM_ENCODINGS+1];
00383
00384 plist::Primitive<int> resolution;
00385 plist::ArrayOf<plist::Primitive<std::string> > thresh;
00386 plist::Primitive<std::string> colors;
00387 plist::Primitive<bool> restore_image;
00388 plist::Primitive<bool> region_calc_total;
00389 static const char * dct_method_names[];
00390 plist::NamedEnumeration<J_DCT_METHOD> jpeg_dct_method;
00391 plist::Primitive<float> aspectRatio;
00392 float x_range;
00393 float y_range;
00394 float x_focalLen;
00395 float y_focalLen;
00396
00397
00398 class StreamingConfig : public ConfigDictionary {
00399 public:
00400 explicit StreamingConfig(int portNum) : ConfigDictionary(), port(portNum), transport(Config::UDP,transport_names), interval(0)
00401 {
00402 addEntry("port",port,"the port number to open for sending data over");
00403 addEntry("transport",transport,"the IP protocol to use when sending data");
00404 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");
00405 }
00406 plist::Primitive<unsigned short> port;
00407 plist::NamedEnumeration<Config::transports> transport;
00408 plist::Primitive<unsigned int> interval;
00409 };
00410
00411
00412 class RawCamConfig : public StreamingConfig {
00413 public:
00414 RawCamConfig() : StreamingConfig(10011),
00415 encoding(ENCODE_COLOR,encoding_names), channel(0), compression(COMPRESS_JPEG,compression_names), compress_quality(85), y_skip(2), uv_skip(3)
00416 {
00417 addEntry("encoding",encoding,"holds whether to send color or single channel\n"+encoding.getDescription());
00418 addEntry("channel",channel,"if encoding is single channel, this indicates the channel to send");
00419 addEntry("compression",compression,"the type of compression to apply the image\n"+compression.getDescription());
00420 addEntry("compress_quality",compress_quality,"0-100, compression quality (currently only used by jpeg)");
00421 addEntry("y_skip",y_skip,"resolution level to transmit y channel\nAlso used as the resolution level when in single-channel encoding mode ");
00422 addEntry("uv_skip",uv_skip,"resolution level to transmit uv channel at when using 'color' encoding mode");
00423 }
00424
00425
00426 plist::NamedEnumeration<Config::vision_config::encoding_t> encoding;
00427 plist::Primitive<int> channel;
00428
00429
00430 enum compression_t {
00431 COMPRESS_NONE,
00432 COMPRESS_JPEG,
00433 COMPRESS_PNG,
00434 };
00435 static const unsigned int NUM_COMPRESSIONS=4;
00436 static const char * compression_names[NUM_COMPRESSIONS+1];
00437 plist::NamedEnumeration<compression_t> compression;
00438
00439 plist::Primitive<unsigned int> compress_quality;
00440 plist::Primitive<unsigned int> y_skip;
00441 plist::Primitive<unsigned int> uv_skip;
00442 } rawcam;
00443
00444 class DepthCamConfig : public StreamingConfig {
00445 public:
00446 DepthCamConfig() : StreamingConfig(10014), compression(COMPRESS_JPEG, compression_names), compress_quality(85), y0_skip(2), y1_skip(2)
00447 {
00448 transport = Config::TCP;
00449 addEntry("compression",compression,"what compression to use on the segmented image"+compression.getDescription());
00450 addEntry("compress_quality",compress_quality,"0-100, compression quality (currently only used by jpeg)");
00451 addEntry("y0_skip",y0_skip,"resolution level to transmit y channel\nAlso used as the resolution level when in single-channel encoding mode ");
00452 addEntry("y1_skip",y1_skip,"resolution level to transmit uv channel at when using 'color' encoding mode");
00453 }
00454
00455 enum compression_t {
00456 COMPRESS_NONE,
00457 COMPRESS_JPEG,
00458 COMPRESS_PNG
00459 };
00460 static const unsigned int NUM_COMPRESSIONS=4;
00461 static const char * compression_names[NUM_COMPRESSIONS+1];
00462 plist::NamedEnumeration<compression_t> compression;
00463 plist::Primitive<unsigned int> compress_quality;
00464 plist::Primitive<unsigned int> y0_skip;
00465 plist::Primitive<unsigned int> y1_skip;
00466 } depthcam;
00467
00468
00469 class SegCamConfig : public StreamingConfig {
00470 public:
00471 SegCamConfig() : StreamingConfig(10012), skip(1), channel(0), compression(COMPRESS_RLE, compression_names)
00472 {
00473 addEntry("skip",skip,"resolution level to transmit segmented images at");
00474 addEntry("channel",channel,"channel of RLEGenerator to send (i.e. which threshold map to use");
00475 addEntry("compression",compression,"what compression to use on the segmented image"+compression.getDescription());
00476 }
00477 plist::Primitive<unsigned int> skip;
00478 plist::Primitive<unsigned int> channel;
00479
00480
00481 enum compression_t {
00482 COMPRESS_NONE,
00483 COMPRESS_RLE
00484 };
00485 static const unsigned int NUM_COMPRESSIONS=4;
00486 static const char * compression_names[NUM_COMPRESSIONS+1];
00487 plist::NamedEnumeration<compression_t> compression;
00488 } segcam;
00489
00490
00491 class RegionCamConfig : public StreamingConfig {
00492 public:
00493 RegionCamConfig() : StreamingConfig(10013), skip(1) {
00494 addEntry("skip",skip,"resolution level to extract regions from");
00495 }
00496 plist::Primitive<unsigned int> skip;
00497 } regioncam;
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 void computeRay(float x, float y, float& r_x, float& r_y, float& r_z);
00512
00513
00514
00515
00516
00517
00518
00519 void computePixel(float r_x, float r_y, float r_z, float& x, float& y);
00520
00521
00522
00523
00524
00525
00526
00527
00528 void computePixelCorrected(float r_x, float r_y, float r_z, float& x, float &y);
00529
00530 protected:
00531 void aspectRatioChanged();
00532 plist::PrimitiveCallbackMember<vision_config> aspectRatioListener;
00533
00534 } vision;
00535
00536
00537
00538
00539 class motion_config : public ConfigDictionary {
00540 public:
00541
00542 motion_config(Config* c)
00543 : ConfigDictionary(), thisconfig(c), root("data/motion"), walk("walk.prm"), kinematics(std::string(RobotInfo::RobotName).append(".kin")),
00544 calibration_scale(PIDJointOffset, NumPIDJoints,1), calibration_offset(PIDJointOffset, NumPIDJoints, 0),
00545 estop_on_snd(), estop_off_snd(),
00546 max_head_tilt_speed(0), max_head_pan_speed(0), max_head_roll_speed(0), inf_walk_accel(false),
00547 console_port(10003), stderr_port(10004)
00548 {
00549 addEntry("root",root,"path on memory stick to \"motion\" files - for instance, position (.pos) and motion sequence (.mot)\n"
00550 "Any motion related paths which are not absolute (i.e. do not start with '/')\n"
00551 "will be assumed to be relative to this directory ");
00552 addEntry("walk",walk,"the walk parameter file to load by default for new WalkMC's");
00553 addEntry("kinematics",kinematics,"the ROBOOP format kinematics description file to load");
00554 addEntry("calibration_scale",calibration_scale,"Multiplier from desired position to command for each PID joint, applied after calibration_offset.");
00555 addEntry("calibration_offset",calibration_offset,"These values indicate the offset from user specified zero point to the\n"
00556 "physical system's zero point. Added before calibration_scale when\n"
00557 "converting from user's desired position to command to send to hardware.");
00558 addEntry("estop_on_snd",estop_on_snd,"sound file to use when e-stop turned on");
00559 addEntry("estop_off_snd",estop_off_snd,"sound file to use when e-stop turned off");
00560 addEntry("max_head_tilt_speed",max_head_tilt_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00561 addEntry("max_head_pan_speed",max_head_pan_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00562 addEntry("max_head_roll_speed",max_head_roll_speed,"max speed for the head joints, used by HeadPointerMC; rad/s");
00563 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");
00564 addEntry("console_port",console_port,"port to send/receive \"console\" information on (separate from system console)");
00565 addEntry("stderr_port",stderr_port,"port to send error information to");
00566 }
00567
00568
00569 std::string makePath(const std::string& name) { return thisconfig->searchPath(name, root); }
00570
00571 Config* thisconfig;
00572 plist::Primitive<std::string> root;
00573 plist::Primitive<std::string> walk;
00574 plist::Primitive<std::string> kinematics;
00575 OutputConfig<plist::Primitive<float> > calibration_scale;
00576 OutputConfig<plist::Primitive<float> > calibration_offset;
00577 plist::Primitive<std::string> estop_on_snd;
00578 plist::Primitive<std::string> estop_off_snd;
00579 plist::Primitive<float> max_head_tilt_speed;
00580 plist::Primitive<float> max_head_pan_speed;
00581 plist::Primitive<float> max_head_roll_speed;
00582 plist::Primitive<bool> inf_walk_accel;
00583 plist::Primitive<int> console_port;
00584 plist::Primitive<int> stderr_port;
00585
00586 private:
00587 motion_config(const motion_config&);
00588 motion_config& operator=(const motion_config&);
00589 } motion;
00590
00591
00592
00593
00594 class sound_config : public ConfigDictionary {
00595 public:
00596
00597 sound_config(Config* c) : ConfigDictionary(), thisconfig(c), root("data/sound"), verbose(0), volume(HIGH), sample_rate(16000),
00598 sample_bits(16), preload(), pitchConfidenceThreshold(.6f), streaming()
00599 {
00600 addEntry("root",root,"path to sound clips");
00601 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");
00602 volume.addNameForVal("mute",MUTE);
00603 volume.addNameForVal("level_1",LOW);
00604 volume.addNameForVal("low",LOW);
00605 volume.addNameForVal("level_2",MID);
00606 volume.addNameForVal("mid",MID);
00607 volume.addNameForVal("level_3",HIGH);
00608 volume.addNameForVal("high",HIGH);
00609 volume.setStrict(false);
00610 addEntry("volume",volume,"volume in decibels - the value is interpreted as a signed short, where\n"
00611 "0x8000 is mute, 0xFFFF is full volume (low=0xE700, mid=0xEE00, high=0xF600)\n"
00612 "If you directly set the decibel level, be warned sony recommends against going above 0xF600\n"
00613 "However, I believe the commercial software on the ERS-7 runs at 0xFF00.\n"
00614 "Going above 0xF800 on a ERS-210 causes distortion (clipping) - full volume on a ERS-7 sounds fine though.\n"+volume.getDescription());
00615 addEntry("sample_rate",sample_rate,"sample rate to send to system, currently only 8000 or 16000 supported");
00616 addEntry("sample_bits",sample_bits,"sample bit depth, either 8 or 16");
00617 addEntry("preload",preload,"list of sounds to preload at boot");
00618 addEntry("pitchConfidenceThreshold",pitchConfidenceThreshold,"confidence threshold required to generate a pitch event [0-1]");
00619 addEntry("streaming",streaming);
00620 }
00621
00622
00623 std::string makePath(const std::string& name) {
00624 if(name[0]=='/')
00625 return thisconfig->portPath(name);
00626 if(root[root.size()-1]=='/')
00627 return thisconfig->portPath(root+name);
00628 else
00629 return thisconfig->portPath(root+"/"+name);
00630 }
00631
00632 Config* thisconfig;
00633 plist::Primitive<std::string> root;
00634
00635
00636
00637
00638
00639
00640 plist::Primitive<int> verbose;
00641
00642
00643
00644 enum volume_levels { MUTE=ospkvolinfdB, LOW=ospkvol25dB, MID=ospkvol18dB, HIGH=ospkvol10dB };
00645 plist::NamedEnumeration<volume_levels> volume;
00646
00647 plist::Primitive<unsigned int> sample_rate;
00648 plist::Primitive<unsigned int> sample_bits;
00649 plist::ArrayOf<plist::Primitive<std::string> > preload;
00650 plist::Primitive<float> pitchConfidenceThreshold;
00651
00652
00653 class streaming_config : public ConfigDictionary {
00654 public:
00655
00656 streaming_config() : ConfigDictionary(), mic_port(10070), mic_sample_rate(16000),
00657 mic_sample_bits(16), mic_stereo(true),
00658 speaker_port(10071), speaker_frame_length(64),
00659 speaker_max_delay(1000)
00660 {
00661 addEntry("mic_port",mic_port,"port for streaming microphone samples");
00662 addEntry("mic_sample_rate",mic_sample_rate,"sample rate from the microphone");
00663 addEntry("mic_sample_bits",mic_sample_bits,"sample bit depth from the microphone (either 8 or 16)");
00664 addEntry("mic_stereo",mic_stereo,"whether to stream stereo or mono from the microphone");
00665
00666 addEntry("speaker_port",speaker_port,"port for streaming speaker samples");
00667 addEntry("speaker_frame_length",speaker_frame_length,"length of frame sent to the speaker (ms)");
00668 addEntry("speaker_max_delay",speaker_max_delay,"maximum delay (ms) during playback");
00669 }
00670 plist::Primitive<unsigned int> mic_port;
00671 plist::Primitive<unsigned int> mic_sample_rate;
00672 plist::Primitive<unsigned int> mic_sample_bits;
00673 plist::Primitive<bool> mic_stereo;
00674
00675 plist::Primitive<unsigned int> speaker_port;
00676 plist::Primitive<unsigned int> speaker_frame_length;
00677 plist::Primitive<unsigned int> speaker_max_delay;
00678 } streaming;
00679 private:
00680 sound_config(const sound_config&);
00681 sound_config& operator=(const sound_config&);
00682 } sound;
00683
00684
00685
00686 virtual void saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const;
00687 using ConfigDictionary::saveXML;
00688 virtual unsigned int loadBuffer(const char buf[], unsigned int len, const char* filename=NULL);
00689 virtual unsigned int loadFile(const char* filename);
00690 virtual unsigned int loadFileStream(FILE* f, const char* filename=NULL);
00691
00692
00693
00694 void* setValue(const std::string& section, std::string key, const std::string& value);
00695
00696 protected:
00697 static const char * xmlIntro1;
00698 static const char * xmlIntro2;
00699 static const char * xmlIntro3;
00700
00701 static const std::locale& curLocale;
00702 static char localeToLower(char c) { return std::tolower(c,curLocale); };
00703
00704 unsigned int loadOldFormat(const char buf[], unsigned int len);
00705 unsigned int loadOldFormat(FILE* f);
00706 void parseLine(const char buf[], unsigned int lineno, std::vector<std::string>& modelStack, bool& ignoring, std::string& section);
00707
00708
00709
00710 std::string fsRoot;
00711 };
00712
00713 template<typename T>
00714 void OutputConfig<T>::saveXML(xmlNode* node, bool onlyOverwrite, std::set<std::string>& seen) const {
00715
00716 ConfigDictionary::saveXML(node,true,seen);
00717
00718 if(!onlyOverwrite && seen.size()!=dict.size()) {
00719
00720 for(xmlNode* cur=xNodeGetLastChild(node); cur!=NULL && xNodeIsText(cur); cur=xNodeGetLastChild(node)) {
00721 xmlUnlinkNode(cur);
00722 xmlFreeNode(cur);
00723 }
00724 size_t longestKeyLen = getLongestKeyLen(NULL,1);
00725 std::string indentStr=getIndentationPrefix(node);
00726
00727 for(unsigned int i=0; i<outputs.size(); ++i) {
00728 if(seen.find(outputNames[i+offset])==seen.end())
00729 saveXMLNode(node,outputNames[i+offset],&outputs[i],indentStr,longestKeyLen);
00730 }
00731 std::string parentIndent;
00732 if(indentStr.size()>=perIndent().size())
00733 parentIndent=indentStr.substr(perIndent().size());
00734 xmlAddChild(node,xmlNewText((const xmlChar*)("\n"+parentIndent).c_str()));
00735 }
00736 }
00737
00738
00739 extern Config* config;
00740
00741
00742
00743
00744
00745
00746
00747 #endif