UsTK : Ultrasound ToolKit  version 2.0.1 under development (2023-12-07)
usViper850WrapperVelocityControl.cpp
1 #include <visp3/ustk_gui/usViper850WrapperVelocityControl.h>
2 
3 #if defined(USTK_HAVE_VTK_QT) && defined(VISP_HAVE_VIPER850) && defined(VISP_HAVE_MODULE_ROBOT)
4 
6 {
7  m_initialized = false;
8  m_run = false;
9  velocityProbeContact = vpColVector(6, 0);
10 
11  connect(this, SIGNAL(startControlLoop()), this, SLOT(controlLoop()));
12  connect(this, SIGNAL(startControlLoopAutomatic()), this, SLOT(controlLoopAutomatic()));
13 }
14 
16 {
17  if (viper->getPowerState()) {
18  viper->stopMotion();
19  viper->powerOff();
20  }
21 }
22 
24 {
25  try {
26  // create viper object
27  viper = new vpRobotViper850();
28  } catch (...) {
29  std::cout << "Viper robot could not be initialized" << std::endl;
30  emit(robotError());
31  }
32 
33  // Transformation from end-effector frame to the probe contact frame
34  vpHomogeneousMatrix eMp;
35  eMp[0][0] = 0;
36  eMp[1][1] = 0;
37  eMp[2][2] = 0;
38  eMp[0][2] = 1; // Z in force sensor becomes X in the probe control frame
39  eMp[1][0] = 1; // X in force sensor becomes Y in the probe control frame
40  eMp[2][1] = 1; // Y in force sensor becomes Z in the probe control frame
41  eMp[2][3] = 0.2; // tz = 20cm
42 
43  // Build the transformation that allows to convert a velocity in the end-effector frame to the probe contact frame
44  eVp.buildFrom(eMp);
45 
46  startRobot();
47  m_initialized = true;
48 }
49 
50 void usViper850WrapperVelocityControl::startRobot(void)
51 {
52  // Test if Viper is in MANUAL contol mode
53  if (viper->getControlMode() == vpRobotViper850::MANUAL) {
54  // Power On the Viper robot
55  try {
56  viper->powerOn();
57  viper->setRobotState(vpRobot::STATE_VELOCITY_CONTROL);
58  } catch (...) {
59  viper->setRobotState(vpRobot::STATE_STOP);
60  std::cout << "Viper robot could not be initialized" << std::endl;
61  emit(robotError());
62  }
63  } else
64  std::cout << "For security reason, the Viper robot has to be used with the dead man switch)" << std::endl;
65 }
66 
68 {
69  if (m_initialized) {
70  m_run = true;
71  emit(startControlLoop());
72  }
73 }
74 
76 {
77 
78  // stop loop
79  m_run = false;
80 
81  // stop robot
82  viper->setRobotState(vpRobot::STATE_STOP);
83 }
84 
85 void usViper850WrapperVelocityControl::controlLoop()
86 {
87  while (m_run) {
88  // transform the velocity
89  ve = eVp * velocityProbeContact;
90 
91  // Get the robot jacobian eJe
92  try {
93  viper->get_eJe(eJe);
94  q_dot = eJe.pseudoInverse() * ve;
95 
96  // Send the joint velocities to the robot
97  viper->setVelocity(vpRobot::ARTICULAR_FRAME, q_dot);
98  } catch (...) {
99  viper->setRobotState(vpRobot::STATE_STOP);
100  std::cout << "Viper robot could not be initialized" << std::endl;
101  emit(robotError());
102  }
103 
104  // as we are in a loop in a slot, we have to tell to the qapplication to take in account incoming signals and
105  // execute corresponding slots
106  qApp->processEvents();
107  }
108 }
109 
110 void usViper850WrapperVelocityControl::controlLoopAutomatic()
111 {
112  // Transformation from end-effector frame to the force/torque sensor
113  // Note that the end-effector frame is located on the lower part of
114  // male component of the tool changer.
115  vpHomogeneousMatrix eMs;
116  eMs[2][3] = -0.062; // tz = -6.2cm
117 
118  // Transformation from force/torque sensor to the probe frame from where
119  // we want to control the robot
120  vpHomogeneousMatrix sMp;
121 
122  // Transformation from force/torque sensor to the end-effector frame
123  vpHomogeneousMatrix sMe;
124  eMs.inverse(sMe);
125 
126  // Build the transformation that allows to convert a velocity in the
127  // end-effector frame to the FT sensor frame
128  vpVelocityTwistMatrix sVe;
129  sVe.buildFrom(sMe);
130 
131  vpColVector sHs(6); // force/torque sensor measures
132  vpColVector pHp_star(6); // force/torque sensor desired values in probe frame
133  vpColVector gHg(6); // force/torque due to the gravity
134  vpMatrix lambdaProportionnal(6, 6); // gain of proportionnal part of the force controller
135  vpMatrix lambdaDerivate(6, 6); // gain of derivate part of the force controller
136  vpMatrix lambdaIntegral(6, 6); // gain of derivate part of the force controller
137  vpColVector sEs(6, 0); // force/torque error
138  vpColVector sEs_last(6, 0); // force/torque error
139  vpColVector sEs_sum(6, 0); // force/torque sum error
140  // Position of the cog of the object attached after the sensor in the sensor frame
141  vpTranslationVector stg;
142  vpColVector sHs_bias(6); // force/torque sensor measures for bias
143 
144  // Cartesian velocities corresponding to the force/torque control in the
145  // sensor frame
146  vpColVector v_s(6);
147 
149  // Initialized the force gains, for proportionnal component
150  lambdaProportionnal = 0;
151  for (int i = 0; i < 3; i++)
152  lambdaProportionnal[i][i] = 0.015;
153  // Initialized the torque gains, for proportionnal component
154  for (int i = 3; i < 6; i++)
155  lambdaProportionnal[i][i] = 0;
156  // Initialized the force gains, for derivate component
157  lambdaDerivate = 0;
158  for (int i = 0; i < 3; i++)
159  lambdaDerivate[i][i] = 0.09;
160  // Initialized the torque gains, for derivate component
161  for (int i = 3; i < 6; i++)
162  lambdaDerivate[i][i] = 0;
163  // Initialized the force gains, for integral component
164  lambdaIntegral = 0;
165  for (int i = 0; i < 3; i++)
166  lambdaIntegral[i][i] = 0;
167  // Initialized the torque gains, for integral component
168  for (int i = 3; i < 6; i++)
169  lambdaIntegral[i][i] = 0;
170 
171  // Initialize the desired force/torque values
172  pHp_star = 0;
173  pHp_star[1] = 4; // Fy = 4N
174 
175  // Set the probe frame control
176  sMp[0][0] = 0;
177  sMp[1][1] = 0;
178  sMp[2][2] = 0;
179  sMp[0][2] = 1; // Z in force sensor becomes X in the probe control frame
180  sMp[1][0] = 1; // X in force sensor becomes Y in the probe control frame
181  sMp[2][1] = 1; // Y in force sensor becomes Z in the probe control frame
182  sMp[2][3] = 0.262; // tz = 26.2cm
183 
184  // Init the force/torque due to the gravity
185  gHg[2] = -(0.696 + 0.476) * 9.81; // m*g
186 
187  // Position of the cog of the object attached after the sensor in the sensor frame
188  stg[0] = 0;
189  stg[1] = 0;
190  stg[2] = 0.088; // tz = 88.4mm
191 
192  vpRotationMatrix sRp;
193  sMp.extract(sRp);
194  vpTranslationVector stp;
195  sMp.extract(stp);
196 
197  vpHomogeneousMatrix eMp = eMs * sMp;
198  vpVelocityTwistMatrix eVp(eMp);
199 
200  // Get the position of the end-effector in the reference frame
201  vpColVector q;
202  vpHomogeneousMatrix fMe;
203  vpHomogeneousMatrix fMs;
204  vpRotationMatrix sRf;
205  viper->getPosition(vpRobot::ARTICULAR_FRAME, q);
206  viper->get_fMe(q, fMe);
207  // Compute the position of the sensor frame in the reference frame
208  fMs = fMe * eMs;
209  vpHomogeneousMatrix sMf;
210  fMs.inverse(sMf);
211  sMf.extract(sRf);
212 
213  // Build the transformation that allows to convert the forces due to the
214  // gravity in the sensor frame
215  vpForceTwistMatrix sFg(sMf); // Only the rotation part is to consider
216  // Modify the translational part
217  for (int i = 0; i < 3; i++)
218  for (int j = 0; j < 3; j++)
219  sFg[i + 3][j] = (stg.skew() * sRf)[i][j];
220 
221  // Build the transformation that allows to convert a FT expressed in the
222  // FT probe frame into the sensor frame
223  vpForceTwistMatrix sFp(sMp);
224 
225  // Bias the force/torque sensor
226  viper->biasForceTorqueSensor();
227 
228  // Set the robot to velocity control
229  viper->setRobotState(vpRobot::STATE_VELOCITY_CONTROL);
230 
231  unsigned int iter = 0;
232 
233  // signal filtering
234  unsigned int bufferSize = 80;
235  double signalBuffer[bufferSize];
236  for (unsigned int i = 0; i < bufferSize; i++)
237  signalBuffer[i] = 0;
238 
239  double t0 = vpTime::measureTimeMs();
240  double deltaTmilliseconds = 1; // 1ms for each loop cycle
241 
242  while (m_run) {
243  try {
244  t0 = vpTime::measureTimeMs();
245 
246  // Get the force/torque measures from the sensor
247  sHs = viper->getForceTorque();
248 
249  // Multiply the measures by -1 to get the force/torque exerced by the
250  // robot to the environment.
251  sHs *= -1;
252 
253  // Update the gravity transformation matrix
254  viper->getPosition(vpRobot::ARTICULAR_FRAME, q);
255  viper->get_fMe(q, fMe);
256  // Compute the position of the sensor frame in the reference frame
257  fMs = fMe * eMs;
258  // Compute the inverse transformation
259  fMs.inverse(sMf);
260  sMf.extract(sRf);
261  // Update the transformation that allows to convert the forces due to the
262  // gravity in the sensor frame
263  sFg.buildFrom(sMf); // Only the rotation part is to consider
264  // Modify the translational part
265  for (int i = 0; i < 3; i++)
266  for (int j = 0; j < 3; j++)
267  sFg[i + 3][j] = (stg.skew() * sRf)[i][j];
268 
269  if (iter == 0) {
270  sHs_bias = sHs - sFg * gHg;
271  }
272 
273  // save last error for derivate part of the controller
274  sEs_last = sEs;
275 
276  // Compute the force/torque error in the sensor frame
277  sEs = sFp * pHp_star - (sHs - sFg * gHg - sHs_bias);
278 
279  // fill filtering buffer
280  signalBuffer[iter % bufferSize] = sEs[2];
281 
282  // filter
283  double sum = 0;
284  unsigned int realBufferSize = iter + 1 < bufferSize ? iter + 1 : bufferSize;
285  for (unsigned int i = 0; i < realBufferSize; i++) {
286  sum += signalBuffer[i];
287  }
288  sEs[2] = sum / realBufferSize;
289 
290  sEs_sum += sEs;
291 
292  // to avoid hudge derivate error at first iteration, we set the derivate error to 0
293  if (iter == 0) {
294  sEs_last = sEs;
295  }
296 
297  // Compute the force/torque control law in the sensor frame (propotionnal + derivate controller)
298  v_s = lambdaProportionnal * sEs + lambdaDerivate * (sEs - sEs_last) + lambdaIntegral * sEs_sum;
299 
300  // set other speeds
301  v_s[0] = 0.0;
302  v_s[1] = 0.0;
303  v_s[3] = 0.0;
304  v_s[4] = 0.0;
305  v_s[5] = 0.0;
306 
307  vpVelocityTwistMatrix eVs;
308  sVe.inverse(eVs);
309 
310  vpColVector v_e = velocityProbeContact;
311  v_e[1] = 0.0;
312 
313  ve = eVs * v_s + this->eVp * v_e;
314 
315  // Get the robot jacobian eJe
316  viper->get_eJe(eJe);
317 
318  // Compute the joint velocities to achieve the force/torque control
319  q_dot = eJe.pseudoInverse() * ve;
320 
321  // Send the joint velocities to the robot
322  viper->setVelocity(vpRobot::ARTICULAR_FRAME, q_dot);
323  iter++;
324 
325  } catch (...) {
326  viper->setRobotState(vpRobot::STATE_STOP);
327  std::cout << "Viper robot could not be initialized" << std::endl;
328  emit(robotError());
329  }
330 
331  // as we are in a loop in a slot, we have to tell to the qapplication to take in account incoming signals and
332  // execute corresponding slots
333  qApp->processEvents();
334  vpTime::wait(t0, deltaTmilliseconds);
335  }
336 }
337 
343 {
344  velocityProbeContact[0] = (double)xVelocity / 1000.0;
345 }
346 
352 {
353  velocityProbeContact[1] = (double)yVelocity / 1000.0;
354 }
355 
361 {
362  velocityProbeContact[2] = (double)zVelocity / 1000.0;
363 }
364 
370 {
371  velocityProbeContact[3] = vpMath::rad((double)xAngularVelocity / 10.0);
372 }
373 
379 {
380  velocityProbeContact[4] = vpMath::rad((double)yAngularVelocity / 10.0);
381 }
382 
388 {
389  velocityProbeContact[5] = vpMath::rad((double)zAngularVelocity / 10.0);
390 }
391 
393 {
394 
395  m_run = false; // stop the running loop
396 
397  // reset velocities vector to zero
398  for (unsigned int i = 0; i < velocityProbeContact.size(); i++)
399  velocityProbeContact[i] = 0;
400 
401  if (!viper->getPowerState())
402  startRobot();
403 
404  m_run = true;
406 }
407 
409 {
410  m_run = false; // stop the running loop
411 
412  // reset velocities vector to zero
413  for (unsigned int i = 0; i < velocityProbeContact.size(); i++)
414  velocityProbeContact[i] = 0;
415 
416  m_run = true;
417  emit(startControlLoop()); // go back to manual mode
418 }
419 
420 void usViper850WrapperVelocityControl::moveLeft() { velocityProbeContact[0] = 0.01; }
421 
422 void usViper850WrapperVelocityControl::moveRight() { velocityProbeContact[0] = -0.01; }
423 
424 void usViper850WrapperVelocityControl::stopMoveLateral() { velocityProbeContact[0] = 0; }
425 #endif
void setZVelocity(int zVelocity)
Set the linear velocity along z axis in 4DC7 probe contact frame.
void setXVelocity(int xVelocity)
Set the linear velocity along x axis in 4DC7 probe contact frame.
void setYVelocity(int yVelocity)
Set the linear velocity along y axis in 4DC7 probe contact frame.
void setXAngularVelocity(int xAngularVelocity)
Set the angular velocity around x axis in 4DC7 probe contact frame.
void setZAngularVelocity(int zAngularVelocity)
Set the angular velocity around z axis in 4DC7 probe contact frame.
void setYAngularVelocity(int yAngularVelocity)
Set the angular velocity around y axis in 4DC7 probe contact frame.