visual_servo_pioneer_pan.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 #include <ros/console.h>
00003 #include <std_msgs/Int8.h>
00004 #include <geometry_msgs/Twist.h>
00005 #include <geometry_msgs/PoseStamped.h>
00006 
00007 #include <visp_bridge/3dpose.h>
00008 
00009 #include <visp/vpAdaptiveGain.h>
00010 #include <visp/vpCameraParameters.h>
00011 #include <visp/vpDot.h>
00012 #include <visp/vpDot2.h>
00013 #include <visp/vpFeatureBuilder.h>
00014 #include <visp/vpFeatureDepth.h>
00015 #include <visp/vpFeaturePoint.h>
00016 #include <visp/vpHomogeneousMatrix.h>
00017 #include <visp/vpPioneerPan.h>
00018 #include <visp/vpRobot.h>
00019 #include <visp/vpServo.h>
00020 #include <visp/vpVelocityTwistMatrix.h>
00021 
00022 class VS
00023 {
00024 private:
00025   ros::NodeHandle nh_;
00026   ros::Publisher  pubTwistPioneer_; // cmd_vel
00027   ros::Publisher  pubTwistBiclops_; // cmd_vel
00028   ros::Subscriber subPoseTarget_;  // pose_stamped
00029   ros::Subscriber subStatusTarget_;  // pose_stamped
00030   ros::Subscriber subBiclopsOdom_;  // pose_stamped
00031 
00032   vpServo task;
00033   // Current and desired visual feature associated to the x coordinate of the point
00034   vpFeaturePoint s_x, s_xd;
00035   vpFeatureDepth s_Z, s_Zd;
00036 
00037   vpCameraParameters cam;
00038   double depth;
00039   double Z, Zd;
00040   double lambda;
00041 
00042   bool valid_pose;
00043   bool valid_pose_prev;
00044 
00045   double t_start_loop;
00046   double tinit;
00047 
00048   vpColVector v;
00049   vpColVector vi;
00050   vpColVector qm; // Biclops odom
00051   double qm_pan; // Measured pan position (tilt is not handled in that example)
00052   double mu;
00053   vpAdaptiveGain lambda_adapt;
00054   vpPioneerPan robot;
00055 
00056 public:
00057   void init_vs();
00058   void poseCallback(const geometry_msgs::PoseStampedConstPtr& msg);
00059   void biclopsOdomCallback(const geometry_msgs::PoseStampedConstPtr& msg);
00060   void statusCallback(const std_msgs::Int8ConstPtr& msg);
00061   VS(int argc, char**argv);
00062   virtual ~VS() {
00063     task.kill();
00064   };
00065 };
00066 
00067 VS::VS(int argc, char**argv)
00068 {
00069   init_vs();
00070 
00071   subPoseTarget_   = nh_.subscribe("/visp_auto_tracker/object_position", 1000, &VS::poseCallback, this);
00072   subStatusTarget_ = nh_.subscribe("/visp_auto_tracker/status", 1000, &VS::statusCallback, this);
00073   subBiclopsOdom_   = nh_.subscribe("/biclops/odom", 1000, &VS::biclopsOdomCallback, this);
00074   pubTwistPioneer_  = nh_.advertise<geometry_msgs::Twist>("vs/pioneer/cmd_vel", 1000);
00075   pubTwistBiclops_  = nh_.advertise<geometry_msgs::Twist>("vs/biclops/cmd_vel", 1000);
00076 }
00077 
00078 void VS::init_vs()
00079 {
00080   depth = 0.4;
00081   lambda = 1.;
00082   valid_pose = false;
00083   valid_pose_prev = false;
00084 
00085   Z = Zd = depth;
00086 
00087   v.resize(2);
00088   vi.resize(2);
00089   qm.resize(2);
00090   v = 0; vi = 0; qm = 0;
00091   mu = 4;
00092   qm_pan = 0;
00093 
00094   //lambda_adapt.initStandard(4, 0.5, 40);
00095   lambda_adapt.initStandard(3.5, 1.5, 15);
00096 
00097   cam.initPersProjWithoutDistortion(800, 795, 320, 216);
00098 
00099   task.setServo(vpServo::EYEINHAND_L_cVe_eJe) ;
00100   task.setInteractionMatrixType(vpServo::DESIRED, vpServo::PSEUDO_INVERSE) ;
00101   task.setLambda(lambda_adapt) ;
00102 
00103   vpVelocityTwistMatrix cVe = robot.get_cVe();
00104   // Update the robot jacobian that depends on the pan position
00105   robot.set_eJe(qm_pan);
00106   // Get the robot jacobian
00107   vpMatrix eJe = robot.get_eJe();
00108   task.set_eJe( eJe );
00109 
00110   vpImagePoint ip(0,0);
00111 
00112   // Create the current x visual feature
00113   vpFeatureBuilder::create(s_x, cam, ip);
00114 
00115   // Create the desired x* visual feature
00116   s_xd.buildFrom(0, 0, Zd);
00117 
00118   // Add the feature
00119   task.addFeature(s_x, s_xd, vpFeaturePoint::selectX()) ;
00120 
00121   s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z , 0); // log(Z/Z*) = 0 that's why the last parameter is 0
00122   s_Zd.buildFrom(s_x.get_x(), s_x.get_y(), Zd , 0); // log(Z/Z*) = 0 that's why the last parameter is 0
00123 
00124   // Add the feature
00125   task.addFeature(s_Z, s_Zd) ;
00126 
00127 }
00128 
00129 void VS::statusCallback(const std_msgs::Int8ConstPtr& msg)
00130 {
00131   if (msg->data == 3)
00132     valid_pose = true;
00133   else
00134     valid_pose = false;
00135 }
00136 
00137 void VS::biclopsOdomCallback(const geometry_msgs::PoseStampedConstPtr& msg)
00138 {
00139   geometry_msgs::PoseStamped position;
00140   qm[1] = position.pose.orientation.x;
00141   qm[0] = position.pose.orientation.y;
00142 }
00143 
00144 void VS::poseCallback(const geometry_msgs::PoseStampedConstPtr& msg)
00145 {
00146   geometry_msgs::Twist out_cmd_vel;
00147   geometry_msgs::Twist pioneer_cmd_vel;
00148   geometry_msgs::Twist biclops_cmd_vel;
00149   try {
00150     t_start_loop = vpTime::measureTimeMs();
00151 
00152     std::ostringstream strs;
00153     strs << "Receive a new pose" << std::endl;
00154     std::string str;
00155     str = strs.str();
00156     ROS_DEBUG("%s", str.c_str());
00157 
00158     vpHomogeneousMatrix cMo = visp_bridge::toVispHomogeneousMatrix(msg->pose);
00159 
00160     vpPoint origin;
00161     origin.setWorldCoordinates(0,0,0);
00162     origin.project(cMo);
00163     Z = origin.get_Z();
00164 
00165     if (Z <= 0)
00166       ROS_DEBUG("Z <= 0");
00167 
00168     if (! valid_pose || Z <= 0) {
00169       ROS_DEBUG("not valid pose");
00170 
00171       out_cmd_vel.linear.x = 0;
00172       out_cmd_vel.linear.y = 0;
00173       out_cmd_vel.linear.z = 0;
00174       out_cmd_vel.angular.x = 0;
00175       out_cmd_vel.angular.y = 0;
00176       out_cmd_vel.angular.z = 0;
00177       pubTwistPioneer_.publish(out_cmd_vel);
00178       pubTwistBiclops_.publish(out_cmd_vel);
00179 
00180       valid_pose = false;
00181       valid_pose_prev = valid_pose;
00182 
00183       return;
00184     }
00185 
00186     // Update the current x feature
00187     s_x.set_xyZ(origin.p[0], origin.p[1], Z);
00188 
00189     // Update log(Z/Z*) feature. Since the depth Z change, we need to update the intection matrix
00190     s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z, log(Z/Zd)) ;
00191 
00192     vpVelocityTwistMatrix cVe = robot.get_cVe();
00193     task.set_cVe( cVe );
00194     
00195       // Update the robot jacobian that depends on the pan position
00196       robot.set_eJe(qm_pan);
00197       // Get the robot jacobian
00198       vpMatrix eJe = robot.get_eJe();
00199       // Update the jacobian that will be used to compute the control law
00200       task.set_eJe(eJe);
00201 
00202     // Compute the control law. Velocities are computed in the mobile robot reference frame
00203     v = task.computeControlLaw() ;
00204 
00205     static unsigned long iter = 0;
00206 //    if (valid_pose_prev == false) {
00207     if (iter == 0) {
00208       // Start a new visual servo
00209       ROS_INFO("Reinit visual servo");
00210 
00211       tinit = t_start_loop;
00212       vi = v;
00213     }
00214     iter ++;
00215 
00216     //v = v - vi*exp(-mu*(t_start_loop - tinit)/1000.);
00217     double max_linear_vel = 0.5;
00218     double max_angular_vel = vpMath::rad(50);
00219     vpColVector v_max(3);
00220     v_max[0] = max_linear_vel;
00221     v_max[1] = max_angular_vel;
00222     v_max[2] = max_angular_vel;
00223 
00224     vpColVector v_sat = vpRobot::saturateVelocities(v, v_max);
00225 
00226 //    if (std::abs(v[0]) > max_linear_vel || std::abs(v[1]) > max_angular_vel || std::abs(v[2]) > max_angular_vel) {
00227 //      ROS_INFO("Vel exceed max allowed");
00228 //      for (unsigned int i=0; i< v.size(); i++)
00229 //        ROS_INFO("v[%d]=%f", i, v[i]);
00230 //      v = 0;
00231 //    }
00232 
00233  
00234     pioneer_cmd_vel.linear.x = v_sat[0];
00235     pioneer_cmd_vel.linear.y = 0;
00236     pioneer_cmd_vel.linear.z = 0;
00237     pioneer_cmd_vel.angular.x = 0;
00238     pioneer_cmd_vel.angular.y = 0;
00239     pioneer_cmd_vel.angular.z = v_sat[1];
00240 
00241     biclops_cmd_vel.linear.x = 0;
00242     biclops_cmd_vel.linear.y = 0;
00243     biclops_cmd_vel.linear.z = 0;
00244     biclops_cmd_vel.angular.x = 0;
00245     biclops_cmd_vel.angular.y = v_sat[2];
00246     biclops_cmd_vel.angular.z = 0;
00247 
00248     pubTwistPioneer_.publish(pioneer_cmd_vel);
00249     if (t_start_loop - tinit>2000)
00250       pubTwistBiclops_.publish(biclops_cmd_vel);
00251     valid_pose_prev = valid_pose;
00252 
00253     valid_pose = false;
00254   }
00255   catch(...) {
00256     ROS_INFO("Catch an exception: set vel to 0");
00257     out_cmd_vel.linear.x = 0;
00258     out_cmd_vel.linear.y = 0;
00259     out_cmd_vel.linear.z = 0;
00260     out_cmd_vel.angular.x = 0;
00261     out_cmd_vel.angular.y = 0;
00262     out_cmd_vel.angular.z = 0;
00263     pubTwistPioneer_.publish(out_cmd_vel);
00264     pubTwistBiclops_.publish(out_cmd_vel);
00265   }
00266 }
00267 
00268 int main(int argc, char **argv)
00269 {
00270   ros::init(argc, argv, "PioneerPan");
00271 
00272   VS vs(argc, argv);
00273 
00274   ros::spin();
00275 }
00276 
00277 


demo_pioneer
Author(s): Fabien Spindler
autogenerated on Thu Aug 27 2015 12:56:37