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:
00448 RegionCamConfig() : StreamingConfig(10013), skip(1) {
00449 addEntry("skip",skip,"resolution level to extract regions from");
00450 }
00451 plist::Primitive<int> skip;
00452 } regioncam;
00453
00454
00455
00456
00457
00458
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;
00480 plist::Primitive<float> focal_len_y;
00481 plist::Primitive<float> principle_point_x;
00482 plist::Primitive<float> principle_point_y;
00483 plist::Primitive<float> skew;
00484 plist::Primitive<float> kc1_r2;
00485 plist::Primitive<float> kc2_r4;
00486 plist::Primitive<float> kc5_r6;
00487 plist::Primitive<float> kc3_tan1;
00488 plist::Primitive<float> kc4_tan2;
00489 plist::Primitive<unsigned int> calibration_res_x;
00490 plist::Primitive<unsigned int> calibration_res_y;
00491 } calibration;
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 void computeRay(float x, float y, float& r_x, float& r_y, float& r_z);
00502
00503
00504
00505
00506
00507
00508
00509 void computePixel(float r_x, float r_y, float r_z, float& x, float& y);
00510
00511
00512 } vision;
00513
00514
00515
00516
00517 class motion_config : public ConfigDictionary {
00518 public:
00519
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
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;
00565 plist::Primitive<std::string> root;
00566 plist::Primitive<std::string> walk;
00567 plist::Primitive<std::string> kinematics;
00568 plist::ArrayOf<plist::Primitive<std::string> > kinematic_chains;
00569 OutputConfig<plist::Primitive<float> > calibration_scale;
00570 OutputConfig<plist::Primitive<float> > calibration_offset;
00571 plist::Primitive<std::string> estop_on_snd;
00572 plist::Primitive<std::string> estop_off_snd;
00573 plist::Primitive<float> max_head_tilt_speed;
00574 plist::Primitive<float> max_head_pan_speed;
00575 plist::Primitive<float> max_head_roll_speed;
00576 plist::Primitive<bool> inf_walk_accel;
00577 plist::Primitive<int> console_port;
00578 plist::Primitive<int> stderr_port;
00579 #ifdef TGT_HAS_WHEELS
00580 plist::Primitive<float> wheelBaseWidth;
00581 plist::Primitive<float> wheelRadius;
00582 #endif
00583
00584
00585 private:
00586 motion_config(const motion_config&);
00587 motion_config& operator=(const motion_config&);
00588 } motion;
00589
00590
00591
00592
00593 class sound_config : public ConfigDictionary {
00594 public:
00595
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
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 enum volume_levels { MUTE=ospkvolinfdB, LOW=ospkvol25dB, MID=ospkvol18dB, HIGH=ospkvol10dB };
00636 plist::NamedEnumeration<volume_levels> volume;
00637
00638 plist::Primitive<unsigned int> sample_rate;
00639 plist::Primitive<unsigned int> sample_bits;
00640 plist::ArrayOf<plist::Primitive<std::string> > preload;
00641 plist::Primitive<float> pitchConfidenceThreshold;
00642
00643
00644 class streaming_config : public ConfigDictionary {
00645 public:
00646
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;
00662 plist::Primitive<unsigned int> mic_sample_rate;
00663 plist::Primitive<unsigned int> mic_sample_bits;
00664 plist::Primitive<bool> mic_stereo;
00665
00666 plist::Primitive<unsigned int> speaker_port;
00667 plist::Primitive<unsigned int> speaker_frame_length;
00668 plist::Primitive<unsigned int> speaker_max_delay;
00669 } streaming;
00670 private:
00671 sound_config(const sound_config&);
00672 sound_config& operator=(const sound_config&);
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
00684
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
00700
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
00707 ConfigDictionary::saveXML(node,true,seen);
00708
00709 if(!onlyOverwrite && seen.size()!=dict.size()) {
00710
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
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
00729 extern Config* config;
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 #endif