Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

P_SensorConfig.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: P_SensorConfig.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.37 $       $Date: 2010/12/16 04:08:31 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  * This is Paul's new Tracker code -- pgrayson@ks.uiuc.edu
00019  ***************************************************************************/
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include "P_SensorConfig.h"
00024 #include "Inform.h"
00025 #include "utilities.h"
00026 
00027 
00028 // This function goes through all the vmdsensors files, opens them and calls
00029 // a functio defined by "behavior" for each one, and then closes the files.
00030 // It passes along the pointer "params" to the called function.
00031 // This mechanism is a bit clumsy, but it best accomodated the re-use of
00032 // the previous code.
00033 enum Scanning_Behaviors { PARSE_FOR_NAMES, PARSE_FOR_DEVICE };
00034 
00035 void SensorConfig::ScanSensorFiles (int behavior, SensorConfig *sensor, void* params) {
00036   JString sensorfile;
00037   FILE *file;
00038   int found_sensorfile=FALSE; //keeps track of whether we found a sensor file
00039 
00040 #if !defined(_MSC_VER)
00041   // First try looking for a .vmdsensors file in the user's
00042   // UNIX home directory 
00043   sensorfile = getenv("HOME");
00044   sensorfile += "/.vmdsensors";
00045   if ( (file = fopen(sensorfile,"r")) ) {
00046     found_sensorfile=TRUE;
00047     switch (behavior) {
00048       case PARSE_FOR_DEVICE:
00049         sensor->parseconfigfordevice(file, params);
00050         break;
00051       case PARSE_FOR_NAMES:
00052         parseconfigfornames(file, params);
00053         break;
00054     }
00055     fclose(file);
00056   }
00057 #endif
00058   
00059   // Then, try path pointed to by the VMDSENSORS env. variable  
00060   if (!found_sensorfile) {
00061     char *sensorfile_str = getenv("VMDSENSORS");
00062     if (sensorfile_str && (file = fopen(sensorfile_str,"r"))) {
00063       found_sensorfile=TRUE;
00064       switch (behavior) {
00065         case PARSE_FOR_DEVICE:
00066           sensor->parseconfigfordevice(file, params);
00067           break;
00068         case PARSE_FOR_NAMES:
00069           parseconfigfornames(file, params);
00070           break;
00071       }
00072       fclose(file);
00073     }
00074   }
00075   
00076   // If we couldn't find a file in the home dir or VMDSENSORS env. variable
00077   // then try finding one in the VMD installation area.  
00078   if (!found_sensorfile) {
00079     sensorfile = getenv("VMDDIR");
00080 #if defined(_MSC_VER)
00081     sensorfile += "\\.vmdsensors";
00082 #else
00083     sensorfile += "/.vmdsensors";
00084 #endif
00085     if ((file = fopen(sensorfile,"r"))) {
00086       switch (behavior) {
00087         case PARSE_FOR_DEVICE:
00088           sensor->parseconfigfordevice(file, params);
00089           break;
00090         case PARSE_FOR_NAMES:
00091           parseconfigfornames(file, params);
00092           break;
00093       }
00094       fclose(file);
00095     }
00096   }
00097   
00098 }
00099 
00100 
00101 static int splitline(FILE *f, JString *argv, int maxarg) {
00102   int argc, pos;
00103   char buf[100], word[100];
00104   if(!fgets(buf,100,f)) return -1;
00105 
00106   argc = 0;
00107   pos = 0;
00108   while(argc<maxarg && pos<100 && buf[pos]!=0 && buf[pos]!='\n'
00109         && buf[pos]!='\r') {
00110     if(buf[pos]!=' ' && buf[pos]!='\t') {
00111       sscanf(buf+pos,"%99s",word); 
00112       pos += strlen(word);
00113       argv[argc] = (JString)word;
00114       argc++;
00115     }
00116     else pos++;
00117   }
00118   
00119   return argc;
00120 }
00121 
00122 
00123 static int need_args(int argc,int need, int line) {
00124   if(need!=argc) {
00125     msgErr << "SensorConfig: Wrong number of arguments at line " << line << "." << sendmsg;
00126     msgErr << "Expected " << need << ", got " << argc << "." << sendmsg;
00127     return 1;
00128   }
00129   return 0;
00130 }
00131 
00132 float SensorConfig::getfloat(const char *from, float defalt) {
00133   int ret;
00134   float f;
00135   ret=sscanf(from,"%f",&f);
00136   if(!ret) {
00137     msgErr << "SensorConfig: Error parsing float at line " << line << sendmsg;
00138     return defalt;
00139   }
00140   return f;
00141 }
00142  
00143 int SensorConfig::needargs(int argc,int need) {
00144   return need_args(argc,need,line);
00145 }
00146 
00147 
00148 void SensorConfig::parseconfigfordevice(FILE *file, void *) {
00149   // now we have an open configuration file, search for device lines
00150   int found=FALSE, argc;
00151   line = 0;
00152   JString argv[20];
00153   while ((argc=splitline(file,argv,20))>=0) {
00154     line++;
00155     
00156     if (!argc) continue;
00157     if (argv[0][0]=='#') continue; // this line is a comment
00158 
00159     if (!compare(argv[0],"device")) { // found a device
00160       if (found) break; // done reading info about our device
00161       if (needargs(argc,3)) return;
00162       if (!compare(argv[1],device)) { // found our device
00163         // Comment out chatty options for now, until we can reduce the number
00164         // of times we have to read the .vmdsensors file.
00165         // msgInfo << "Found device '" << argv[1] << "'" << " on line " << line << "." << sendmsg;
00166               found = TRUE;
00167               USL = argv[2];
00168               continue; // we start parsing the options on the next line
00169       }
00170     }
00171 
00172     if (!found) continue;
00173 
00174     // Comment out chatty options for now, until we can reduce the number
00175     // of times we have to read the .vmdsensors file.
00176     // msgInfo << "Reading option '" <<  argv[0] << "'" << sendmsg;
00177 
00178     if (!compare(argv[0],"scale")) {
00179       if (needargs(argc,2)) return;
00180       scale = getfloat(argv[1],1);
00181     }
00182     else if (!compare(argv[0],"maxforce")) {
00183       // XXX Maxforce doesn't seem to work at the moment, causing dangerously
00184       // high forces to be sent to the haptic device.  Disabling for now until
00185       // the reason is discovered.
00186 #if 0
00187       if (needargs(argc,2)) return;
00188       maxforce = getfloat(argv[1],1);
00189 #else
00190       msgInfo << "Sorry, maxforce parameter not currently implemented." 
00191               << sendmsg;
00192 #endif
00193     }
00194     else if (!compare(argv[0],"offset")) {
00195       int i;
00196       if (needargs(argc,4)) return;
00197       for (i=0;i<3;i++)
00198               offset[i] = getfloat(argv[1+i],0);
00199     }
00200     else if (!compare(argv[0],"rot")) {
00201       int i;
00202       if (needargs(argc,11)) return;
00203       if (!compare(argv[1],"right"))
00204               for (i=0;i<9;i++)
00205                 right_rot.mat[i+i/3] = getfloat(argv[2+i],right_rot.mat[i+i/3]);
00206       else
00207               for (i=0;i<9;i++)
00208                 left_rot.mat[i+i/3] = getfloat(argv[2+i],right_rot.mat[i+i/3]);
00209     }
00210     else msgErr << "Error: Unrecognized tool option on line " << line << sendmsg;
00211   }
00212 
00213   if (USL=="") msgErr << "Device " << device << " not found." << sendmsg;
00214   else parseUSL();
00215 }
00216 
00217 
00218 SensorConfig::SensorConfig(const char *thedevice) {
00219 
00220   if (thedevice==NULL) return;
00221 
00222   USL = "";
00223   strcpy(nums,"");
00224   strcpy(name,"");
00225   strcpy(place,"");
00226   strcpy(type,"");
00227   strcpy(device,thedevice);
00228   offset[0] = offset[1] = offset[2] = 0;
00229   scale = 1;
00230   maxforce = -1; // default is to not enforce a maximum
00231   right_rot.identity();
00232   left_rot.identity();
00233   
00234   ScanSensorFiles(PARSE_FOR_DEVICE, this, NULL);
00235 }
00236 
00237 
00238 int SensorConfig::parseUSL() {
00239   int ret;
00240   strcpy(nums,"0"); // fill in default of zero
00241 
00242   ret = sscanf(USL,"%20[^:]://%100[^/]/%100[^:]:%101s",
00243                            type,     place,   name,    nums);
00244   
00245   if(ret<3) {
00246     msgErr << "USL on line " << line << " is not of the form: "
00247            << "type://place/name[:num,num,...]" << sendmsg;
00248     return 0; // if we get anything less than blah://blah/blah
00249   }
00250 
00251   read_sensor_nums();
00252   
00253   return 1;
00254 }
00255 
00256 void SensorConfig::read_sensor_nums() {
00257   char *s=strdup(nums);
00258   char *r=s;
00259 
00260   for (int cur=0; cur<= 200; cur++) {
00261     if(s[cur]==',' || s[cur]==0) {
00262       int tmp = 0;
00263       sscanf(r,"%d",&tmp);
00264       sensors.append(tmp);
00265       r = s + cur + 1;
00266       if(s[cur]==0) break;
00267       s[cur]=0;
00268     }
00269   }
00270 
00271   free(s);
00272 }
00273 
00274 
00275 // Used as a callback in SensorConfig::getnames()
00276 void SensorConfig::parseconfigfornames(FILE *f, void *ret_void) {
00277   int argc, line=0;
00278   JString argv[20];
00279   
00280   while((argc=splitline(f,argv,20))>=0) {
00281     line++;
00282     
00283     if(!argc) continue;
00284     if(argv[0][0]=='#') continue; // this line is a comment
00285 
00286     if(!compare(argv[0],"device")) { // found a device
00287       if(need_args(argc,3,line)) continue;
00288       JString *newname = new JString(argv[1]);
00289       ((ResizeArray<JString *>*) ret_void)->append(newname);
00290     }
00291   }
00292 }
00293 
00294 
00295 ResizeArray<JString *> *SensorConfig::getnames() {
00296   ResizeArray<JString *> *ret = new ResizeArray<JString *>;
00297   
00298   ScanSensorFiles(PARSE_FOR_NAMES, NULL, (void*)ret);
00299   return ret;
00300 }
00301 
00302 
00303 const char *SensorConfig::getUSL() const {
00304   return USL;
00305 }
00306 
00307 float SensorConfig::getscale() const {
00308   return scale;
00309 }
00310 
00311 float SensorConfig::getmaxforce() const {
00312   return maxforce;
00313 }
00314 
00315 const float *SensorConfig::getoffset() const {
00316   return offset;
00317 }
00318 
00319 const Matrix4 *SensorConfig::getright_rot() const {
00320   return &right_rot;
00321 }
00322 
00323 const Matrix4 *SensorConfig::getleft_rot() const {
00324   return &left_rot;
00325 }
00326 
00327 const char *SensorConfig::getdevice() const { return device; }
00328 const char *SensorConfig::gettype() const { return type; }
00329 const char *SensorConfig::getplace() const { return place; }
00330 const char *SensorConfig::getname() const { return name; }
00331 const char *SensorConfig::getnums() const { return nums; }
00332 const ResizeArray<int> *SensorConfig::getsensors() const { return &sensors; }
00333 
00334 SensorConfig::~SensorConfig() {
00335 }
00336 
00337 int SensorConfig::have_one_sensor() const {
00338   if (sensors.num() != 1) {
00339     msgErr << "Please specify exactly one sensor." << sendmsg;
00340     return 0;
00341   }
00342   return 1;
00343 }
00344  
00345 void SensorConfig::make_vrpn_address(char *buf) const {
00346   if (!name || !place) 
00347     *buf = '\0';
00348   else {
00349     // As of VRPN 7.15 enforcing TCP-only connections is supported
00350     // by appending @tcp to the device name and using an USL in 
00351     // format Device@tcp://machine:port instead of Device@machine:port.
00352     // Create a new style USL when the name contains @tcp. 
00353     if (strstr(name,"@tcp"))
00354       sprintf(buf, "%s://%s", name, place);
00355     else
00356       sprintf(buf, "%s@%s", name, place);
00357   }
00358 }
00359    
00360 int SensorConfig::require_local() const {
00361   if(strcmp(place,"local")) {
00362     msgErr << "Sorry, this local device requires place name \"local\"."
00363             << sendmsg;
00364     return 0;
00365   }
00366   return 1;
00367 }
00368 
00369 int SensorConfig::require_cave_name() const {
00370   if(!require_local()) return 0;
00371   if(strcmp(name,"cave")) {
00372     msgErr << "Sorry, the device name for the CAVE is \"cave\"." << sendmsg;
00373     return 0;
00374   }
00375   return 1;
00376 }
00377 
00378 int SensorConfig::require_freevr_name() const {
00379   if(!require_local()) return 0;
00380   if(strcmp(name,"freevr")) {
00381     msgErr << "Sorry, the device name for FreeVR is \"freevr\"." << sendmsg;
00382     return 0;
00383   }
00384   return 1;
00385 }
00386 

Generated on Tue May 22 01:48:02 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002