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

Go to the documentation of this file.
00001 // $Id: joystick.cpp,v 1.8 2006/05/24 16:52:39 sean Exp $
00002 // $Copyright: (c)2001 National Biocomputation Center, Stanford University $
00003 //
00004 //  joystick.cpp
00005 //
00006 //  Author: Chris (caschwan@hawaii.edu) - Hawaii
00007 
00008 #include "joystick.h"
00009 #include "glui.h"
00010 #include <stdio.h>
00011 #include <math.h>
00012 #include <stdlib.h>
00013 
00014 #ifdef _WIN32
00015 #else
00016 #include <string.h>
00017 #endif
00018 
00019 const char* Joystick::rcsid = "@(#) $Id: joystick.cpp,v 1.8 2006/05/24 16:52:39 sean Exp $ $Copyright: (c)2001 National Biocomputation Center, Stanford University $";
00020 
00021 // buffer size- well under the 1500 bytes ethernet limit, 
00022 // so will fit in 1 packet
00023 #define BUFSIZE 500
00024 
00025 // debug level for info messages
00026 int Joystick::debug = 0;
00027 
00028 
00029 
00030 // Joystick constructor
00031 Joystick::Joystick(char* machine_name, int port_num) : Sensor(Sensor::joystick_sensor)
00032 {
00033         int i;
00034 
00035         // output debug info
00036     if (debug == 1) {
00037         cerr << "Joystick::constructor(\"" 
00038                          << machine_name << "\", "
00039              << port_num << ")\n";
00040     }
00041 
00042     // set up socket: (need a separate, non global buffer so each instantiation
00043     // has it's own messages coming in
00044     buf = (char *)malloc(sizeof(char)*BUFSIZE);
00045     char server[80];
00046     strncpy(server, machine_name, 80);
00047     
00048     cerr << "making new socket to: " << server << endl;
00049     hsock = new Socket(server,Socket::tcp,port_num);
00050     cerr << "created socket" << endl;
00051       
00052         // reset timer
00053         timer = Timer();
00054         lastUpdate = 0.0;
00055 
00056         // default joystick emulation mode (x-y like mouse)
00057         joystickEmulation = Joystick::mouse_emulation;
00058         scalefactor = 25.0;
00059 
00060         // init joystick data structure
00061         joydata = new Joydata;
00062         joydata->num_axes = 0;
00063         joydata->num_buttons = 0;
00064         for (i = 0; i < Joystick::MAX_JOYSTICK_BUTTONS; i++) {
00065                 joydata->buttons[i] = 0;
00066         }
00067         for (i = 0; i < Joystick::MAX_JOYSTICK_AXES; i++) {
00068                 joydata->axes[i] = 0;
00069         }
00070 
00071     // // send initial handshake
00072     sprintf(buf, "joystick v1.0");
00073 #ifdef BUFFERED
00074     hsock->BufferedSend(buf,strlen(buf));
00075 #else
00076     hsock->Send(buf,BUFSIZE);
00077 #endif
00078     cerr << " SEND HANDSHAKE BUF: [" << buf << "]\n";
00079     
00080     // Check to make sure haptic responded with an acknowledgement
00081     // (should ideally respond with what type of device it is, so we can
00082     // do device-specific things on this side)
00083 #ifdef BUFFERED
00084     hsock->BufferedReceive(buf,BUFSIZE);
00085 #else
00086     hsock->Receive(buf,BUFSIZE);
00087 #endif
00088     cerr << " RECEIVE HANDSHAKE BUF: [" << buf << "]\n";
00089     
00090     // test their response- do they support this version of the protocol?
00091     if (strncmp(buf,"ACK",3) != 0) {
00092         // no ACK, so an error has occured and we cannot connect
00093         cerr << "ERROR - denied connection" << endl;
00094     } else {
00095         // success
00096         cerr << "Connection made" << endl;
00097     }
00098 }
00099 
00100 // ends the joystick server
00101 Joystick::~Joystick()
00102 {
00103         // destructor info
00104     if (debug == 1) cerr << "Joystick::destructor()\n";
00105     
00106     sprintf(buf, "quit");
00107 #ifdef BUFFERED
00108     hsock->BufferedSend(buf,strlen(buf));
00109 #else
00110     hsock->Send(buf,BUFSIZE);
00111 #endif
00112     
00113     delete hsock;
00114     free(buf);
00115     num_active = -1;
00116 }
00117 
00118 void Joystick::send_force()
00119 {
00120     // not supported yet
00121         // -> SDL (on the joystickserver) only supports status read, but not setting
00122         //    forces: suggest to wait for future releases of SDL
00123         // -> see haptic_v1 on how to implement sending forces over the network
00124 }
00125 
00126 void Joystick::receive_info()
00127 {
00128     // Get the joystick data (activation values only)
00129     int num = sscanf(buf, "%i %i %i %i %i %i %i %i %i %i %i %i %i %i %lf %lf %lf %lf %lf %lf",
00130          &joydata->num_buttons, 
00131                  &joydata->buttons[0],  
00132                  &joydata->buttons[1],  
00133                  &joydata->buttons[2],  
00134                  &joydata->buttons[3],  
00135                  &joydata->buttons[4],  
00136                  &joydata->buttons[5],  
00137                  &joydata->buttons[6],  
00138                  &joydata->buttons[7],  
00139                  &joydata->buttons[8],  
00140                  &joydata->buttons[9],  
00141                  &joydata->buttons[10],  
00142                  &joydata->buttons[11],  
00143          &joydata->num_axes,
00144                  &joydata->axes[0],
00145                  &joydata->axes[1],
00146                  &joydata->axes[2],
00147                  &joydata->axes[3],
00148                  &joydata->axes[4],
00149                  &joydata->axes[5]
00150     );
00151     
00152         // debugging
00153     if (debug == 4) {
00154         cerr << "Joystick: Received BUF: " << buf << endl;
00155         }
00156     else if (debug == 5) {
00157                 cerr << "\tgot " << num << " args from device\n";
00158     }
00159 }
00160 
00161 // update joystick data
00162 void Joystick::Update()
00163 {
00164     int i;
00165 
00166     // get the buffer
00167     int data_waiting = hsock->InputQueueSize();
00168 
00169         // if nothing to do, bail
00170         if (data_waiting > 0) {
00171                 // eat all waiting data to get to last
00172                 while (data_waiting > 0) {
00173 #ifdef BUFFERED
00174                         int nb = hsock->BufferedReceive(buf, BUFSIZE);
00175 #else
00176                         int nb = hsock->Receive(buf, BUFSIZE);
00177 #endif
00178                         data_waiting -= nb;
00179                 }
00180                 // there's data and we got it- process it
00181                 receive_info();
00182     }
00183 
00184         // do selected emulation
00185         if (lastUpdate != 0.0) {
00186                 // time diff since last update (seconds that passed)
00187                 double timeDiff = timer.GetTime() - lastUpdate;
00188 
00189                 if (joystickEmulation == Joystick::no_emulation) {
00190                         // NO_EMULATION: save the activation values
00191                         num_active = joydata->num_buttons + joydata->num_axes;    // calculate from number of arguments seen
00192                         for (i = 0; i < joydata->num_axes; i++) {
00193                                 active[i] = (joydata->axes[i] + 1) / 2;     // convert from [-1..1] -> [0..1]
00194                         }
00195                         for (i = 0; i < joydata->num_buttons; i++) {
00196                                 active[i + joydata->num_axes] = (float)joydata->buttons[i];
00197                         }
00198                 }
00199                 else if (joystickEmulation == Joystick::mouse_emulation) {
00200                         // MOUSE_EMULATION
00201                         num_active = joydata->num_buttons;    // calculate from number of arguments seen
00202                         for (i = 0; i < joydata->num_buttons; i++) {
00203                                 active[i] = (float)joydata->buttons[i];
00204                         }
00205 
00206                         if (joydata->num_axes >= 3) {
00207                                 // use axis 0 + 1 for x + y movements
00208                                 pos.x += joydata->axes[0] * scalefactor * timeDiff;
00209                                 pos.y -= joydata->axes[1] * scalefactor * timeDiff;
00210                                 // use axis 2 for z movements
00211                                 pos.z += joydata->axes[2] * scalefactor * timeDiff;
00212                         }
00213                 }
00214                 else if (joystickEmulation == Joystick::enhanced_3d_emulation) {
00215                         // ENHANCED_3D_EMULATION
00216                         num_active = joydata->num_buttons;    // calculate from number of arguments seen
00217                         for (int i = 0; i < joydata->num_buttons; i++) {
00218                                 active[i] = (float)joydata->buttons[i];
00219                         }
00220 
00221                         if (joydata->num_axes >= 4) {
00222                                 // calculate new position
00223                                 Point3D posIncrement = Point3D(0, 0, joydata->axes[1] * scalefactor * timeDiff);
00224                                 pos = pos + m.Xform(posIncrement);
00225 
00226                                 // camera rotation
00227                                 m.EulerMultiply('z', 60.0 * joydata->axes[0] * timeDiff);
00228                                 m.EulerMultiply('x', 60.0 * joydata->axes[2] * timeDiff);
00229                                 m.EulerMultiply('y', 60.0 * joydata->axes[3] * timeDiff);
00230                         }
00231                 }
00232                 else if (joystickEmulation == Joystick::first_person_emulation) {
00233                         // FIRST_PERSON_EMULATION
00234                         num_active = joydata->num_buttons;    // calculate from number of arguments seen
00235                         for (int i = 0; i < joydata->num_buttons; i++) {
00236                                 active[i] = (float)joydata->buttons[i];
00237                         }
00238 
00239                         if (joydata->num_axes >= 4) {
00240                                 // calculate new position
00241                                 Point3D posIncrement = Point3D(0, 0, joydata->axes[1] * scalefactor * timeDiff);
00242                                 pos = pos + m.Xform(posIncrement);
00243                                 posIncrement = Point3D(joydata->axes[0] * scalefactor * timeDiff, 0, 0);
00244                                 pos = pos + m.Xform(posIncrement);
00245 
00246                                 // camera rotation
00247                                 m.EulerMultiply('x', 60.0 * joydata->axes[2] * timeDiff);
00248                                 m.EulerMultiply('y', 60.0 * joydata->axes[3] * timeDiff);
00249                         }
00250                 }
00251                 else if (joystickEmulation == Joystick::pedal_emulation) {
00252                         // PEDAL_EMULATION (CH Products pedal)
00253                         num_active = joydata->num_buttons;    // calculate from number of arguments seen
00254                         for (int i = 0; i < joydata->num_buttons; i++) {
00255                                 active[i] = (float)joydata->buttons[i];
00256                         }
00257                         
00258                         if (joydata->num_axes >= 3) {
00259                                 // calculate new position
00260                                 double zoomMovement = joydata->axes[2];
00261                                 if (zoomMovement >= 0.15) {
00262                                         zoomMovement -= 0.15;
00263                                 }
00264                                 else if (zoomMovement <= -0.15) {
00265                                         zoomMovement += 0.15;
00266                                 }
00267                                 else {
00268                                         zoomMovement = 0.0;
00269                                 }
00270                                 Point3D posIncrement = Point3D(0, 0, -zoomMovement / 2 * scalefactor * timeDiff);
00271                                 pos = pos + m.Xform(posIncrement);
00272 
00273                                 // camera rotation
00274                                 if (joydata->axes[1] >= -0.5) {
00275                                         m.EulerMultiply('x', 20.0 * (joydata->axes[1] + 0.5) / 2 * timeDiff);
00276                                 }
00277                                 else if (joydata->axes[0] >= -0.5) {
00278                                         m.EulerMultiply('x', -20.0 * (joydata->axes[0] + 0.5) / 2 * timeDiff);
00279                                 }
00280                         }
00281                 }
00282                 else if (joystickEmulation == Joystick::button_pedal_emulation) {
00283                         // BUTTON_PEDAL_EMULATION (X-keys pedal)
00284                         num_active = 3;    
00285                         for (int i = 0; i < num_active; i++) {
00286                                 active[i] = (float)joydata->buttons[i];
00287                         }
00288                         
00289                         // button mapping X-keys Pedal:
00290                         // Left=Button0, Center=Button1, Right=Button2
00291                         float zoomMovement = 0;
00292                         if (joydata->buttons[0]) {
00293                                 zoomMovement = -0.7;
00294                         }
00295                         else if (joydata->buttons[2]) {
00296                                 zoomMovement = 0.7;
00297                         }
00298 
00299                         if (zoomMovement != 0) {
00300                                 Point3D posIncrement = Point3D(0, 0, -zoomMovement / 2 * scalefactor * timeDiff);
00301                                 pos = pos + m.Xform(posIncrement);
00302                         }
00303                 }
00304 
00305                 // update timer
00306                 lastUpdate = lastUpdate + timeDiff;
00307         }
00308         else {
00309                 // reset timer
00310                 lastUpdate = timer.GetTime();
00311         }
00312 
00313         // and send the force update
00314     send_force();
00315 }

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