void updateHaptics(void)
{
    // reset clock
    simClock.reset();

    // main haptic simulation loop
    while(simulationRunning)
    {
        // stop the simulation clock
        simClock.stop();

        // read the time increment in seconds
        double timeInterval = simClock.getCurrentTimeSeconds();
        if (timeInterval > 0.001) { timeInterval = 0.001; }

        // restart the simulation clock
        simClock.reset();
        simClock.start();

        // read position from haptic device
        cVector3d pos;
        hapticDevice->getPosition(pos);
        pos.mul(workspaceScaleFactor);
        device->setPos(pos);

        // init temp variable
        cVector3d force;
        force.zero();

        // compute reaction forces
        for (int y=0; y<10; y++)
        {
            for (int x=0; x<10; x++)
            {
               cVector3d nodePos = nodes[x][y]->m_pos;
               cVector3d f = computeForce(pos, deviceRadius, nodePos, radius, stiffness);
               cVector3d tmpfrc = cNegate(f);
               nodes[x][y]->setExternalForce(tmpfrc);
               force.add(f);
            }
        }

        // integrate dynamics
        defWorld->updateDynamics(timeInterval);

        // scale force
        force.mul(deviceForceScale);

        // send forces to haptic device
        hapticDevice->setForce(force);
    }

    // exit haptics thread
    simulationFinished = true;
}
Example #2
0
void updateHaptics(void)
{
	// reset simulation clock
	simClock.reset();
	simClock.start();

    // main haptic simulation loop
    while(simulationRunning)
    {
        // read position from haptic device
        cVector3d pos;
        hapticDevice->getPosition(pos);
        pos.mul(workspaceScaleFactor);
        device->setPos(pos);

        // init temp variable
        cVector3d force;
        force.zero();

        // compute reaction forces
        list<cGELMesh*>::iterator i;

        // model water level
        for(i = defWorld->m_gelMeshes.begin(); i != defWorld->m_gelMeshes.end(); ++i)
        {
            cGELMesh *nextItem = *i;

            if (nextItem->m_useMassParticleModel)
            {
                int numVertices = nextItem->m_gelVertices.size();
                for (int i=0; i<numVertices; i++)
                {
                   cVector3d nodePos = nextItem->m_gelVertices[i].m_massParticle->m_pos;
                   cVector3d force = cVector3d(-0.002 * nodePos.x, -0.002 * nodePos.y, 0.0);
                   if (nodePos.z < level)
                   {
                        double depth = nodePos.z - level;
                        force.add(cVector3d(0,0,-100*depth));
                   }
                   nextItem->m_gelVertices[i].m_massParticle->setExternalForce(force);
                }
            }

            if (nextItem->m_useSkeletonModel)
            {
                list<cGELSkeletonNode*>::iterator i;
                for(i = nextItem->m_nodes.begin(); i != nextItem->m_nodes.end(); ++i)
                {
                    cGELSkeletonNode* node = *i;
                    cVector3d nodePos = node->m_pos;
                    double radius = node->m_radius;
                    cVector3d force = cVector3d(-0.01 * nodePos.x, -0.01 * (nodePos.y), 0.0);
                    if ((nodePos.z-radius) < level)
                    {
                        double depth = (nodePos.z-radius) - level;
                        force.add(cVector3d(0,0,-1.0 * depth));
                        node->m_vel.mul(0.95);
                    }
                    node->setExternalForce(force);
                }
            }
        }


        // compute haptic feedback
		for(i = defWorld->m_gelMeshes.begin(); i != defWorld->m_gelMeshes.end(); ++i)
		{
			cGELMesh *nextItem = *i;

			if (nextItem->m_useMassParticleModel)
			{
				int numVertices = nextItem->m_gelVertices.size();
				for (int i=0; i<numVertices; i++)
				{
				cVector3d nodePos = nextItem->m_gelVertices[i].m_massParticle->m_pos;
				cVector3d f = computeForce(pos, deviceRadius, nodePos, radius, stiffness);
				if (f.lengthsq() > 0)
				{
					cVector3d tmpfrc = cNegate(f);
					nextItem->m_gelVertices[i].m_massParticle->setExternalForce(tmpfrc);
				}
				force.add(cMul(1.0, f));
				}
			}

			if (nextItem->m_useSkeletonModel)
			{
				list<cGELSkeletonNode*>::iterator i;
				for(i = nextItem->m_nodes.begin(); i != nextItem->m_nodes.end(); ++i)
				{
					cGELSkeletonNode* node = *i;
					cVector3d nodePos = node->m_pos;
					double radius = node->m_radius;
					cVector3d f = computeForce(pos, deviceRadius, nodePos, radius, stiffness);
					if (f.lengthsq() > 0)
					{
						cVector3d tmpfrc = cNegate(f);
						node->setExternalForce(tmpfrc);
					}
					force.add(cMul(4.0, f));
				}
			}
		}

        // integrate dynamics
		double interval = simClock.stop();
		simClock.reset();
		simClock.start();

        if (interval > 0.001) { interval = 0.001; }
        defWorld->updateDynamics(interval);

        // scale force
        force.mul(0.6 * deviceForceScale);

        // water viscosity
        if ((pos.z - deviceRadius) < level)
        {
            // read damping properties of haptic device
            cHapticDeviceInfo info = hapticDevice->getSpecifications();
            double Kv = 0.8 * info.m_maxLinearDamping;

            // read device velocity
            cVector3d linearVelocity;
            hapticDevice->getLinearVelocity(linearVelocity);

            // compute a scale factor [0,1] proportional to percentage
            // of tool volume immersed in the water
            double val = (level - (pos.z - deviceRadius)) / (2.0 * deviceRadius);
            double scale = cClamp(val, 0.1, 1.0);

            // compute force
            cVector3d forceDamping = cMul(-Kv * scale, linearVelocity);
            force.add(forceDamping);
        }

        // send forces to haptic device
        hapticDevice->setForce(force);
    }

    // exit haptics thread
    simulationFinished = true;
}
Example #3
0
void updateHaptics(void)
{
    // simulation clock
    cPrecisionClock simClock;
    simClock.start(true);

    // reset haptics activation clock
    startHapticsClock.reset();
	startHapticsClock.start();
	bool hapticsReady = false;

    // main haptic simulation loop
    while(simulationRunning)
    {
        // wait for some time before enabling haptics
		if (!hapticsReady)
		{
			if (startHapticsClock.getCurrentTimeSeconds() > 3.0)
			{
				hapticsReady = true;
			}
		}

        // compute global reference frames for each object
        world->computeGlobalPositions(true);

        // update position and orientation of tool
        tool->updatePose();

        // compute interaction forces
        tool->computeInteractionForces();

        // check if the tool is touching an object
        cGenericObject* object = tool->m_proxyPointForceModel->m_contactPoint0->m_object;

        // read user switch status
        bool userSwitch = tool->getUserSwitch(0);

        // if the tool is currently grasping an object we simply update the interaction grasp force
        // between the tool and the object (modeled by a virtual spring)
        if (graspActive && userSwitch)
        {
            // retrieve latest position and orientation of grasped ODE object in world coordinates
            cMatrix3d globalGraspObjectRot = graspObject->getGlobalRot();
            cVector3d globalGraspObjectPos = graspObject->getGlobalPos();

            // compute the position of the grasp point on object in global coordinates
            cVector3d globalGraspPos = globalGraspObjectPos + cMul(globalGraspObjectRot, graspPos);

            // retrieve the position of the tool in global coordinates
            cVector3d globalToolPos  = tool->getProxyGlobalPos();

            // compute the offset between the tool and grasp point on the object
            cVector3d offset = globalToolPos - globalGraspPos;

            // model a spring between both points
            double STIFFNESS = 4;
            cVector3d force = STIFFNESS * offset;

            // apply attraction force (grasp) onto object
            graspObject->addGlobalForceAtGlobalPos(force, globalGraspPos);

            // scale magnitude and apply opposite force to haptic device
            tool->m_lastComputedGlobalForce.add(cMul(-1.0, force));

            // update both end points of the line which is used for display purposes only
            graspLine->m_pointA = globalGraspPos;
            graspLine->m_pointB = globalToolPos;
        }

        // the user is not or no longer currently grasping the object
        else
        {
            // was the user grasping the object at the previous simulation loop
            if (graspActive)
            {
                // we disable grasping
                graspActive = false;

                // we hide the virtual line between the tool and the grasp point
                graspLine->setShowEnabled(false);

                // we enable haptics interaction between the tool and the previously grasped object
                if (graspObject != NULL)
                {
                    graspObject->m_imageModel->setHapticEnabled(true, true);
                }
            }

            // the user is touching an object
            if (object != NULL)
            {
                // check if object is attached to an external ODE parent
                cGenericType* externalParent = object->getExternalParent();
                cODEGenericBody* ODEobject = dynamic_cast<cODEGenericBody*>(externalParent);
                if (ODEobject != NULL)
                {
                    // get position of tool
                    cVector3d pos = tool->m_proxyPointForceModel->m_contactPoint0->m_globalPos;

                    // check if user has enabled the user switch to gras the object
                    if (userSwitch)
                    {
                        // a new object is being grasped
                        graspObject = ODEobject;

                        // retrieve the grasp position on the object in local coordinates
                        graspPos    = tool->m_proxyPointForceModel->m_contactPoint0->m_localPos;

                        // grasp in now active!
                        graspActive = true;

                        // enable small line which display the offset between the tool and the grasp point
                        graspLine->setShowEnabled(true);

                        // disable haptic interaction between the tool and the grasped device.
                        // this is performed for stability reasons.
                        graspObject->m_imageModel->setHapticEnabled(false, true);
                    }

                    // retrieve the haptic interaction force being applied to the tool
                    cVector3d force = tool->m_lastComputedGlobalForce;

                    // apply haptic force to ODE object
                    cVector3d tmpfrc = cNegate(force);
                    if (hapticsReady)
                    {
                        ODEobject->addGlobalForceAtGlobalPos(tmpfrc, pos);
                    }
                }
            }
        }

        // send forces to device
        tool->applyForces();

        // retrieve simulation time and compute next interval
        double time = simClock.getCurrentTimeSeconds();
        double nextSimInterval = cClamp(time, 0.001, 0.004);

        // reset clock
        simClock.reset();
        simClock.start();

        // update simulation
        ODEWorld->updateDynamics(nextSimInterval);
    }

    // exit haptics thread
    simulationFinished = true;
}
Example #4
0
void updateHaptics(void)
{
    // reset clock
    simClock.reset();

    // main haptic simulation loop
    while(simulationRunning)
    {
        // compute global reference frames for each object
        world->computeGlobalPositions(true);

        // update position and orientation of tool
        tool->updatePose();

        // compute interaction forces
        tool->computeInteractionForces();

        // send forces to device
        tool->applyForces();

        // stop the simulation clock
        simClock.stop();

        // read the time increment in seconds
        double timeInterval = simClock.getCurrentTimeSeconds();

        // restart the simulation clock
        simClock.reset();
        simClock.start();

        // temp variable to compute rotational acceleration
        cVector3d rotAcc(0,0,0);

        // check if tool is touching an object
        cGenericObject* objectContact = tool->m_proxyPointForceModel->m_contactPoint0->m_object;
        if (objectContact != NULL)
        {
            // retrieve the root of the object mesh
            cGenericObject* obj = objectContact->getSuperParent();

            // get position of cursor in global coordinates
            cVector3d toolPos = tool->m_deviceGlobalPos;

            // get position of object in global coordinates
            cVector3d objectPos = obj->getGlobalPos();

            // compute a vector from the center of mass of the object (point of rotation) to the tool
            cVector3d vObjectCMToTool = cSub(toolPos, objectPos);

            // compute acceleration based on the interaction forces
            // between the tool and the object
            if (vObjectCMToTool.length() > 0.0)
            {
                // get the last force applied to the cursor in global coordinates
                // we negate the result to obtain the opposite force that is applied on the
                // object
                cVector3d toolForce = cNegate(tool->m_lastComputedGlobalForce);

                // compute effective force to take into account the fact the object
                // can only rotate around a its center mass and not translate
                cVector3d effectiveForce = toolForce - cProject(toolForce, vObjectCMToTool);

                // compute the resulting torque
                cVector3d torque = cMul(vObjectCMToTool.length(), cCross( cNormalize(vObjectCMToTool), effectiveForce));

                // update rotational acceleration
                const double OBJECT_INERTIA = 0.4;
                rotAcc = (1.0 / OBJECT_INERTIA) * torque;
            }
        }

        // update rotational velocity
        rotVel.add(timeInterval * rotAcc);

        // set a threshold on the rotational velocity term
        const double ROT_VEL_MAX = 10.0;
        double velMag = rotVel.length();
        if (velMag > ROT_VEL_MAX)
        {
            rotVel.mul(ROT_VEL_MAX / velMag);
        }

        // add some damping too
        const double DAMPING_GAIN = 0.1;
        rotVel.mul(1.0 - DAMPING_GAIN * timeInterval);

        // if user switch is pressed, set velocity to zero
        if (tool->getUserSwitch(0) == 1)
        {
            rotVel.zero();
        }

        // compute the next rotation configuration of the object
        if (rotVel.length() > CHAI_SMALL)
        {
            object->rotate(cNormalize(rotVel), timeInterval * rotVel.length());
        }
    }
    
    // exit haptics thread
    simulationFinished = true;
}
Example #5
0
void updateHaptics(void)
{
    double timeV = 0.0;

    cLabel* label = new cLabel();
    cLabel* label2 = new cLabel();
    rootLabels->addChild(label);
    rootLabels->addChild(label2);
    label->setPos(0, 0, 0);
    label2->setPos(0, -20, 0);
    label->m_fontColor.set(1.0, 1.0, 1.0);
    label2->m_fontColor.set(1.0, 1.0, 1.0);

    // main haptic simulation loop
    while(simulationRunning)
    {
        float deltaTime = pClock.getCurrentTimeSeconds() - lastTime;
        lastTime = pClock.getCurrentTimeSeconds();

        cVector3d equilibrium (0.0, 0.0, 0.0);
        cVector3d pos0 (0.0, 0.0, 0.0), pos1 (0.0, 0.0, 0.0);

        // for each device
        int i=0;
        while (i < numHapticDevices)
        {
            // read position of haptic device
            cVector3d newPosition;
            hapticDevices[i]->getPosition(newPosition);
            newPosition = deviceToWorld(newPosition, i);

            ((i == 0)? pos0 : pos1) = newPosition;

            // read orientation of haptic device
            cMatrix3d newRotation;
            hapticDevices[i]->getRotation(newRotation);

            // update position and orientation of cursor
            cursors[i]->setPos(newPosition);
            cursors[i]->setRot(newRotation);

            // read linear velocity from device
            cVector3d linearVelocity;
            hapticDevices[i]->getLinearVelocity(linearVelocity);

            // update arrow
//            velocityVectors[i]->m_pointA = newPosition;
//            velocityVectors[i]->m_pointB = cAdd(newPosition, linearVelocity);

            // read user button status
            bool buttonStatus;
            hapticDevices[i]->getUserSwitch(0, buttonStatus);

            // adjustthe  color of the cursor according to the status of
            // the user switch (ON = TRUE / OFF = FALSE)
            if (i == 0)
                cursors[i]->m_material = matCursor2;
            else
                cursors[i]->m_material = matCursor1;

            // increment counter
            i++;
        }

        double f0, f1;
        f0 = pos0.length();
        f1 = pos1.length();

        f0 = f0/(f0 + f1);
        f1 = 1.0 - f0;

        equilibrium = pos1 + (pos0 - pos1)*f0;

        // Update the position of the sun
        cVector3d dir = pos1 - pos0;
        double dist = dir.length();
        dir.normalize();

        double vibrationSpeed = 20.0;
        double vibrationAmount = 0.02;

        //sun->setPos(sun->getPos()*(1.0 - deltaTime*speed) + equilibrium*(deltaTime*speed));
        //timeV += deltaTime*vibrationSpeed*(0.7 - cAbs(f0 - 0.5)*2.0);
        sun->setPos(equilibrium /*+ vibrationAmount*dir*cSinRad(timeV)*/);

        // Update logic
        if (!calibrationFinished) {
            label->m_string = "Calibrating, please move the haptic devices around in order to determine their limitations in movement.";
            label2->m_string = "Press 'c' to finish calibration.";

            if (sun->getPos().x < min.x)
                min.x = sun->getPos().x;
            if (sun->getPos().y < min.y)
                min.y = sun->getPos().y;
            if (sun->getPos().z < min.z)
                min.z = sun->getPos().z;

            if (sun->getPos().x > max.x)
                max.x = sun->getPos().x;
            if (sun->getPos().y > max.y)
                max.y = sun->getPos().y;
            if (sun->getPos().z > max.z)
                max.z = sun->getPos().z;
        } else if (logic->isReady()) {
            if (logic->gameIsOver() && !scoreDisplayed) {
                std::stringstream strs;
                strs << logic->playTime();
                std::string playString = strs.str();

                // define its position, color and string message
                label->m_string = "Congratulation! Your Time: " + playString;
                label2->m_string = "Press 'r' to restart!";

                for (i = 0; i < numHapticDevices; i++) {
                    cVector3d zero(0.0, 0.0, 0.0);
                    hapticDevices[i]->setForce(zero);
                }

                scoreDisplayed = true;
            } else if (!scoreDisplayed) {
                label->m_string = "";
                label2->m_string = "";

                logic->update(deltaTime);

            }

            for (i = 0; i < numHapticDevices; i++) {
                // compute a reaction force
                cVector3d newForce (0,0,0);

                cVector3d devicePosition;
                hapticDevices[i]->getPosition(devicePosition);
                devicePosition = deviceToWorld(devicePosition, i);

                double k = 0.4;
                if (test == 1) k = 0.3;
                double dist = (devicePosition - sun->getPos()).length();
                //dist=dist-0.1;

                newForce = k*(devicePosition - sun->getPos())/(dist*dist*dist);
                //double intensity = (newForce.length())*1.0;
                //newForce.normalize();
                //newForce *= intensity;

    //            newForce = k*(devicePosition - sun->getPos())/(dist*dist*dist);

                if (i == 0) {  // Device on positive X (RIGHT)
                    newForce.x *= -1.0;
                    newForce.y *= -1.0;
                }

                // send computed force to haptic device
    //            bool status = true;
    //            if (hapticDevices[i]->getUserSwitch(0))
    //                printf("button pressed\n");

                // Check if the sphere is in the target area. If so, vibrate
                cVector3d vibrationForce(0.0, 0.0, 0.0);
                if (logic->sphereInTarget() && !logic->gameIsOver()) {
                    Cube* target = logic->getTarget();
                    double dist = target->getPos().distance(sun->getPos());
                    double factor = 1.0 - dist/(target->size/2.0);
                    timeV += deltaTime * (0.5 + factor/2.0);

                    double f = 2*cSinRad(40*timeV);
                    vibrationForce = cVector3d(f, f, f);
                }

                newForce += vibrationForce;
                if (test <= 2 || i == 0)
                    hapticDevices[i]->setForce(newForce);
                else {
                    cVector3d zero;
                    zero.zero();
                    hapticDevices[i]->setForce(zero);
                }
          }
        }
    }
    
    // exit haptics thread
    simulationFinished = true;
}
Example #6
0
int main(int argc, char* argv[])
{
    //-----------------------------------------------------------------------
    // INITIALIZATION
    //-----------------------------------------------------------------------

    printf ("\n");
    printf ("-----------------------------------\n");
    printf ("Be God\n");
    printf ("DH2660 Haptics\n");
    printf ("-----------------------------------\n");
    printf ("\n\n");

    // parse first arg to try and locate resources
    resourceRoot = string(argv[0]).substr(0,string(argv[0]).find_last_of("/\\")+1);

    pClock.start(true);
    lastTime = pClock.getCurrentTimeSeconds();

    //-----------------------------------------------------------------------
    // 3D - SCENEGRAPH
    //-----------------------------------------------------------------------

    // create a new world.
    world = new cWorld();

    // set the background color of the environment
    // the color is defined by its (R,G,B) components.
    world->setBackgroundColor(0.25, 0.55, 0.8);

    // create a camera and insert it into the virtual world
    camera = new cCamera(world);
    world->addChild(camera);

    // position and oriente the camera
    camera->set( cVector3d (-1.0, 0.0, 0.3),    // camera position (eye)
                 cVector3d (0.0, 0.0, 0.0),    // lookat position (target)
                 cVector3d (0.0, 0.0, 1.0));   // direction of the "up" vector

    // set the near and far clipping planes of the camera
    // anything in front/behind these clipping planes will not be rendered
    camera->setClippingPlanes(0.01, 10.0);
    camera->enableMultipassTransparency(true);

    // create a light source and attach it to the camera
    light = new cLight(world);
    camera->addChild(light);                   // attach light to camera
    light->setEnabled(true);                   // enable light source
    light->setPos(cVector3d( 2.0, 0.5, 1.0));  // position the light source
    light->setDir(cVector3d(-2.0, 0.5, 1.0));  // define the direction of the light beam


    //-----------------------------------------------------------------------
    // HAPTIC DEVICES / TOOLS
    //-----------------------------------------------------------------------

    // create a haptic device handler
    handler = new cHapticDeviceHandler();

    // read the number of haptic devices currently connected to the computer
    numHapticDevices = handler->getNumDevices();

    // Check if two devices are plugged in.
    if(numHapticDevices != 2) {
        std::cout << "Application shut down: Two falcon devices are needed." << std::endl;
        exit(0);
    }

    // create a node on which we will attach small labels that display the
    // position of each haptic device
    rootLabels = new cGenericObject();
    camera->m_front_2Dscene.addChild(rootLabels);

    // create a small label as title
//    cLabel* titleLabel = new cLabel();
//    rootLabels->addChild(titleLabel);

//    // define its position, color and string message
//    titleLabel->setPos(0, 30, 0);
//    titleLabel->m_fontColor.set(1.0, 1.0, 1.0);
//    titleLabel->m_string = "Haptic Device Pos [mm]:";

    // for each available haptic device, create a 3D cursor
    // and a small line to show velocity
    int i = 0;
    while (i < numHapticDevices)
    {
        // get a handle to the next haptic device
        cGenericHapticDevice* newHapticDevice;
        handler->getDevice(newHapticDevice, i);

        // open connection to haptic device
        newHapticDevice->open();

		// initialize haptic device
        newHapticDevice->initialize();

        // store the handle in the haptic device table
        hapticDevices[i] = newHapticDevice;

        // retrieve information about the current haptic device
        cHapticDeviceInfo info = newHapticDevice->getSpecifications();

        // create a cursor by setting its radius
        cShapeSphere* newCursor = new cShapeSphere(0.01);

        // add cursor to the world
        world->addChild(newCursor);

        // add cursor to the cursor table
        cursors[i] = newCursor;

        // create a small line to illustrate velocity
//        cShapeLine* newLine = new cShapeLine(cVector3d(0,0,0), cVector3d(0,0,0));
//        velocityVectors[i] = newLine;

//        // add line to the world
//        world->addChild(newLine);

        // create a string that concatenates the device number and model name.
//        string strID;
//        cStr(strID, i);
//        string strDevice = "#" + strID + " - " +info.m_modelName;

        // attach a small label next to the cursor to indicate device information
//        cLabel* newLabel = new cLabel();
//        newCursor->addChild(newLabel);
//        newLabel->m_string = strDevice;
//        newLabel->setPos(0.00, 0.02, 0.00);
//        newLabel->m_fontColor.set(1.0, 1.0, 1.0);

        // if the device provided orientation sensing (stylus), a reference
        // frame is displayed
        if (info.m_sensedRotation == true)
        {
            // display a reference frame
            newCursor->setShowFrame(true);

            // set the size of the reference frame
            newCursor->setFrameSize(0.05, 0.05);
        }

        // crate a small label to indicate the position of the device
//        cLabel* newPosLabel = new cLabel();
//        rootLabels->addChild(newPosLabel);
//        newPosLabel->setPos(0, -20 * i, 0);
//        newPosLabel->m_fontColor.set(0.6, 0.6, 0.6);
//        labels[i] = newPosLabel;

        // increment counter
        i++;
    }


    // here we define the material properties of the cursor when the
    // user button of the device end-effector is engaged (ON) or released (OFF)

    // a light orange material color
    matCursor1.m_ambient.set(0.5, 0.2, 0.0);
    matCursor1.m_diffuse.set(1.0, 0.5, 0.0);
    matCursor1.m_specular.set(1.0, 1.0, 1.0);

    // a blue material color
    matCursor2.m_ambient.set(0.1, 0.1, 0.4);
    matCursor2.m_diffuse.set(0.3, 0.3, 0.8);
    matCursor2.m_specular.set(1.0, 1.0, 1.0);

    room = new Room(world, 0.5);

    matSun.m_ambient.set(0.4, 0.3, 0.0);
    matSun.m_diffuse.set(1.0, 0.7, 0.0);
    matSun.m_specular.set(1.0, 1.0, 1.0);
    sun = new Sphere(world, 0.05, matSun, -room->getHeight()/2);

    max = cVector3d(-DBL_MAX, -DBL_MAX, -DBL_MAX);
    min = cVector3d(DBL_MAX, DBL_MAX, DBL_MAX);
    logic = new Logic(world, sun);

    //-----------------------------------------------------------------------
    // OPEN GL - WINDOW DISPLAY
    //-----------------------------------------------------------------------

    // initialize GLUT
    glutInit(&argc, argv);

    // retrieve the resolution of the computer display and estimate the position
    // of the GLUT window so that it is located at the center of the screen
    int screenW = glutGet(GLUT_SCREEN_WIDTH);
    int screenH = glutGet(GLUT_SCREEN_HEIGHT);
    int windowPosX = (screenW - WINDOW_SIZE_W) / 2;
    int windowPosY = (screenH - WINDOW_SIZE_H) / 2;

    // initialize the OpenGL GLUT window
    glutInitWindowPosition(windowPosX, windowPosY);
    glutInitWindowSize(WINDOW_SIZE_W, WINDOW_SIZE_H);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    glutCreateWindow(argv[0]);
    glutDisplayFunc(updateGraphics);
    glutKeyboardFunc(keySelect);
    glutReshapeFunc(resizeWindow);
    glutSetWindowTitle("Haptics - BG");

    // create a mouse menu (right button)
    glutCreateMenu(menuSelect);
    glutAddMenuEntry("full screen", OPTION_FULLSCREEN);
    glutAddMenuEntry("window display", OPTION_WINDOWDISPLAY);
    glutAttachMenu(GLUT_RIGHT_BUTTON);


    //-----------------------------------------------------------------------
    // START SIMULATION
    //-----------------------------------------------------------------------

    // simulation in now running
    simulationRunning = true;

    // create a thread which starts the main haptics rendering loop
    cThread* hapticsThread = new cThread();
    hapticsThread->set(updateHaptics, CHAI_THREAD_PRIORITY_HAPTICS);

    // start the main graphics rendering loop
    glutMainLoop();

    // close everything
    close();

    // exit
    return (0);
}
Example #7
0
  /*!
  * \brief Callback for receiving a point cloud.
  *
  * This description is displayed lower in the doxygen as an extended description along with
  * the above brief description.
  */
  void cloudCallback(const sensor_msgs::PointCloud2ConstPtr& input)
  {

//    const std::string& publisher_name = event.getPublisherName();
//    ros::M_string connection_header = event.getConnectionHeader();
//    ros::Time receipt_time = event.getReceiptTime();
//    const std::string topic = connection_header["topic"];

//    const sensor_msgs::PointCloud2& input = event.getMessage();

    std::string topic = "none";

    int cloud_size = input->width*input->height;
    ROS_DEBUG_NAMED("haptics", "Got a cloud on topic %s in frame %s with %d points!",
               topic.c_str(),
               input->header.frame_id.c_str(),
               cloud_size);

    if(cloud_size == 0) return;

    pcl::fromROSMsg(*input, last_cloud_);
    
    if(last_cloud_.header.frame_id.compare("/tool_frame"))
    {
//        ROS_INFO("Transforming cloud with %d points from %s to %s.",
//                 (int)last_cloud_.points.size(), last_cloud_.header.frame_id.c_str(),
//                 "/world");
        if(!tfl_.waitForTransform("/tool_frame", last_cloud_.header.frame_id,
                                  last_cloud_.header.stamp, ros::Duration(2.0)) )
        {
            ROS_ERROR("Couldn't get transform for cloud, returning FAILURE!");
            return;
        }
        pcl_ros::transformPointCloud("/tool_frame", last_cloud_, last_cloud_, tfl_);
    }

    //ROS_INFO("m_shape is %d", m_shape);
    //if(new_object->m_shape == hviz::Haptics_CLOUD)
    {
      boost::mutex::scoped_lock lock(mutex_);
      if(object->m_shape == hviz::Haptics_CLOUD)
        object->createFromCloud(last_cloud_);
    }

    if(!got_first_cloud_){
      got_first_cloud_ = true;
      ROS_INFO("Got first cloud!");
    }

    static bool firstTime = true;
    static int counter = 0;
    static cPrecisionClock pclock;
    float sample_period = 2.0;

    if(firstTime) // start a clock to estimate the rate
    {
        pclock.setTimeoutPeriodSeconds(sample_period);
        pclock.start(true);
        firstTime = false;
    }

    // estimate the refresh rate and publish
    ++counter;
    if (pclock.timeoutOccurred()) {
        pclock.stop();
        float rate = counter/sample_period;
        counter = 0;
        pclock.start(true);
        std_msgs::String msg;
        char status_string[256];
        sprintf(status_string, "Cloud rate: %.3f",
                rate );
        msg.data = status_string;
        pub_status_.publish(msg);
    }

  }
Example #8
0
  /*!
  * \brief The timer callback sends graphical output to rviz.
  *
  * This description is displayed lower in the doxygen as an extended description along with
  * the above brief description.
  */
  void timerCallback()
  {
    if(!tool) return;

    ros::Time time_now = ros::Time::now(); // use single time for all output

    static bool firstTime = true;
    static int counter = 0;
    static cPrecisionClock pclock;

    if(firstTime) // start a clock to estimate the rate
    {
        pclock.setTimeoutPeriodSeconds(1.0);
        pclock.start(true);
        firstTime = false;
    }

    // estimate the refresh rate and publish
    ++counter;
    if (pclock.timeoutOccurred()) {
        pclock.stop();
        graphicRateEstimate = counter;
        counter = 0;
        pclock.start(true);
        std_msgs::String msg;
        char status_string[256];
        sprintf(status_string, "Haptic rate: %.3f Graphics Rate: %.3f",
                rateEstimate, graphicRateEstimate);
        msg.data = status_string;
        pub_status_.publish(msg);
    }

    // Transmit the visualizations of the tool/proxy
    float proxy_radius = config_.tool_radius;
    cVector3d pos =  object->m_interactionProjectedPoint; //tool->getDeviceGlobalPos();
    cVector3d HIP = tool->getDeviceGlobalPos();
    cMatrix3d tool_rotation = tool->m_deviceGlobalRot;

    if(false && device_info.m_sensedRotation)
    {
      object_manipulator::shapes::Mesh mesh;
      mesh.dims = tf::Vector3(0.5, 0.5, 0.5);
      mesh.frame.setRotation(chai_tools::cMatrixToTFQuaternion(tool_rotation));
      mesh.frame.setOrigin(tf::Vector3(pos.x, pos.y, pos.z));
      mesh.header.stamp = time_now;
      mesh.header.frame_id = "/tool_frame";
      mesh.use_embedded_materials = true;
      mesh.mesh_resource = std::string("package://pr2_description/meshes/gripper_v0/gripper_palm.dae");
//      std::string proximal_finger_string("package://pr2_description/meshes/gripper_v0/l_finger.dae");
//      std::string distal_finger_string("package://pr2_description/meshes/gripper_v0/l_finger_tip.dae");
      object_manipulator::drawMesh(pub_marker_, mesh, "gripper", 0, ros::Duration(), object_manipulator::msg::createColorMsg(1.0, 0.3, 0.7, 1.0));
    }
    else
    {
      object_manipulator::shapes::Sphere sphere;
      sphere.dims = tf::Vector3(2*proxy_radius, 2*proxy_radius, 2*proxy_radius);
      sphere.frame = tf::Transform(tf::Quaternion(0,0,0,1), tf::Vector3(pos.x, pos.y, pos.z));
      sphere.header.frame_id = "/tool_frame";
      sphere.header.stamp = time_now;
      object_manipulator::drawSphere(pub_marker_, sphere, "proxy", 0, ros::Duration(), object_manipulator::msg::createColorMsg(1.0, 0.3, 0.7, 1.0));

      //object_manipulator::shapes::Sphere sphere;
      sphere.dims = tf::Vector3(1.9*proxy_radius, 1.9*proxy_radius, 1.9*proxy_radius);
      sphere.frame = tf::Transform(tf::Quaternion(0,0,0,1), tf::Vector3(HIP.x, HIP.y, HIP.z));
      sphere.header.frame_id = "/tool_frame";
      sphere.header.stamp = time_now;
      object_manipulator::drawSphere(pub_marker_, sphere, "HIP", 0, ros::Duration(), object_manipulator::msg::createColorMsg(1.0, 0.0, 0.0, 0.6));
    }


    object_manipulator::shapes::Cylinder box;
    tf::Quaternion quat = chai_tools::cMatrixToTFQuaternion(object->tPlane->getRot());
    box.frame.setRotation(quat);
    box.frame.setOrigin(chai_tools::cVectorToTF(object->tPlane->getPos()) - 0.5*proxy_radius*box.frame.getBasis().getColumn(2));
    box.dims = tf::Vector3(5*proxy_radius, 5*proxy_radius, 0.0015);
    box.header.frame_id = "/tool_frame";
    box.header.stamp = time_now;
    if(object->m_interactionInside){
      object_manipulator::drawCylinder(pub_marker_, box, "tPlane", 0, ros::Duration(), object_manipulator::msg::createColorMsg(0.2, 0.6, 1.0, 0.8), false);
    }
    else
      object_manipulator::drawCylinder(pub_marker_, box, "tPlane", 0, ros::Duration(), object_manipulator::msg::createColorMsg(0.2, 0.6, 1.0, 0.8), true);


    boost::mutex::scoped_lock lock(mutex_);
    if(config_.publish_cloud)
    {
//      if(object->last_normals->points.size() == object->last_points->points.size())
//      {
//        visualization_msgs::Marker marker;
//        marker.header = object->last_points->header;
//        marker.ns = "cloud";
//        marker.id = 0;
//        marker.type = visualization_msgs::Marker::SPHERE_LIST; // CUBE, SPHERE, ARROW, CYLINDER
//        marker.action = false?((int32_t)visualization_msgs::Marker::DELETE):((int32_t)visualization_msgs::Marker::ADD);
//        marker.lifetime = ros::Duration();
//        float scale = object->m_active_radius/2;
//        marker.scale = object_manipulator::msg::createVector3Msg(scale, scale, scale);
//        marker.color = object_manipulator::msg::createColorMsg(0.5, 0.5, 0.5,1.0);

//        float angle = time_now.toSec();
//        angle = config_.light_angle * M_PI/180.0;
//        tf::Vector3 light_source = tf::Vector3(0.1*cos(angle), 0.1*sin(angle), 0.3);
//        object_manipulator::shapes::Sphere sphere;
//        sphere.dims = tf::Vector3(0.02, 0.02, 0.02);
//        sphere.frame = tf::Transform(tf::Quaternion(0,0,0,1), light_source);
//        sphere.header.frame_id = "/tool_frame";
//        sphere.header.stamp = marker.header.stamp;
//        object_manipulator::drawSphere(pub_marker_, sphere, "light", 0, ros::Duration(), object_manipulator::msg::createColorMsg(1.0, 1.0, 1.0, 0.5));



//        for(int i = 0; i < object->last_points->points.size(); i++)
//        {
//          const PointT &pt = object->last_points->points[i];
//          const pcl::Normal &nl = object->last_normals->points[i];
//          tf::Vector3 point = tf::Vector3(pt.x, pt.y, pt.z);
//          tf::Vector3 N_vec = tf::Vector3(nl.normal[0], nl.normal[1], nl.normal[2]).normalized();
//          tf::Vector3 L_vec = (light_source - point).normalized();
//          tf::Vector3 color = fabs(L_vec.dot(N_vec))*tf::Vector3(1.0, 1.0, 1.0) + tf::Vector3(0.2, 0.2, 0.2);
//          //tf::Vector3 color = tf::Vector3(pt.x*pt.x, pt.y*pt.y, 1.0);
//          marker.colors.push_back(object_manipulator::msg::createColorMsg(color.x(), color.y(), color.z(), 1.0));;
//          marker.points.push_back(object_manipulator::msg::createPointMsg(pt.x, pt.y, pt.z));
//        }
//        //ROS_INFO("Publishing marker cloud with %d points!", marker.points.size());
//        pub_marker_.publish(marker);
//      }
      sensor_msgs::PointCloud2 msg;
      pcl::toROSMsg(*(object->last_points), msg);
      msg.header.frame_id = "/tool_frame";
      msg.header.stamp = time_now;
      pub_cloud_.publish(msg);
    }
  }
Example #9
0
void hapticsLoop(void* a_pUserData)
{
    // read the position of the haptic device
    cursor->updatePose();

    // compute forces between the cursor and the environment
    cursor->computeForces();

    // stop the simulation clock
    g_clock.stop();

    // read the time increment in seconds
    double increment = g_clock.getCurrentTime() / 1000000.0;

    // restart the simulation clock
    g_clock.initialize();
    g_clock.start();

    // get position of cursor in global coordinates
    cVector3d cursorPos = cursor->m_deviceGlobalPos;

    // compute velocity of cursor;
    timeCounter = timeCounter + increment;
    if (timeCounter > 0.01)
    {
        cursorVel = (cursorPos - lastCursorPos) / timeCounter;
        lastCursorPos = cursorPos;
        timeCounter = 0;
    }

    // get position of torus in global coordinates
    cVector3d objectPos = object->getGlobalPos();

    // compute the velocity of the sphere at the contact point
    cVector3d contactVel = cVector3d(0.0, 0.0, 0.0);
    if (rotVelocity.length() > CHAI_SMALL)
    {
        cVector3d projection = cProjectPointOnLine(cursorPos, objectPos, rotVelocity);
        cVector3d vpc = cursorPos - projection;
        if (vpc.length() > CHAI_SMALL)
        {
            contactVel = vpc.length() * rotVelocity.length() * cNormalize(cCross(rotVelocity, vpc));
        }
    }

    // get the last force applied to the cursor in global coordinates
    cVector3d cursorForce = cursor->m_lastComputedGlobalForce;

    // compute friction force
    cVector3d friction = -40.0 * cursorForce.length() * cProjectPointOnPlane((cursorVel - contactVel), cVector3d(0.0, 0.0, 0.0), (cursorPos - objectPos));

    // add friction force to cursor
    cursor->m_lastComputedGlobalForce.add(friction);

    // update rotational velocity
    if (friction.length() > CHAI_SMALL)
    {
        rotVelocity.add( cMul(-10.0 * increment, cCross(cSub(cursorPos, objectPos), friction)));
    }

    // add some damping...
    //rotVelocity.mul(1.0 - increment);
    
    // compute the next rotation of the torus
    if (rotVelocity.length() > CHAI_SMALL)
    {
        object->rotate(cNormalize(rotVelocity), increment * rotVelocity.length());
    }

    // send forces to haptic device
    cursor->applyForces();
}