OmniDriver.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/component/controller/OmniDriver.h>
00026 #include <sofa/simulation/common/MechanicalVisitor.h>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <math.h>
00029 #include <iostream>
00030 
00031 //Required by for vfork
00032 #include <sys/types.h>
00033 // #include <unistd.h>
00034 
00035 //event handling
00036 #include <sofa/core/objectmodel/KeypressedEvent.h>
00037 #include <sofa/core/objectmodel/OmniEvent.h>
00038 
00039 //force feedback
00040 #include <sofa/component/controller/NullForceFeedback.h>
00041 #include <sofa/component/controller/EnslavementForceFeedback.h>
00042 
00043 #include <sofa/simulation/common/AnimateBeginEvent.h>
00044 #include <sofa/simulation/common/AnimateEndEvent.h>
00045 
00046 using std::cout;
00047 using std::cerr;
00048 using std::endl;
00049 
00050 //sensable namespace
00051 using namespace sofa::defaulttype;
00052 using namespace sofa::simulation::tree;
00053 
00054 
00055 /*
00056 static DeviceData gServoDeviceData;
00057 static DeviceData deviceData;
00058 static HHD hHD;
00059 bool isInitialized = false;
00060 static HDSchedulerHandle hForceHandle = 0;
00061 static HDSchedulerHandle hStateHandle = 0;
00062 static hduVector3Dd force;
00063 */
00064 
00065 double prevTime;
00066 
00067 namespace sofa
00068 {
00069 
00070 namespace component
00071 {
00072 
00073 namespace controller
00074 {
00075 
00076 using namespace sofa::defaulttype;
00077 using namespace core::componentmodel::behavior;
00078 
00079 //static DeviceData gServoDeviceData;
00080 //static DeviceData deviceData;
00081 //static DeviceData previousData;
00082 static HHD hHD = HD_INVALID_HANDLE ;
00083 static bool isInitialized = false;
00084 static HDSchedulerHandle hStateHandle = HD_INVALID_HANDLE;
00085 
00086 
00087 HDCallbackCode HDCALLBACK stateCallback(void *userData)
00088 {
00089     OmniData* data = static_cast<OmniData*>(userData);
00090     //FIXME : Apparenlty, this callback is run before the mechanical state initialisation. I've found no way to know whether the mechcanical state is initialized or not, so i wait ...
00091     //static int wait = 0;
00092 
00093     if (data->servoDeviceData.stop)
00094     {
00095         return HD_CALLBACK_DONE;
00096     }
00097 
00098     if (!data->servoDeviceData.ready)
00099     {
00100         return HD_CALLBACK_CONTINUE;
00101     }
00102 
00103     HHD hapticHD = hdGetCurrentDevice();
00104     hdBeginFrame(hapticHD);
00105 
00106     //static int renderForce = true;
00107     int nButtons = 0;
00108 
00109     // Retrieve the current button(s).
00110     hdGetIntegerv(HD_CURRENT_BUTTONS, &nButtons);
00111 
00112     data->servoDeviceData.m_buttonState1 = (nButtons & HD_DEVICE_BUTTON_1) ? true : false;
00113     data->servoDeviceData.m_buttonState2 = (nButtons & ~HD_DEVICE_BUTTON_1) ? true : false;
00114 
00115     //hdGetDoublev(HD_CURRENT_POSITION, data->servoDeviceData.m_devicePosition);
00116     // Get the column major transform
00117     HDdouble transform[16];
00118     hdGetDoublev(HD_CURRENT_TRANSFORM, transform);
00119 
00120     // Swap the X and Z axis
00121 
00122     transform[0]  *= 1;//previously was 1
00123     transform[1]  *= 1;//previously was 1
00124     transform[2]  *= 1;//previously was 1
00125 
00126 //  transform[4]  *= -1;
00127 //  transform[5]  *= -1;
00128 //  transform[6]  *= -1;
00129 
00130     transform[8]  *= 1;//previously was 1
00131     transform[9]  *= 1;//previously was 1
00132     transform[10] *= 1;//previously was 1
00133 
00134 /*
00135     data->servoDeviceData.transform[12+0]  *= 1;
00136     data->servoDeviceData.transform[12+1]  *= -1;
00137     data->servoDeviceData.transform[12+2]  *= -1;
00138 */
00139     Mat3x3d mrot;
00140 
00141     Quat rot;
00142     for (int i=0; i<3; i++)
00143         for (int j=0; j<3; j++)
00144             mrot[i][j] = transform[j*4+i];
00145 
00146     mrot = data->rotation * mrot;
00147     data->servoDeviceData.pos = data->translation + data->rotation * (Vec3d(transform[12+0], transform[12+1], transform[12+2]) * data->scale);
00148 
00149     rot.fromMatrix(mrot);
00150     rot.normalize();
00151     
00152     if ((rot[0]*data->servoDeviceData.quat[0]+rot[1]*data->servoDeviceData.quat[1]+rot[2]*data->servoDeviceData.quat[2]+rot[3]*data->servoDeviceData.quat[3]) < 0)
00153         for (int i=0;i<4;i++)
00154             rot[i] *= -1;
00155 
00156     data->servoDeviceData.quat[0] = rot[0];
00157     data->servoDeviceData.quat[1] = rot[1];
00158     data->servoDeviceData.quat[2] = rot[2];
00159     data->servoDeviceData.quat[3] = rot[3];
00160 
00161     //if(data->servoDeviceData.m_buttonState1)
00162     //  renderForce = !renderForce;
00163 
00164     double fx=0.0, fy=0.0, fz=0.0;
00165     if (data->forceFeedback != NULL)
00166         (data->forceFeedback)->computeForce(data->servoDeviceData.pos[0], data->servoDeviceData.pos[1], data->servoDeviceData.pos[2], data->servoDeviceData.quat[0], data->servoDeviceData.quat[1], data->servoDeviceData.quat[2], data->servoDeviceData.quat[3], fx, fy, fz);
00167 
00168 
00169     double currentForce[3];
00170     currentForce[0] = ( data->rotation[0][0] * fx + data->rotation[1][0] * fy + data->rotation[2][0] * fz) * data->forceScale;
00171     currentForce[1] = ( data->rotation[0][1] * fx + data->rotation[1][1] * fy + data->rotation[2][1] * fz) * data->forceScale;
00172     currentForce[2] = ( data->rotation[0][2] * fx + data->rotation[1][2] * fy + data->rotation[2][2] * fz) * data->forceScale;
00173 
00174     if(data->servoDeviceData.m_buttonState1)
00175         hdSetDoublev(HD_CURRENT_FORCE, currentForce);
00176 
00177     ++data->servoDeviceData.nupdates;
00178     hdEndFrame(hapticHD);
00179 
00180 
00181      HDErrorInfo error;
00182     if (HD_DEVICE_ERROR(error = hdGetError()))
00183     {
00184         hduPrintError(stderr, &error, "Error during scheduler callback");
00185         if (hduIsSchedulerError(&error))
00186         {
00187         return HD_CALLBACK_DONE;
00188         }
00189     }
00190 /*
00191     OmniX = data->servoDeviceData.transform[12+0]*0.1;
00192     OmniY = data->servoDeviceData.transform[12+1]*0.1;
00193     OmniZ = data->servoDeviceData.transform[12+2]*0.1;
00194 */
00195 
00196     return HD_CALLBACK_CONTINUE;
00197 }
00198 
00199 void exitHandler()
00200 {
00201     hdStopScheduler();
00202     hdUnschedule(hStateHandle);
00203 /*
00204     if (hHD != HD_INVALID_HANDLE)
00205     {
00206         hdDisableDevice(hHD);
00207         hHD = HD_INVALID_HANDLE;
00208     }
00209 */
00210 }
00211 
00212 
00213 HDCallbackCode HDCALLBACK copyDeviceDataCallback(void *pUserData)
00214 {
00215     OmniData *data = static_cast<OmniData*>(pUserData);
00216     memcpy(&data->deviceData, &data->servoDeviceData, sizeof(DeviceData));
00217     //data->servoDeviceData.quat[0] = data->servoDeviceData.quat[1] = data->servoDeviceData.quat[2] = data->servoDeviceData.quat[3] = 0.0;
00218     data->servoDeviceData.nupdates = 0;
00219     data->servoDeviceData.ready = true;
00220     return HD_CALLBACK_DONE;
00221 }
00222 
00223 HDCallbackCode HDCALLBACK stopCallback(void *pUserData)
00224 {
00225     OmniData *data = static_cast<OmniData*>(pUserData);
00226     data->servoDeviceData.stop = true;
00227     return HD_CALLBACK_DONE;
00228 }
00229 
00233 int initDevice(OmniData* data)
00234 {
00235     if (isInitialized) return 0;
00236     isInitialized = true;
00237     //deviceData.transform[0*4+0] = 1;
00238     //deviceData.transform[1*4+1] = 1;
00239     //deviceData.transform[2*4+2] = 1;
00240     //deviceData.transform[3*4+3] = 1;
00241     data->deviceData.quat[0] = 0;
00242     data->deviceData.quat[1] = 0;
00243     data->deviceData.quat[2] = 0;
00244     data->deviceData.quat[3] = 1;
00245     data->servoDeviceData.quat[0] = 0;
00246     data->servoDeviceData.quat[1] = 0;
00247     data->servoDeviceData.quat[2] = 0;
00248     data->servoDeviceData.quat[3] = 1;
00249     HDErrorInfo error;
00250     // Initialize the device, must be done before attempting to call any hd functions.
00251     if (hHD == HD_INVALID_HANDLE)
00252 {
00253     hHD = hdInitDevice(HD_DEFAULT_DEVICE);
00254     if (HD_DEVICE_ERROR(error = hdGetError())) {
00255         hduPrintError(stderr, &error, "Failed to initialize the device");
00256         return -1;
00257     }
00258     printf("Found device %s\n",hdGetString(HD_DEVICE_MODEL_TYPE));
00259 
00260     hdEnable(HD_FORCE_OUTPUT);
00261     hdEnable(HD_MAX_FORCE_CLAMPING);
00262 
00263     // Start the servo loop scheduler.
00264     hdStartScheduler();
00265     if (HD_DEVICE_ERROR(error = hdGetError())) {
00266         hduPrintError(stderr, &error, "Failed to start the scheduler");
00267         return -1;
00268     }
00269 }
00270 
00271     data->servoDeviceData.ready = false;
00272     data->servoDeviceData.stop = false;
00273     hStateHandle = hdScheduleAsynchronous( stateCallback, data, HD_MAX_SCHEDULER_PRIORITY);
00274 
00275     if (HD_DEVICE_ERROR(error = hdGetError()))
00276     {
00277         hduPrintError(stderr, &error, "Failed to initialize haptic device");
00278         fprintf(stderr, "\nPress any key to quit.\n");
00279         getchar();
00280         exit(-1);
00281     }
00282 
00283     return 0;
00284 }
00285 
00286 
00287 
00288 OmniDriver::OmniDriver() 
00289 : scale(initData(&scale, 0.1, "scale","Default scale applied to the Phantom Coordinates. "))
00290 , forceScale(initData(&forceScale, 1.0, "forceScale","Default forceScale applied to the force feedback. "))
00291 , position(initData(&position, Vec3d(0,0,0), "position","Default position applied to the Phantom Coordinates"))
00292 , orientation(initData(&orientation, Vec3d(0,0,0), "orientation","Default orientation applied to the Phantom Coordinates"))
00293 {
00294     this->f_listening.setValue(true);
00295     data = new OmniData;
00296     data->forceFeedback = new NullForceFeedback();
00297 }
00298 
00299 OmniDriver::~OmniDriver()
00300 {
00301 }
00302 
00303 void OmniDriver::cleanup()
00304 {
00305     std::cout << "OmniDriver::cleanup()" << std::endl;
00306     hdScheduleSynchronous(stopCallback, data, HD_MIN_SCHEDULER_PRIORITY);
00307     //exitHandler();
00308     isInitialized = false;
00309 //    delete forceFeedback;
00310 }
00311 
00312 void OmniDriver::setForceFeedback(ForceFeedback* ff)
00313 {
00314     cout << "change ff" << endl;
00315     if(data->forceFeedback)
00316         delete data->forceFeedback;
00317     data->forceFeedback = ff;
00318 };
00319 
00320 void OmniDriver::init()
00321 {
00322     std::cout << "OmniDriver::init()" << std::endl;
00323     context = dynamic_cast<simulation::tree::GNode *>(this->getContext()); // access to current node
00324     double fx, fy, fz;
00325     data->forceFeedback->computeForce(0,0,0, 0,0,0,1, fx, fy, fz);
00326     //OmniData* data = new OmniData();
00327     data->context = context;
00328     //data->forceFeedback = &forceFeedback;
00329     data->scale = scale.getValue();
00330     data->forceScale = forceScale.getValue();
00331     data->translation = position.getValue();
00332     Vector3 radV = orientation.getValue() * M_PI/180; 
00333     Quaternion q = helper::Quater<double>::createFromRotationVector(radV);
00334     q.toMatrix(data->rotation);
00335     initDevice(data);
00336     std::cout << "OmniDriver::init() done" << std::endl;
00337 }
00338 
00339 void OmniDriver::reinit()
00340 {
00341     init();
00342 }
00343 
00344 void OmniDriver::handleEvent(core::objectmodel::Event *event)
00345 {
00346     if (dynamic_cast<sofa::simulation::AnimateBeginEvent *>(event))
00347     {
00348         //getData(); // copy data->servoDeviceData to gDeviceData
00349     hdScheduleSynchronous(copyDeviceDataCallback, data, HD_MIN_SCHEDULER_PRIORITY);
00350 if (data->deviceData.ready)
00351 {
00352     data->deviceData.quat.normalize();
00353         //cout << "driver is working ! " << data->servoDeviceData.transform[12+0] << endl;
00354         sofa::core::objectmodel::OmniEvent::State omniState = sofa::core::objectmodel::OmniEvent::Button1;
00355 //      sofa::core::objectmodel::OmniEvent omniEvent(omniState, deviceData.transform[12+0]*0.1,
00356 //      deviceData.transform[12+1]*0.1,
00357 //      deviceData.transform[12+2]*0.1);
00358 //std::cout << "omni pos="<<data->deviceData.pos<<" quat="<<data->deviceData.quat<<std::endl;
00359         sofa::core::objectmodel::OmniEvent omniEvent(omniState, data->deviceData.pos, data->deviceData.quat);
00360         
00361         this->getContext()->propagateEvent(&omniEvent);
00362 }
00363     }
00364 }
00365 
00366 int OmniDriverClass = core::RegisterObject("Solver to test compliance computation for new articulated system objects")
00367     .add< OmniDriver >();
00368 
00369 SOFA_DECL_CLASS(OmniDriver)
00370 
00371 
00372 } // namespace controller
00373 
00374 } // namespace component
00375 
00376 } // namespace sofa

Generated on Sun Nov 23 02:50:35 2008 for Sofa by  doxygen 1.5.7.1