Пример #1
0
cVector3d computeForce(const cVector3d& a_cursor,
                       double a_cursorRadius,
                       const cVector3d& a_spherePos,
                       double a_radius,
                       double a_stiffness)
{

    // compute the reaction forces between the tool and the ith sphere.
    cVector3d force;
    force.zero();
    cVector3d vSphereCursor = a_cursor - a_spherePos;

    // check if both objects are intersecting
    if (vSphereCursor.length() < 0.0000001)
    {
        return (force);
    }

    if (vSphereCursor.length() > (a_cursorRadius + a_radius))
    {
        return (force);
    }

    // compute penetration distance between tool and surface of sphere
    double penetrationDistance = (a_cursorRadius + a_radius) - vSphereCursor.length();
    cVector3d forceDirection = cNormalize(vSphereCursor);
    force = cMul( penetrationDistance * a_stiffness, forceDirection);

    // return result
    return (force);
}
//==============================================================================
void cShapeTorus::computeLocalInteraction(const cVector3d& a_toolPos,
        const cVector3d& a_toolVel,
        const unsigned int a_IDN)
{
    cVector3d toolProjection = a_toolPos;
    toolProjection.z(0.0);
    m_interactionNormal.set(0,0,1);

    // search for the nearest point on the torus medial axis
    if (a_toolPos.lengthsq() > C_SMALL)
    {
        cVector3d pointAxisTorus = cMul(m_outerRadius, cNormalize(toolProjection));

        // compute eventual penetration of tool inside the torus
        cVector3d vectTorusTool = cSub(a_toolPos, pointAxisTorus);

        double distance = vectTorusTool.length();

        // normal
        if (distance > 0.0)
        {
            m_interactionNormal = vectTorusTool;
            m_interactionNormal.normalize();
        }

        // tool is located inside the torus
        if ((distance < m_innerRadius) && (distance > 0.001))
        {
            m_interactionInside = true;
        }

        // tool is located outside the torus
        else
        {
            m_interactionInside = false;
        }

        // compute surface point
        double dist = vectTorusTool.length();
        if (dist > 0)
        {
            vectTorusTool.mul(1/dist);
        }
        vectTorusTool.mul(m_innerRadius);
        pointAxisTorus.addr(vectTorusTool, m_interactionPoint);
    }
    else
    {
        m_interactionInside = false;
        m_interactionPoint = a_toolPos;
    }
}
Пример #3
0
//===========================================================================
cVector3d cShapeTorus::computeLocalForce(const cVector3d& a_localPosition)
{
	
    // In the following we compute the reaction forces between the tool and the
    // sphere.
    cVector3d localForce;

    // project pointer on torus plane (z=0)
    cVector3d fingerProjection = a_localPosition;
    fingerProjection.z = 0;
    
    // search for the nearest point on the torus medial axis
    if (a_localPosition.lengthsq() > CHAI_SMALL)
    {
        cVector3d pointAxisTorus = cMul(m_outerRadius, cNormalize(fingerProjection));

        // compute eventual penetration of finger inside the torus
        cVector3d vectTorusFinger = cSub(a_localPosition, pointAxisTorus);

        double distance = vectTorusFinger.length();

        // finger inside torus, compute forces
        if ((distance < m_innerRadius) && (distance > 0.001))
        {
            localForce = cMul((m_innerRadius - distance) * (m_material.getStiffness()), cNormalize(vectTorusFinger));
        }

        // finger is outside torus
        else
        {
            localForce.zero();
        }
    }
    else
    {
        localForce.zero();
    }

    return (localForce);
}
Пример #4
0
void updateHaptics(void)
{
    // reset clock
    cPrecisionClock clock;
    clock.reset();

    // main haptic simulation loop
    while(simulationRunning)
    {
        /////////////////////////////////////////////////////////////////////
        // SIMULATION TIME    
        /////////////////////////////////////////////////////////////////////

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

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

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

        // update frequency counter
        frequencyCounter.signal(1);


        /////////////////////////////////////////////////////////////////////
        // HAPTIC FORCE COMPUTATION
        /////////////////////////////////////////////////////////////////////

        // 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();


        /////////////////////////////////////////////////////////////////////
        // HAPTIC SIMULATION
        /////////////////////////////////////////////////////////////////////

        // get position of cursor in global coordinates
        cVector3d toolPos = tool->getDeviceGlobalPos();

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

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

        // compute angular acceleration based on the interaction forces
        // between the tool and the object
        cVector3d angAcc(0,0,0);
        if (v.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 the effective force that contributes to rotating the object.
            cVector3d force = toolForce - cProject(toolForce, v);

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

            // update rotational acceleration
            const double INERTIA = 0.4;
            angAcc = (1.0 / INERTIA) * torque;
        }

        // update rotational velocity
        angVel.add(timeInterval * angAcc);

        // set a threshold on the rotational velocity term
        const double MAX_ANG_VEL = 10.0;
        double vel = angVel.length();
        if (vel > MAX_ANG_VEL)
        {
            angAcc.mul(MAX_ANG_VEL / vel);
        }

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

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

        // compute the next rotation configuration of the object
        if (angVel.length() > C_SMALL)
        {
            object->rotateAboutGlobalAxisRad(cNormalize(angVel), timeInterval * angVel.length());
        }
    }
    
    // exit haptics thread
    simulationFinished = true;
}
Пример #5
0
//===========================================================================
bool cEffectMagnet::computeForce(const cVector3d& a_toolPos,
                                  const cVector3d& a_toolVel,
                                  const unsigned int& a_toolID,
                                  cVector3d& a_reactionForce)
{
    // compute distance from object to tool
    double distance = cDistance(a_toolPos, m_parent->m_interactionProjectedPoint);

    // get parameters of magnet
    double magnetMaxForce = m_parent->m_material.getMagnetMaxForce();
    double magnetMaxDistance = m_parent->m_material.getMagnetMaxDistance();
    double stiffness = m_parent->m_material.getStiffness();
    double forceMagnitude = 0;

    if ((distance > 0) && (distance < magnetMaxDistance) && (stiffness > 0))
    {
        double limitLinearModel = magnetMaxForce / stiffness;
        cClamp(limitLinearModel, 0.0, 0.5 * distance);

        if (distance < limitLinearModel)
        {
            // apply local linear model near magnet
            forceMagnitude = stiffness * distance;
        }
        else
        {
            // compute quadratic model
            cMatrix3d sys;
            sys.m[0][0] = limitLinearModel * limitLinearModel;
            sys.m[0][1] = limitLinearModel;
            sys.m[0][2] = 1.0;
            sys.m[1][0] = magnetMaxDistance * magnetMaxDistance;
            sys.m[1][1] = magnetMaxDistance;
            sys.m[1][2] = 1.0;
            sys.m[2][0] = 2.0 * limitLinearModel;
            sys.m[2][1] = 1.0;
            sys.m[2][2] = 0.0;
            sys.invert();

            cVector3d param;
            sys.mulr(cVector3d(magnetMaxForce, 0.0, -1.0), param);

            // apply quadratic model
            double val = distance - limitLinearModel;
            forceMagnitude = param.x * val * val + param.y * val + param.z;
        }

        // compute magnetic force
        a_reactionForce = cMul(forceMagnitude, cNormalize(cSub(m_parent->m_interactionProjectedPoint, a_toolPos)));

        // add damping component
        double viscosity = m_parent->m_material.getViscosity();
        cVector3d viscousForce = cMul(-viscosity, a_toolVel);
        a_reactionForce.add(viscousForce);

        return (true);
    }
    else
    {
        // the tool is located outside the magnet zone
        a_reactionForce.zero();
        return (false);
    }
}
Пример #6
0
void updateHaptics(void)
{
    // main haptic simulation loop
    while(simulationRunning)
    {
        // update position and orientation of tool
        tool->updatePose();

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

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

        // if the haptic device does track orientations, we automatically
        // oriente the drill to remain perpendicular to the tooth
        cVector3d pos = tool->m_proxyPointForceModel->getProxyGlobalPosition();
        cMatrix3d rot = tool->m_deviceGlobalRot;

        if (info.m_sensedRotation == false)
        {
            cVector3d pos = tool->m_proxyPointForceModel->getProxyGlobalPosition();
            rot.identity();

             cVector3d vx, vy, vz;
            cVector3d zUp (0,0,1);
            cVector3d yUp (0,1,0);
            vx = pos - tooth->getPos();
            if (vx.length() > 0.001)
            {
                vx.normalize();

                if (cAngle(vx,zUp) > 0.001)
                {
                    vy = cCross(zUp, vx);
                    vy.normalize();
                    vz = cCross(vx, vy);
                    vz.normalize();

                }
                else
                {
                    vy = cCross(yUp, vx);
                    vy.normalize();
                    vz = cCross(vx, vy);
                    vz.normalize();
                }

                rot.setCol(vx, vy, vz);
                drill->setRot(rot);
            }
        }


        int button = tool->getUserSwitch(0);
        if (button == 0)
        {
            lastPosDevice = pos;
            lastRotDevice = rot;
            lastPosObject = tooth->getPos();
            lastRotObject = tooth->getRot();
            lastDeviceObjectPos = cTrans(lastRotDevice) * ((lastPosObject - lastPosDevice) + 0.01*cNormalize(lastPosObject - lastPosDevice));
            lastDeviceObjectRot = cMul(cTrans(lastRotDevice), lastRotObject);
            tooth->setHapticEnabled(true, true);
            tool->setShowEnabled(true, true);
            drill->setShowEnabled(true, true);
        }
        else
        {
            tool->setShowEnabled(false, true);
            drill->setShowEnabled(false, true);
            cMatrix3d rotDevice01 = cMul(cTrans(lastRotDevice), rot);
            cMatrix3d newRot =  cMul(rot, lastDeviceObjectRot);
            cVector3d newPos = cAdd(pos, cMul(rot, lastDeviceObjectPos));
            tooth->setPos(newPos);
            tooth->setRot(newRot);
            world->computeGlobalPositions(true);
            tooth->setHapticEnabled(false, true);
        }

		//-----------------Jake--------------//

		char serialData[50];
		double pos1 = 0;
		double pos2 = 0;
	   
		if (sp->ReadData(serialData, strlen(serialData)) > 0)
		{
			if (sp->parse_num(serialData, pos1))
			{
				Sleep(50);
				if (pos1 > 0.3)
				{
 					pos1 = 0.126*pow(pos1,-1.07);
					pos1 = (pos1+pos1_1+pos1_2)/3;
					//pos1 = (pos1 + pos1_1 + pos1_2 + pos1_3 + pos1_4)/5;
					pos1_5 = pos1_4;
					pos1_4 = pos1_3;
					pos1_3 = pos1_2;
					pos1_2 = pos1_1;
					pos1_1 = pos1;

 					pos2 = 0.126*pow(pos2,-1.07);
					pos2 = (pos2 + pos2_1 + pos2_2 + pos2_3 + pos2_4)/5;
					pos2_5 = pos2_4;
					pos2_4 = pos2_3;
					pos2_3 = pos2_2;
					pos2_2 = pos2_1;
					pos2_1 = pos2;
				}
				else 
				{
					pos1 = previous_pos1;
					pos2 = previous_pos2;
				}

				printf("Received data %f and %f \n", pos1, pos2);
			} else 
			{
				printf("Conversion failed\n");
			}
			
		} else {
			printf("Receive failed\n");
		}

		if (pos_counter > 2)
		{
			double dx1 = pos1 - previous_pos1;
			double dx2 = pos2 - previous_pos2;

			if (abs(dx1) < 0.1)
			{
				overall_pos1 -= dx1*10;
				if (overall_pos1 < -0.1)
				{
					overall_pos1 = -0.1;
				} else if(overall_pos1 > 0)
				{
					overall_pos1 = 0;
				}
			}

			if (abs(dx2) < 0.1)
			{
				overall_pos2 -= dx2;
				if (overall_pos2 < -0.1)
				{
					overall_pos2 = -0.1;
				} else if(overall_pos2 > 0)
				{
					overall_pos2 = 0;
				}
			}
		} else {
			pos_counter++;
		}

		previous_pos1 = pos1;
		previous_pos2 = pos2;

		index_finger->setPos(pos.x - 0.15, pos.y, pos.z + overall_pos1);
		index_finger->setRot(rot);

		index_finger->computeInteractionForces();

		index_finger->updatePose();

		thumb->setPos(pos.x + 0.1, pos.y - 0.15 + overall_pos2, pos.z - 0.05);
		thumb->setRot(rot);

		thumb->computeInteractionForces();

		thumb->updatePose();

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

		std::stringstream torque_str_tmp;

		double torque_temp1 = sqrt(pow(index_finger->m_lastComputedGlobalForce.x,2) + pow(index_finger->m_lastComputedGlobalForce.y,2) + pow(index_finger->m_lastComputedGlobalForce.z,2));
		double torque_temp2 = sqrt(pow(thumb->m_lastComputedGlobalForce.x,2) + pow(thumb->m_lastComputedGlobalForce.y,2) + pow(thumb->m_lastComputedGlobalForce.z,2));

		/*torque_str_tmp << std::setprecision(2) << torque_temp;

		const std::string& torque_to_send = torque_str_tmp.str();

		char to_send[50];
		strcpy(to_send, "T");
		strcat(to_send, torque_to_send.c_str());
		strcat(to_send, ";");
		*/

		char to_send[50];
		if (torque_temp1 > 0 && torque_temp2 > 0)
		{
			strcpy(to_send, "T");
			strcat(to_send, "1/1");
			strcat(to_send, ";");
		} else if (torque_temp1 == 0 && torque_temp2 > 0)
		{
			strcpy(to_send, "T");
			strcat(to_send, "0/1");
			strcat(to_send, ";");
		} else if (torque_temp1 > 0 && torque_temp2 == 0)
		{
			strcpy(to_send, "T");
			strcat(to_send, "1/0");
			strcat(to_send, ";");
		} else 
		{
			strcpy(to_send, "T");
			strcat(to_send, "0/0");
			strcat(to_send, ";");
		}

		if (sp->WriteData(to_send, strlen(to_send)))
		{
			printf("Sent %s\n", to_send);
		} else 
		{
			printf("Force data %s could not be sent\n", to_send);
		}

    }

    // exit haptics thread
    simulationFinished = true;
}
Пример #7
0
void updateHaptics(void)
{
    // main haptic simulation loop
    while(simulationRunning)
    {
        // update position and orientation of tool
        tool->updatePose();

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

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

        // if the haptic device does track orientations, we automatically
        // oriente the drill to remain perpendicular to the tooth
        cVector3d pos = tool->m_proxyPointForceModel->getProxyGlobalPosition();
        cMatrix3d rot = tool->m_deviceGlobalRot;

        if (info.m_sensedRotation == false)
        {
            cVector3d pos = tool->m_proxyPointForceModel->getProxyGlobalPosition();
            rot.identity();

            cVector3d vx, vy, vz;
            cVector3d zUp (0,0,1);
            cVector3d yUp (0,1,0);
            vx = pos - tooth->getPos();
            if (vx.length() > 0.001)
            {
                vx.normalize();

                if (cAngle(vx,zUp) > 0.001)
                {
                    vy = cCross(zUp, vx);
                    vy.normalize();
                    vz = cCross(vx, vy);
                    vz.normalize();

                }
                else
                {
                    vy = cCross(yUp, vx);
                    vy.normalize();
                    vz = cCross(vx, vy);
                    vz.normalize();
                }

                rot.setCol(vx, vy, vz);
                drill->setRot(rot);
            }
        }


        int button = tool->getUserSwitch(0);
        if (button == 0)
        {
            lastPosDevice = pos;
            lastRotDevice = rot;
            lastPosObject = tooth->getPos();
            lastRotObject = tooth->getRot();
            lastDeviceObjectPos = cTrans(lastRotDevice) * ((lastPosObject - lastPosDevice) + 0.01*cNormalize(lastPosObject - lastPosDevice));
            lastDeviceObjectRot = cMul(cTrans(lastRotDevice), lastRotObject);
            tooth->setHapticEnabled(true, true);
            tool->setShowEnabled(true, true);
            drill->setShowEnabled(true, true);
        }
        else
        {
            tool->setShowEnabled(false, true);
            drill->setShowEnabled(false, true);
            cMatrix3d rotDevice01 = cMul(cTrans(lastRotDevice), rot);
            cMatrix3d newRot =  cMul(rot, lastDeviceObjectRot);
            cVector3d newPos = cAdd(pos, cMul(rot, lastDeviceObjectPos));
            tooth->setPos(newPos);
            tooth->setRot(newRot);
            world->computeGlobalPositions(true);
            tooth->setHapticEnabled(false, true);
        }

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

    // exit haptics thread
    simulationFinished = true;
}
Пример #8
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;
}
Пример #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();
}