00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00042 
00043 #include <ros/ros.h>
00044 
00045 #include <sensor_msgs/PointCloud.h>
00046 #include <sensor_msgs/LaserScan.h>
00047 #include <geometry_msgs/Point32.h>
00048 #include <boost/algorithm/string.hpp>
00049 #include <boost/thread/mutex.hpp>
00050 #include <Eigen/Core>
00051 #include <point_cloud_mapping/geometry/nearest.h>
00052 
00053 #include <mapping_srvs/RotatePTU.h>
00054 #include <mapping_srvs/TriggerSweep.h>
00055 #include <perception_srvs/David.h>
00056 using namespace std;
00057 using namespace ros;
00058 using namespace sensor_msgs;
00059 using namespace geometry_msgs;
00060 
00061 #define ANGLE -180.0
00062 #define S_ANGLE -180.0
00063 
00064 class RotatingDPPTU
00065 {
00066   protected:
00067     NodeHandle nh_;
00068     boost::mutex s_lock_, a_lock_;
00069     bool david_connect_, spin_;
00070     int total_laser_scans_;
00071   public:
00072     
00073     list<LaserScanConstPtr> scans_;
00074     double first_act_stamp_;
00075 
00076     PointCloud cloud_;
00077 
00078     Publisher cloud_pub_;
00079 
00080     ServiceClient ptu_serv_, scan_serv_, david_scan_, save_images_serv_;
00081 
00082     
00083     double min_distance_, max_distance_, laser_min_angle_, laser_max_angle_;
00084     double angle_step_;
00085     string object_;
00086     bool left_arm_;
00087     
00088     int is_david_;
00089     
00090     int is_ptu_;
00091     
00092     int is_image_;
00093     
00094     int is_laser_;
00095     
00096     int sweeps_;
00097 
00099     RotatingDPPTU () : total_laser_scans_ (0),
00100                        left_arm_ (true)
00101     {
00102       david_connect_ = true, spin_ = true;
00103       nh_.param ("~min_distance", min_distance_, .7);     
00104       nh_.param ("~max_distance", max_distance_, 3.01);   
00105       nh_.param ("~angle_step", angle_step_, 30.0);     
00106       nh_.param ("~object", object_, string("mug"));   
00107       nh_.param ("~sweeps", sweeps_, 1);                
00108       nh_.param ("~is_ptu", is_ptu_, 0);
00109       nh_.param ("~is_image", is_image_, 0);
00110       nh_.param ("~is_laser", is_laser_, 0);
00111       nh_.param("~is_david", is_david_, 0);
00112 
00113       cloud_pub_ = nh_.advertise<PointCloud> ("/tilt_laser_cloud", 1);
00114 
00115       ptu_serv_  = nh_.serviceClient<mapping_srvs::RotatePTU>("get_angle_service");
00116       scan_serv_ = nh_.serviceClient<mapping_srvs::TriggerSweep>("amtec_sweep");
00117       david_scan_ = nh_.serviceClient<perception_srvs::David>("david");
00118       save_images_serv_ = nh_.serviceClient<mapping_srvs::TriggerSweep>("save_images_service");
00119     }
00120 
00122     virtual ~RotatingDPPTU () { }
00123 
00124 
00126     Eigen::Matrix3f
00127       assembleRotationMatrixZ (float angle)
00128     {
00129       double cz = cos (angle), sz = sin (angle);
00130       Eigen::Matrix3f rot_mat;
00131       rot_mat << 
00132         cz, -sz, 0, 
00133         sz,  cz, 0,
00134         0 ,   0, 1;
00135       return (rot_mat);
00136     }
00137 
00139     
00140     void
00141       rotateCloudRelative (float relative_angle, const PointCloud &cloud_in, PointCloud &cloud_out)
00142     {
00143       cloud_out.header   = cloud_in.header;
00144       cloud_out.channels = cloud_in.channels;
00145       cloud_out.points.resize (cloud_in.points.size ());
00146 
00147       
00148       Point32 centroid;
00149       cloud_geometry::nearest::computeCentroid (cloud_in, centroid); 
00150       
00151       
00152       Eigen::Matrix3f rot_mat = assembleRotationMatrixZ (relative_angle);
00153       
00154       for (unsigned int i = 0; i < cloud_in.points.size (); i++)
00155       {
00156         double cx = cloud_in.points[i].x - centroid.x; 
00157         double cy = cloud_in.points[i].y - centroid.y; 
00158         double cz = cloud_in.points[i].z - centroid.z; 
00159 
00160         cloud_out.points[i].x = rot_mat (0, 0) * cx + rot_mat (0, 1) * cy + rot_mat (0, 2) * cz;
00161         cloud_out.points[i].y = rot_mat (1, 0) * cx + rot_mat (1, 1) * cy + rot_mat (1, 2) * cz;
00162         cloud_out.points[i].x = rot_mat (2, 0) * cx + rot_mat (2, 1) * cy + rot_mat (2, 2) * cz;
00163       }
00164     }
00165 
00166 
00168     bool
00169       spin ()
00170     {
00171       
00172       
00173       
00174       float s_angle = S_ANGLE, angle = ANGLE; 
00175       mapping_srvs::RotatePTU p_s;
00176       mapping_srvs::TriggerSweep s_s;
00177       mapping_srvs::TriggerSweep i_s;
00178       perception_srvs::David d_s;
00179       ros::Duration tictoc (1, 0);
00180       ros::Duration wait_grab_texture (3, 0);
00181       ros::Duration david_wait (0.1);
00182       ros::Rate loop_rate(5);
00183       PointCloud cloud_r;
00184       bool home;
00185       home = true;
00186 
00187       while (nh_.ok ())
00188       {
00189         update_parameters_from_server();
00190         ROS_INFO("is_image %d", is_image_);
00191         ROS_INFO("is_laser %d", is_laser_);
00192         if(spin_)
00193           {
00194             ROS_INFO("New Spin----------------------------------------------");
00195             ROS_INFO("------------------------------------------------------");
00196             ROS_INFO("------------------------------------------------------");
00197             
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206             
00207             if (is_ptu_)
00208               {
00209                 p_s.request.angle = angle;
00210                 ROS_INFO ("Setting ____PTU______ angle to %f. Sleeping for %f seconds.", angle, tictoc.toSec ());
00211                 ptu_serv_.call (p_s);
00212                 tictoc.sleep ();
00213               }
00214             
00215             if (is_david_)
00216               {
00217                 
00218                 
00219                 if(david_connect_){
00220                   ROS_WARN("Connecting to DAVID server");
00221                   
00222                   d_s.request.david_method = "connect";
00223                   david_connect_ = false;
00224                 }
00225                 david_scan_.call(d_s);
00226                 david_wait.sleep();
00227                 d_s.request.david_method = "erase";
00228                 david_scan_.call(d_s);
00229                 david_wait.sleep();
00230                 d_s.request.david_method = "eraseTexture";
00231                 david_scan_.call(d_s);
00232                 david_wait.sleep();
00233                 d_s.request.david_method = "start";
00234                 david_scan_.call(d_s);
00235                 ROS_INFO ("David started. Sleeping for %f seconds.", tictoc.toSec ());
00236                 tictoc.sleep();
00237               }
00238             
00239             
00240             
00241             if (is_laser_)
00242               {
00243                 tictoc.sleep ();
00244                 for (int i = 0; i < sweeps_; i++)
00245                   {
00246                     s_s.request.object = object_;
00247                     s_s.request.angle_filename = angle;
00248                     scan_serv_.call (s_s);
00249                     ROS_INFO ("___Sweeping___ %d times. Setting angle to %f, object to %s. ", i, angle, object_.c_str());
00250                   }
00251               }
00252             
00253             
00254             
00255             
00256             
00257             
00258             
00259             
00260             
00261             
00262             
00263             if (is_david_)
00264               {
00265                 d_s.request.david_method = "stop";
00266                 david_scan_.call(d_s);
00267                 david_wait.sleep();
00268                 d_s.request.david_method = "grabTexture";
00269                 david_scan_.call(d_s);
00270                 david_wait.sleep();
00271                 
00272                 char angle_tmp[100];
00273                 int angle_int = round(angle);
00274                 sprintf (angle_tmp, "%d",  angle_int);
00275                 string david_save = "save_" + object_ + "_" +  string(angle_tmp) + "_" + ".obj";
00276                 ROS_INFO("Saving David scan to %s", david_save.c_str());
00277                 d_s.request.david_method = david_save;
00278                 david_scan_.call(d_s);
00279                 ROS_INFO("Sleeping for %f seconds.", wait_grab_texture.toSec ());
00280                 wait_grab_texture.sleep();
00281                 
00282                 d_s.request.david_method = "erase";
00283                 david_scan_.call(d_s);
00284                 ROS_INFO ("David stopped. Sleeping for %f seconds.", tictoc.toSec ());
00285                 tictoc.sleep();
00286               }
00287 
00288             if (is_image_)
00289               {
00290                 i_s.request.object = object_;
00291                 i_s.request.angle_filename = angle;
00292                 ROS_INFO ("Capturing Images!");
00293                 save_images_serv_.call (i_s);
00294                 tictoc.sleep ();
00295               }
00296             
00297             angle += angle_step_;
00298             if (angle > 180.0)
00299               {
00300                 spin_ = false;
00301                 s_angle = S_ANGLE, angle = ANGLE;
00302                 home = true;
00303                 
00304               }
00305           }
00306         ROS_WARN("Looping!!!!");
00307         ros::spinOnce ();
00308         if(!spin_)
00309           loop_rate.sleep();  
00310       }
00311  
00312        ROS_INFO ("Another Scanning completed.");
00313        return (true);
00314     }
00315   
00317   
00319   void
00320   update_parameters_from_server()
00321   {
00322     if (nh_.hasParam("~object"))
00323       {
00324         string object_tmp_ = object_;
00325         nh_.getParam("~object", object_);
00326         if (object_tmp_ != object_)
00327           {
00328             spin_ = true;
00329           }
00330         ROS_INFO("Updating parameters from server");
00331       }
00332   }
00333 
00334 };
00335 
00336 
00337 int
00338   main (int argc, char** argv)
00339 {
00340   init (argc, argv, "rotating_dp_ptu");
00341 
00342   RotatingDPPTU p;
00343   p.spin ();
00344 
00345   return (0);
00346 }
00347