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

P_SensorConfig.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 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.41 $       $Date: 2019/01/17 21:21:01 $
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[128], word[128];
00104   memset(buf, 0, sizeof(buf));
00105   memset(word, 0, sizeof(word));
00106 
00107   if(!fgets(buf, sizeof(buf), f)) return -1;
00108 
00109   argc = 0;
00110   pos = 0;
00111   while (argc<maxarg && pos<100 && buf[pos]!=0 && buf[pos]!='\n'
00112         && buf[pos]!='\r') {
00113 
00114     if (buf[pos]!=' ' && buf[pos]!='\t') {
00115       sscanf(buf+pos, "%99s", word); 
00116       pos += strlen(word);
00117       argv[argc] = (JString)word;
00118       argc++;
00119     } else {
00120       pos++;
00121     }
00122   }
00123   
00124   return argc;
00125 }
00126 
00127 
00128 static int need_args(int argc,int need, int line) {
00129   if (need!=argc) {
00130     msgErr << "SensorConfig: Wrong number of arguments at line " << line << "." << sendmsg;
00131     msgErr << "Expected " << need << ", got " << argc << "." << sendmsg;
00132     return 1;
00133   }
00134   return 0;
00135 }
00136 
00137 float SensorConfig::getfloat(const char *from, float defalt) {
00138   int ret;
00139   float f;
00140   ret=sscanf(from,"%f",&f);
00141   if(!ret) {
00142     msgErr << "SensorConfig: Error parsing float at line " << line << sendmsg;
00143     return defalt;
00144   }
00145   return f;
00146 }
00147  
00148 int SensorConfig::needargs(int argc,int need) {
00149   return need_args(argc,need,line);
00150 }
00151 
00152 
00153 void SensorConfig::parseconfigfordevice(FILE *file, void *) {
00154   // now we have an open configuration file, search for device lines
00155   int found=FALSE, argc;
00156   line = 0;
00157   JString argv[20];
00158   while ((argc=splitline(file, argv, 20))>=0) {
00159     line++;
00160     
00161     if (!argc) continue;
00162     if (argv[0][0]=='#') continue; // this line is a comment
00163 
00164     if (!compare(argv[0],"device")) { // found a device
00165       if (found) break; // done reading info about our device
00166       if (needargs(argc,3)) return;
00167       if (!compare(argv[1],device)) { // found our device
00168         // Comment out chatty options for now, until we can reduce the number
00169         // of times we have to read the .vmdsensors file.
00170         // msgInfo << "Found device '" << argv[1] << "'" << " on line " << line << "." << sendmsg;
00171               found = TRUE;
00172               USL = argv[2];
00173               continue; // we start parsing the options on the next line
00174       }
00175     }
00176 
00177     if (!found) continue;
00178 
00179     // Comment out chatty options for now, until we can reduce the number
00180     // of times we have to read the .vmdsensors file.
00181     // msgInfo << "Reading option '" <<  argv[0] << "'" << sendmsg;
00182 
00183     if (!compare(argv[0],"scale")) {
00184       if (needargs(argc,2)) return;
00185       scale = getfloat(argv[1],1);
00186     }
00187     else if (!compare(argv[0],"maxforce")) {
00188       // XXX Maxforce doesn't seem to work at the moment, causing dangerously
00189       // high forces to be sent to the haptic device.  Disabling for now until
00190       // the reason is discovered.
00191 #if 0
00192       if (needargs(argc,2)) return;
00193       maxforce = getfloat(argv[1],1);
00194 #else
00195       msgInfo << "Sorry, maxforce parameter not currently implemented." 
00196               << sendmsg;
00197 #endif
00198     }
00199     else if (!compare(argv[0],"offset")) {
00200       int i;
00201       if (needargs(argc,4)) return;
00202       for (i=0;i<3;i++)
00203               offset[i] = getfloat(argv[1+i],0);
00204     }
00205     else if (!compare(argv[0],"rot")) {
00206       int i;
00207       if (needargs(argc,11)) return;
00208       if (!compare(argv[1],"right"))
00209               for (i=0;i<9;i++)
00210                 right_rot.mat[i+i/3] = getfloat(argv[2+i],right_rot.mat[i+i/3]);
00211       else
00212               for (i=0;i<9;i++)
00213                 left_rot.mat[i+i/3] = getfloat(argv[2+i],right_rot.mat[i+i/3]);
00214     }
00215     else msgErr << "Error: Unrecognized tool option on line " << line << sendmsg;
00216   }
00217 
00218   if (USL=="") msgErr << "Device " << device << " not found." << sendmsg;
00219   else parseUSL();
00220 }
00221 
00222 
00223 SensorConfig::SensorConfig(const char *thedevice) {
00224 
00225   if (thedevice==NULL) return;
00226 
00227   USL = "";
00228   strcpy(nums,"");
00229   strcpy(name,"");
00230   strcpy(place,"");
00231   strcpy(type,"");
00232   strcpy(device,thedevice);
00233   offset[0] = offset[1] = offset[2] = 0;
00234   scale = 1;
00235   maxforce = -1; // default is to not enforce a maximum
00236   right_rot.identity();
00237   left_rot.identity();
00238   
00239   ScanSensorFiles(PARSE_FOR_DEVICE, this, NULL);
00240 }
00241 
00242 
00243 int SensorConfig::parseUSL() {
00244   int ret;
00245   strcpy(nums,"0"); // fill in default of zero
00246 
00247   ret = sscanf(USL,"%20[^:]://%100[^/]/%100[^:]:%101s",
00248                            type,     place,   name,    nums);
00249   
00250   if(ret<3) {
00251     msgErr << "USL on line " << line << " is not of the form: "
00252            << "type://place/name[:num,num,...]" << sendmsg;
00253     return 0; // if we get anything less than blah://blah/blah
00254   }
00255 
00256   read_sensor_nums();
00257   
00258   return 1;
00259 }
00260 
00261 void SensorConfig::read_sensor_nums() {
00262   char *s=strdup(nums);
00263   char *r=s;
00264 
00265   for (int cur=0; cur<= 200; cur++) {
00266     if(s[cur]==',' || s[cur]==0) {
00267       int tmp = 0;
00268       sscanf(r,"%d",&tmp);
00269       sensors.append(tmp);
00270       r = s + cur + 1;
00271       if(s[cur]==0) break;
00272       s[cur]=0;
00273     }
00274   }
00275 
00276   free(s);
00277 }
00278 
00279 
00280 // Used as a callback in SensorConfig::getnames()
00281 void SensorConfig::parseconfigfornames(FILE *f, void *ret_void) {
00282   int argc, line=0;
00283   JString argv[20];
00284   
00285   while ((argc=splitline(f, argv, 20))>=0) {
00286     line++;
00287     
00288     if(!argc) continue;
00289     if(argv[0][0]=='#') continue; // this line is a comment
00290 
00291     if(!compare(argv[0],"device")) { // found a device
00292       if(need_args(argc,3,line)) continue;
00293       JString *newname = new JString(argv[1]);
00294       ((ResizeArray<JString *>*) ret_void)->append(newname);
00295     }
00296   }
00297 }
00298 
00299 
00300 ResizeArray<JString *> *SensorConfig::getnames() {
00301   ResizeArray<JString *> *ret = new ResizeArray<JString *>;
00302   
00303   ScanSensorFiles(PARSE_FOR_NAMES, NULL, (void*)ret);
00304   return ret;
00305 }
00306 
00307 
00308 const char *SensorConfig::getUSL() const {
00309   return USL;
00310 }
00311 
00312 float SensorConfig::getscale() const {
00313   return scale;
00314 }
00315 
00316 float SensorConfig::getmaxforce() const {
00317   return maxforce;
00318 }
00319 
00320 const float *SensorConfig::getoffset() const {
00321   return offset;
00322 }
00323 
00324 const Matrix4 *SensorConfig::getright_rot() const {
00325   return &right_rot;
00326 }
00327 
00328 const Matrix4 *SensorConfig::getleft_rot() const {
00329   return &left_rot;
00330 }
00331 
00332 const char *SensorConfig::getdevice() const { return device; }
00333 const char *SensorConfig::gettype() const { return type; }
00334 const char *SensorConfig::getplace() const { return place; }
00335 const char *SensorConfig::getname() const { return name; }
00336 const char *SensorConfig::getnums() const { return nums; }
00337 const ResizeArray<int> *SensorConfig::getsensors() const { return &sensors; }
00338 
00339 SensorConfig::~SensorConfig() {
00340 }
00341 
00342 int SensorConfig::have_one_sensor() const {
00343   if (sensors.num() != 1) {
00344     msgErr << "Please specify exactly one sensor." << sendmsg;
00345     return 0;
00346   }
00347   return 1;
00348 }
00349  
00350 void SensorConfig::make_vrpn_address(char *buf) const {
00351   // As of VRPN 7.15 enforcing TCP-only connections is supported
00352   // by appending @tcp to the device name and using an USL in 
00353   // format Device@tcp://machine:port instead of Device@machine:port.
00354   // Create a new style USL when the name contains @tcp. 
00355   if (strstr(name,"@tcp"))
00356     sprintf(buf, "%s://%s", name, place);
00357   else
00358     sprintf(buf, "%s@%s", name, place);
00359 }
00360    
00361 int SensorConfig::require_local() const {
00362   if(strcmp(place,"local")) {
00363     msgErr << "Sorry, this local device requires place name \"local\"."
00364             << sendmsg;
00365     return 0;
00366   }
00367   return 1;
00368 }
00369 
00370 int SensorConfig::require_cave_name() const {
00371   if(!require_local()) return 0;
00372   if(strcmp(name,"cave")) {
00373     msgErr << "Sorry, the device name for the CAVE is \"cave\"." << sendmsg;
00374     return 0;
00375   }
00376   return 1;
00377 }
00378 
00379 int SensorConfig::require_freevr_name() const {
00380   if(!require_local()) return 0;
00381   if(strcmp(name,"freevr")) {
00382     msgErr << "Sorry, the device name for FreeVR is \"freevr\"." << sendmsg;
00383     return 0;
00384   }
00385   return 1;
00386 }
00387 

Generated on Thu Mar 28 02:43:57 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002