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
00026
00027 #include <stdio.h>
00028 #include <assert.h>
00029
00030 #include <sofa/helper/system/gl.h>
00031 #include <sofa/helper/system/glut.h>
00032
00033
00034 #include <HD/hd.h>
00035 #include <HDU/hduVector.h>
00036 #include <HDU/hduError.h>
00037
00038 #include "SensAble.h"
00039
00040 #include <sofa/simulation/tree/GNode.h>
00041 #include <sofa/simulation/common/MechanicalVisitor.h>
00042 #include <sofa/simulation/common/UpdateMappingVisitor.h>
00043 #include <sofa/simulation/common/MechanicalVisitor.h>
00044 #include <sofa/core/objectmodel/KeypressedEvent.h>
00045 #include <sofa/core/objectmodel/KeyreleasedEvent.h>
00046 #include <sofa/core/ObjectFactory.h>
00047
00048 using namespace sofa::defaulttype;
00049 using namespace sofa::simulation::tree;
00050 using namespace sofa::simulation;
00051
00052 SOFA_DECL_CLASS(SensAble)
00053
00054 int SensAbleClass = sofa::core::RegisterObject("Phantom device")
00055 .add< SensAble >();
00056
00058 typedef struct {
00059 int nupdates;
00060 HDboolean m_buttonState1;
00061 HDboolean m_buttonState2;
00062 hduVector3Dd m_devicePosition;
00063 HDErrorInfo m_error;
00064 HDdouble transform[16];
00065 Quat quat;
00066 } DeviceData;
00067
00068 static DeviceData gServoDeviceData;
00069 static DeviceData deviceData;
00070 static HDSchedulerHandle hUpdateHandle = 0;
00071 static HDSchedulerHandle hCallbackHandle = 0;
00072 static HHD hHD;
00073
00074
00075 HDCallbackCode HDCALLBACK SetForceCallback(void *pUserData);
00076 HDErrorInfo error;
00077 static volatile HDboolean bRenderForce = false;
00078 static hduVector3Dd force;
00079 static volatile HDboolean bRenderPivot = false;
00080 static Vec3d devicePivot;
00081
00082
00083 HDCallbackCode HDCALLBACK applyForceCallback(void *pUserData);
00084
00085
00089 HDCallbackCode HDCALLBACK updateDeviceCallback(void * ) {
00090 int nButtons = 0;
00091 hdBeginFrame(hdGetCurrentDevice());
00092
00093 hdGetIntegerv(HD_CURRENT_BUTTONS, &nButtons);
00094
00095
00096 gServoDeviceData.m_buttonState1 = (nButtons & HD_DEVICE_BUTTON_1) ? true : false;
00097 gServoDeviceData.m_buttonState2 = (nButtons & HD_DEVICE_BUTTON_2) ? true : false;
00098
00099
00100
00101 hdGetDoublev(HD_CURRENT_POSITION, gServoDeviceData.m_devicePosition);
00102
00103 hdGetDoublev(HD_CURRENT_TRANSFORM, gServoDeviceData.transform);
00104
00105 gServoDeviceData.m_error = hdGetError();
00106
00107 hdEndFrame(hdGetCurrentDevice());
00108 return HD_CALLBACK_CONTINUE;
00109 }
00110
00114 HDCallbackCode HDCALLBACK copyDeviceDataCallback(void *pUserData) {
00115 DeviceData *pDeviceData = (DeviceData *) pUserData;
00116 if (gServoDeviceData.nupdates > 0)
00117 {
00118 memcpy(pDeviceData, &gServoDeviceData, sizeof(DeviceData));
00119 pDeviceData->quat.normalize();
00120 gServoDeviceData.quat = Quat(0,0,0,0);
00121 gServoDeviceData.nupdates = 0;
00122 }
00123 return HD_CALLBACK_DONE;
00124 }
00125
00126 bool isInitialized = false;
00127
00131 int initDevice() {
00132 if (isInitialized) return 0;
00133 isInitialized = true;
00134 deviceData.transform[0*4+0] = 1;
00135 deviceData.transform[1*4+1] = 1;
00136 deviceData.transform[2*4+2] = 1;
00137 deviceData.transform[3*4+3] = 1;
00138 deviceData.quat[3] = 1;
00139
00140 HDErrorInfo error;
00141
00142 hHD = hdInitDevice(HD_DEFAULT_DEVICE);
00143 if (HD_DEVICE_ERROR(error = hdGetError())) {
00144 hduPrintError(stderr, &error, "Failed to initialize the device");
00145 return -1;
00146 }
00147
00148
00149
00150
00151
00152 hCallbackHandle = hdScheduleAsynchronous( applyForceCallback, 0, HD_MAX_SCHEDULER_PRIORITY);
00153
00154 hdEnable(HD_FORCE_OUTPUT);
00155
00156
00157 hdStartScheduler();
00158 if (HD_DEVICE_ERROR(error = hdGetError())) {
00159 hduPrintError(stderr, &error, "Failed to start the scheduler");
00160 return -1;
00161 }
00162 return 0;
00163 }
00164
00168 int uninitDevice() {
00169 hdStopScheduler();
00170
00171 hdUnschedule(hCallbackHandle);
00172 hdDisableDevice(hHD);
00173 return 0;
00174 }
00175
00179 void getData() {
00180
00181 hdScheduleSynchronous(copyDeviceDataCallback, &deviceData, HD_MIN_SCHEDULER_PRIORITY);
00182 }
00183
00184 SensAble::SensAble()
00185 : scale(initData(&scale, 0.1, "scale","Default scale applied to the Phantom Coordinates. "))
00186 , tipOffset(initData(&tipOffset, -10.0, "tipOffset","tipOffset. [needs information]"))
00187 , xform(initData(&xform, sofa::defaulttype::RigidTypes::Coord(), "xform","Transformation applied to the Phantom coordinates."))
00188 , xform2(initData(&xform2, sofa::defaulttype::RigidTypes::Coord(), "xform2","Additional rotation."))
00189 , pivot(initData(&pivot, sofa::defaulttype::Vec3d(1.75, 4.0, -3.75), "pivot","Constrained point where the tool is pivoting."))
00190 , flip(initData(&flip, true, "flip","Rotate the instrument by 180�"))
00191 , bDraw(initData(&bDraw, true, "draw","Enable drawing of Sensable force state"))
00192 , key1(initData(&key1, '0', "key1","Key event generated when the first button is pressed")), button1State(false)
00193 , key2(initData(&key2, '1', "key2","Key event generated when the second button is pressed")), button2State(false)
00194 {
00195 this->f_listening.setValue(true);
00196
00197 sofa::defaulttype::Quat _rotation;
00198 _rotation = xform.getValue().getOrientation();
00199
00200 _rotation.normalize();
00201 _rotation.toMatrix(mrotation);
00202 std::cout << "Device post transform: scale = " << scale.getValue() <<" rotation = "<<xform.getValue().getOrientation()<<" translation = "<<xform.getValue().getCenter()<<" mrotation = "<<mrotation<<std::endl;
00203 devicePivot = mrotation.multTranspose(pivot.getValue() - xform.getValue().getCenter()) / scale.getValue();
00204 initDevice();
00205
00206 sphereModel = new sofa::component::collision::SphereModel();
00207 double r = 1;
00208 sphereModel->addSphere(Vec3d(0,0,0),r);
00209 }
00210
00211 void SensAble::handleEvent(sofa::core::objectmodel::Event* event)
00212 {
00213 if (sofa::core::objectmodel::KeypressedEvent* ev = dynamic_cast<sofa::core::objectmodel::KeypressedEvent*>(event))
00214 {
00215 switch(ev->getKey())
00216 {
00217 case '7':
00218 case 'f':
00219 bRenderForce = !bRenderForce;
00220 std::cout << "HAPTICS FORCE "<<(bRenderForce?"ENABLED":"DISABLED")<<std::endl;
00221 break;
00222 case '8':
00223 case 'p':
00224 bRenderPivot = !bRenderPivot;
00225 std::cout << "HAPTICS PIVOT "<<(bRenderPivot?"ENABLED":"DISABLED")<<std::endl;
00226 break;
00227 }
00228 }
00229 }
00230
00231 SensAble::~SensAble()
00232 {
00233
00234 }
00235
00236
00237 void SensAble::init()
00238 {
00239 cout << "init called";
00240 rigidModel = dynamic_cast<sofa::component::MechanicalObject<RigidTypes>*>(getContext()->getMechanicalState());
00241 reinit();
00242 }
00243
00244
00245 void SensAble::reinit()
00246 {
00247 sofa::defaulttype::Quat _rotation;
00248 _rotation = xform.getValue().getOrientation();
00249 sofa::defaulttype::Quat _rotation2;
00250 _rotation2 = xform2.getValue().getOrientation();
00251
00252 _rotation.normalize();
00253 _rotation2.normalize();
00254 if (_rotation2[3] != 1)
00255 {
00256 _rotation = _rotation2 * _rotation;
00257 xform.beginEdit()->getOrientation() = _rotation;
00258 xform.endEdit();
00259 xform2.beginEdit()->getOrientation() = sofa::defaulttype::Quat(0,0,0,1);
00260 xform2.endEdit();
00261 }
00262 _rotation.toMatrix(mrotation);
00263 std::cout << "Device post transform: scale = " << scale.getValue() <<" rotation = "<<xform.getValue().getOrientation()<<" translation = "<<xform.getValue().getCenter()<<" mrotation = "<<mrotation<<std::endl;
00264 devicePivot = mrotation.multTranspose(pivot.getValue() - xform.getValue().getCenter()) / scale.getValue();
00265 }
00266
00267 void SensAble::updatePosition(double ) {
00268
00269 Mat3x3d mrot;
00270 deviceData.quat.toMatrix(mrot);
00271
00272 double x = deviceData.transform[12] + mrot[0][2]*tipOffset.getValue();
00273 double y = deviceData.transform[13] + mrot[1][2]*tipOffset.getValue();
00274 double z = deviceData.transform[14] + mrot[2][2]*tipOffset.getValue();
00275 Vec3d pos(x,y,z);
00276 pos *= scale.getValue();
00277 pos = mrotation*pos;
00278 pos += xform.getValue().getCenter();
00279 Quat rot;
00280
00281
00282
00283
00284 mrot = mrotation * mrot;
00285
00286 if (flip.getValue())
00287 {
00288
00289 Mat3x3d mrot2;
00290 mrot2[0][0]=1;
00291 mrot2[1][1]=-1;
00292 mrot2[2][2]=-1;
00293
00294 mrot = mrot * mrot2;
00295 }
00296 rot.fromMatrix(mrot);
00297 Mat3x3d finalrot;
00298 rot.toMatrix(finalrot);
00299
00300
00301
00302 sphereModel->setSphere( 0, pos, 0.5*scale.getValue() );
00303
00304
00305 typedef sofa::core::componentmodel::behavior::BaseMechanicalState::VecId VecId;
00306
00307
00308 if (bRenderForce)
00309 {
00310
00311 Vec3d f = (*sphereModel->getF())[0];
00312 if (rigidModel != NULL)
00313 {
00314 MechanicalComputeForceVisitor(VecId::force()).execute( rigidModel->getContext() );
00315 f += (*rigidModel->getF())[0].getVCenter();
00316 }
00317
00318 currentForce = f * 1.0e-10;
00319
00320 cout << currentForce[0] << " " << currentForce[1] << " " << currentForce[2] << "\n";
00321 }
00322 else
00323 {
00324 currentForce = Vec3d(0,0,0);
00325 }
00326 {
00327
00328
00329
00330
00331
00332 if (bRenderForce)
00333 hdScheduleSynchronous(SetForceCallback, ¤tForce, HD_DEFAULT_SCHEDULER_PRIORITY);
00334 }
00335
00336 (*sphereModel->getF())[0] = Vec3d(0,0,0);
00337 if (rigidModel != NULL)
00338 {
00339 MechanicalResetForceVisitor(VecId::force()).execute( rigidModel->getContext() );
00340 }
00341
00342 if (rigidModel != NULL)
00343 {
00344 RigidTypes::VecCoord& x = *rigidModel->getX();
00345 x[0].getCenter() = pos;
00346 x[0].getOrientation() = rot;
00347 }
00348
00349
00350 sofa::simulation::tree::GNode* node = static_cast<sofa::simulation::tree::GNode*>(this->getContext());
00351 node->execute<sofa::simulation::MechanicalPropagatePositionAndVelocityVisitor>();
00352 node->execute<sofa::simulation::UpdateMappingVisitor>();
00353
00354 while (node->getParent() != NULL)
00355 node = static_cast<sofa::simulation::tree::GNode*>(node->getParent());
00356
00357 bool button1NewState = (deviceData.m_buttonState1!=0);
00358 if (button1NewState != button1State)
00359 {
00360 button1State = button1NewState;
00361 if (button1NewState)
00362 {
00363 sofa::core::objectmodel::KeypressedEvent ev(key1.getValue());
00364 node->propagateEvent(&ev);
00365 }
00366 else
00367 {
00368 sofa::core::objectmodel::KeyreleasedEvent ev(key1.getValue());
00369 node->propagateEvent(&ev);
00370 }
00371 }
00372 bool button2NewState = (deviceData.m_buttonState2!=0);
00373 if (button2NewState != button2State)
00374 {
00375 button2State = button2NewState;
00376 if (button2NewState)
00377 {
00378 sofa::core::objectmodel::KeypressedEvent ev(key2.getValue());
00379 node->propagateEvent(&ev);
00380 }
00381 else
00382 {
00383 sofa::core::objectmodel::KeyreleasedEvent ev(key2.getValue());
00384 node->propagateEvent(&ev);
00385 }
00386 }
00387
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 void SensAble::draw()
00404 {
00405 if (!bDraw.getValue()) return;
00406 getData();
00407 glPushMatrix();
00408 Vec3f c;
00409 if ( deviceData.m_buttonState1 && ! deviceData.m_buttonState2 ) {
00410 c = Vec3f(1,0,1);
00411 } else if ( !deviceData.m_buttonState1 && deviceData.m_buttonState2 ) {
00412 c = Vec3f(0,1,0);
00413 } else if ( deviceData.m_buttonState1 && deviceData.m_buttonState2 ) {
00414 c = Vec3f(1,1,0);
00415 } else {
00416 c = Vec3f(1,1,1);
00417 }
00418 glColor3fv(c.ptr());
00419
00420
00421
00422 double x = deviceData.transform[12];
00423 double y = deviceData.transform[13];
00424 double z = deviceData.transform[14];
00425 Vec3d p = Vec3d(x, y, z);
00426 p *= scale.getValue();
00427 p = mrotation*p;
00428 p += xform.getValue().getCenter();
00429
00430 glEnable(GL_LIGHTING);
00431 glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c.ptr());
00432 glPushMatrix();
00433
00434 glTranslated(p[0],p[1],p[2]);
00435
00436 glPopMatrix();
00437 glDisable(GL_LIGHTING);
00438 if (currentForce.norm()>0.0001)
00439 {
00440 Vec3d f = currentForce;
00441 Vec3d n = f;
00442 n.normalize();
00443 glLineWidth(5);
00444 Vec3d p1,p2;
00445 p1 = (*sphereModel->getX())[0]+n*0.5*scale.getValue();
00446 p2 = (*sphereModel->getX())[0]+n*0.5*scale.getValue()+f*2;
00447 glBegin(GL_LINES);
00448
00449
00450 glEnd();
00451 glLineWidth(1);
00452 }
00453 if ( bRenderPivot) {
00454 Vec3d p0, dir;
00455 p0 = p;
00456 dir[0] = deviceData.transform[8];
00457 dir[1] = deviceData.transform[9];
00458 dir[2] = deviceData.transform[10];
00459 dir = mrotation*dir;
00460 dir.normalize();
00461 Vec3d dp = p0 - pivot.getValue();
00462 dp -= dir * (dot(dir,dp));
00463 glLineWidth(5);
00464 Vec3d p1,p2;
00465 p1 = pivot.getValue();
00466 p2 = pivot.getValue()+dp;
00467 glBegin(GL_LINES);
00468
00469
00470 glEnd();
00471 glLineWidth(1);
00472 }
00473 }
00474
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 HDCallbackCode HDCALLBACK applyForceCallback(void * )
00558 {
00559 static int lastButtons = 0;
00560 int nButtons = 0;
00561 hdBeginFrame(hdGetCurrentDevice());
00562
00563 hdGetIntegerv(HD_CURRENT_BUTTONS, &nButtons);
00564
00565
00566 gServoDeviceData.m_buttonState1 = (nButtons & HD_DEVICE_BUTTON_1) ? true : false;
00567
00568 gServoDeviceData.m_buttonState2 = (nButtons & ~HD_DEVICE_BUTTON_1) ? true : false;
00569
00570
00571
00572 hdGetDoublev(HD_CURRENT_POSITION, gServoDeviceData.m_devicePosition);
00573
00574 hdGetDoublev(HD_CURRENT_TRANSFORM, gServoDeviceData.transform);
00575
00576
00577
00578
00579 gServoDeviceData.transform[0] *= -1;
00580 gServoDeviceData.transform[1] *= -1;
00581 gServoDeviceData.transform[2] *= -1;
00582 gServoDeviceData.transform[8] *= -1;
00583 gServoDeviceData.transform[9] *= -1;
00584 gServoDeviceData.transform[10] *= -1;
00585
00586
00587 Quat rot;
00588 Mat3x3d mrot;
00589 for (int i=0; i<3; i++)
00590 for (int j=0; j<3; j++)
00591 mrot[i][j] = gServoDeviceData.transform[j*4+i];
00592 rot.fromMatrix(mrot);
00593
00594 if ((rot[0]*gServoDeviceData.quat[0]+rot[1]*gServoDeviceData.quat[1]+rot[2]*gServoDeviceData.quat[2]+rot[3]*gServoDeviceData.quat[3]) < 0)
00595 {
00596 for (int i=0;i<4;i++)
00597 rot[i] *= -1;
00598 }
00599
00600 gServoDeviceData.quat[0] += rot[0];
00601 gServoDeviceData.quat[1] += rot[1];
00602 gServoDeviceData.quat[2] += rot[2];
00603 gServoDeviceData.quat[3] += rot[3];
00604
00605
00606
00607
00608
00609 lastButtons = nButtons;
00610
00611 if ( bRenderForce || bRenderPivot ) {
00612 hduVector3Dd f(0,0,0);
00613 if ( bRenderForce) {
00614 f += force;
00615 }
00616 if ( bRenderPivot ) {
00617 Vec3d p0, dir;
00618 p0[0] = gServoDeviceData.transform[12];
00619 p0[1] = gServoDeviceData.transform[13];
00620 p0[2] = gServoDeviceData.transform[14];
00621 dir[0] = gServoDeviceData.transform[8];
00622 dir[1] = gServoDeviceData.transform[9];
00623 dir[2] = gServoDeviceData.transform[10];
00624 dir.normalize();
00625 Vec3d dp = p0 - devicePivot;
00626 dp -= dir * (dot(dir,dp));
00627 dp *= -0.5;
00628 if (dp.norm() > 1) dp*= 1/dp.norm();
00629 f[0] += dp[0];
00630 f[1] += dp[1];
00631 f[2] += dp[2];
00632 }
00633 hdSetDoublev(HD_CURRENT_FORCE, f);
00634
00635 gServoDeviceData.m_error = hdGetError();
00636 if (HD_DEVICE_ERROR(gServoDeviceData.m_error = hdGetError()))
00637 {
00638 if (hduIsForceError(&gServoDeviceData.m_error))
00639 {
00640 bRenderForce = false;
00641 }
00642 else if (hduIsSchedulerError(&gServoDeviceData.m_error))
00643 {
00644 return HD_CALLBACK_DONE;
00645 }
00646 }
00647 }
00648 else
00649 gServoDeviceData.m_error = hdGetError();
00650
00651 ++gServoDeviceData.nupdates;
00652 hdEndFrame(hdGetCurrentDevice());
00653 return HD_CALLBACK_CONTINUE;
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 HDCallbackCode HDCALLBACK SetForceCallback(void *pUserData)
00724 {
00725 Vec3d* pForce = (Vec3d*) pUserData;
00726 force[0] = (*pForce)[0];
00727 force[1] = (*pForce)[1];
00728 force[2] = (*pForce)[2];
00729 return HD_CALLBACK_DONE;
00730 }