Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
testVirtuoseHapticBox.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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 https://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
41
42#include <visp3/core/vpTime.h>
43#include <visp3/robot/vpVirtuose.h>
44
45#if defined(VISP_HAVE_VIRTUOSE)
46#ifdef ENABLE_VISP_NAMESPACE
47using namespace VISP_NAMESPACE_NAME;
48#endif
49
50void CallBackVirtuose(VirtContext VC, void *ptr)
51{
52 (void)VC;
53
54 static bool firstIteration = true;
55 static vpPoseVector localPosition0;
56
57 vpPoseVector localPosition;
58 vpColVector forceFeedback(6, 0);
59 vpColVector finalForce(6, 0);
60 vpColVector forceEe(6, 0);
61 int force_limit = 15;
62 int force_increase_rate = 500;
63 float cube_size = 0.05f;
64
65 // Virtual spring to let the user know where the initial position is
66 // Estimated Virtuose handle mass = 0.1;
67 // Estimated Virtuose handle length = 0.23;
68 // In the ee frame: Virtuose Handle as a cylinder for the inertia
69 // Estimated Inertia1 = m*l*l/12
70 // Estimated Inertia2 = m*l*l/2 (rotation w.r.t. e-e z axis)
71 double virtualStiffnessAng = 20;
72 double virtualDamperAng = 0.182; // greater than sqrt 4*Inertia1*virtualStiffnessAng
73 double virtualDamperAng2 = 0.0456; // greater than sqrt 4*Inertia2*virtualStiffnessAng
74
75 vpColVector xd(3, 0);
76 vpColVector yd(3, 0);
77 vpColVector zd(3, 0);
78 vpColVector xee(3, 0);
79 vpColVector zee(3, 0);
80 vpColVector xeed(3, 0);
81 vpColVector zeed(3, 0);
82 vpColVector zYZ(3, 0);
83 vpColVector zXZ(3, 0);
84 vpColVector xXY(3, 0);
86 vpColVector omegad(3, 0);
89 vpPoseVector pee;
90 vpColVector vee(6, 0);
91 vpColVector veed(6, 0);
92
93 double alpha;
94
95 vpColVector torque1(3, 0);
96 vpColVector torque2(3, 0);
97 vpColVector torque3(3, 0);
98
99 vpVirtuose *p_virtuose = (vpVirtuose *)ptr;
100 localPosition = p_virtuose->getPhysicalPosition();
101
102 if (firstIteration) {
103 localPosition0 = localPosition;
104 firstIteration = false;
105 }
106
107 // Position and velocity in of the ee expressed in the base frame
108 pee = localPosition;
109 vee = p_virtuose->getPhysicalVelocity();
110 // Z axis = [pee_x pee_y 0]
111 zd[0] = pee[0];
112 zd[1] = pee[1];
113 zd.normalize();
114 // X axis = [0 0 1]
115 xd[2] = 1;
116 // Y axis from cross product
117 yd = zd.skew(zd) * xd;
118
119 // Current orientation of the ee frame
120 pee.extract(Qee);
121 pee.extract(tee);
122 // X and Z axis of the ee frame expressed in the base frame
123 xee = Qee.getCol(0);
124 zee = Qee.getCol(2);
125
126 // Rotation matrix from Desired Frame to Base Frame
127 Qd[0][0] = xd[0];
128 Qd[1][0] = xd[1];
129 Qd[2][0] = xd[2];
130 Qd[0][1] = yd[0];
131 Qd[1][1] = yd[1];
132 Qd[2][1] = yd[2];
133 Qd[0][2] = zd[0];
134 Qd[1][2] = zd[1];
135 Qd[2][2] = zd[2];
136
137 // X and Z axis of the ee frame expressed in the desired frame
138 xeed = Qd.inverse() * xee;
139 zeed = Qd.inverse() * zee;
140
141 vpHomogeneousMatrix dMb(tee, Qd);
142 // Velocity twist matrix for expressing velocities in the desired frame
143 vpVelocityTwistMatrix dVMb(dMb.inverse());
144 // Force twist matrix for expressing forces in the base frame
145 vpForceTwistMatrix dFMb(dMb);
146
147 veed = dVMb * vee;
148
149 // Angular velocity in the desired frame
150 omegad[0] = veed[3];
151 omegad[1] = veed[4];
152 omegad[2] = veed[5];
153
154 // Projection of Z axis of the ee frame onto plane YZ (expressed in the
155 // 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
160 // desired frame)
161 zXZ[0] = zeed[0];
162 zXZ[2] = zeed[2];
163
164 // Hard spring to keep Z axis of the ee frame in the horizontal plane
165 // Spring applied to the angle between the Z axis of the ee frame and its
166 // projection in the YZ (horizontal) plane
167 vpColVector rotzYZ(3, 0);
168 rotzYZ = zeed.skew(zeed) * zYZ.normalize();
169 vpColVector forceStiff1 = virtualStiffnessAng * rotzYZ;
170 vpColVector forceDamp1 = virtualDamperAng * (omegad * rotzYZ.normalize()) * rotzYZ.normalize();
171
172 for (unsigned int i = 0; i < 3; i++)
173 torque1[i] = forceStiff1[i] - forceDamp1[i];
174
175 // Hard spring to keep Z axis of the ee frame pointing at the origin
176 // Spring applied to the angle between the Z axis of the ee frame and its
177 // projection in the XZ (vertical) plane
178 vpColVector rotzXZ(3, 0);
179 rotzXZ = zeed.skew(zeed) * zXZ.normalize();
180 vpColVector forceStiff2 = virtualStiffnessAng * rotzXZ;
181 vpColVector forceDamp2 = virtualDamperAng * (omegad * rotzXZ.normalize()) * rotzXZ.normalize();
182
183 for (unsigned int i = 0; i < 3; i++)
184 torque2[i] = forceStiff2[i] - forceDamp2[i];
185
186 // Hard spring for rotation around z axis of the ee
187 xXY[0] = xeed[0];
188 xXY[1] = xeed[1];
189 vpColVector xdd(3, 0);
190 xdd[0] = 1;
191 vpColVector zdd(3, 0);
192 zdd[2] = 1;
193 vpColVector rotxXY(3, 0);
194 rotxXY = xdd.skew(xdd) * xXY.normalize();
195 alpha = asin(rotxXY[2]);
196
197 vpColVector forceStiff3 = virtualStiffnessAng * alpha * zdd;
198 vpColVector forceDamp3 = virtualDamperAng2 * (omegad * zdd) * zdd;
199 for (unsigned int i = 0; i < 3; i++)
200 torque3[i] = forceStiff3[i] - forceDamp3[i];
201
202 for (unsigned int j = 0; j < 3; j++)
203 forceEe[j + 3] = torque1[j] + torque2[j] + torque3[j];
204
205 forceEe = dFMb * forceEe;
206
207 // ---------------
208 // Haptic Box
209 // ---------------
210 vpColVector p_min(3, 0), p_max(3, 0);
211 for (unsigned int i = 0; i < 3; i++) {
212 p_min[i] = localPosition0[i] - cube_size / 2;
213 p_max[i] = localPosition0[i] + cube_size / 2;
214 }
215
216 for (int i = 0; i < 3; i++) {
217 if ((p_min[i] >= localPosition[i])) {
218 forceFeedback[i] = (p_min[i] - localPosition[i]) * force_increase_rate;
219 if (forceFeedback[i] >= force_limit)
220 forceFeedback[i] = force_limit;
221 }
222 else if ((p_max[i] <= localPosition[i])) {
223 forceFeedback[i] = (p_max[i] - localPosition[i]) * force_increase_rate;
224 if (forceFeedback[i] <= -force_limit)
225 forceFeedback[i] = -force_limit;
226 }
227 else
228 forceFeedback[i] = 0;
229 }
230
231 for (unsigned int j = 0; j < 6; j++)
232 finalForce[j] = forceFeedback[j] + forceEe[j];
233
234 // Set force feedback
235 p_virtuose->setForce(finalForce);
236
237 return;
238}
239
240int main(int argc, char **argv)
241{
242 std::string opt_ip = "localhost";
243 int opt_port = 5000;
244 for (int i = 1; i < argc; i++) {
245 if (std::string(argv[i]) == "--ip" && i + 1 < argc) {
246 opt_ip = std::string(argv[++i]);
247 }
248 else if (std::string(argv[i]) == "--port" && i + 1 < argc) {
249 opt_port = std::atoi(argv[++i]);
250 }
251 else if (std::string(argv[i]) == "--help" || std::string(argv[i]) == "-h") {
252 std::cout << "\nUsage: " << argv[0]
253 << " [--ip <localhost>] [--port <port>]"
254 " [--help] [-h]\n"
255 << std::endl
256 << "Description: " << std::endl
257 << " --ip <localhost>" << std::endl
258 << "\tHost IP address. Default value: \"localhost\"." << std::endl
259 << std::endl
260 << " --port <port>" << std::endl
261 << "\tCommunication port. Default value: 5000." << std::endl
262 << "\tSuggested values: " << std::endl
263 << "\t- 5000 to communicate with the Virtuose." << std::endl
264 << "\t- 53210 to communicate with the Virtuose equipped with the Glove." << std::endl
265 << std::endl;
266 return EXIT_SUCCESS;
267 }
268 }
269
270 try {
271 vpVirtuose virtuose;
272 std::cout << "Try to connect to " << opt_ip << " port " << opt_port << std::endl;
273 virtuose.setIpAddressAndPort(opt_ip, opt_port);
274 virtuose.setVerbose(true);
275 virtuose.setPowerOn();
276 virtuose.setPeriodicFunction(CallBackVirtuose);
277 virtuose.startPeriodicFunction();
278
279 int counter = 0;
280 bool swtch = true;
281
282 while (swtch) {
283 if (counter >= 10) {
284 virtuose.stopPeriodicFunction();
285 virtuose.setPowerOff();
286 swtch = false;
287 }
288 counter++;
289 vpTime::sleepMs(1000);
290 }
291 std::cout << "The end" << std::endl;
292 }
293 catch (const vpException &e) {
294 std::cout << "Catch an exception: " << e.getStringMessage() << std::endl;
295 return EXIT_FAILURE;
296 }
297 return EXIT_SUCCESS;
298}
299
300#else
301int main()
302{
303 std::cout << "You should install pthread and/or Virtuose API to use this "
304 "binary..."
305 << std::endl;
306 return EXIT_SUCCESS;
307}
308#endif
Implementation of column vector and the associated operations.
vpColVector & normalize()
error that can be emitted by ViSP classes.
Definition vpException.h:60
Implementation of an homogeneous matrix and operations on such kind of matrices.
Implementation of a pose vector and operations on poses.
void extract(vpRotationMatrix &R) const
Implementation of a rotation matrix and operations on such kind of matrices.
vpColVector getCol(unsigned int j) const
vpRotationMatrix inverse() const
Class that consider the case of a translation vector.
void setIpAddressAndPort(const std::string &ip, int port)
void setPowerOff()
void setForce(const vpColVector &force)
vpPoseVector getPhysicalPosition() const
void setPeriodicFunction(VirtPeriodicFunction CallBackVirt)
void stopPeriodicFunction()
void setPowerOn()
void setVerbose(bool mode)
Definition vpVirtuose.h:194
void startPeriodicFunction()
vpColVector getPhysicalVelocity() const
VISP_EXPORT void sleepMs(double t)