00001
00018 #include <ros/ros.h>
00019 #include <asr_msgs/AsrObject.h>
00020 #include <geometry_msgs/PoseStamped.h>
00021 #include <sensor_msgs/JointState.h>
00022 #include <string>
00023 #include <stdio.h>
00024 #include <iostream>
00025 #include <boost/thread.hpp>
00026 #include <boost/date_time/posix_time/posix_time.hpp>
00027 #include <tf/transform_listener.h>
00028 #include <tf/transform_broadcaster.h>
00029 #include <tf/transform_datatypes.h>
00030 #include <unistd.h>
00031 #include <termios.h>
00032
00033 #define RAD_TO_DEG (180.0 / M_PI)
00034 #define DEG_TO_RAD (1 / RAD_TO_DEG)
00035
00036 class PTUTracker {
00037
00038 struct Point3f{
00039 float x, y, z;
00040 };
00041 struct Point2f{
00042 float x, y;
00043 };
00044 public:
00045 ros::NodeHandle nh;
00046
00047
00048 ros::Subscriber fob_sub;
00049 ros::Subscriber ptu_sub;
00050 ros::Publisher ptu_pub;
00051
00052
00053 std::string ptu_state_cmd, ptu_state, fob_topic, fob_tracking_point_left, fob_tracking_point_right;
00054 int panAmount, tiltAmount;
00055
00056
00057 std::vector<double> ptuPosition;
00058
00059 geometry_msgs::Pose fob_pose_left;
00060 geometry_msgs::Pose fob_pose_right;
00061
00062 geometry_msgs::PointStamped ptuPoint;
00063 geometry_msgs::PointStamped fobPoint;
00064
00065 struct termios oldt;
00066
00067
00068 tf::TransformListener tf;
00069 tf::TransformBroadcaster tb;
00070
00071
00072 void fobCB(const asr_msgs::AsrObject& fob_msg) {
00073
00074 if(!fob_msg.sampledPoses.size()){
00075 std::cerr << "Got a AsrObject without poses." << std::endl;
00076 std::exit(1);
00077 }
00078
00079 if (!fob_msg.identifier.empty() && strcmp(fob_msg.identifier.c_str(), fob_tracking_point_left.c_str()) == 0) {
00080 ROS_DEBUG("fob left message recieved");
00081 fob_pose_left = fob_msg.sampledPoses.front().pose;
00082 }else if (!fob_msg.identifier.empty() && strcmp(fob_msg.identifier.c_str(), fob_tracking_point_right.c_str()) == 0) {
00083 ROS_DEBUG("fob right message recieved");
00084 fob_pose_right = fob_msg.sampledPoses.front().pose;
00085 }
00086 }
00087
00088
00089 void ptuCB(const sensor_msgs::JointState& ptu_msg) {
00090 ptuPosition = ptu_msg.position;
00091 }
00092
00093
00094 PTUTracker(ros::NodeHandle nh){
00095 this->nh = nh;
00096 nh.getParam("ptu_pub_topic", ptu_state_cmd);
00097 nh.getParam("ptu_sub_topic", ptu_state);
00098 nh.getParam("fob_sub_topic", fob_topic);
00099 nh.getParam("fob_tracking_point_left", fob_tracking_point_left);
00100 nh.getParam("fob_tracking_point_right", fob_tracking_point_right);
00101
00102 nh.getParam("panAmount", panAmount);
00103 nh.getParam("tiltAmount", tiltAmount);
00104
00105 std::string fob_frame, ptu_frame;
00106 nh.getParam("tracker_frame", fob_frame);
00107 nh.getParam("ptu_base_frame", ptu_frame);
00108
00109 fob_sub = nh.subscribe(fob_topic, 1, &PTUTracker::fobCB, this);
00110 ptu_sub = nh.subscribe("/asr_flir_ptu_driver/state", 1, &PTUTracker::ptuCB, this);
00111 ptu_pub = nh.advertise<sensor_msgs::JointState>(ptu_state_cmd, 5);
00112
00113 fobPoint.header.frame_id = fob_frame;
00114 fobPoint.header.stamp = ros::Time(0);
00115 ptuPoint.header.frame_id = ptu_frame;
00116 ptuPoint.header.stamp = ros::Time(0);
00117
00118 boost::thread trackerThread(spin, this);
00119 ros::spin();
00120 trackerThread.interrupt();
00121
00122
00123 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
00124
00125 }
00126
00127 Point2f toSphereCoords(geometry_msgs::PointStamped p) {
00128 Point3f temp;
00129 temp.x = p.point.x;
00130 temp.y = p.point.y;
00131 temp.z = p.point.z;
00132
00133 return toSphereCoords(temp);
00134 }
00135
00136 Point2f toSphereCoords(Point3f pt) {
00137 Point2f pantilt;
00138 Point3f p;
00139 p.x = -pt.y;
00140 p.y = -pt.x;
00141 p.z = -pt.z;
00142 double panAngle = (p.x < 0)? 1 : -1;
00143 panAngle *= acos(-p.y / (sqrt(p.x * p.x + p.y * p.y))) * RAD_TO_DEG;
00144
00145 double tiltAngle = (p.z > 0)? -1 : 1;
00146 tiltAngle *= acos(-p.y / (sqrt(p.y * p.y + p.z * p.z))) * RAD_TO_DEG;
00147
00148 pantilt.x = panAngle;
00149 pantilt.y = tiltAngle;
00150
00151 return pantilt;
00152 }
00153
00154 void movePTU(char c){
00155 if(c!='l' && c !='r'){
00156 return;
00157 }
00158
00159
00160 if(c == 'l'){
00161 fobPoint.point.x = fob_pose_left.position.x;
00162 fobPoint.point.y = fob_pose_left.position.y;
00163 fobPoint.point.z = fob_pose_left.position.z;
00164 }else if(c == 'r'){
00165 fobPoint.point.x = fob_pose_right.position.x;
00166 fobPoint.point.y = fob_pose_right.position.y;
00167 fobPoint.point.z = fob_pose_right.position.z;
00168 }
00169 tf.transformPoint(ptuPoint.header.frame_id, fobPoint, ptuPoint);
00170 Point2f pantiltTarget = toSphereCoords(ptuPoint);
00171 rotPTUAbsolute(pantiltTarget.x, pantiltTarget.y);
00172
00173 }
00174 void rotPTUAbsolute(double pan, double tilt){
00175 ROS_INFO("Target pan tilt angle: ([%f %f])", pan, tilt);
00176
00177 sensor_msgs::JointState pantiltState;
00178 pantiltState.header.stamp = ros::Time::now();
00179
00180 pantiltState.name.push_back("pan");
00181 pantiltState.name.push_back("tilt");
00182
00183 pantiltState.position.push_back(pan);
00184 pantiltState.position.push_back(tilt);
00185
00186 pantiltState.velocity.push_back(0);
00187 pantiltState.velocity.push_back(0);
00188
00189 ptu_pub.publish(pantiltState);
00190 }
00191 void rotPTURelative(double pan, double tilt){
00192 pan = pan + ptuPosition[0];
00193 tilt = tilt + ptuPosition[1];
00194 rotPTUAbsolute(pan, tilt);
00195 }
00196
00197 int getch(void)
00198 {
00199
00200 int ch;
00201 struct termios newt;
00202 tcgetattr(STDIN_FILENO, &oldt);
00203 newt = oldt;
00204 newt.c_lflag &= ~(ICANON | ECHO);
00205 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
00206 ch = getchar();
00207 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
00208 return ch;
00209 }
00210
00211 int getKey()
00212 {
00213 int result=getch();
00214 if(result==0){
00215 result=256+getch();
00216 }
00217 return result;
00218 }
00219
00220 static void spin(PTUTracker* tracker){
00221 std::string input;
00222 ROS_INFO("Press <l> to move PTU to left tracker.");
00223 ROS_INFO("Press <r> to move PTU to right tracker.");
00224 ROS_INFO("Use Arrowkeys to move PTU (do not hold key down).");
00225
00226 while (true){
00227 char c = tracker->getKey();
00228
00229 if(c == 'l' || c == 'r'){
00230 tracker->movePTU(c);
00231 }else if(c == 65){
00232 tracker->rotPTURelative(0,tracker->tiltAmount);
00233 }else if(c == 66){
00234 tracker->rotPTURelative(0,-tracker->tiltAmount);
00235 }else if(c == 67){
00236 tracker->rotPTURelative(-tracker->panAmount,0);
00237 }else if(c == 68){
00238 tracker->rotPTURelative(tracker->panAmount,0);
00239 }
00240 boost::this_thread::sleep(boost::posix_time::milliseconds(100));
00241 }
00242 }
00243 };
00244
00245 int main(int argc, char** argv)
00246 {
00247 ros::init(argc, argv, "ptu_tracker");
00248 ros::NodeHandle nh("~");
00249 new ::PTUTracker(nh);
00250 return 0;
00251 }