00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00032 #include <sys/types.h>
00033
00034
00035
00036 #include <sofa/core/objectmodel/KeypressedEvent.h>
00037 #include <sofa/core/objectmodel/OmniEvent.h>
00038
00039
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
00051 using namespace sofa::defaulttype;
00052 using namespace sofa::simulation::tree;
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
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
00080
00081
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
00091
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
00107 int nButtons = 0;
00108
00109
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
00116
00117 HDdouble transform[16];
00118 hdGetDoublev(HD_CURRENT_TRANSFORM, transform);
00119
00120
00121
00122 transform[0] *= 1;
00123 transform[1] *= 1;
00124 transform[2] *= 1;
00125
00126
00127
00128
00129
00130 transform[8] *= 1;
00131 transform[9] *= 1;
00132 transform[10] *= 1;
00133
00134
00135
00136
00137
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
00162
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
00192
00193
00194
00195
00196 return HD_CALLBACK_CONTINUE;
00197 }
00198
00199 void exitHandler()
00200 {
00201 hdStopScheduler();
00202 hdUnschedule(hStateHandle);
00203
00204
00205
00206
00207
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
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
00238
00239
00240
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
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
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
00308 isInitialized = false;
00309
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());
00324 double fx, fy, fz;
00325 data->forceFeedback->computeForce(0,0,0, 0,0,0,1, fx, fy, fz);
00326
00327 data->context = context;
00328
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
00349 hdScheduleSynchronous(copyDeviceDataCallback, data, HD_MIN_SCHEDULER_PRIORITY);
00350 if (data->deviceData.ready)
00351 {
00352 data->deviceData.quat.normalize();
00353
00354 sofa::core::objectmodel::OmniEvent::State omniState = sofa::core::objectmodel::OmniEvent::Button1;
00355
00356
00357
00358
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 }
00373
00374 }
00375
00376 }