00001 #include <ros/ros.h>
00002 #include <geometry_msgs/PoseStamped.h>
00003 #include <tf/transform_broadcaster.h>
00004 #include <geometry_msgs/Wrench.h>
00005 #include <geometry_msgs/WrenchStamped.h>
00006
00007 #include <string.h>
00008 #include <stdio.h>
00009 #include <math.h>
00010 #include <assert.h>
00011 #include <sstream>
00012
00013 #include <HL/hl.h>
00014 #include <HD/hd.h>
00015 #include <HDU/hduError.h>
00016 #include <HDU/hduVector.h>
00017 #include <HDU/hduMatrix.h>
00018
00019 #include "phantom_omni/PhantomButtonEvent.h"
00020 #include "phantom_omni/OmniFeedback.h"
00021 #include <pthread.h>
00022
00023 float prev_time;
00024
00025 struct OmniState
00026 {
00027 hduVector3Dd position;
00028 hduVector3Dd velocity;
00029 hduVector3Dd inp_vel1;
00030 hduVector3Dd inp_vel2;
00031 hduVector3Dd inp_vel3;
00032 hduVector3Dd out_vel1;
00033 hduVector3Dd out_vel2;
00034 hduVector3Dd out_vel3;
00035 hduVector3Dd pos_hist1;
00036 hduVector3Dd pos_hist2;
00037 hduVector3Dd rot;
00038 hduVector3Dd joints;
00039 hduVector3Dd force;
00040 float thetas[7];
00041 int buttons[2];
00042 int buttons_prev[2];
00043 bool lock;
00044 hduVector3Dd lock_pos;
00045 };
00046
00047
00048 class PhantomROS {
00049
00050 public:
00051 ros::NodeHandle n;
00052 ros::Publisher pose_publisher;
00053
00054
00055 ros::Publisher button_publisher;
00056 ros::Subscriber haptic_sub;
00057 std::string omni_name;
00058 std::string sensable_frame_name;
00059 std::string link_names[7];
00060
00061 OmniState *state;
00062 tf::TransformBroadcaster br;
00063
00064 void init(OmniState *s)
00065 {
00066 ros::param::param(std::string("~omni_name"), omni_name, std::string("omni1"));
00067
00068
00069 std::ostringstream stream00;
00070 stream00 << omni_name << "_pose";
00071 std::string pose_topic_name = std::string(stream00.str());
00072 pose_publisher = n.advertise<geometry_msgs::PoseStamped>(pose_topic_name.c_str(), 100);
00073
00074
00075
00076 std::ostringstream stream0;
00077 stream0 << omni_name << "_button";
00078 std::string button_topic = std::string(stream0.str());
00079 button_publisher = n.advertise<phantom_omni::PhantomButtonEvent>(button_topic.c_str(), 100);
00080
00081
00082 std::ostringstream stream01;
00083 stream01 << omni_name << "_force_feedback";
00084 std::string force_feedback_topic = std::string(stream01.str());
00085 haptic_sub = n.subscribe(force_feedback_topic.c_str(), 100, &PhantomROS::force_callback, this);
00086
00087
00088 std::ostringstream stream2;
00089 stream2 << omni_name << "_sensable";
00090 sensable_frame_name = std::string(stream2.str());
00091
00092 for (int i = 0; i < 7; i++)
00093 {
00094 std::ostringstream stream1;
00095 stream1 << omni_name << "_link" << i;
00096 link_names[i] = std::string(stream1.str());
00097 }
00098
00099
00100 state = s;
00101 state->buttons[0] = 0;
00102 state->buttons[1] = 0;
00103 state->buttons_prev[0] = 0;
00104 state->buttons_prev[1] = 0;
00105 hduVector3Dd zeros(0, 0, 0);
00106 state->velocity = zeros;
00107 state->inp_vel1 = zeros;
00108 state->inp_vel2 = zeros;
00109 state->inp_vel3 = zeros;
00110 state->out_vel1 = zeros;
00111 state->out_vel2 = zeros;
00112 state->out_vel3 = zeros;
00113 state->pos_hist1 = zeros;
00114 state->pos_hist2 = zeros;
00115 state->lock = true;
00116 state->lock_pos = zeros;
00117 }
00118
00119
00120
00121
00122
00123 void force_callback(const phantom_omni::OmniFeedbackConstPtr& omnifeed)
00124 {
00129 state->force[0] = omnifeed->force.x - 0.001*state->velocity[0];
00130 state->force[1] = omnifeed->force.y - 0.001*state->velocity[1];
00131 state->force[2] = omnifeed->force.z - 0.001*state->velocity[2];
00132
00133 state->lock_pos[0] = omnifeed->position.x;
00134 state->lock_pos[1] = omnifeed->position.y;
00135 state->lock_pos[2] = omnifeed->position.z;
00136
00137 }
00138
00139 void publish_omni_state()
00140 {
00141
00142 tf::Transform l0, sensable, l1, l2, l3, l4, l5, l6, l0_6;
00143 l0.setOrigin(tf::Vector3(0., 0, 0.15));
00144 l0.setRotation(tf::Quaternion(0, 0, 0));
00145 br.sendTransform(tf::StampedTransform(l0, ros::Time::now(), omni_name.c_str(), link_names[0].c_str()));
00146
00147 sensable.setOrigin(tf::Vector3(0., 0, 0));
00148 sensable.setRotation(tf::Quaternion(-M_PI/2, 0, M_PI/2));
00149 br.sendTransform(tf::StampedTransform(sensable, ros::Time::now(),
00150 omni_name.c_str(), sensable_frame_name.c_str()));
00151
00152 l1.setOrigin(tf::Vector3(0., 0, 0.));
00153 l1.setRotation(tf::Quaternion(-state->thetas[1], 0, 0));
00154
00155 l2.setOrigin(tf::Vector3(0., 0, 0.));
00156 l2.setRotation(tf::Quaternion(0, state->thetas[2], 0));
00157
00158 l3.setOrigin(tf::Vector3(-.131, 0, 0.));
00159 l3.setRotation(tf::Quaternion(0, state->thetas[3], 0));
00160
00161 l4.setOrigin(tf::Vector3(0., 0, -.137));
00162 l4.setRotation(tf::Quaternion(state->thetas[4]+M_PI, 0, 0));
00163
00164 l5.setOrigin(tf::Vector3(0., 0., 0.));
00165 l5.setRotation(tf::Quaternion(0., -state->thetas[5]+M_PI,0));
00166
00167 l6.setOrigin(tf::Vector3(0., 0., 0.));
00168 l6.setRotation(tf::Quaternion(0.,0, state->thetas[6]+M_PI));
00169
00170 l0_6 = l0 * l1 * l2 * l3 * l4 * l5 * l6;
00171 br.sendTransform(tf::StampedTransform(l0_6, ros::Time::now(), link_names[0].c_str(), link_names[6].c_str()));
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 geometry_msgs::PoseStamped pose_stamped;
00182 pose_stamped.header.frame_id = link_names[6].c_str();
00183 pose_stamped.header.stamp = ros::Time::now();
00184 pose_stamped.pose.position.x = 0.0;
00185 pose_stamped.pose.orientation.w = 1.;
00186 pose_publisher.publish(pose_stamped);
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 if ((state->buttons[0] != state->buttons_prev[0]) or (state->buttons[1] != state->buttons_prev[1]))
00197 {
00198
00199 if ((state->buttons[0] == state->buttons[1]) and (state->buttons[0] == 1))
00200 {
00201 state->lock = !(state->lock);
00202 }
00203 phantom_omni::PhantomButtonEvent button_event;
00204 button_event.grey_button = state->buttons[0];
00205 button_event.white_button = state->buttons[1];
00206 state->buttons_prev[0] = state->buttons[0];
00207 state->buttons_prev[1] = state->buttons[1];
00208 button_publisher.publish(button_event);
00209 }
00210 }
00211 };
00212
00213 HDCallbackCode HDCALLBACK omni_state_callback(void *pUserData)
00214 {
00215 OmniState *omni_state = static_cast<OmniState *>(pUserData);
00216
00217
00218 hdBeginFrame(hdGetCurrentDevice());
00219
00220 hdGetDoublev(HD_CURRENT_GIMBAL_ANGLES, omni_state->rot);
00221 hdGetDoublev(HD_CURRENT_POSITION, omni_state->position);
00222 hdGetDoublev(HD_CURRENT_JOINT_ANGLES, omni_state->joints);
00223
00224 hduVector3Dd vel_buff(0, 0, 0);
00225 vel_buff = (omni_state->position*3 - 4*omni_state->pos_hist1 + omni_state->pos_hist2)/0.002;
00226
00227 omni_state->velocity = (.2196*(vel_buff+omni_state->inp_vel3)+.6588*(omni_state->inp_vel1+omni_state->inp_vel2))/1000.0-(-2.7488*omni_state->out_vel1+2.5282*omni_state->out_vel2 - 0.7776*omni_state->out_vel3);
00228 omni_state->pos_hist2 = omni_state->pos_hist1;
00229 omni_state->pos_hist1 = omni_state->position;
00230 omni_state->inp_vel3 = omni_state->inp_vel2;
00231 omni_state->inp_vel2 = omni_state->inp_vel1;
00232 omni_state->inp_vel1 = vel_buff;
00233 omni_state->out_vel3 = omni_state->out_vel2;
00234 omni_state->out_vel2 = omni_state->out_vel1;
00235 omni_state->out_vel1 = omni_state->velocity;
00236
00237
00238 if (omni_state->lock == true)
00239 {
00240 omni_state->force = 0.04*(omni_state->lock_pos-omni_state->position) - 0.001*omni_state->velocity;
00241 }
00242
00243 hdSetDoublev(HD_CURRENT_FORCE, omni_state->force);
00244
00245
00246 int nButtons = 0;
00247 hdGetIntegerv(HD_CURRENT_BUTTONS, &nButtons);
00248 omni_state->buttons[0] = (nButtons & HD_DEVICE_BUTTON_1) ? 1 : 0;
00249 omni_state->buttons[1] = (nButtons & HD_DEVICE_BUTTON_2) ? 1 : 0;
00250
00251 hdEndFrame(hdGetCurrentDevice());
00252
00253 HDErrorInfo error;
00254 if (HD_DEVICE_ERROR(error = hdGetError()))
00255 {
00256 hduPrintError(stderr, &error, "Error during main scheduler callback\n");
00257 if (hduIsSchedulerError(&error))
00258 return HD_CALLBACK_DONE;
00259 }
00260
00261 float t[7] = {0., omni_state->joints[0], omni_state->joints[1], omni_state->joints[2]-omni_state->joints[1],
00262 omni_state->rot[0], omni_state->rot[1], omni_state->rot[2]};
00263 for (int i = 0; i < 7; i++)
00264 omni_state->thetas[i] = t[i];
00265 return HD_CALLBACK_CONTINUE;
00266 }
00267
00268
00269
00270
00271 void HHD_Auto_Calibration()
00272 {
00273 int calibrationStyle;
00274 int supportedCalibrationStyles;
00275 HDErrorInfo error;
00276
00277 hdGetIntegerv(HD_CALIBRATION_STYLE, &supportedCalibrationStyles);
00278 if (supportedCalibrationStyles & HD_CALIBRATION_ENCODER_RESET)
00279 {
00280 calibrationStyle = HD_CALIBRATION_ENCODER_RESET;
00281 ROS_INFO("HD_CALIBRATION_ENCODER_RESE..\n\n");
00282 }
00283 if (supportedCalibrationStyles & HD_CALIBRATION_INKWELL)
00284 {
00285 calibrationStyle = HD_CALIBRATION_INKWELL;
00286 ROS_INFO("HD_CALIBRATION_INKWELL..\n\n");
00287 }
00288 if (supportedCalibrationStyles & HD_CALIBRATION_AUTO)
00289 {
00290 calibrationStyle = HD_CALIBRATION_AUTO;
00291 ROS_INFO("HD_CALIBRATION_AUTO..\n\n");
00292 }
00293
00294 do
00295 {
00296 hdUpdateCalibration(calibrationStyle);
00297 ROS_INFO("Calibrating.. (put stylus in well)\n");
00298 if (HD_DEVICE_ERROR(error = hdGetError()))
00299 {
00300 hduPrintError(stderr, &error, "Reset encoders reset failed.");
00301 break;
00302 }
00303 } while (hdCheckCalibration() != HD_CALIBRATION_OK);
00304
00305 ROS_INFO("\n\nCalibration complete.\n");
00306 }
00307
00308 void *ros_publish(void *ptr)
00309 {
00310 PhantomROS *omni_ros = (PhantomROS *) ptr;
00311 int publish_rate;
00312 omni_ros->n.param(std::string("publish_rate"), publish_rate, 100);
00313 ros::Rate loop_rate(publish_rate);
00314 ros::AsyncSpinner spinner(2);
00315 spinner.start();
00316
00317 while(ros::ok())
00318 {
00319 omni_ros->publish_omni_state();
00320 loop_rate.sleep();
00321 }
00322 return NULL;
00323 }
00324
00325 int main(int argc, char** argv)
00326 {
00328
00330 HDErrorInfo error;
00331 HHD hHD;
00332 hHD = hdInitDevice(HD_DEFAULT_DEVICE);
00333 if (HD_DEVICE_ERROR(error = hdGetError()))
00334 {
00335
00336 ROS_ERROR("Failed to initialize haptic device");
00337 return -1;
00338 }
00339
00340 ROS_INFO("Found %s.\n\n", hdGetString(HD_DEVICE_MODEL_TYPE));
00341 hdEnable(HD_FORCE_OUTPUT);
00342 hdStartScheduler();
00343 if (HD_DEVICE_ERROR(error = hdGetError()))
00344 {
00345 ROS_ERROR("Failed to start the scheduler");
00346 return -1;
00347 }
00348 HHD_Auto_Calibration();
00349
00351
00353 ros::init(argc, argv, "omni_haptic_node");
00354 OmniState state;
00355 PhantomROS omni_ros;
00356
00357 omni_ros.init(&state);
00358 hdScheduleAsynchronous(omni_state_callback, &state, HD_MAX_SCHEDULER_PRIORITY);
00359
00361
00363 pthread_t publish_thread;
00364 pthread_create(&publish_thread, NULL, ros_publish, (void*) &omni_ros);
00365 pthread_join(publish_thread, NULL);
00366
00367 ROS_INFO("Ending Session....\n");
00368 hdStopScheduler();
00369 hdDisableDevice(hHD);
00370
00371 return 0;
00372 }
00373
00374