/Users/craigcornelius/Projects/SPRING Mac Release 0.2/haptic_v1.cpp

Go to the documentation of this file.
00001 // $Id: haptic_v1.cpp,v 1.23 2006/05/24 16:52:39 sean Exp $
00002 //
00003 //  haptic_v1.cpp
00004 //
00005 
00006 #include "haptic_v1.h"
00007 #include "glui.h"
00008 #include <stdio.h>
00009 #include <math.h>
00010 #include <stdlib.h>
00011 
00012 #ifdef _WIN32
00013 #else
00014 #include <string.h>
00015 #endif
00016 
00017 const char* Haptic_v1::rcsid = "@(#) $Id: haptic_v1.cpp,v 1.23 2006/05/24 16:52:39 sean Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00018 
00019 // buffer size- well under the 1500 bytes ethernet limit, 
00020 // so will fit in 1 packet
00021 #define BUFSIZE 500
00022 
00023 int Haptic_v1::debug = 0;
00024 
00025 Haptic_v1::Haptic_v1(char* machine_name, int port_num, bool forcegridmode)
00026 : Sensor(Sensor::haptic_v1_sensor)
00027 {
00028     if (debug == 1) 
00029         cerr << "Haptic_v1::constructor(\"" << machine_name << "\", "
00030         << port_num << ")\n";
00031     
00032     // force initialization
00033     old_force.x = old_force.y = old_force.z =0.0;
00034     
00035     // forcegrid initialization
00036     old_grid[0].x = old_grid[0].y = old_grid[0].z =0.0;
00037     old_grid[1].x = old_grid[1].y = old_grid[1].z =0.0;
00038 
00039         // misc initialization
00040     twist_force = grip_force = 0.0;
00041     old_twist_force = old_grip_force = 0.0;
00042     force_scalefactor = 1.0;
00043     active_status = false;
00044     first_grab = true;
00045     //  grid_mode = forcegridmode;
00046         update_iterations = 0;
00047         force_iterations = 0;
00048     
00049     // linked haptics initialization
00050     haptic_link_mode = link_position;
00051     linked_device = NULL;
00052     
00053     num_active = 2;
00054     
00055     // set up socket: (need a separate, non global buffer so each instantiation
00056     // has it's own messages coming in
00057     buf = (char *)malloc(sizeof(char)*BUFSIZE);
00058     char server[80]; // = "maki.stanford.edu";
00059     strncpy(server, machine_name, 80);
00060     
00061     cerr << "making new socket to: " << server << endl;
00062 #ifdef __APPLE__
00063         int sock_buf_size = 1024;
00064         hsock = new Socket(server,Socket::tcp,port_num, sock_buf_size);
00065 #else
00066     hsock = new Socket(server,Socket::tcp,port_num);
00067 #endif // __APPLE__
00068     cerr << "created socket" << endl;
00069     
00070     // Set grid_mode 
00071     SetGridMode(forcegridmode);
00072     
00073     // // send initial handshake
00074     if (!grid_mode) sprintf(buf, "haptic v1.0");
00075     else sprintf(buf, "haptic v1.1");
00076 #ifdef BUFFERED
00077     hsock->BufferedSend(buf,strlen(buf));
00078 #else
00079     hsock->Send(buf,BUFSIZE);
00080 #endif
00081     cerr << " SEND HANDSHAKE BUF: [" << buf << "]\n";
00082     
00083     // Check to make sure haptic responded with an acknowledgement
00084     // (should ideally respond with what type of device it is, so we can
00085     // do device-specific things on this side)
00086 #ifdef BUFFERED
00087     hsock->BufferedReceive(buf,BUFSIZE);
00088 #else
00089     hsock->Receive(buf,BUFSIZE);
00090 #endif
00091     cerr << " RECEIVE HANDSHAKE BUF: [" << buf << "]\n";
00092     
00093     // test their response- do they support this version of the protocol?
00094     if (strncmp(buf,"ACK",3) != 0) {
00095         // no ACK, so an error has occured and we cannot connect
00096         cerr << "ERROR - denied connection" << endl;
00097     } else {
00098         // success
00099         cerr << "Connection made" << endl;
00100     }
00101 }
00102 
00103 Haptic_v1::~Haptic_v1()
00104 {
00105     if (debug == 1) cerr << "Haptic_v1::destructor()\n";
00106     
00107     sprintf(buf, "quit");
00108 #ifdef BUFFERED
00109     hsock->BufferedSend(buf,strlen(buf));
00110 #else
00111     hsock->Send(buf,BUFSIZE);
00112 #endif
00113     
00114     delete hsock;
00115     free(buf);
00116     num_active = -1;
00117 }
00118 
00119 void Haptic_v1::SetActive(bool status)
00120 {
00121     active_status = status;
00122 } 
00123 
00124 void  Haptic_v1::SetGridMode(bool mode)
00125 {
00126     if ((grid_mode == false) && (mode == true))
00127         first_grab = true;
00128     grid_mode = mode;
00129 }
00130 
00131 bool  Haptic_v1::GetGridMode()
00132 {
00133     return grid_mode;
00134 }
00135 
00136 void Haptic_v1::Update()
00137 {
00138     grid[1] = force;
00139 
00140         // if interested in real haptic update rates
00141         update_iterations++;
00142         if (debug == 2) {
00143           const int granularity = 100;
00144           if (update_iterations % granularity == 0) {
00145                   double secs = timer.GetElapsedTime();
00146               cerr << "Haptic Update Rate = " << update_iterations/secs
00147                        << " updates per second over " << granularity << " samples\n";
00148                   cerr << "  Force update rate = " << force_iterations/secs << endl;
00149               timer.Reset();
00150                   update_iterations = 0;
00151           }
00152         }
00153     
00154     // handle linked haptic devices first
00155     if (linked_device) {
00156         updateLinked();                 // to calculate the force
00157         updateStreaming();              // to actually send the values + get new position
00158     }
00159     else if (grid_mode)   // handle forcegrid
00160         updateForcegrid();
00161     else                                        // is streaming protocol
00162         updateStreaming();
00163     
00164 }
00165 
00166 // link to another haptic device
00167 void Haptic_v1::updateLinked()
00168 {
00169     if (!linked_device) return;
00170     
00171     switch (haptic_link_mode) {
00172     case link_position: {       // make a force to their position
00173         Point3D other_pos = linked_device->pos;
00174         force = (other_pos - pos) * force_scalefactor;
00175         break;
00176                         }
00177     case link_force: {  // feel their force
00178         Haptic_v1* other_haptic = (Haptic_v1*)linked_device;
00179         force = other_haptic->force;
00180         twist_force = other_haptic->twist_force;
00181         grip_force = other_haptic->grip_force;
00182         break;
00183                      }
00184     }  // end switch
00185 }
00186 
00187 void Haptic_v1::send_force()
00188 {
00189     // remap the force vector to the axis of the device
00190     Point3D hforce(force.x,force.y,force.z);
00191         
00192     // scale it up
00193     hforce *= force_scalefactor;
00194     if (debug == 4) {
00195         fprintf(stderr,"force=(%.1f,%.1f,%.1f)=%.1f,twist=%.1f,grip=%.1f\n", 
00196             force.x, force.y, force.z, force.Length(), 
00197             twist_force, grip_force);
00198     }
00199     
00200     // create the buffer
00201     int numbytes = sprintf(buf,"%f %f %f %f %f",hforce.x, hforce.y, hforce.z, 
00202         twist_force, grip_force);
00203     
00204     // send the buffer
00205 #ifdef BUFFERED
00206     hsock->BufferedSend(buf, numbytes);
00207 #else
00208     hsock->Send(buf, BUFSIZE);
00209 #endif
00210         
00211         // stats
00212         force_iterations++;
00213 
00214         // debugging
00215     if (debug == 4) {
00216         printf("Haptic_v1: Force sent: %f\t %f\t %f\t %f \t%f", 
00217             hforce.x, hforce.y, hforce.z, twist_force, grip_force);
00218     }
00219 }
00220 
00221 void Haptic_v1::receive_info()
00222 {
00223     //
00224     // Get the position and rotation matrix
00225     //
00226         
00227     // locals
00228     Point3D hpos;
00229     double hm[3][3];
00230     float hactive[max_active];  // ideally, should support as many as need
00231         
00232     // parse the position info
00233     int num = sscanf(buf,"%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
00234         &hpos.x, &hpos.y, &hpos.z,
00235         &hm[0][0], &hm[1][0], &hm[2][0], 
00236         &hm[0][1], &hm[1][1], &hm[2][1], 
00237         &hm[0][2], &hm[1][2], &hm[2][2], 
00238         &hactive[0], &hactive[1], &hactive[2], &hactive[3], &hactive[4],
00239         &hactive[5], &hactive[6], &hactive[7], &hactive[8], &hactive[9],
00240         &hactive[10], &hactive[11], &hactive[12], &hactive[13], &hactive[14],
00241         &hactive[15], &hactive[16], &hactive[17], &hactive[18], &hactive[19],
00242         &hactive[20], &hactive[21], &hactive[22], &hactive[23], &hactive[24]
00243         );
00244         
00245     // debugging
00246     if (debug == 5) cerr << "\tgot " << num << " args from device\n";
00247         
00248     // they map it to be correct: x to right, y up, z towards me
00249     pos = hpos;    
00250         
00251     // and handle the recentering of the world
00252     pos -= init_pos;
00253         
00254     // and scaling
00255     pos *= scalefactor;
00256         
00257     // copy the rotation matrix, too
00258     {
00259         for(int i=0; i<3; i++)
00260             for(int j=0; j<3; j++)
00261                 m.m[i][j] = hm[i][j];
00262     }
00263         
00264     // save whether it's active
00265     num_active = num-12;    // calculate from number of arguments seen
00266     if (debug == 5) cerr << "\tmaking " << num_active << " active values\n";
00267     for (int i=0; i<num_active; i++)
00268         active[i] = hactive[i];
00269     
00270     if (debug == 4)
00271         cerr << "Haptic_v1: Received BUF: " << buf << endl;
00272 }
00273 
00274 void Haptic_v1::updateStreaming()
00275 {
00276         // Send the force only if it changed
00277         // Note: we would probably like to send every time to help out 
00278         //   interpolation schemes, but that would be alot of bandwidth eaten.  
00279         //   Also, we'd end up having flow-control problems with a slow receiver 
00280         //   and this would eventually make us block, waiting for them to eat it 
00281         //   all
00282         // Note #2: We've moved this below in an attempt to ensure that we don't
00283         //   overwhelm a slow receiver.  Now we send the force only if we've had
00284         //   a position update- the idea being that if they can send that fast,
00285         //   then they can receive that fast, too.
00286         //   So, the paradigm is that we have a haptic server that can send
00287         //   positions very fast, a simulation that's a bit slower and, if for
00288         //   some reason this is reversed, then we'll max out at the senders rate
00289     //if (this->forceChanged())
00290                 //send_force();
00291     
00292     //
00293     // Get the position and rotation matrix
00294     //
00295     
00296     // get the buffer
00297     int data_waiting = hsock->InputQueueSize();
00298 
00299         // if nothing to do, bail
00300         if (data_waiting <= 0) return;
00301     
00302     // eat all waiting data to get to last
00303     while (data_waiting > 0)
00304     {
00305 #ifdef BUFFERED
00306         int nb = hsock->BufferedReceive(buf,BUFSIZE);
00307 #else
00308         int nb = hsock->Receive(buf,BUFSIZE);
00309 #endif
00310         data_waiting -= nb;
00311     }
00312     
00313     // there's data and we got it- process it
00314         receive_info();
00315 
00316         // and send the force update (see the note above)
00317         // (what the heck- send even if hasn't changed)
00318     //if (this->forceChanged())
00319                 send_force();
00320 }
00321 
00322 // The haptic uses a forcegrid, and thus needs a little more info...
00323 void Haptic_v1::updateForcegrid()
00324 {
00325     // DATA TO SEND
00326     if (active_status == true) {
00327         
00328         Point3D to_send[2];
00329         
00330         // grid[0] is the position received from the haptic device 
00331         // (a priori different fom the position of the tool in spring, 
00332         // due to scalefactor, offset...
00333         to_send[0] = grid[0];
00334         
00335         // grid[1] is the corresponding force
00336         // forcefactor: Phantom wants 0.1, LapIE wants 40
00337         to_send[1] = grid[1] * force_scalefactor;
00338         
00339         // create the buffer
00340         if (first_grab == true) {
00341             
00342             first_grab = false;
00343             int numbytes = sprintf(buf,"build");
00344             hsock->BufferedSend(buf, numbytes);
00345         }
00346         
00347         else {
00348             int nb = sprintf(buf,"fill %f %f %f %f %f %f",
00349                 to_send[0].x, to_send[0].y, to_send[0].z,
00350                 to_send[1].x, to_send[1].y, to_send[1].z);
00351             hsock->BufferedSend(buf, nb);
00352         }
00353     }
00354     else {
00355         // else, notify the haptics that we are not active here, in spring
00356         if (first_grab == false) {
00357             int numbytes = sprintf(buf,"destruct");
00358             hsock->BufferedSend(buf, numbytes);
00359             //cerr << "Sending buf[" << buf << "]\n";
00360         }
00361         first_grab = true;
00362     }
00363     
00364     // DATA TO RECEIVE
00365     
00366     int data_waiting = hsock->InputQueueSize() / BUFSIZE;
00367     
00368     if(data_waiting == 0)
00369         return;
00370     
00371     // Necessary pre-flush, to avoid congestion
00372     while(data_waiting > 0)
00373     {
00374         hsock->BufferedReceive(buf,BUFSIZE);
00375         data_waiting--;
00376         
00377         // if it's not a position buffer, don't flush it
00378         if (strncmp(buf, "pos", 3) != 0)
00379             break;
00380     }
00381     
00382     // parse the buffer info
00383     
00384     // if it's a position buffer
00385     if (strncmp(buf, "pos", 3) == 0) {
00386         Point3D hpos;
00387         double hm[3][3];
00388         float hactive;
00389         sscanf(buf + 3," %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %f",
00390             &hpos.x, &hpos.y, &hpos.z,
00391             &hm[0][0], &hm[0][1], &hm[0][2],
00392             &hm[1][0], &hm[1][1], &hm[1][2], 
00393             &hm[2][0], &hm[2][1], &hm[2][2], &hactive);
00394         
00395         grid[0] = hpos;
00396         
00397         // then map it to be correct: x to right, y up, z towards me
00398         pos = hpos;     
00399         
00400         // and handle the recentering of the world
00401         pos -= init_pos;
00402         
00403         // and scaling
00404         pos *= scalefactor;
00405         
00406         // copy the rotation matrix, too
00407         for(int i=0; i<3; i++)
00408             for(int j=0; j<3; j++)
00409                 m.m[i][j] = hm[i][j];
00410             
00411             // save whether it's active
00412             active[0] = hactive;
00413     }
00414     
00415     else if (strcmp(buf, "stop") == 0)
00416     {
00417         // Flush the entire buffer
00418         while(data_waiting > 0)
00419         {
00420             hsock->Receive(buf,BUFSIZE);
00421             data_waiting--;
00422         }
00423         return;
00424     }
00425     
00426     // Anything else is an error buffer -> discard and flush.
00427     else {
00428         //cerr << "Irrelevant data received from haptics, Flushing...";
00429         //cerr << "\nBuffer received: [" << buf << "]";
00430         data_waiting = ((hsock->InputQueueSize() / BUFSIZE) -1);
00431         while (data_waiting >= 0) {
00432             hsock->BufferedReceive(buf, BUFSIZE);
00433             data_waiting --;
00434         }
00435     }
00436 }
00437 
00438 int Haptic_v1::forceChanged()
00439 {
00440     int res;
00441     
00442     res = ((force.x != old_force.x) || (force.y != old_force.y) 
00443         || (force.z != old_force.z) || (twist_force != old_twist_force)
00444         || (grip_force != old_grip_force));
00445     
00446     // update old force
00447     if (res) { 
00448         old_force = force; 
00449         old_twist_force = twist_force; 
00450         old_grip_force = grip_force; 
00451     }
00452     
00453     // printf("%d", res);
00454     return res;
00455 }
00456 
00457 int Haptic_v1::gridChanged()
00458 {
00459     int res;
00460     
00461     res = ((grid[0].x != old_grid[0].x) || (grid[0].y != old_grid[0].y) 
00462         || (grid[0].z != old_grid[0].z) || (grid[1].x != old_grid[1].x) 
00463         || (grid[0].y != old_grid[1].y) || (grid[1].z != old_grid[1].z));
00464     if(res)
00465     {
00466         old_grid[0] = grid[0];
00467         old_grid[1] = grid[1];
00468     }
00469     return res;
00470 }
00471 
00472 void Haptic_v1::HapticLink(Sensor* sensor)
00473 {
00474     linked_device = sensor;
00475     
00476     // turn off any leftover forces
00477     if (linked_device == NULL) 
00478         force = Point3D(0,0,0);
00479 }

Generated on Thu Aug 30 11:03:14 2007 for SPRING Mac by  doxygen 1.5.3