vrep_perturbations.cpp
Go to the documentation of this file.
1 
14 
15 #define PI 3.14159265
16 
17 using namespace std;
18 
20 
21 HDCallbackCode HDCALLBACK UpdateCalibrationCallback(void *pUserData);
22 HDboolean CheckCalibration();
23 HDSchedulerHandle gCallbackHandle = HD_INVALID_HANDLE;
24 
25 ros::Subscriber simulation_state_sub;
28 
29 geometry_msgs::PoseStamped right_platform;
30 geometry_msgs::PoseStamped left_platform;
31 
32 geometry_msgs::Vector3 right_platform_init;
33 geometry_msgs::Vector3 left_platform_init;
34 
35 geometry_msgs::Point pelvis_target;
36 geometry_msgs::Point pelvis_target_init;
37 geometry_msgs::PointStamped pelvis_target_stamped;
38 
39 int simulator_state(4);
40 double simulationTime (0);
41 double time_inc = 0.05;
42 double poly_time;
43 string move_type = "move_down";
44 
45 string plane;
46 string amplitude;
47 string frequency;
48 
49 
50 HDCallbackCode HDCALLBACK SchedulerCallback(void *pUserData)
51 {
52  /* Scheduler callback responsible for device data extraction and force rendering.
53  * Calling operations within a haptic frame ensures consistency for the data being used, since the device
54  * state remains the same within the frame. */
55 
56  HDErrorInfo error;
57 
58  HDint nButtons = 0;
59 
60  hdBeginFrame(hdGetCurrentDevice());
61 
62  hdGetDoublev(HD_CURRENT_POSITION, state.device_position);
63  hdGetDoublev(HD_CURRENT_GIMBAL_ANGLES, state.gimbal_angle);
64 
65  hdGetIntegerv(HD_CURRENT_BUTTONS, &nButtons);
66 
67  state.button_state[0] =
68  (nButtons & HD_DEVICE_BUTTON_1) ? HD_TRUE : HD_FALSE;
69 
70  hdEndFrame(hdGetCurrentDevice());
71 
75 
76  /*cout << "Gimbal angles: " << "(" << state.gimbal_angle[0]*(180/M_PI) << ", " << state.gimbal_angle[1]*(180/M_PI) << "," << state.gimbal_angle[2]*(180/M_PI) << ")" << endl;*/
77  /*cout << "Device position: " << "(" << state.device_position[0]/1700 << ", " << state.device_position[1]/1700 << "," << state.device_position[2]/1700 << ")" << endl;*/
78 
79  if (HD_DEVICE_ERROR(error = hdGetError()))
80  {
81  hduPrintError(stderr, &error, "Error during main scheduler callback\n");
82  if (hduIsSchedulerError(&error))
83  return HD_CALLBACK_DONE;
84  }
85 
86  return HD_CALLBACK_CONTINUE;
87 }
88 
89 
90 /* Implements the rotary motion for the platform in the sagittal and frontal planes (x and y axis),
91  * based on the input parameters inserted by the user - amplitude and frequency, or on the joystick gimbal angles. */
92 void setPlatformPose(double& time)
93 {
94  double A = atof(amplitude.c_str());
95  double fc = atof(frequency.c_str());
96  double w = 2*PI*fc;
97 
98  double roll = A*sin(w*time);
99  double pitch = A*sin(w*time);
100 
101  if (plane == "lat")
102  {
103  roll = 0;
104  pitch = pitch;
105  }
106  else if (plane == "sag")
107  {
108  roll = roll;
109  pitch = 0;
110  }
111 
112  /*right_platform.pose.position.x = cos(state.gimbal_angle[2]/scale_div-right_platform_init.y)*0.125;
113  right_platform.pose.position.y = 0;
114  right_platform.pose.position.z = 0.07-sin(state.gimbal_angle[2]/scale_div-right_platform_init.y)*0.125;
115 
116  right_platform.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(state.gimbal_angle[1]/scale_div-right_platform_init.x, state.gimbal_angle[2]/scale_div-right_platform_init.y, 0);
117 
118 
119  left_platform.pose.position.x = -cos(state.gimbal_angle[2]/scale_div-right_platform_init.y)*0.125;
120  left_platform.pose.position.y = 0;
121  left_platform.pose.position.z = 0.07+sin(state.gimbal_angle[2]/scale_div-right_platform_init.y)*0.125;
122 
123  left_platform.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(state.gimbal_angle[1]/scale_div-right_platform_init.x, state.gimbal_angle[2]/scale_div-right_platform_init.y, 0);*/
124 
125 
126  right_platform.pose.position.x = cos(pitch*PI/180)*0.125;
127  right_platform.pose.position.y = 0;
128  right_platform.pose.position.z = 0.07-sin(pitch*PI/180)*0.125;
129 
130  right_platform.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(roll*PI/180, pitch*PI/180, 0);
131 
132  right_platform.header.stamp.sec = simulationTime*100000;
133 
134  left_platform.pose.position.x = -cos(pitch*PI/180)*0.125;
135  left_platform.pose.position.y = 0;
136  left_platform.pose.position.z = 0.07+sin(pitch*PI/180)*0.125;
137 
138  left_platform.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(roll*PI/180, pitch*PI/180, 0);
139 
140  left_platform.header.stamp.sec = simulationTime*100000;
141 
142  cout << "Platform's roll: " << roll << " pitch: " << pitch << endl;
143  cout << "--------------------------------------" << endl;
144 
147 }
148 
149 
150 void simulationCallback(const vrep_common::VrepInfo& msg)
151 {
152  if (simulator_state == 5 && msg.simulatorState.data == 4) /* Simulation stopped. */
153  ros::shutdown();
154 
155  simulator_state = msg.simulatorState.data;
156  simulationTime = msg.simulationTime.data;
157 
158  int scale_div = 3;
159 
160  if (simulationTime == 0)
161  {
162  right_platform_init.x = (state.gimbal_angle[1])/scale_div;
163  right_platform_init.y = (state.gimbal_angle[2])/scale_div;
164  right_platform_init.z = 0; /*(state.gimbal_angle[0])/scale_div;*/
165  }
166 
168 }
169 
170 
171 void setupMessaging(ros::NodeHandle nh)
172 {
173  simulation_state_sub = nh.subscribe("/vrep/info", 1000, simulationCallback);
174 
175  command_right_platform_pub = nh.advertise<geometry_msgs::PoseStamped>("/vrep/command_right_platform",1000);
176 
177  command_left_platform_pub = nh.advertise<geometry_msgs::PoseStamped>("/vrep/command_left_platform",1000);
178 }
179 
180 
181 void mainLoop(int argc, char **argv)
182 {
183  ros::init(argc, argv, "platform_control");
184  ros::NodeHandle nh;
185 
186  if (!ros::param::get("plane", plane))
187  ROS_ERROR("Failed to read symbols on parameter server");
188  else if (!ros::param::get("amplitude", amplitude))
189  ROS_ERROR("Failed to read symbols on parameter server");
190  else if (!ros::param::get("frequency", frequency))
191  ROS_ERROR("Failed to read symbols on parameter server");
192 
193  setupMessaging(nh);
194 
195  ros::spin();
196 }
197 
198 
199 HDCallbackCode HDCALLBACK UpdateCalibrationCallback(void *pUserData)
200 {
201  HDenum *calibrationStyle = (HDenum *) pUserData;
202 
203  if (hdCheckCalibration() == HD_CALIBRATION_NEEDS_UPDATE)
204  {
205  hdUpdateCalibration(*calibrationStyle);
206  }
207 
208  return HD_CALLBACK_DONE;
209 }
210 
211 
212 HDboolean CheckCalibration()
213 {
214  HDint supportedCalibrationStyles;
215  HDenum calibrationStyle;
216 
217  /* Choose a calibration style. Some devices may support multiple types of calibration.
218  * In that case, prefer auto calibration over inkwell calibration, and prefer inkwell calibration over reset encoders. */
219 
220  hdGetIntegerv(HD_CALIBRATION_STYLE, &supportedCalibrationStyles);
221 
222  if (supportedCalibrationStyles & HD_CALIBRATION_ENCODER_RESET)
223  {
224  calibrationStyle = HD_CALIBRATION_ENCODER_RESET;
225  /* Calibration style encoder reset: the device needs to be put in a reset position to be calibrated. */
226  }
227 
228  if (supportedCalibrationStyles & HD_CALIBRATION_INKWELL)
229  {
230  calibrationStyle = HD_CALIBRATION_INKWELL;
231  /* Calibration style inkwell: the device needs to be put into a fixture, inkwell, before calibration can be performed. */
232  }
233 
234  if (supportedCalibrationStyles & HD_CALIBRATION_AUTO)
235  {
236  calibrationStyle = HD_CALIBRATION_AUTO;
237  /* Calibration style auto: the device will gather new calibration information as the armature is moved. */
238  }
239 
240  /* Some haptic devices are calibrated when the gimbal is placed into the device inkwell and updateCalibration is called.
241  * This form of calibration is always performed after the servoloop has started running. For devices that require inkwell reset,
242  * such as the PHANToM Omni, calibration is successfully performed whenever the device is put into the inkwell. */
243 
244  HDenum status = hdCheckCalibration();
245 
246  if (status == HD_CALIBRATION_OK)
247  {
248  return HD_TRUE;
249  }
250  else if (status == HD_CALIBRATION_NEEDS_MANUAL_INPUT)
251  {
252  cout << "Calibration requires manual input." << endl;
253  return HD_FALSE;
254  }
255  else if (status == HD_CALIBRATION_NEEDS_UPDATE)
256  {
257  /* Synchronous scheduler callback to check the joystick internal calibration parameters. */
258  hdScheduleSynchronous(UpdateCalibrationCallback, &calibrationStyle, HD_DEFAULT_SCHEDULER_PRIORITY);
259 
260  if (HD_DEVICE_ERROR(hdGetError()))
261  {
262  cout << "\nFailed to update calibration.\n" << endl;
263  return HD_FALSE;
264  }
265  else
266  {
267  cout << "\nCalibration updated successfully.\n" << endl;
268  return HD_TRUE;
269  }
270  }
271  else
272  {
273  assert(!"Unknown calibration status");
274  return HD_FALSE;
275  }
276 }
277 
278 
279 int main(int argc, char **argv)
280 {
281  /*if (argv[1] == NULL || argv[2] == NULL || argv[3] == NULL)
282  ROS_ERROR("Insert the plane, amplitude and frequency of the rotary motion.");
283  else
284  {
285  plane = argv[1];
286  amplitude = atoi(argv[2]);
287  frequency = atof(argv[3]);
288  }*/
289 
290  HDErrorInfo error;
291 
292  /* General pattern of use for the HDAPI: */
293 
294  /* Initialize the device. */
295  HHD hHD = hdInitDevice(HD_DEFAULT_DEVICE);
296  if (HD_DEVICE_ERROR(error = hdGetError()))
297  {
298  hduPrintError(stderr, &error, "Failed to initialize the device");
299  fprintf(stderr, "\nPress any key to quit.\n");
300  getch();
301 
302  return -1;
303  }
304  ROS_INFO("Found %s.\n\n", hdGetString(HD_DEVICE_MODEL_TYPE));
305 
306  /* Create asynchronous scheduler callback. */
307  gCallbackHandle = hdScheduleAsynchronous(SchedulerCallback, 0, HD_MAX_SCHEDULER_PRIORITY);
308  if (HD_DEVICE_ERROR(error = hdGetError()))
309  {
310  hduPrintError(stderr, &error, "Failed to schedule servoloop callback");
311 
312  hdDisableDevice(hHD);
313 
314  fprintf(stderr, "\nPress any key to quit.\n");
315  getch();
316 
317  return -1;
318  }
319 
320  /* Enable force output. */
321  hdEnable(HD_FORCE_OUTPUT);
322 
323  /* Start the scheduler - responsible for managing a high frequency thread
324  *for sending forces and retrieving state information from the device. */
325  hdSetSchedulerRate(1000);
326  hdStartScheduler();
327  if (HD_DEVICE_ERROR(error = hdGetError()))
328  {
329  hduPrintError(stderr, &error, "Failed to start the scheduler");
330 
331  fprintf(stderr, "\nPress any key to quit.\n");
332  getch();
333  return -1;
334  }
335 
336  /* A parallel loop is started where the ROS node will be running, if the device is properly calibrated. */
337  if (CheckCalibration())
338  mainLoop(argc, argv);
339 
340  /* When the application is terminated (ROS node is shutted down), the device and scheduler are cleanup. */
341  hdStopScheduler();
342  hdUnschedule(gCallbackHandle);
343  hdDisableDevice(hHD);
344 
345  return 0;
346 }
double poly_time
geometry_msgs::Vector3 right_platform_init
HDSchedulerHandle gCallbackHandle
string frequency
string move_type
void setupMessaging(ros::NodeHandle nh)
#define PI
string amplitude
int main(int argc, char **argv)
int scale_div
geometry_msgs::PoseStamped left_platform
HDdouble gimbal_angle[3]
HDboolean button_state[2]
HDdouble device_position[3]
int simulator_state(4)
geometry_msgs::Vector3 left_platform_init
static device_state state
double simulationTime(0)
ros::Subscriber simulation_state_sub
int getch()
Definition: conio.cpp:103
geometry_msgs::PoseStamped right_platform
double time_inc
geometry_msgs::Point pelvis_target
ros::Publisher command_left_platform_pub
void simulationCallback(const vrep_common::VrepInfo &msg)
HDCallbackCode HDCALLBACK SchedulerCallback(void *pUserData)
HDCallbackCode HDCALLBACK UpdateCalibrationCallback(void *pUserData)
void setPlatformPose(double &time)
HDboolean CheckCalibration()
ros::Publisher command_right_platform_pub
void mainLoop(int argc, char **argv)
geometry_msgs::PointStamped pelvis_target_stamped
geometry_msgs::Point pelvis_target_init
string plane


humanoid_simulation
Author(s): João Barros
autogenerated on Mon Mar 2 2015 01:31:43