Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
testVirtuoseHapticBox.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Test for Virtuose SDK wrapper.
32  *
33  * Authors:
34  * Nicolò Pedemonte
35  * Firas Abi Farraj
36  *
37  *****************************************************************************/
38 
46 #include <visp3/core/vpTime.h>
47 #include <visp3/robot/vpVirtuose.h>
48 
49 #if defined(VISP_HAVE_VIRTUOSE)
50 
51 void CallBackVirtuose(VirtContext VC, void* ptr)
52 {
53  (void) VC;
54 
55  static bool firstIteration = true;
56  static vpPoseVector localPosition0;
57 
58  vpPoseVector localPosition;
59  vpColVector forceFeedback(6,0);
60  vpColVector finalForce(6,0);
61  vpColVector forceEe(6,0);
62  int force_limit = 15;
63  int force_increase_rate = 500;
64  float cube_size = 0.05f;
65 
66  // Virtual spring to let the user know where the initial position is
67  // Estimated Virtuose handle mass = 0.1;
68  // Estimated Virtuose handle length = 0.23;
69  // In the ee frame: Virtuose Handle as a cylinder for the inertia
70  // Estimated Inertia1 = m*l*l/12
71  // Estimated Inertia2 = m*l*l/2 (rotation w.r.t. e-e z axis)
72  double virtualStiffnessAng = 20;
73  double virtualDamperAng = 0.182; // greater than sqrt 4*Inertia1*virtualStiffnessAng
74  double virtualDamperAng2 = 0.0456; // greater than sqrt 4*Inertia2*virtualStiffnessAng
75 
76  vpColVector xd(3,0);
77  vpColVector yd(3,0);
78  vpColVector zd(3,0);
79  vpColVector xee(3,0);
80  vpColVector zee(3,0);
81  vpColVector xeed(3,0);
82  vpColVector zeed(3,0);
83  vpColVector zYZ(3,0);
84  vpColVector zXZ(3,0);
85  vpColVector xXY(3,0);
87  vpColVector omegad(3,0);
89  vpRotationMatrix Qee;
90  vpPoseVector pee;
91  vpColVector vee(6,0);
92  vpColVector veed(6,0);
93 
94  double alpha;
95 
96  vpColVector torque1(3,0);
97  vpColVector torque2(3,0);
98  vpColVector torque3(3,0);
99 
100  vpVirtuose* p_virtuose=(vpVirtuose*)ptr;
101  localPosition = p_virtuose->getPhysicalPosition();
102 
103  if (firstIteration) {
104  localPosition0 = localPosition;
105  firstIteration = false;
106  }
107 
108  // Position and velocity in of the ee expressed in the base frame
109  pee = localPosition;
110  vee = p_virtuose->getPhysicalVelocity();
111  // Z axis = [pee_x pee_y 0]
112  zd[0] = pee[0];
113  zd[1] = pee[1];
114  zd.normalize();
115  // X axis = [0 0 1]
116  xd[2] = 1;
117  // Y axis from cross product
118  yd = zd.skew(zd)*xd;
119 
120  // Current orientation of the ee frame
121  pee.extract(Qee);
122  pee.extract(tee);
123  // X and Z axis of the ee frame expressed in the base frame
124  xee = Qee.getCol(0);
125  zee = Qee.getCol(2);
126 
127  // Rotation matrix from Desired Frame to Base Frame
128  Qd[0][0] = xd[0];
129  Qd[1][0] = xd[1];
130  Qd[2][0] = xd[2];
131  Qd[0][1] = yd[0];
132  Qd[1][1] = yd[1];
133  Qd[2][1] = yd[2];
134  Qd[0][2] = zd[0];
135  Qd[1][2] = zd[1];
136  Qd[2][2] = zd[2];
137 
138  // X and Z axis of the ee frame expressed in the desired frame
139  xeed = Qd.inverse()*xee;
140  zeed = Qd.inverse()*zee;
141 
142  vpHomogeneousMatrix dMb(tee,Qd);
143  // Velocity twist matrix for expressing velocities in the desired frame
144  vpVelocityTwistMatrix dVMb(dMb.inverse());
145  // Force twist matrix for expressing forces in the base frame
146  vpForceTwistMatrix dFMb(dMb);
147 
148  veed = dVMb * vee;
149 
150  // Angular velocity in the desired frame
151  omegad[0] = veed[3];
152  omegad[1] = veed[4];
153  omegad[2] = veed[5];
154 
155  // Projection of Z axis of the ee frame onto plane YZ (expressed in the desired frame)
156  zYZ[1] = zeed[1];
157  zYZ[2] = zeed[2];
158 
159  // Projection of Z axis of the ee frame onto plane XZ (expressed in the desired frame)
160  zXZ[0] = zeed[0];
161  zXZ[2] = zeed[2];
162 
163  // Hard spring to keep Z axis of the ee frame in the horizontal plane
164  // Spring applied to the angle between the Z axis of the ee frame and its projection in the YZ (horizontal) plane
165  vpColVector rotzYZ(3,0);
166  rotzYZ = zeed.skew(zeed)*zYZ.normalize();
167  vpColVector forceStiff1 = virtualStiffnessAng*rotzYZ;
168  vpColVector forceDamp1= virtualDamperAng*(omegad*rotzYZ.normalize())*rotzYZ.normalize();
169 
170  for (unsigned int i=0; i<3; i++)
171  torque1[i] = forceStiff1[i] - forceDamp1[i];
172 
173  // Hard spring to keep Z axis of the ee frame pointing at the origin
174  // Spring applied to the angle between the Z axis of the ee frame and its projection in the XZ (vertical) plane
175  vpColVector rotzXZ(3,0);
176  rotzXZ = zeed.skew(zeed)*zXZ.normalize();
177  vpColVector forceStiff2 = virtualStiffnessAng*rotzXZ;
178  vpColVector forceDamp2 = virtualDamperAng*(omegad*rotzXZ.normalize())*rotzXZ.normalize();
179 
180  for (unsigned int i=0; i<3; i++)
181  torque2[i] = forceStiff2[i] - forceDamp2[i];
182 
183  // Hard spring for rotation around z axis of the ee
184  xXY[0] = xeed[0];
185  xXY[1] = xeed[1];
186  vpColVector xdd(3,0);
187  xdd[0]=1;
188  vpColVector zdd(3,0);
189  zdd[2]=1;
190  vpColVector rotxXY(3,0);
191  rotxXY = xdd.skew(xdd)*xXY.normalize();
192  alpha = asin(rotxXY[2]);
193 
194  vpColVector forceStiff3 = virtualStiffnessAng*alpha*zdd;
195  vpColVector forceDamp3 = virtualDamperAng2*(omegad*zdd)*zdd;
196  for (unsigned int i=0; i<3; i++)
197  torque3[i] = forceStiff3[i] - forceDamp3[i];
198 
199  for (unsigned int j=0; j<3; j++)
200  forceEe[j+3] = torque1[j] + torque2[j]+torque3[j];
201 
202  forceEe = dFMb * forceEe;
203 
204  // ---------------
205  // Haptic Box
206  // ---------------
207  vpColVector p_min(3,0), p_max(3,0);
208  for (unsigned int i=0; i<3; i++) {
209  p_min[i] = localPosition0[i] - cube_size / 2;
210  p_max[i] = localPosition0[i] + cube_size / 2;
211  }
212 
213  for (int i=0; i < 3; i++) {
214  if ((p_min[i] >= localPosition[i]))
215  {
216  forceFeedback[i] = (p_min[i] - localPosition[i]) * force_increase_rate;
217  if (forceFeedback[i] >= force_limit) forceFeedback[i] = force_limit;
218  }
219  else if ((p_max[i] <= localPosition[i]))
220  {
221  forceFeedback[i] = (p_max[i] - localPosition[i]) * force_increase_rate;
222  if (forceFeedback[i] <= -force_limit) forceFeedback[i] = -force_limit;
223  }
224  else
225  forceFeedback[i] = 0;
226  }
227 
228  for (unsigned int j=0; j<6; j++)
229  finalForce[j] = forceFeedback[j] + forceEe[j];
230 
231  // Set force feedback
232  p_virtuose->setForce(finalForce);
233 
234  return;
235 }
236 
237 int main()
238 {
239  try {
240  vpVirtuose virtuose;
241  virtuose.setIpAddress("localhost#5000");
242  virtuose.setVerbose(true);
243  virtuose.setPowerOn();
244  virtuose.setPeriodicFunction(CallBackVirtuose);
245  virtuose.startPeriodicFunction();
246 
247  int counter = 0;
248  bool swtch = true;
249 
250  while(swtch) {
251  if (counter>=10)
252  {
253  virtuose.stopPeriodicFunction();
254  virtuose.setPowerOff();
255  swtch = false;
256  }
257  counter++;
258  vpTime::sleepMs(1000);
259  }
260  std::cout << "The end" << std::endl;
261  }
262  catch(vpException &e) {
263  std::cout << "Catch an exception: " << e.getStringMessage() << std::endl;
264  }
265 }
266 
267 #else
268 int main()
269 {
270  std::cout << "You should install pthread and/or Virtuose API to use this binary..." << std::endl;
271 }
272 #endif
void startPeriodicFunction()
Definition: vpVirtuose.cpp:974
vpRotationMatrix inverse() const
Implementation of an homogeneous matrix and operations on such kind of matrices.
error that can be emited by ViSP classes.
Definition: vpException.h:73
void setPeriodicFunction(VirtPeriodicFunction CallBackVirt)
Definition: vpVirtuose.cpp:825
vpColVector getCol(const unsigned int j) const
void setForce(const vpColVector &force)
Definition: vpVirtuose.cpp:701
Implementation of a rotation matrix and operations on such kind of matrices.
void extract(vpRotationMatrix &R) const
vpColVector getPhysicalVelocity() const
Definition: vpVirtuose.cpp:432
vpColVector & normalize()
void setPowerOn()
Definition: vpVirtuose.cpp:881
void setPowerOff()
Definition: vpVirtuose.cpp:867
void setVerbose(bool mode)
Definition: vpVirtuose.h:183
VISP_EXPORT void sleepMs(double t)
Definition: vpTime.cpp:266
Implementation of a velocity twist matrix and operations on such kind of matrices.
void setIpAddress(const std::string &ip)
Definition: vpVirtuose.h:169
Implementation of a force/torque twist matrix and operations on such kind of matrices.
void stopPeriodicFunction()
Definition: vpVirtuose.cpp:992
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:93
vpPoseVector getPhysicalPosition() const
Definition: vpVirtuose.cpp:396
const std::string & getStringMessage(void) const
Send a reference (constant) related the error message (can be empty).
Class that consider the case of a translation vector.