/*========================================================================== -------------------------------------------------- Program: ESQUI Info and Bugs: {marf,jballesteros}@itccanarias.org url: http://motivando.me -------------------------------------------------- Copyright (c) 2006-2007, Center for Technology in Medicine (CTM), University of Las Palmas de Gran Canaria (ULPGC), Canary Islands, Spain. Copyright (c) 2007-2010, Institute of Technology at CanaryIslands (ITC), Canary Islands, Spain. This software is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==========================================================================*/ #include "vtkIHP.h" #include "vtkObjectFactory.h" #include "vtkMath.h" #include "vtkScenarioObjectCollection.h" #include "vtkScenarioObject.h" #include "vtkTool.h" #include "vtkToolGrasper.h" #include "vtkToolProbe.h" vtkCxxRevisionMacro(vtkIHP, "$Revision: 0.1 $"); vtkStandardNewMacro(vtkIHP); //-------------------------------------------------------------------------- vtkIHP::vtkIHP() { this->InitialPitch = 0; } //-------------------------------------------------------------------------- vtkIHP::~vtkIHP(){ } //-------------------------------------------------------------------------- void vtkIHP::PrintSelf(ostream& os,vtkIndent indent) { this->Superclass::PrintSelf(os,indent); } //-------------------------------------------------------------------------- int vtkIHP::Init() { xiSoftwareVendor("itc_las_palmas"); int connected; bool initialized = false; char *Description = new char[1024]; connected = xiTrocarAcquire(); xiTrocarGetDeviceDescription(0, Description); xiTrocarGetDeviceDescription(1, Description); std::cout << "Waiting for tool initialization\n"; while (!initialized) { this->RetrieveDeviceState(); std::string str; if (!!(this->Trocar0.flags & XI_InitNeedToolOut)) { str += "Take the tool out. "; } if (!!(this->Trocar0.flags & XI_InitNeedLeftIPulse) || !!(this->Trocar0.flags & XI_InitNeedRightIPulse)) { str += "Tilt the trocar. "; } initialized = !!(this->Trocar0.flags & XI_TrocarIsInitialized); if(!initialized) std::cout << str.c_str() << std::endl; } //Set Initial Forces this->Trocar0Force.tipForce[0] = 0; ///< force in Newtons applied to a virtual instrument tip of unit length this->Trocar0Force.tipForce[1] = 0; this->Trocar0Force.tipForce[2] = 0; this->Trocar0Force.rollForce = 0; ///< force applied to rotate the instrument (clockwise Nm). this->Trocar0Force.opening = 0; this->Trocar1Force.tipForce[0] = 0; ///< force in Newtons applied to a virtual instrument tip of unit length this->Trocar1Force.tipForce[1] = 0; this->Trocar1Force.tipForce[2] = 0; this->Trocar1Force.rollForce = 0; ///< force applied to rotate the instrument (clockwise Nm). this->Trocar1Force.opening = 0; std::cout << "Device was successfully initialized.\n"; // Return > 0 if a IHP device was found return connected; } //-------------------------------------------------------------------------- void vtkIHP::Update() { this->UpdateDevice(); //Scenario tools will be updated this->Tools->InitTraversal(); vtkIdType id = 0; while(vtkScenarioObject * o = this->Tools->GetNextObject()) { vtkTool * t = vtkTool::SafeDownCast(o); if(t && t->GetToolType() == vtkTool::Laparoscopy) { vtkToolLaparoscopy * tool = vtkToolLaparoscopy::SafeDownCast(t); //Trocar state float * state = this->GetTrocarState(id); //Trocar's direction angles //Haptic coordinate system differs from VTK system // | Haptic | VTK | // | X | Y | // | Y | Z | // | Z | X | tool->Yaw(this->GetTrocarYaw(id)); tool->Pitch(this->GetTrocarPitch(id)); tool->Roll(this->GetToolRoll(id)); //Tool-in-the-trocar parameters //Set tool's depth tool->SetDepth(20*this->GetToolDepth(id)); if(tool->GetToolModel() == vtkToolLaparoscopy::Grasper){ vtkToolGrasper * grasper = vtkToolGrasper::SafeDownCast(t); //Set tool's opening. grasper->SetOpening(this->GetToolOpening(id)); } //Display tool buttons/pedal state if(this->GetToolButtonState(id)){ std::cout << "Tool("<GetLeftPedalState()){ std::cout << "Tool("<GetRightPedalState()){ std::cout << "Tool("<GetDepth() > 3) { std::cout << "Tool Depth > 3. Force Applied" << std::endl; force[2] = 1; } else force[2] = 0; this->SetToolTipForce(id, force); this->ApplyForce(id); id++; } } // Flush forces to the haptic device this->FlushForces(); } //-------------------------------------------------------------------------- void vtkIHP::Release() { //Clear force from previous executions xiTrocarRelease(); } //-------------------------------------------------------------------------- void vtkIHP::UpdateDevice() { this->RetrieveDeviceState(); } //-------------------------------------------------------------------------- void vtkIHP::RetrieveDeviceState() { //Query Tools' State xiTrocarQueryStates(); xiTrocarGetState(0,&this->Trocar0); xiTrocarGetState(1,&this->Trocar1); } //-------------------------------------------------------------------------- void vtkIHP::SetInitialPitchAngle(float angle) { this->InitialPitch = angle; } //-------------------------------------------------------------------------- float vtkIHP::GetInitialPitchAngle() { return this->InitialPitch; } //-------------------------------------------------------------------------- float *vtkIHP::GetTrocarState(int id) { if(id == 0) { return this->GetLeftTrocarState(); } else { return this->GetRightTrocarState(); } } //-------------------------------------------------------------------------- float *vtkIHP::GetLeftTrocarState() { // 0..2 trocarDir[3]; ///< Unit vector defining the trocar's direction // 3 toolDepth; ///< depth in meters of the tool's insertion (may be negative) // 4 toolRoll; ///< roll around the tool/trocar axis in radians // 5 opening; ///< [0..1] value for opening of instrument handle (or angled optics roll angle) float *data; data = new float[6]; data[0] = this->Trocar0.trocarDir[0]; data[1] = this->Trocar0.trocarDir[1]; data[2] = this->Trocar0.trocarDir[2]; data[3] = this->Trocar0.toolDepth; data[4] = this->Trocar0.toolRoll; data[5] = this->Trocar0.opening; return data; } //-------------------------------------------------------------------------- float *vtkIHP::GetRightTrocarState() { // 0..2 trocarDir[3]; ///< Unit vector defining the trocar's direction // 3 toolDepth; ///< depth in meters of the tool's insertion (may be negative) // 4 toolRoll; ///< roll around the tool/trocar axis in radians // 5 opening; ///< [0..1] value for opening of instrument handle (or angled optics roll angle) float *data; data = new float[6]; data[0] = this->Trocar1.trocarDir[0]; data[1] = this->Trocar1.trocarDir[1]; data[2] = this->Trocar1.trocarDir[2]; data[3] = this->Trocar1.toolDepth; data[4] = this->Trocar1.toolRoll; data[5] = this->Trocar1.opening; return data; } //-------------------------------------------------------------------------- float *vtkIHP::GetTrocarDirection(int id) { if(id == 0) { return this->GetLeftTrocarDirection(); } else { return this->GetRightTrocarDirection(); } } //-------------------------------------------------------------------------- float *vtkIHP::GetLeftTrocarDirection() { // 0..2 trocarDir[3]; ///< Unit vector defining the trocar's direction float *data; data = new float[6]; data[0] = this->Trocar0.trocarDir[0]; data[1] = this->Trocar0.trocarDir[1]; data[2] = this->Trocar0.trocarDir[2]; return data; } //-------------------------------------------------------------------------- float *vtkIHP::GetRightTrocarDirection() { // 0..2 trocarDir[3]; ///< Unit vector defining the trocar's direction float *data; data = new float[6]; data[0] = this->Trocar1.trocarDir[0]; data[1] = this->Trocar1.trocarDir[1]; data[2] = this->Trocar1.trocarDir[2]; return data; } //-------------------------------------------------------------------------- float vtkIHP::GetTrocarYaw(int id) { if(id == 0) { return this->GetLeftTrocarYaw(); } else { return this->GetRightTrocarYaw(); } } //-------------------------------------------------------------------------- float vtkIHP::GetLeftTrocarYaw() { // Yaw angle is obtained from the x unit vector component // Range [-90,90] // Angle in degrees must be translated to VTK coordinate system return -(vtkMath::DegreesFromRadians(acos(this->Trocar0.trocarDir[0]))-90); } //-------------------------------------------------------------------------- float vtkIHP::GetRightTrocarYaw() { // Yaw angle is obtained from the x unit vector component // Range [-90,90] // Angle in degrees must be translated to VTK coordinate system return -(vtkMath::DegreesFromRadians(acos(this->Trocar1.trocarDir[0]))-90); } //-------------------------------------------------------------------------- float vtkIHP::GetTrocarPitch(int id) { if(id == 0) { return this->GetLeftTrocarPitch(); } else { return this->GetRightTrocarPitch(); } } //-------------------------------------------------------------------------- float vtkIHP::GetLeftTrocarPitch() { // Pitch angle is obtained from the y unit vector component // Haptic Range [-90,30] // Angle in degrees must be translated to VTK coordinate system // Range = InitialPitch + [0, -120]. Horizontal plane set as 0 degrees reference float pitch = this->InitialPitch; if (this->Trocar0.trocarDir[2] > 0) { //Haptic Pitch > 0 pitch += vtkMath::DegreesFromRadians(-acos(this->Trocar0.trocarDir[1]))-90; } else { //Haptic Pitch < 0 pitch += vtkMath::DegreesFromRadians(acos(this->Trocar0.trocarDir[1]))-90; } return pitch; } //-------------------------------------------------------------------------- float vtkIHP::GetRightTrocarPitch() { // Pitch angle is obtained from the y unit vector component // Haptic Range [-90,30] // Angle in degrees must be translated to VTK coordinate system // Range = InitialPitch + [0, -120]. Horizontal plane set as 0 degrees reference float pitch = this->InitialPitch; if (this->Trocar0.trocarDir[2] > 0) { //Haptic Pitch > 0 pitch += vtkMath::DegreesFromRadians(-acos(this->Trocar1.trocarDir[1]))-90; } else { //Haptic Pitch < 0 pitch += vtkMath::DegreesFromRadians(acos(this->Trocar1.trocarDir[1]))-90; } return pitch; } //-------------------------------------------------------------------------- float vtkIHP::GetToolDepth(int id) { if(id == 0) { return this->GetLeftToolDepth(); } else { return this->GetRightToolDepth(); } } //-------------------------------------------------------------------------- float vtkIHP::GetLeftToolDepth() { // Depth in meters // Range [-0.04, 0.32] // Return Range [0, 1] -> Correction Factor (K) = 3.57 float K = 3.57; return (this->Trocar0.toolDepth +0.04)*K; } //-------------------------------------------------------------------------- float vtkIHP::GetRightToolDepth() { // Depth in meters // Range [-0.04, 0.32] // Return Range [0, 1] -> Correction Factor (K) = 3.57 float K = 3.57; return (this->Trocar1.toolDepth +0.04)*K; } //-------------------------------------------------------------------------- float vtkIHP::GetToolRoll(int id) { if(id == 0) { return this->GetLeftToolRoll(); } else { return this->GetRightToolRoll(); } } //-------------------------------------------------------------------------- float vtkIHP::GetLeftToolRoll() { // Roll Angle is returned in degrees // Haptic Range [-0.04, 0.32] return - vtkMath::DegreesFromRadians(this->Trocar0.toolRoll); } //-------------------------------------------------------------------------- float vtkIHP::GetRightToolRoll() { // Roll Angle is returned in degrees // Haptic Range [-0.04, 0.32] return - vtkMath::DegreesFromRadians(this->Trocar1.toolRoll); } //-------------------------------------------------------------------------- float vtkIHP::GetToolOpening(int id) { if(id == 0) { return this->GetLeftToolOpening(); } else { return this->GetRightToolOpening(); } } //-------------------------------------------------------------------------- float vtkIHP::GetLeftToolOpening() { // Tool Opening // Range [0,1] return this->Trocar0.opening; } //-------------------------------------------------------------------------- float vtkIHP::GetRightToolOpening() { // Tool Opening // Range [0,1] return this->Trocar1.opening; } //-------------------------------------------------------------------------- int vtkIHP::GetToolButtonState(int id) { if(id == 0) { return this->GetLeftToolButtonState(); } else { return this->GetRightToolButtonState(); } } //-------------------------------------------------------------------------- int vtkIHP::GetLeftToolButtonState(){ return (this->Trocar0.flags & XI_ToolButtonMain); } //-------------------------------------------------------------------------- int vtkIHP::GetRightToolButtonState(){ return (this->Trocar1.flags & XI_ToolButtonMain); } //-------------------------------------------------------------------------- int vtkIHP::GetToolLeftButtonState(int id){ if(id == 0) { return this->GetLeftToolLeftButtonState(); } else { return this->GetRightToolLeftButtonState(); } } //-------------------------------------------------------------------------- int vtkIHP::GetLeftToolLeftButtonState(){ return (this->Trocar0.flags & XI_ToolButtonLeft); } //-------------------------------------------------------------------------- int vtkIHP::GetRightToolLeftButtonState(){ return (this->Trocar1.flags & XI_ToolButtonLeft); } //-------------------------------------------------------------------------- int vtkIHP::GetToolRightButtonState(int id){ if(id == 0) { return this->GetLeftToolRightButtonState(); } else { return this->GetRightToolRightButtonState(); } } //-------------------------------------------------------------------------- int vtkIHP::GetLeftToolRightButtonState(){ return (this->Trocar0.flags & XI_ToolButtonRight); } //-------------------------------------------------------------------------- int vtkIHP::GetRightToolRightButtonState(){ return (this->Trocar1.flags & XI_ToolButtonRight); } //-------------------------------------------------------------------------- int vtkIHP::GetLeftPedalState(){ return (this->GetLeftToolLeftButtonState() || this->GetRightToolLeftButtonState()); } //-------------------------------------------------------------------------- int vtkIHP::GetRightPedalState(){ return (this->GetLeftToolRightButtonState() || this->GetRightToolRightButtonState()); } //-------------------------------------------------------------------------- void vtkIHP::ApplyForce(int id) { XiToolForce trocar; if(id == 0) { trocar = this->Trocar0Force; } else { trocar = this->Trocar1Force; } xiTrocarSetForce(id, &trocar); } //-------------------------------------------------------------------------- void vtkIHP::FlushForces() { xiTrocarFlushForces(); } //-------------------------------------------------------------------------- void vtkIHP::SetToolTipForce(int id, float * tipForce) { if(id == 0) { this->SetLeftToolTipForce(tipForce); } else { this->SetRightToolTipForce(tipForce); } } //-------------------------------------------------------------------------- void vtkIHP::SetLeftToolTipForce(float * tipForce){ this->Trocar0Force.tipForce[0] = tipForce[0]; this->Trocar0Force.tipForce[1] = tipForce[1]; this->Trocar0Force.tipForce[2] = tipForce[2]; } //-------------------------------------------------------------------------- void vtkIHP::SetRightToolTipForce(float * tipForce){ this->Trocar1Force.tipForce[0] = tipForce[0]; this->Trocar1Force.tipForce[1] = tipForce[1]; this->Trocar1Force.tipForce[2] = tipForce[2]; } //-------------------------------------------------------------------------- void vtkIHP::SetToolTipForce(int id, float tipForceX, float tipForceY, float tipForceZ) { if(id == 0) { this->SetLeftToolTipForce(tipForceX, tipForceY, tipForceZ); } else { this->SetRightToolTipForce(tipForceX, tipForceY, tipForceZ); } } //-------------------------------------------------------------------------- void vtkIHP::SetLeftToolTipForce(float tipForceX, float tipForceY, float tipForceZ){ this->Trocar0Force.tipForce[0] = tipForceX; this->Trocar0Force.tipForce[1] = tipForceY; this->Trocar0Force.tipForce[2] = tipForceZ; } //-------------------------------------------------------------------------- void vtkIHP::SetRightToolTipForce(float tipForceX, float tipForceY, float tipForceZ){ this->Trocar1Force.tipForce[0] = tipForceX; this->Trocar1Force.tipForce[1] = tipForceY; this->Trocar1Force.tipForce[2] = tipForceZ; } //-------------------------------------------------------------------------- void vtkIHP::SetToolRollForce(int id, float rollForce){ if(id == 0) { this->SetLeftToolRollForce(rollForce); } else { this->SetRightToolRollForce(rollForce); } } //-------------------------------------------------------------------------- void vtkIHP::SetLeftToolRollForce(float rollForce){ this->Trocar0Force.rollForce = rollForce; } //-------------------------------------------------------------------------- void vtkIHP::SetRightToolRollForce(float rollForce){ this->Trocar1Force.rollForce = rollForce; } //-------------------------------------------------------------------------- void vtkIHP::SetToolOpeningForce(int id, float openingForce) { if(id == 0) { this->SetLeftToolOpeningForce(openingForce); } else { this->SetRightToolOpeningForce(openingForce); } } //-------------------------------------------------------------------------- void vtkIHP::SetLeftToolOpeningForce(float openingForce){ this->Trocar0Force.opening = openingForce; } //-------------------------------------------------------------------------- void vtkIHP::SetRightToolOpeningForce(float openingForce){ this->Trocar0Force.opening = openingForce; } //-------------------------------------------------------------------------- /*void vtkIHP::PrintSelf(ostream & os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); // os << indent << "Name: " << this->Name << endl; // os << indent << "Id: " << this->Id << endl; // os << indent << "Type: " << this->Type << endl; // os << indent << "FileName: " << this->FileName << endl; // os << indent << "PolyData (#points): " << this->PolyData->GetNumberOfPoints() << endl; }*/