-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhand_virtual_environment.c
More file actions
221 lines (183 loc) · 7.62 KB
/
hand_virtual_environment.c
File metadata and controls
221 lines (183 loc) · 7.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/**
******************************************************************************
* @file hand_virtual_environment.c
* @author
* @version 1.0
* @date April-2022
* @brief Haptic hand virtual environment
******************************************************************************
*/
#include "main.h"
#include <math.h>
#include "stdlib.h"
#include "hand_virtual_environment.h"
#include "delta_thumb.h"
#include "haplink_motors.h"
#include "haplink_position.h"
/* Global Variables ----------------------------------------------------------*/
//variables needed declared in other files:
extern double J00, J01, J10, J11; //jacobian variables
extern double J00_f1, J01_f1, J10_f1, J11_f1; //jacobian variables
extern double J00_f2, J01_f2, J10_f2, J11_f2; //jacobian variables
extern double rx, ry, dx, dy; // 2-DOF position variables
extern double xH, dxH; //1-DOF position variables
double TorqueX, TorqueY, ForceX, ForceY, ForceH;
double TorqueMotor4, TorqueMotor5, TorqueMotor6, TorqueMotor7;
double xf1_global, yf1_global, xf2_global, yf2_global;
/*******************************************************************************
* @name renderOutsideSphere
* @brief Render sphere at a specified location
* @param None.
* @retval None.
*/
void renderOutsideSphere( void ) {
/********************* THUMB *************************/
// Check if thumb is inside sphere
double dist = sphereDistance(deltaThumbX, deltaThumbY, deltaThumbZ) / 1000.0;
double torque1, torque2, torque3, F_coeff;
double Fx=0, Fy=0, Fz=0;
static double Fx_prev=0, Fy_prev=0, Fz_prev=0;
static double alpha = 0.6; // how much of new value to include
if (dist < (SPHERE1_RADIUS / 1000.0)) {
// Calculate the forces to apply in order to resist the user
F_coeff = K_DELTA_THUMB * ((SPHERE1_RADIUS / 1000.0) - dist) / dist;
Fx = F_coeff * (deltaThumbX - SPHERE1_X) / 1000.0;
Fy = F_coeff * (deltaThumbY - SPHERE1_Y) / 1000.0;
Fz = F_coeff * (deltaThumbZ - SPHERE1_Z) / 1000.0;
// // Apply smoothing
// Fx = Fx * alpha + Fx_prev * (1-alpha);
// Fy = Fy * alpha + Fy_prev * (1-alpha);
// Fz = Fz * alpha + Fz_prev * (1-alpha);
// // Set previous values
// Fx_prev = Fx;
// Fy_prev = Fy;
// Fz_prev = Fz;
// printf("Fx=%f, Fy=%f, Fz=%f\n", Fx, Fy, Fz);
}
// Use jacobians to transforms forces into motor torques
// Get the jacobians
double J11, J12, J13,
J21, J22, J23,
J31, J32, J33;
// DeltaThumbGetJacobian (&J11, &J12, &J13,
// &J21, &J22, &J23,
// &J31, &J32, &J33);
DeltaThumbGetJacobian_OhioVersion (&J11, &J12, &J13,
&J21, &J22, &J23,
&J31, &J32, &J33);
/* Force to Torque*/
/* transpose */
// torque1 = J11 * Fx + J21 * Fy + J31 * Fz;
// torque2 = J12 * Fx + J22 * Fy + J32 * Fz;
// torque3 = J13 * Fx + J23 * Fy + J33 * Fz;
/* non - transpose */
torque1 = J11 * Fx + J12 * Fy + J13 * Fz;
torque2 = J21 * Fx + J22 * Fy + J23 * Fz;
torque3 = J31 * Fx + J32 * Fy + J33 * Fz;
outputTorqueMotor1(torque1);
outputTorqueMotor2(torque2);
outputTorqueMotor3(torque3);
/********************* FINGER 1 *************************/
// Check if finger 1 is inside sphere
xf1_global = getRx1() + NORMAL_XF; // mm, translated to be in global frame
yf1_global = getRy1() + NORMAL_YF; // mm, translated to be in global frame
double dist_f1 = sphereDistance(xf1_global, yf1_global, NORMAL_ZF1); // mm
double TorqueX_f1, TorqueY_f1;
double Fx_f1=0, Fy_f1=0;
if (dist_f1 < SPHERE1_RADIUS) {
// Calculate the forces to apply in order to resist the user
dist_f1 = dist_f1/1000.0; // m
xf1_global = xf1_global/1000.0; // m
yf1_global = yf1_global/1000.0; // m
Fx_f1 = K_FINGERS*(SPHERE1_RADIUS/1000.0 - dist_f1) * ((1.0/dist_f1) * (xf1_global - SPHERE1_X/1000.0)); // N
Fy_f1 = K_FINGERS*(SPHERE1_RADIUS/1000.0 - dist_f1) * ((1.0/dist_f1) * (yf1_global - SPHERE1_Y/1000.0)); // N
}
// Map back to local coordinate axes
Fx_f1 = Fx_f1; // axes aligned, no rotation needed
Fy_f1 = Fy_f1;
// Use jacobians to transforms forces into motor torques
/* Force to Torque*/
TorqueX_f1 = J00_f1*Fx_f1 + J10_f1*Fy_f1;
TorqueX_f1 = TorqueX_f1*0.001;
TorqueY_f1 = J01_f1*Fx_f1 + J11_f1*Fy_f1;
TorqueY_f1 = TorqueY_f1*0.001;
TorqueMotor4 = ((TorqueX_f1*R_MA)/R_A);
TorqueMotor5 = ((TorqueY_f1*R_MB)/R_B);
outputTorqueMotor4(TorqueMotor4);
outputTorqueMotor5(TorqueMotor5);
/********************* FINGER 2 *************************/
// Check if finger 2 is inside sphere
xf2_global = getRx2() + NORMAL_XF; // mm, translated to be in global frame
yf2_global = getRy2() + NORMAL_YF; // mm, translated to be in global frame
double dist_f2 = sphereDistance(xf2_global, yf2_global, NORMAL_ZF2); // mm
double TorqueX_f2, TorqueY_f2;
double Fx_f2=0, Fy_f2=0;
if (dist_f2 < SPHERE1_RADIUS) {
// Calculate the forces to apply in order to resist the user
dist_f2 = dist_f2/1000.0; // m
xf2_global = xf2_global/1000.0; // m
yf2_global = yf2_global/1000.0; // m
Fx_f2 = K_FINGERS*(SPHERE1_RADIUS/1000.0 - dist_f2) * ((1.0/dist_f2) * (xf2_global - SPHERE1_X/1000.0)); // N
Fy_f2 = K_FINGERS*(SPHERE1_RADIUS/1000.0 - dist_f2) * ((1.0/dist_f2) * (yf2_global - SPHERE1_Y/1000.0)); // N
}
// Map back to local coordinate axes
Fx_f2 = Fx_f2; // axes aligned, no rotation needed
Fy_f2 = Fy_f2;
// Use jacobians to transforms forces into motor torques
/* Force to Torque*/
TorqueX_f2 = J00_f2*Fx_f2 + J10_f2*Fy_f2;
TorqueX_f2 = TorqueX_f2*0.001;
TorqueY_f2 = J01_f2*Fx_f2 + J11_f2*Fy_f2;
TorqueY_f2 = TorqueY_f2*0.001;
TorqueMotor6 = -((TorqueX_f2*R_MA)/R_A);
TorqueMotor7 = -((TorqueY_f2*R_MB)/R_B);
outputTorqueMotor6(TorqueMotor6);
outputTorqueMotor7(TorqueMotor7);
// if (torque1 != 0){
// printf("Tx=%f, Ty=%f, Tz=%f\n", torque1, torque2, torque3);
// printf("J11=%f, J12=%f, J13=%f\nJ21=%f, J22=%f, J23=%f\nJ31=%f, J32=%f, J33=%f\n",J11, J12, J13,
// J21, J22, J23,
// J31, J32, J33);
// }
//if (!isnan(torque1)) outputTorqueMotor1(torque1);
//if (!isnan(torque2)) outputTorqueMotor2(torque2);
//if (!isnan(torque3)) outputTorqueMotor3(torque3);
}
/*******************************************************************************
* @name sphereDistance
* @brief Euclidean distance from user location to sphere's center
* @param user_x user's x position.
* @param user_y user's y position.
* @param user_z user's z position.
* @retval distance in doubles.
*/
double sphereDistance( double user_x, double user_y, double user_z ) {
double diff_x = user_x - SPHERE1_X;
double diff_y = user_y - SPHERE1_Y;
double diff_z = user_z - SPHERE1_Z;
return sqrt(diff_x*diff_x + diff_y*diff_y + diff_z*diff_z);
}
double getSphereX( void ) {
return SPHERE1_X;
}
double getSphereY( void ) {
return SPHERE1_Y;
}
double getSphereZ( void ) {
return SPHERE1_Z;
}
double getSphereRadius( void ) {
return SPHERE1_RADIUS;
}
double getXf1_global( void ) {
return xf1_global;
}
double getYf1_global( void ) {
return yf1_global;
}
double getXf2_global( void ) {
return xf2_global;
}
double getYf2_global( void ) {
return yf2_global;
}