00001 /*!@file Psycho/HandData.H Struct for hand(joystick/steering wheel) data with a wrapped ParamMap */ 00002 // //////////////////////////////////////////////////////////////////// // 00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00004 // by the University of Southern California (USC) and the iLab at USC. // 00005 // See http://iLab.usc.edu for information about this project. // 00006 // //////////////////////////////////////////////////////////////////// // 00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00009 // in Visual Environments, and Applications'' by Christof Koch and // 00010 // Laurent Itti, California Institute of Technology, 2001 (patent // 00011 // pending; application number 09/912,225 filed July 23, 2001; see // 00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00015 // // 00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00017 // redistribute it and/or modify it under the terms of the GNU General // 00018 // Public License as published by the Free Software Foundation; either // 00019 // version 2 of the License, or (at your option) any later version. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00024 // PURPOSE. See the GNU General Public License for more details. // 00025 // // 00026 // You should have received a copy of the GNU General Public License // 00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00029 // Boston, MA 02111-1307 USA. // 00030 // //////////////////////////////////////////////////////////////////// // 00031 // 00032 // Primary maintainer for this file: Dicky Nauli Sihite <sihite@usc.edu> 00033 // $HeadURL: 00034 // $Id: 00035 00036 #ifndef PSYCHO_HANDDATA_H_DEFINED 00037 #define PSYCHO_HANDDATA_H_DEFINED 00038 #include <iostream> 00039 00040 #include "Image/Point2D.H" 00041 //#include "Psycho/SaccadeState.H" 00042 #include "Util/Types.H" 00043 #include "Util/StringUtil.H" 00044 #include "Util/log.H" 00045 #include "rutz/compat_cmath.h" // for isnan() 00046 #include "rutz/shared_ptr.h" 00047 #include "Component/ParamMap.H" 00048 #include <cmath> 00049 00050 //! Simple struct for hand movement data 00051 /*! Different joystick/steering wheel trackers may or may not fill all data 00052 members. Members that should always be filled are x and y. Note that this 00053 class is costly in terms of storage, so typically one would want to use it 00054 only to pass data samples around, but not to store a long series of samples 00055 in memory. For example, Psycho/HandTrace.H uses a more compact format to 00056 internally store eye data, and uses HandData objects to deliver that data 00057 to whoever wants it. 00058 Originally this function is for joystick only, therefore to maintain code 00059 consistency, the naming without mouse or keyboard will refer to joystick 00060 */ 00061 class HandData 00062 { 00063 public: 00064 /*! HandData Constructors & Destructors */ 00065 //{@ 00066 //!!! Fully initialized constructor, no extra data 00067 00068 // Joystick only 00069 HandData(const int x_, const int y_, const std::vector<bool> b_); 00070 // Mouse only 00071 HandData(const int mx_, const int my_, const int nmx_, const int nmy_, 00072 const bool mlb_, const bool mmb_, const bool mrb_); 00073 // Keyboard only 00074 HandData(const char* kbch_); 00075 00076 // Keyboard + Mouse 00077 HandData(const char* kbch_, 00078 const int mx_, const int my_, const int nmx_, const int nmy_, 00079 const bool mlb_, const bool mmb_, const bool mrb_); 00080 // Keyboard + Mouse + Joystick = impossible? 00081 HandData(const char* kbch_, 00082 const int mx_, const int my_, const int nmx_, const int nmy_, 00083 const bool mlb_, const bool mmb_, const bool mrb_, 00084 const int x_, const int y_, const std::vector<bool> b_); 00085 00086 //!!! Fully initialized constructor, extra data in ParamMap 00087 // Joystick only 00088 HandData(const int x_, const int y_, const std::vector<bool> b_, 00089 rutz::shared_ptr<ParamMap> dat); 00090 // Mouse only 00091 HandData(const int mx_, const int my_, const int nmx_, const int nmy_, 00092 const bool mlb_, const bool mmb_, const bool mrb_, 00093 rutz::shared_ptr<ParamMap> dat); 00094 // Keyboard only 00095 HandData(const char* kbch_, rutz::shared_ptr<ParamMap> dat); 00096 // Keyboard + Mouse 00097 HandData(const char* kbch_, 00098 const int mx_, const int my_, const int nmx_, const int nmy_, 00099 const bool mlb_, const bool mmb_, const bool mrb_, 00100 rutz::shared_ptr<ParamMap> dat); 00101 // Keyboard + Mouse + Joystick = impossible? 00102 HandData(const char* kbch_, 00103 const int mx_, const int my_, const int nmx_, const int nmy_, 00104 const bool mlb_, const bool mmb_, const bool mrb_, 00105 const int x_, const int y_, const std::vector<bool> b_, 00106 rutz::shared_ptr<ParamMap> dat); 00107 00108 00109 //! Destructor 00110 ~HandData(); 00111 00112 //@} 00113 // ###################################################################### 00114 /*! @name Helper functions */ 00115 //@{ 00116 00117 // _ ____ _ _ ____ ___ _ ____ _ _ 00118 // | | | \_/ [__ | | | |_/ 00119 //_| |__| | ___] | | |___ | \_ 00120 // 00121 00122 //! Is the n-th button is pressed? 00123 bool isPressed(uint& b_) const; 00124 00125 //! Is there any pressed button? 00126 bool isAnyPressed() const; 00127 00128 //! Do we have buttons? 00129 bool isButtonEmpty() const; 00130 00131 //! Do we have valid (x,y) coordinates? 00132 bool isValid() const; 00133 00134 //! Are our coordinates within some dims? 00135 bool isWithin(const Dims& dims) const; 00136 00137 /* _ _ ____ _ _ ____ ____ 00138 ** |\/| | | | | [__ |___ 00139 ** | | |__| |__| ___] |___ 00140 */ 00141 00142 //! Is mouse position valid? 00143 bool isMouseValid() const; 00144 00145 //! Is there any pressed mouse button? 00146 bool isMouseAnyPressed() const; 00147 00148 /* _ _ ____ _ _ ___ ____ ____ ____ ___ 00149 ** |_/ |___ \_/ |__] | | |__| |__/ | \ 00150 ** | \_ |___ | |__] |__| | | | \ |__/ 00151 */ 00152 00153 //! Is keyboard input empty? 00154 bool isKeyboardEmpty() const; 00155 00156 /* _ _ ____ ___ ____ ___ ____ ___ ____ 00157 ** |\/| |___ | |__| | \ |__| | |__| 00158 ** | | |___ | | | |__/ | | | | | 00159 */ 00160 00161 //! Do we have valid extra metadata? 00162 /*! Only a very few samples in an eye trace have this extra data, 00163 possibly none. The data may be present at the onset of each 00164 event and contains information about each event. */ 00165 bool hasMetaData(const std::string field) const; 00166 00167 bool hasSpecialMetaData(const std::string field) const; 00168 00169 //! Is this field name a special field? 00170 bool isSpecialField(std::string field) const; 00171 00172 //@} 00173 00174 // ###################################################################### 00175 /*! @name Access functions */ 00176 //@{ 00177 00178 //!-> If these features are not needed, consider removing them 00179 00180 /* _ ____ _ _ ____ ___ _ ____ _ _ 00181 ** | | | \_/ [__ | | | |_/ 00182 ** _| |__| | ___] | | |___ | \_ 00183 */ 00184 00185 //! Check number of buttons 00186 size_t numButton() const; 00187 00188 /*! These are for single value of wheel's accl,brake,left,right */ 00189 //! Get Accelerator value 00190 int getAccelerator() const; // ( 0 ~ 127 ) 00191 float getAcceleratorF() const; // ( 0.0 ~ 1.0 ) 00192 00193 //! Get Brake value 00194 int getBrake() const; // ( 0 ~ 128 ) 00195 float getBrakeF() const; // ( 0.0 ~ 1.0 ) 00196 00197 //! Get Wheel Left value 00198 int getWheelLeft() const; // ( 0 ~ 127 ) 00199 float getWheelLeftF() const;// ( 0.0 ~ 1.0 ) 00200 00201 //! Get Wheel Right value 00202 int getWheelRight() const; // ( 0 ~ 128 ) 00203 float getWheelRightF() const;// ( 0.0 ~ 1.0 ) 00204 00205 00206 /*! These are combined value of wheel's axises (accl-brake, left-right) */ 00207 //! Get Wheel value 00208 int getWheel() const; // ( 0 ~ 127 ~ 255 ) --> 127 left - 128 right 00209 float getWheelF() const; // ( -1.0 ~ 0.0 ~ 1.0 ) --> -1.0 left - 1.0 right 00210 int getX() const; // Same as getWheel 00211 00212 //! Get Both Accl & Brake value 00213 int getAcclBrake() const; // ( 0 ~ 127 ~ 255 ) --> 127 accl - 128 brake 00214 float getAcclBrakeF() const; // ( -1.0 ~ 0.0 ~ 1.0 ) --> -1.0 left - 1.0 right 00215 int getY() const; // Same as getAcclBrake 00216 00217 /*! These are combined value of all wheel's axis */ 00218 //! Get All joystick/wheel position 00219 Point2D<int> getPosition() const; // ( 0 ~ 255 ) for all axis 00220 Point2D<float> getPositionF() const; // ( -1.0 ~ 1.0 ) for all axis 00221 00222 /* _ _ ____ _ _ ____ ____ 00223 ** |\/| | | | | [__ |___ 00224 ** | | |__| |__| ___] |___ 00225 */ 00226 00227 //! Get raw data 00228 int getMouseX() const; 00229 int getMouseY() const; 00230 int getNativeX() const; 00231 int getNativeY() const; 00232 bool getMouseBL() const; 00233 bool getMouseBM() const; 00234 bool getMouseBR() const; 00235 00236 /* _ _ ____ _ _ ___ ____ ____ ____ ___ 00237 ** |_/ |___ \_/ |__] | | |__| |__/ | \ 00238 ** | \_ |___ | |__] |__| | | | \ |__/ 00239 */ 00240 00241 //! Get raw data 00242 char *getKeyboard() const; 00243 00244 //@} 00245 00246 // ###################################################################### 00247 /*! @name Extra data management */ 00248 //{@ 00249 //! Get all metadata 00250 rutz::shared_ptr<ParamMap> getMetaData() const; 00251 00252 //! Get list of metadata fields 00253 std::vector<std::string> getMetaDataList() const; 00254 00255 //! Get one field of metadata 00256 double getMetaDataField(std::string field) const; 00257 00258 //@} 00259 // ###################################################################### 00260 /*! Misc */ 00261 //! Get text output report 00262 void outputData(std::ostream &out) const; 00263 00264 00265 // ###################################################################### 00266 00267 private: 00268 //! Joystick 00269 const int x, y; // Joystick/steering wheel position 00270 // for steering wheel, it has the following: 00271 // x= 127, 0 left, 255 right 00272 // y= 127, 0 accl, 255 brake 00273 const std::vector<bool> b; // buttons of joystick/steering wheel 00274 00275 //! Mouse 00276 const int mx, my; // Mouse X & Y 00277 const int nmx, nmy; // Native resolution 00278 const bool mlb, mmb, mrb; // The 3 mouse buttons 00279 00280 //! Keyboard 00281 const char* kbch; // Stores the character inputted 00282 00283 //Optional data in tree of ParamMaps 00284 const rutz::shared_ptr<ParamMap> itsExtraData; 00285 00286 //! To add/remove special field 00287 std::string special(std::string field) const; 00288 std::string unspecial(std::string field) const; 00289 }; 00290 00291 // ###################################################################### 00292 // ###################################################################### 00293 // ########## inlined functions ############ 00294 // ###################################################################### 00295 // ###################################################################### 00296 00297 00298 // ###################################################################### 00299 /*! Constructors and Destructors*/ 00300 00301 //!!! Without Param Map 00302 00303 // Joystick only 00304 inline HandData::HandData(const int x_, const int y_, 00305 const std::vector<bool> b_) : 00306 x(x_), y(y_), b(b_), 00307 mx(-1), my(-1), nmx(-1), nmy(-1), mlb(false), mmb(false), mrb(false), 00308 kbch("") 00309 { } 00310 00311 // Mouse only 00312 inline HandData::HandData(const int mx_, const int my_, 00313 const int nmx_, const int nmy_, 00314 const bool mlb_, const bool mmb_, const bool mrb_) : 00315 x(-1), y(-1), b(), 00316 mx(mx_), my(my_), nmx(nmx_), nmy(nmy_), mlb(mlb_), mmb(mmb_), mrb(mrb_), 00317 kbch("") 00318 { } 00319 00320 // Keyboard only 00321 inline HandData::HandData(const char* kbch_) : 00322 x(-1), y(-1), b(), 00323 mx(-1), my(-1), nmx(-1), nmy(-1), mlb(false), mmb(false), mrb(false), 00324 kbch(kbch_) 00325 { } 00326 00327 // Keyboard + Mouse 00328 inline HandData::HandData(const char* kbch_, 00329 const int mx_, const int my_, 00330 const int nmx_, const int nmy_, 00331 const bool mlb_, const bool mmb_, const bool mrb_) : 00332 x(-1), y(-1), b(), 00333 mx(mx_), my(my_), nmx(nmx_), nmy(nmy_), mlb(mlb_), mmb(mmb_), mrb(mrb_), 00334 kbch(kbch_) 00335 { } 00336 // Keyboard + Mouse + Joystick = impossible? 00337 inline HandData::HandData(const char* kbch_, 00338 const int mx_, const int my_, 00339 const int nmx_, const int nmy_, 00340 const bool mlb_, const bool mmb_, const bool mrb_, 00341 const int x_, const int y_, 00342 const std::vector<bool> b_) : 00343 x(x_), y(y_), b(b_), 00344 mx(mx_), my(my_), nmx(nmx_), nmy(nmy_), mlb(mlb_), mmb(mmb_), mrb(mrb_), 00345 kbch(kbch_) 00346 { } 00347 00348 //!!! With param map 00349 00350 // Joystick only 00351 inline HandData::HandData(const int x_, const int y_, 00352 const std::vector<bool> b_, 00353 rutz::shared_ptr<ParamMap> dat) : 00354 x(x_), y(y_), b(b_), 00355 mx(-1), my(-1), nmx(-1), nmy(-1), mlb(false), mmb(false), mrb(false), 00356 kbch("") 00357 { } 00358 00359 // Mouse only 00360 inline HandData::HandData(const int mx_, const int my_, 00361 const int nmx_, const int nmy_, 00362 const bool mlb_, const bool mmb_, const bool mrb_, 00363 rutz::shared_ptr<ParamMap> dat) : 00364 x(-1), y(-1), b(), 00365 mx(mx_), my(my_), nmx(nmx_), nmy(nmy_), mlb(mlb_), mmb(mmb_), mrb(mrb_), 00366 kbch("") 00367 { } 00368 00369 // Keyboard only 00370 inline HandData::HandData(const char* kbch_, rutz::shared_ptr<ParamMap> dat) : 00371 x(-1), y(-1), b(), 00372 mx(-1), my(-1), nmx(-1), nmy(-1), mlb(false), mmb(false), mrb(false), 00373 kbch(kbch_) 00374 { } 00375 00376 // Keyboard + Mouse 00377 inline HandData::HandData(const char* kbch_, 00378 const int mx_, const int my_, 00379 const int nmx_, const int nmy_, 00380 const bool mlb_, const bool mmb_, const bool mrb_, 00381 rutz::shared_ptr<ParamMap> dat) : 00382 x(-1), y(-1), b(), 00383 mx(mx_), my(my_), nmx(nmx_), nmy(nmy_), mlb(mlb_), mmb(mmb_), mrb(mrb_), 00384 kbch(kbch_) 00385 { } 00386 // Keyboard + Mouse + Joystick = impossible? 00387 inline HandData::HandData(const char* kbch_, 00388 const int mx_, const int my_, 00389 const int nmx_, const int nmy_, 00390 const bool mlb_, const bool mmb_, const bool mrb_, 00391 const int x_, const int y_, 00392 const std::vector<bool> b_, 00393 rutz::shared_ptr<ParamMap> dat) : 00394 x(x_), y(y_), b(b_), 00395 mx(mx_), my(my_), nmx(nmx_), nmy(nmy_), mlb(mlb_), mmb(mmb_), mrb(mrb_), 00396 kbch(kbch_) 00397 { } 00398 00399 00400 inline HandData::~HandData() 00401 { } 00402 00403 // ###################################################################### 00404 /*! @name Helper Functions */ 00405 00406 //! Joystick 00407 00408 inline bool HandData::isPressed(uint& b_) const 00409 { 00410 try { // Check if the data is available and return it 00411 return b[b_];} 00412 catch (char *str) { // invalid data, just return false 00413 // Should be LFATAL instead? 00414 LERROR("Data %d is out of range, we only have %d buttons", 00415 b_, int(b.size())); 00416 return false;} 00417 } 00418 00419 inline bool HandData::isAnyPressed() const { 00420 for (uint i=0; i<b.size(); i++) 00421 if (b[i]) return true; 00422 return false; 00423 } 00424 00425 inline bool HandData::isButtonEmpty() const { 00426 return b.empty(); } 00427 00428 inline bool HandData::isValid() const { 00429 return !(isnan(x) || isnan(y)) && x > -1 && y > -1; } 00430 00431 inline bool HandData::isWithin(const Dims& dims) const { 00432 if (isValid() == false) return false; 00433 return (x >= 0 && x < dims.w() && y >= 0 && y < dims.h()); 00434 } 00435 00436 //! Mouse 00437 00438 inline bool HandData::isMouseValid() const { 00439 return !(isnan(mx) || isnan(my)) && mx > -1 && my > -1; 00440 } 00441 00442 inline bool HandData::isMouseAnyPressed() const { 00443 return (mlb || mmb || mrb); 00444 } 00445 00446 //! Keyboard 00447 00448 inline bool HandData::isKeyboardEmpty() const { 00449 return (std::string(kbch).empty()); 00450 } 00451 00452 //! Metadata 00453 00454 inline bool HandData::hasMetaData(const std::string field = "any") const 00455 { if(field.compare("any") == 0) return itsExtraData.is_valid(); 00456 else return (itsExtraData.is_valid() && 00457 (itsExtraData->hasParam(field) || 00458 itsExtraData->hasParam(special(field)) )); } 00459 00460 inline bool HandData::hasSpecialMetaData(const std::string field) const 00461 { 00462 return (hasMetaData("any") && itsExtraData->hasParam(special(field))); 00463 } 00464 00465 00466 inline bool HandData::isSpecialField(std::string field) const 00467 { 00468 return field[0]=='*'; 00469 } 00470 00471 // ###################################################################### 00472 /*! Access Functions */ 00473 00474 /* _ ____ _ _ ____ ___ _ ____ _ _ 00475 ** | | | \_/ [__ | | | |_/ 00476 **_| |__| | ___] | | |___ | \_ 00477 */ 00478 00479 inline size_t HandData::numButton() const { 00480 return b.size(); } 00481 00482 inline int HandData::getAccelerator() const { 00483 return (y<127)?(127-y):0; } 00484 inline float HandData::getAcceleratorF() const { 00485 return (y<127)?(127-y)/127.0:0.0; } 00486 00487 inline int HandData::getBrake() const { 00488 return (y>127)?(y-127):0; } 00489 inline float HandData::getBrakeF() const { 00490 return (y>127)?(y-127)/128.0:0; } 00491 00492 inline int HandData::getWheelLeft() const { 00493 return (x<127)?(127-x):0; } 00494 inline float HandData::getWheelLeftF() const { 00495 return (x<127)?(127-x)/127.0:0.0; } 00496 00497 inline int HandData::getWheelRight() const { 00498 return (x>127)?(x-127):0; } 00499 inline float HandData::getWheelRightF() const { 00500 return (x>127)?(x-127)/128.0:0; } 00501 00502 inline int HandData::getWheel() const { 00503 return x; } 00504 inline float HandData::getWheelF() const { 00505 return (x*2.0/255.0) - 1.0; } 00506 inline int HandData::getX() const { 00507 return x; } 00508 00509 inline int HandData::getAcclBrake() const { 00510 return y; } 00511 inline float HandData::getAcclBrakeF() const { 00512 return (y*2.0/255.0) - 1.0; } 00513 inline int HandData::getY() const { 00514 return y; } 00515 00516 inline Point2D<int> HandData::getPosition() const { 00517 return Point2D<int> (x,y); } 00518 inline Point2D<float> HandData::getPositionF() const { 00519 return Point2D<float> (getWheelF(),getAcclBrakeF()); } 00520 00521 /* _ _ ____ _ _ ____ ____ 00522 ** |\/| | | | | [__ |___ 00523 ** | | |__| |__| ___] |___ 00524 */ 00525 00526 inline int HandData::getMouseX() const { 00527 return mx;} 00528 inline int HandData::getMouseY() const { 00529 return my;} 00530 inline int HandData::getNativeX() const { 00531 return nmx;} 00532 inline int HandData::getNativeY() const { 00533 return nmy;} 00534 inline bool HandData::getMouseBL() const { 00535 return mlb;} 00536 inline bool HandData::getMouseBM() const { 00537 return mmb;} 00538 inline bool HandData::getMouseBR() const { 00539 return mrb;} 00540 00541 /* _ _ ____ _ _ ___ ____ ____ ____ ___ 00542 ** |_/ |___ \_/ |__] | | |__| |__/ | \ 00543 ** | \_ |___ | |__] |__| | | | \ |__/ 00544 */ 00545 00546 inline char * HandData::getKeyboard() const { 00547 return (char*)kbch;} 00548 00549 00550 00551 // ###################################################################### 00552 /*! Extra Data Management */ 00553 inline rutz::shared_ptr<ParamMap> HandData::getMetaData() const 00554 { return itsExtraData; } 00555 00556 inline std::vector<std::string> HandData::getMetaDataList() const 00557 { 00558 std::vector<std::string> argList; 00559 if(hasMetaData()) 00560 for (ParamMap::key_iterator iter = getMetaData()->keys_begin(); 00561 iter != getMetaData()->keys_end(); 00562 ++iter) 00563 argList.push_back(*iter); 00564 00565 return argList; } 00566 00567 inline double HandData::getMetaDataField(std::string field) const 00568 { 00569 if (hasSpecialMetaData(field)) 00570 return itsExtraData->getDoubleParam(special(field)); 00571 else if(hasMetaData(field)) 00572 return itsExtraData->getDoubleParam(field); 00573 else LFATAL("No data field %s in HandData",field.c_str()); 00574 return -1; 00575 } 00576 00577 inline void HandData::outputData(std::ostream &out) const 00578 { 00579 out << "(x,y) = (" << x << "," << y << ")\t"<< "buttons ="; 00580 for (uint i = 0; i < b.size(); i++) 00581 out << " " << b[i]; 00582 out << "\n"; 00583 if(hasMetaData()) 00584 { 00585 std::vector<std::string> metaFields = getMetaDataList(); 00586 for(std::vector<std::string>::iterator iter = metaFields.begin(); 00587 iter != metaFields.end(); 00588 ++iter) 00589 out << *iter << " = " << getMetaDataField(*iter) << "\n"; 00590 } 00591 }; 00592 00593 inline std::string HandData::special(std::string field) const 00594 { 00595 if(field[0]=='*') return field; 00596 else return "*"+field; 00597 } 00598 00599 inline std::string HandData::unspecial(std::string field) const 00600 { 00601 if(field[0]=='*') return field.erase(0,1); 00602 else return field; 00603 } 00604 00605 // ###################################################################### 00606 /* So things look consistent in everyone's emacs... */ 00607 /* Local Variables: */ 00608 /* mode: c++ */ 00609 /* indent-tabs-mode: nil */ 00610 /* End: */ 00611 00612 #endif // PSYCHO_HANDDATA_H_DEFINED