-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQueryDevice.c
More file actions
259 lines (202 loc) · 8.72 KB
/
QueryDevice.c
File metadata and controls
259 lines (202 loc) · 8.72 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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*****************************************************************************
Copyright (c) 2004 SensAble Technologies, Inc. All rights reserved.
OpenHaptics(TM) toolkit. The material embodied in this software and use of
this software is subject to the terms and conditions of the clickthrough
Development License Agreement.
For questions, comments or bug reports, go to forums at:
http://dsc.sensable.com
Module Name:
QueryDevice.c
Description:
This example demonstrates how to retrieve information from the haptic device.
*******************************************************************************/
#ifdef _WIN64
#pragma warning (disable:4996)
#endif
#if defined(WIN32)
# include <windows.h>
# include <conio.h>
#else
# include "conio.h"
# include <string.h>
#endif
#define CURL_STATICLIB
#include <curl\curl.h>
#define _USE_MATH_DEFINES // for C
#include <math.h>
#include <stdio.h>
#include <assert.h>
#include <HD/hd.h>
#include <HDU/hduVector.h>
#include <HDU/hduError.h>
/* Holds data retrieved from HDAPI. */
typedef struct
{
HDboolean m_buttonState; /* Has the device button has been pressed. */
hduVector3Dd m_devicePosition; /* Current device coordinates. */
hduVector3Dd m_jointAngles;
hduVector3Dd m_gimbalAngles;
HDErrorInfo m_error;
} DeviceData;
static DeviceData gServoDeviceData;
/*******************************************************************************
Checks the state of the gimbal button and gets the position of the device.
*******************************************************************************/
HDCallbackCode HDCALLBACK updateDeviceCallback(void *pUserData)
{
int nButtons = 0;
hdBeginFrame(hdGetCurrentDevice());
/* Retrieve the current button(s). */
hdGetIntegerv(HD_CURRENT_BUTTONS, &nButtons);
/* In order to get the specific button 1 state, we use a bitmask to
test for the HD_DEVICE_BUTTON_1 bit. */
gServoDeviceData.m_buttonState =
(nButtons & HD_DEVICE_BUTTON_1) ? HD_TRUE : HD_FALSE;
/* Get the current location of the device (HD_GET_CURRENT_POSITION)
We declare a vector of three doubles since hdGetDoublev returns
the information in a vector of size 3. */
hdGetDoublev(HD_CURRENT_POSITION, gServoDeviceData.m_devicePosition);
hdGetDoublev(HD_CURRENT_JOINT_ANGLES, gServoDeviceData.m_jointAngles);
hdGetDoublev(HD_CURRENT_GIMBAL_ANGLES, gServoDeviceData.m_gimbalAngles);
/* Also check the error state of HDAPI. */
gServoDeviceData.m_error = hdGetError();
/* Copy the position into our device_data tructure. */
hdEndFrame(hdGetCurrentDevice());
return HD_CALLBACK_CONTINUE;
}
/*******************************************************************************
Checks the state of the gimbal button and gets the position of the device.
*******************************************************************************/
HDCallbackCode HDCALLBACK copyDeviceDataCallback(void *pUserData)
{
DeviceData *pDeviceData = (DeviceData *) pUserData;
memcpy(pDeviceData, &gServoDeviceData, sizeof(DeviceData));
return HD_CALLBACK_DONE;
}
/*******************************************************************************
Prints out a help string about using this example.
*******************************************************************************/
void printHelp(void)
{
static const char help[] = {"\
Press and release the stylus button to print out the current device location.\n\
Press and hold the stylus button to exit the application\n"};
fprintf(stdout, "%s\n", help);
}
/*******************************************************************************
This routine allows the device to provide information about the current
location of the stylus, and contains a mechanism for terminating the
application.
Pressing the button causes the application to display the current location
of the device.
Holding the button down for N iterations causes the application to exit.
*******************************************************************************/
void mainLoop(void)
{
/* Instantiate the structure used to capture data from the device. */
DeviceData currentData;
DeviceData prevData;
/* Perform a synchronous call to copy the most current device state. */
hdScheduleSynchronous(copyDeviceDataCallback,
¤tData, HD_MIN_SCHEDULER_PRIORITY);
memcpy(&prevData, ¤tData, sizeof(DeviceData));
printHelp();
/* Run the main loop until the gimbal button is held. */
while (1)
{
/* Perform a synchronous call to copy the most current device state.
This synchronous scheduler call ensures that the device state
is obtained in a thread-safe manner. */
hdScheduleSynchronous(copyDeviceDataCallback,
¤tData,
HD_MIN_SCHEDULER_PRIORITY);
/* If the user depresses the gimbal button, display the current
location information. */
if (currentData.m_buttonState && !prevData.m_buttonState)
{
fprintf(stdout, "Current position: (%g, %g, %g)\n",
currentData.m_devicePosition[0],
currentData.m_devicePosition[1],
currentData.m_devicePosition[2]);
int base_deg = currentData.m_jointAngles[0] * 180 / M_PI + 90;
int shoulder_deg = currentData.m_jointAngles[1] * 180 / M_PI + 90;
int elbow_deg = currentData.m_jointAngles[2] * 180 / M_PI;
int wrist_rot_deg = currentData.m_gimbalAngles[0] * 180 / M_PI + 90;
int wrist_vert_deg = currentData.m_gimbalAngles[1] * 180 / M_PI + 90;
int grip_deg = currentData.m_gimbalAngles[2] * 180 / M_PI + 90;
grip_deg = (grip_deg - 0) * (73 - 10) / (360 - 0) + 10;
fprintf(stdout, "Current Joint Angles: (%i, %i, %i) \n",
base_deg,
shoulder_deg,
elbow_deg);
fprintf(stdout, "Current Gimbal Angles: (%i, %i, %i) \n",
wrist_vert_deg,
wrist_rot_deg,
grip_deg);
CURL* curl = curl_easy_init();
if (curl) {
char getParams[100];
sprintf(getParams, "192.168.3.14:4200/?command=10,%d,%d,%d,%d,%d,%d",
base_deg, shoulder_deg, elbow_deg, wrist_rot_deg, wrist_vert_deg, grip_deg);
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, getParams);
fprintf(stdout, "URL: %s", getParams);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
}
/* Check if an error occurred. */
if (HD_DEVICE_ERROR(currentData.m_error))
{
hduPrintError(stderr, ¤tData.m_error, "Device error detected");
if (hduIsSchedulerError(¤tData.m_error))
{
/* Quit, since communication with the device was disrupted. */
fprintf(stderr, "\nPress any key to quit.\n");
getch();
break;
}
}
/* Store off the current data for the next loop. */
memcpy(&prevData, ¤tData, sizeof(DeviceData));
}
}
/*******************************************************************************
Main function.
Sets up the device, runs main application loop, cleans up when finished.
*******************************************************************************/
int main(int argc, char* argv[])
{
HDSchedulerHandle hUpdateHandle = 0;
HDErrorInfo error;
/* Initialize the device, must be done before attempting to call any hd
functions. */
HHD hHD = hdInitDevice(HD_DEFAULT_DEVICE);
if (HD_DEVICE_ERROR(error = hdGetError()))
{
hduPrintError(stderr, &error, "Failed to initialize the device");
fprintf(stderr, "\nPress any key to quit.\n");
getch();
return -1;
}
/* Schedule the main scheduler callback that updates the device state. */
hUpdateHandle = hdScheduleAsynchronous(
updateDeviceCallback, 0, HD_MAX_SCHEDULER_PRIORITY);
/* Start the servo loop scheduler. */
hdStartScheduler();
if (HD_DEVICE_ERROR(error = hdGetError()))
{
hduPrintError(stderr, &error, "Failed to start the scheduler");
fprintf(stderr, "\nPress any key to quit.\n");
getch();
return -1;
}
/* Run the application loop. */
mainLoop();
/* For cleanup, unschedule callbacks and stop the servo loop. */
hdStopScheduler();
hdUnschedule(hUpdateHandle);
hdDisableDevice(hHD);
return 0;
}
/******************************************************************************/