00001
00028
00029 #include <geometry_msgs/PoseStamped.h>
00030
00031 #include "threeD_mouse/3D_mouse.h"
00032
00033
00034 namespace threedmouse
00035 {
00036
00037 ThreeDMouse::ThreeDMouse()
00038 : n_tilde("~"), publish_rate(0.0)
00039 {
00040
00041 double publish_freq;
00042 n_tilde.param("publish_frequency", publish_freq, 50.0);
00043 publish_rate = ros::Rate(publish_freq);
00044
00045
00046 std::string prefix;
00047 std::string searched_param;
00048 n_tilde.searchParam("threedmouse_prefix", searched_param);
00049 n_tilde.param(searched_param, prefix, std::string());
00050 std::string full_topic = prefix + "/pose";
00051 pub = node.advertise<geometry_msgs::PoseStamped>(full_topic, 2);
00052
00053 if(!(dpy = XOpenDisplay(0)))
00054 {
00055 ROS_FATAL( "failed to connect to the X server");
00056 ROS_BREAK();
00057 }
00058
00059 bpix = BlackPixel(dpy, DefaultScreen(dpy));
00060 win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, bpix, bpix);
00061
00062
00063
00064
00065 if(spnav_x11_open(dpy, win) == -1)
00066 {
00067 ROS_FATAL( "failed to connect to the space navigator daemon" );
00068 ROS_BREAK();
00069 }
00070
00071
00072 mouse_mode = BOTH;
00073
00074 info_mouse_mode();
00075
00076 thread_update_mouse_data = boost::thread(boost::bind( &ThreeDMouse::check_stopped, this ));
00077 thread_publish = boost::thread( boost::bind( &ThreeDMouse::update_mouse_data, this ));
00078 }
00079
00080 ThreeDMouse::~ThreeDMouse()
00081 {
00082 thread_update_mouse_data.join();
00083 thread_publish.join();
00084
00085 spnav_close();
00086 }
00087
00088 void ThreeDMouse::check_stopped()
00089 {
00090 }
00091
00092 void ThreeDMouse::update_mouse_data()
00093 {
00094 geometry::Quaternion quater;
00095
00096 bool waiting_for_release = false;
00097
00098 while(ros::ok())
00099 {
00100 spnav_poll_event(&sev);
00101 switch( sev.type )
00102 {
00103 case SPNAV_EVENT_MOTION:
00104 last_pose.translation = geometry::Translation( sev.motion.x, sev.motion.y, sev.motion.z );
00105
00106
00107 last_pose.quaternion = quater.euler_to_quaternion(sev.motion.rx, sev.motion.ry, sev.motion.rz);
00108
00109 ROS_DEBUG("got motion event: t(%d, %d, %d) ", sev.motion.x, sev.motion.y, sev.motion.z);
00110 ROS_DEBUG("r(%d, %d, %d)", sev.motion.rx, sev.motion.ry, sev.motion.rz);
00111
00112 break;
00113
00114 case SPNAV_EVENT_BUTTON:
00115 if(waiting_for_release)
00116 {
00117 if(sev.button.press == false)
00118 waiting_for_release = false;
00119 }
00120 else
00121 {
00122 if(sev.button.press == true)
00123 {
00124 waiting_for_release = true;
00125 if(sev.button.bnum == 0)
00126 mouse_mode == ROTATE ? mouse_mode = TRANSLATE : mouse_mode = ROTATE;
00127 else
00128 mouse_mode == BOTH ? mouse_mode = TRANSLATE : mouse_mode = BOTH;
00129
00130
00131 info_mouse_mode();
00132 }
00133 }
00134 break;
00135
00136 default:
00137 break;
00138 }
00139
00140 ros::spinOnce();
00141 usleep(1000);
00142 }
00143 }
00144
00149 void ThreeDMouse::info_mouse_mode()
00150 {
00151 switch( mouse_mode )
00152 {
00153 case TRANSLATE:
00154 ROS_INFO("3d mouse set to translate mode");
00155 break;
00156 case ROTATE:
00157 ROS_INFO("3d mouse set to rotate mode");
00158 break;
00159 case BOTH:
00160 ROS_INFO("3d mouse set to both mode");
00161 break;
00162 default:
00163 ROS_WARN("3d mouse mode not recognized");
00164 break;
00165 }
00166 }
00167
00168
00169 void ThreeDMouse::publish()
00170 {
00171 geometry_msgs::PoseStamped posestamped_msg;
00172 posestamped_msg.header.stamp = ros::Time::now();
00173
00174 switch( mouse_mode )
00175 {
00176 case TRANSLATE:
00177 posestamped_msg.pose.position.x = last_pose.translation.x;
00178 posestamped_msg.pose.position.y = last_pose.translation.y;
00179 posestamped_msg.pose.position.z = last_pose.translation.z;
00180
00181 posestamped_msg.pose.orientation.x = 0.0;
00182 posestamped_msg.pose.orientation.y = 0.0;
00183 posestamped_msg.pose.orientation.z = 0.0;
00184 posestamped_msg.pose.orientation.w = 0.0;
00185 break;
00186
00187 case ROTATE:
00188 posestamped_msg.pose.position.x = 0.0;
00189 posestamped_msg.pose.position.y = 0.0;
00190 posestamped_msg.pose.position.z = 0.0;
00191
00192 posestamped_msg.pose.orientation.x = last_pose.quaternion.x;
00193 posestamped_msg.pose.orientation.y = last_pose.quaternion.y;
00194 posestamped_msg.pose.orientation.z = last_pose.quaternion.z;
00195 posestamped_msg.pose.orientation.w = last_pose.quaternion.w;
00196 break;
00197
00198 default:
00199 posestamped_msg.pose.position.x = last_pose.translation.x;
00200 posestamped_msg.pose.position.y = last_pose.translation.y;
00201 posestamped_msg.pose.position.z = last_pose.translation.z;
00202
00203 posestamped_msg.pose.orientation.x = last_pose.quaternion.x;
00204 posestamped_msg.pose.orientation.y = last_pose.quaternion.y;
00205 posestamped_msg.pose.orientation.z = last_pose.quaternion.z;
00206 posestamped_msg.pose.orientation.w = last_pose.quaternion.w;
00207 break;
00208 }
00209
00210 pub.publish(posestamped_msg);
00211
00212 ros::spinOnce();
00213 publish_rate.sleep();
00214 }
00215
00216 }
00217